index.vue 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. <template>
  2. <view class="process_detail_container">
  3. <view class="main_container">
  4. <uni-card>
  5. <uni-section titleFontSize="1.3rem" title="申请内容" type="line"></uni-section>
  6. <uni-list>
  7. <uni-list-item v-for="(elem, index) in formElements" :key="index">
  8. <template v-slot:header>
  9. <text class="element_name">{{ elem.elementName }}</text>
  10. </template>
  11. <template v-slot:footer>
  12. <text class="element_value">{{ elem.defaultValue }}</text>
  13. </template>
  14. </uni-list-item>
  15. </uni-list>
  16. </uni-card>
  17. </view>
  18. <view>
  19. <!-- 重复表 -->
  20. <uni-card v-if="repeatingFormNotEmpty" spacing="0" padding="0">
  21. <button @click="handlerepeatingForm" type="primary">查看重复表</button>
  22. </uni-card>
  23. <uni-popup v-if="repeatingFormNotEmpty" ref="repeatingFormPopup">
  24. <uni-card margin="0px" spacing="0px" padding="0px">
  25. <view class="repeating_table_container">
  26. <uni-table :border="true" stripe>
  27. <uni-tr>
  28. <uni-th align="center" v-for="(item, index) in repeatingForm.elementItem" :key="index">
  29. {{ item.elementName.slice(3, 5) }}
  30. </uni-th>
  31. </uni-tr>
  32. <uni-tr
  33. v-for="(item, index) in (repeatingForm.elements.length / repeatingForm.elementItem.length)"
  34. :key="index">
  35. <uni-td align="center" v-for="col in repeatingForm.elementItem.length" :key="col">
  36. <!-- (列数 - 1) * 总行数 + 当前行数 -->
  37. {{ repeatingForm.elements[(col - 1) * (repeatingForm.elements.length /
  38. repeatingForm.elementItem.length) + index]!.defaultValue}}
  39. </uni-td>
  40. </uni-tr>
  41. </uni-table>
  42. </view>
  43. </uni-card>
  44. </uni-popup>
  45. </view>
  46. <!-- 附件 -->
  47. <view v-for="(item, index) in fileList" :key="index">
  48. <uni-card v-if="item.files.length != undefined && item.files.length > 0">
  49. <uni-section titleFontSize="1.3rem" title="附件" type="line"></uni-section>
  50. <attachment-list :attachments="item.files"></attachment-list>
  51. </uni-card>
  52. </view>
  53. <view class="flow_step_container">
  54. <uni-card>
  55. <uni-section titleFontSize="1.3rem" title="流转过程" type="line"></uni-section>
  56. <up-steps :current="stepActive" activeColor="#18bc37" inactiveColor="#2979ff" direction="column">
  57. <view v-for="(step, index) in options">
  58. <up-steps-item v-if="step.state == 3" :title="step.title" :desc="step.desc" :key="index" error>
  59. </up-steps-item>
  60. <up-steps-item v-else-if="index == stepActive" :title="step.title" :desc="step.desc" :key="index">
  61. <template #icon>
  62. <view class="active_step_circle">
  63. <text class="active_step_text">{{ index + 1 }}</text>
  64. </view>
  65. </template>
  66. </up-steps-item>
  67. <up-steps-item v-else :title="step.title" :desc="step.desc" :key="index"></up-steps-item>
  68. </view>
  69. </up-steps>
  70. </uni-card>
  71. </view>
  72. <view v-if="processInfo.tinsId">
  73. <view class="remark_container">
  74. <uni-card>
  75. <uni-section titleFontSize="1.3rem" title="备注" type="line"></uni-section>
  76. <view class="remark_content">
  77. <uni-easyinput type="textarea" autoHeight v-model="remark" placeholder="请输入"></uni-easyinput>
  78. </view>
  79. </uni-card>
  80. </view>
  81. </view>
  82. <view v-if="processInfo.tinsId" class="approve_button">
  83. <uni-card spacing="0" padding="0">
  84. <button :loading="!button_state" type="primary" @click="submitProcess('1')">通过</button>
  85. </uni-card>
  86. </view>
  87. </view>
  88. <view v-if="processInfo.tinsId">
  89. <view class="reject_button">
  90. <uni-card spacing="0" padding="0" :is-shadow="false" :border="false">
  91. <uni-row>
  92. <uni-col :span="11">
  93. <button :loading="!button_state" type="warn" @click="submitProcess('0')">退回上一级</button>
  94. </uni-col>
  95. <uni-col :span="11" :offset="2">
  96. <button :loading="!button_state" type="warn" @click="submitProcess('2')">退回发起人</button>
  97. </uni-col>
  98. </uni-row>
  99. </uni-card>
  100. </view>
  101. </view>
  102. <view style="height: 5px; margin-top: 10px;"></view>
  103. </template>
  104. <script setup lang="ts">
  105. import { onMounted, reactive, ref } from 'vue'
  106. import { onLoad } from '@dcloudio/uni-app'
  107. import attachmentList from '@/components/ygoa/attachmentList.vue'
  108. import $tab from '@/plugins/tab.js'
  109. import $modal from '@/plugins/modal.js'
  110. import { getProcessFlowInfo, getProcessFormInfo, getProcessFormInfoInFlow, getProcessFlow, submitProcessFlow } from '@/api/process.js'
  111. import { useUserStore } from '@/store/user.js'
  112. const userStore = useUserStore()
  113. const processInfo = reactive({
  114. insId: '',
  115. insName: '',
  116. control: 1,
  117. tinsId: undefined
  118. })
  119. onLoad(({ insId, tinsId, insName, control }) => {
  120. // 获取传入的标题参数
  121. const title = insName || '流程信息';
  122. processInfo.insId = insId
  123. processInfo.insName = insName
  124. processInfo.control = control
  125. if (tinsId) {
  126. processInfo['tinsId'] = tinsId
  127. }
  128. // 设置导航栏标题
  129. uni.setNavigationBarTitle({
  130. title: title
  131. });
  132. })
  133. onMounted(() => {
  134. initProcessInfo()
  135. initProcessFlow()
  136. })
  137. const repeatingForm = ref({
  138. elements: [],
  139. elementItem: [],
  140. })
  141. const repeatingFormNotEmpty = ref(false)
  142. function repeatingFormHasValue() {
  143. if (repeatingForm.value === undefined) return
  144. if (repeatingForm.value.elementItem.length <= 0) return
  145. repeatingForm.value.elements.forEach(({ defaultValue }) => {
  146. if (defaultValue != "") {
  147. repeatingFormNotEmpty.value = true
  148. return new Promise((resolve, reject) => {
  149. resolve(repeatingFormNotEmpty)
  150. })
  151. }
  152. })
  153. }
  154. const formElements = ref([])
  155. const formInfo = ref({
  156. formElements: [],
  157. formId: '',
  158. formInsId: ''
  159. })
  160. const fileList = ref([])
  161. function initProcessInfo() {
  162. if (processInfo.tinsId) {
  163. getProcessFormInfoInFlow(userStore.user.useId, processInfo).then(({ returnParams }) => {
  164. formElements.value = returnParams.formElements
  165. formInfo.value = returnParams.formInfo[0]
  166. repeatingForm.value = returnParams.repeatingForm
  167. // fileList.value = returnParams.fileList
  168. repeatingFormHasValue()
  169. })
  170. } else {
  171. getProcessFormInfo(userStore.user.useId, processInfo.insId).then(({ returnParams }) => {
  172. formElements.value = returnParams.formElements
  173. repeatingForm.value = returnParams.repeatingForm
  174. fileList.value = returnParams.fileList
  175. repeatingFormHasValue()
  176. })
  177. }
  178. }
  179. const options = ref([])
  180. const stepActive = ref(-1)
  181. const flowInfo = ref({})
  182. function initProcessFlow() {
  183. getProcessFlow(userStore.user.useId, processInfo).then(({returnParams}) => {
  184. options.value = returnParams.list.map((item, index) => {
  185. const { tmodelName, name, createdate, finishdate, remark, state } = item
  186. if (state == 1) {
  187. stepActive.value = index
  188. }
  189. const title = tmodelName + (name==''?'':' ( ' + name + ' )')
  190. const desc = '创建时间: ' + createdate
  191. + (finishdate==''?'\n':'\n办理时间: ' + finishdate)
  192. + (remark=='\n'?'':'\n环节意见: ' + remark)
  193. return {
  194. title,
  195. desc,
  196. state
  197. }
  198. })
  199. if (stepActive.value === -1) stepActive.value = returnParams.list.length
  200. // 获取未完成过程
  201. if (processInfo.tinsId) {
  202. getProcessFlowInfo(userStore.user.useId, processInfo).then(({returnParams}) => {
  203. options.value.push({title: returnParams.nextTmodels[0].nextTmodelName})
  204. flowInfo.value = returnParams.flow[0]
  205. fileList.value = [
  206. {files: returnParams.flow[0].files}
  207. ]
  208. })
  209. }
  210. })
  211. }
  212. const repeatingFormPopup = ref(null)
  213. function handlerepeatingForm() {
  214. repeatingFormPopup.value.open()
  215. }
  216. const button_state = ref(true)
  217. const remark = ref('')
  218. function submitProcess(result) {
  219. console.log('formElements: ',formElements);
  220. formInfo.value.formElements = formElements.value.map(({tableField, defaultValue}) => {
  221. return {
  222. name: tableField,
  223. value: defaultValue
  224. }
  225. })
  226. let flow = Object.assign({}, flowInfo.value)
  227. flow['staffId'] = userStore.user.useId
  228. flow['gxId'] = userStore.user.gxId
  229. flow['groupId'] = flowInfo.value.groupid
  230. flow['fileIds'] = ''
  231. // result: 1通过 2退回发起人 0退回上一级
  232. flow['result'] = result
  233. flow['remark'] = remark.value
  234. flow['nextTmodelId'] = 'undefined'
  235. submitProcessFlow(flow, formInfo.value, processInfo.control).then(({returnMsg}) => {
  236. if (returnMsg.includes('提交失败')) {
  237. // 启用提交按钮
  238. button_state.value = true
  239. $modal.msgError(returnMsg)
  240. } else {
  241. $modal.msgSuccess(returnMsg)
  242. // 通知列表刷新数据
  243. uni.$emit('ReloadProcessData', '测试$emit');
  244. setTimeout(()=> {
  245. $tab.navigateBack();
  246. }, 1000)
  247. }
  248. })
  249. }
  250. </script>
  251. <style lang="scss">
  252. .element_name {
  253. width: 10rem;
  254. font-weight: 600;
  255. }
  256. .element_value {
  257. width: 100%;
  258. }
  259. .uni-section {
  260. margin-left: -15px;
  261. margin-bottom: 10px;
  262. }
  263. .process_detail_container {
  264. position: relative;
  265. .main_container {
  266. min-height: 70vh;
  267. }
  268. .repeating_table_container {
  269. width: 98vw;
  270. .uni-table-scroll {
  271. max-height: 80vh;
  272. .uni-table {
  273. min-width: 100% !important;
  274. .uni-table-th {
  275. min-width: 50px;
  276. background-color: #2979ff;
  277. font-weight: bold;
  278. color: #fcfcfc;
  279. }
  280. }
  281. }
  282. }
  283. .flow_step_container {
  284. .u-steps {
  285. .u-steps-item {
  286. padding-bottom: 11px;
  287. .active_step_circle {
  288. width: 20px;
  289. height: 20px;
  290. box-sizing: border-box;
  291. flex-shrink: 0;
  292. border-radius: 100px;
  293. border-width: 1px;
  294. border-color: #A78BFA;
  295. background-color: #A78BFA;
  296. border-style: solid;
  297. display: flex;
  298. flex-direction: row;
  299. align-items: center;
  300. justify-content: center;
  301. transition: background-color .3s;
  302. .active_step_text {
  303. color: #fff;
  304. font-size: 11px;
  305. display: flex;
  306. flex-direction: row;
  307. align-items: center;
  308. justify-content: center;
  309. text-align: center;
  310. line-height: 11px;
  311. }
  312. }
  313. }
  314. .u-steps-item view:last-of-type {
  315. margin-top: 0 !important;
  316. .u-text__value--content {
  317. font-size: 16px !important;
  318. }
  319. .u-text__value--main {
  320. font-size: 16px !important;
  321. }
  322. }
  323. }
  324. }
  325. .remark_container {
  326. .remark_content{
  327. margin-bottom: 10px;
  328. }
  329. }
  330. .approve_button {
  331. position: sticky;
  332. z-index: 999;
  333. width: 100%;
  334. bottom: 10px;
  335. }
  336. .reject_button {
  337. .uni-card {
  338. background-color: transparent;
  339. }
  340. }
  341. }
  342. </style>