index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. <template>
  2. <view class="page">
  3. <view class="flex-col item" style="overflow: auto; height: 100%">
  4. <view class="item-process-id">
  5. {{ $t('message.processId') + data.processInstance?.id }}
  6. </view>
  7. <uni-row class="flex-row flex-wrap item-content">
  8. <uni-col :span="7">{{ $t('message.startUser') }}</uni-col>
  9. <uni-col :span="17">{{ data.processInstance?.startUser?.nickname }}</uni-col>
  10. <uni-col :span="7" class="mt-15">{{ $t('message.deviceName') }}</uni-col>
  11. <uni-col :span="17" class="mt-15">{{ faultInfo?.deviceName }}</uni-col>
  12. <template v-if="processId.startsWith('GZ')">
  13. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.name') }}</uni-col>
  14. <uni-col :span="17" class="mt-15">{{ faultInfo?.failureName }}</uni-col>
  15. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.system') }}</uni-col>
  16. <uni-col :span="17" class="mt-15">{{ faultInfo?.failureSystem }}</uni-col>
  17. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.ifDeal') }}</uni-col>
  18. <uni-col :span="17" class="mt-15">{{ getYesOrNo(faultInfo?.ifDeal) }}</uni-col>
  19. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.status') }}</uni-col>
  20. <uni-col :span="17" class="mt-15">{{ getFaultStatusName(faultInfo?.status) }}</uni-col>
  21. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.ifStop') }}</uni-col>
  22. <uni-col :span="17" class="mt-15">{{ getYesOrNo(faultInfo?.ifStop) }}</uni-col>
  23. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.failureTime') }}</uni-col>
  24. <uni-col :span="17" class="mt-15">{{ formatDate(faultInfo?.failureTime) }}</uni-col>
  25. <uni-col v-if="faultInfo?.ifDeal" :span="7" class="mt-15">{{ $t('approval.fault.dealTime') }}</uni-col>
  26. <uni-col v-if="faultInfo?.ifDeal" :span="17" class="mt-15">{{ formatDate(faultInfo?.dealTime) }}</uni-col>
  27. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.needHelp') }}</uni-col>
  28. <uni-col :span="17" class="mt-15">{{ getYesOrNo(faultInfo?.needHelp) }}</uni-col>
  29. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.failureInfluence') }}</uni-col>
  30. <uni-col :span="17" class="mt-15">{{ faultInfo?.failureInfluence }}</uni-col>
  31. <uni-col v-if="faultInfo?.ifDeal" :span="7" class="mt-15">{{ $t('approval.fault.solution') }}</uni-col>
  32. <uni-col v-if="faultInfo?.ifDeal" :span="17" class="mt-15">{{ faultInfo?.solution }}</uni-col>
  33. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.description') }}</uni-col>
  34. <uni-col :span="17" class="mt-15">{{ faultInfo?.description }}</uni-col>
  35. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.remark') }}</uni-col>
  36. <uni-col :span="17" class="mt-15">{{ faultInfo?.remark }}</uni-col>
  37. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.pic') }}</uni-col>
  38. <uni-col :span="17" class="mt-15">
  39. <image :src="faultInfo?.pic" style="width: 50px; height: 50px" @click="previewImage(faultInfo?.pic)" />
  40. </uni-col>
  41. </template>
  42. <template v-else>
  43. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.status') }}</uni-col>
  44. <uni-col :span="17" class="mt-15">{{ getFaultStatusName(faultInfo?.status) }}</uni-col>
  45. <uni-col :span="7" class="mt-15">{{ $t('approval.maintain.type') }}</uni-col>
  46. <uni-col :span="17" class="mt-15">{{ getRepairTypeName(faultInfo?.type) }}</uni-col>
  47. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.ifStop') }}</uni-col>
  48. <uni-col :span="17" class="mt-15">{{ getYesOrNo(faultInfo?.ifStop) }}</uni-col>
  49. <uni-col :span="7" class="mt-15">{{ $t('approval.maintain.startTime') }}</uni-col>
  50. <uni-col :span="17" class="mt-15">{{ formatDate(faultInfo?.maintainStartTime) }}</uni-col>
  51. <uni-col :span="7" class="mt-15">{{ $t('approval.maintain.endTime') }}</uni-col>
  52. <uni-col :span="17" class="mt-15">{{ formatDate(faultInfo?.maintainEndTime) }}</uni-col>
  53. <uni-col :span="7" class="mt-15">{{ $t('approval.maintain.person') }}</uni-col>
  54. <uni-col :span="17" class="mt-15">{{ faultInfo?.nickname }}</uni-col>
  55. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.failureTime') }}</uni-col>
  56. <uni-col :span="17" class="mt-15">{{ formatDate(faultInfo?.failureTime) }}</uni-col>
  57. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.failureInfluence') }}</uni-col>
  58. <uni-col :span="17" class="mt-15">{{ faultInfo?.failureInfluence }}</uni-col>
  59. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.system') }}</uni-col>
  60. <uni-col :span="17" class="mt-15">{{ faultInfo?.failureSystem }}</uni-col>
  61. <uni-col :span="7" class="mt-15">{{ $t('approval.maintain.maintainFee') }}</uni-col>
  62. <uni-col :span="17" class="mt-15">{{ faultInfo?.maintainFee }}</uni-col>
  63. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.description') }}</uni-col>
  64. <uni-col :span="17" class="mt-15">{{ faultInfo?.description }}</uni-col>
  65. <uni-col :span="7" class="mt-15">{{ $t('approval.maintain.desc') }}</uni-col>
  66. <uni-col :span="17" class="mt-15">{{ faultInfo?.maintainDescription }}</uni-col>
  67. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.solution') }}</uni-col>
  68. <uni-col :span="17" class="mt-15">{{ faultInfo?.solution }}</uni-col>
  69. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.remark') }}</uni-col>
  70. <uni-col :span="17" class="mt-15">{{ faultInfo?.remark }}</uni-col>
  71. <uni-col :span="7" class="mt-15">{{ $t('approval.fault.pic') }}</uni-col>
  72. <uni-col :span="17" class="mt-15">
  73. <image :src="faultInfo?.pic" style="width: 50px; height: 50px" @click="previewImage(faultInfo?.pic)" />
  74. </uni-col>
  75. </template>
  76. <uni-col :span="24" class="mt-15 flex-row flex-wrap justify-end">
  77. <view v-for="(button, index) of buttonList">
  78. <button
  79. v-if="button.enable"
  80. class="fill-button"
  81. style="margin-left: 10px; margin-top: 10px"
  82. @click="onButtonClick(index, button.displayName)"
  83. >
  84. {{ button.displayName }}
  85. </button>
  86. </view>
  87. <!-- <view v-if="buttonList && buttonList.length === 0">-->
  88. <!-- <button-->
  89. <!-- class="fill-button"-->
  90. <!-- style="margin-left: 10px; margin-top: 10px"-->
  91. <!-- @click="onButtonClick('7', $t('operation.cancel'))"-->
  92. <!-- >-->
  93. <!-- {{ $t('operation.cancel') }}-->
  94. <!-- </button>-->
  95. <!-- </view>-->
  96. </uni-col>
  97. </uni-row>
  98. </view>
  99. <uni-popup ref="dispatchUserPopup" type="bottom" background-color="white" border-radius="6px 6px 0 0">
  100. <view class="popup">
  101. <uni-forms ref="formRef" :model="form" :rules="rules" label-width="100px">
  102. <uni-forms-item v-if="['1', '3', '4'].includes(clickedButtonIndex)" :label="userFormItemLabel" name="assigneeUserId" required>
  103. <next-data-select
  104. v-model="form.assigneeUserId"
  105. :options="userList"
  106. filterable
  107. themeColor="#004098"
  108. />
  109. </uni-forms-item>
  110. <uni-forms-item v-if="clickedButtonIndex === '5'" :label="userFormItemLabel" name="userIds" required>
  111. <next-data-select
  112. v-model="form.userIds"
  113. :options="userList"
  114. :collapseTagsNum="2"
  115. multiple
  116. filterable
  117. themeColor="#004098"
  118. />
  119. </uni-forms-item>
  120. <uni-forms-item v-if="clickedButtonIndex === '1'" :label="$t('message.repairType')" name="type" required>
  121. <next-data-select
  122. v-model="form.type"
  123. :options="repairTypeList"
  124. format="{label}"
  125. field="value as value, label as text, label as label"
  126. />
  127. </uni-forms-item>
  128. <uni-forms-item v-if="clickedButtonIndex !== '7'" :label="$t('message.reason')" name="reason" :required="['3', '4', '5'].includes(clickedButtonIndex)">
  129. <uni-easyinput v-model="form.reason" type="textarea" />
  130. </uni-forms-item>
  131. <uni-forms-item v-if="clickedButtonIndex === '7'" :label="$t('message.reason1')" name="reason" required>
  132. <uni-easyinput v-model="form.reason" :placeholder="$t('message.cancelHint')" type="textarea" />
  133. </uni-forms-item>
  134. </uni-forms>
  135. <uni-row class="flex-row justify-center">
  136. <button v-if="clickedButtonIndex !== '5'" class="fill-button" style="margin-right: 10px" @click="handleClick">
  137. {{ clickedButtonIndex !== '7' ? clickedButtonText : $t('operation.confirm1') }}
  138. </button>
  139. <button v-if="clickedButtonIndex === '5'" class="fill-button" style="margin-right: 10px" @click="handleClick('before')">
  140. {{ $t('message.form.beforeSign') }}
  141. </button>
  142. <button v-if="clickedButtonIndex === '5'" class="fill-button" style="margin-right: 10px" @click="handleClick('after')">
  143. {{ $t('message.form.afterSign') }}
  144. </button>
  145. <button class="outline-button" plain="true" @click="cancel">{{ $t('operation.cancel') }}</button>
  146. </uni-row>
  147. </view>
  148. </uni-popup>
  149. </view>
  150. </template>
  151. <script setup>
  152. import { computed, getCurrentInstance, reactive, ref } from "vue"
  153. import { onLoad } from '@dcloudio/uni-app'
  154. import {
  155. approvalTask, cancelTask,
  156. createSignTask,
  157. delegateTask,
  158. getApprovalDetail,
  159. rejectTask,
  160. returnTask,
  161. transferTask
  162. } from "@/api/task"
  163. import { getFaultDetail, updateFaultProcess } from "@/api/fault";
  164. import dayjs from "dayjs";
  165. import { useDataDictStore } from "@/store/modules/dataDict";
  166. import { getUserList } from "@/api";
  167. import { reloginByUserId } from "@/utils/auth";
  168. import { getRepairDetail } from "@/api/repair";
  169. const data = ref({}) // 详情数据
  170. const faultInfo = ref({}) // 故障信息
  171. const statusList = ref([]) // 审批状态列表
  172. const repairTypeList = ref([]) // 维修状态列表
  173. const userList = ref([]) // 用户列表
  174. const yesOrNo = ref([]) // 是或否
  175. const faultStatusList = ref([]) // 故障状态列表
  176. // 通过状态码获取状态名称
  177. const getFaultStatusName = (status) => {
  178. if (!status) return ''
  179. for (const item of faultStatusList.value) {
  180. if (item.value === status) {
  181. return item.label
  182. }
  183. }
  184. }
  185. // const getStatusName = (status) => {
  186. // if (!status) return ''
  187. // for (const item of statusList.value) {
  188. // if ((item.value + '') === status) {
  189. // return item.label
  190. // }
  191. // }
  192. // }
  193. // 通过布尔类型获取是或否
  194. const getYesOrNo = (value) => {
  195. if (value === undefined) return ''
  196. for (const item of yesOrNo.value) {
  197. if (value && item.value === 'true') {
  198. return item.label
  199. } else if (!value && item.value === 'false') {
  200. return item.label
  201. }
  202. }
  203. }
  204. // 通过维修类型获取名称
  205. const getRepairTypeName = (type) => {
  206. if (!type) return ''
  207. for (const item of repairTypeList.value) {
  208. if (item.value === type) {
  209. return item.label
  210. }
  211. }
  212. }
  213. // 格式化日期
  214. const formatDate = (date) => {
  215. if (!date) return ''
  216. return dayjs(date).format('YYYY-MM-DD')
  217. }
  218. const getUserName = (userId) => {
  219. if (!userId) return
  220. for (const item of userList.value) {
  221. if (item.value === userId) {
  222. faultInfo.value.nickname = item.label
  223. return item.label
  224. }
  225. }
  226. }
  227. // 预览图片
  228. const previewImage = (url) => {
  229. if (!url) return
  230. uni.previewImage({ urls: [url] })
  231. }
  232. const buttonList = ref()
  233. const setButtonList = (data) => {
  234. if (data && data.todoTask) {
  235. buttonList.value = data.todoTask.buttonsSetting || []
  236. } else {
  237. buttonList.value = []
  238. }
  239. }
  240. const userFormItemLabel = computed(() => {
  241. const index = clickedButtonIndex.value
  242. if (index === '1') {
  243. return t('message.dispatchUser') // 负责人
  244. } else if (index === '3') {
  245. return t('message.form.user3') // 新审批人
  246. } else if (index === '4') {
  247. return t('message.form.user4') // 接收人
  248. } else if (index === '5') {
  249. return t('message.form.user5') // 加签处理人
  250. } else {
  251. return ''
  252. }
  253. })
  254. const clickedButtonIndex = ref(0)
  255. const clickedButtonText = ref('')
  256. const onButtonClick = async (index, text) => {
  257. clickedButtonIndex.value = index
  258. clickedButtonText.value = text
  259. if (index === '1') { // 分配责任人
  260. rules.assigneeUserId.rules = [{ required: true, errorMessage: t('message.form.errorHint1') }]
  261. rules.reason.rules[0].required = false
  262. } else if (index === '2') { // 拒绝
  263. rules.assigneeUserId.rules[0].required = false
  264. rules.reason.rules[0].required = false
  265. } else if (index === '3') { // 转办
  266. rules.assigneeUserId.rules = [{ required: true, errorMessage: t('message.form.errorHint3') }]
  267. rules.reason.rules[0].required = true
  268. } else if (index === '4') { // 委派
  269. rules.assigneeUserId.rules = [{ required: true, errorMessage: t('message.form.errorHint5') }]
  270. rules.reason.rules[0].required = true
  271. } else if (index === '5') { // 加签
  272. rules.assigneeUserId.rules[0].required = false
  273. rules.userIds.rules[0].required = true
  274. rules.reason.rules[0].required = true
  275. } else if (index === '6') { // 退回
  276. const code = (await returnTask(taskId.value)).code
  277. if (code === 0) {
  278. uni.showToast({ title: t('operation.success'), icon: 'none' })
  279. uni.navigateBack()
  280. uni.$emit('update')
  281. }
  282. return
  283. } else if (index === '7') {
  284. rules.reason.rules[0].errorMessage = t('message.form.errorHint7')
  285. }
  286. showDispatchUserPopup()
  287. }
  288. // 分配责任人弹窗
  289. const dispatchUserPopup = ref()
  290. const showDispatchUserPopup = () => {
  291. dispatchUserPopup.value.open('bottom')
  292. }
  293. const form = reactive({
  294. assigneeUserId: undefined,
  295. delegateUserId: undefined,
  296. userIds: undefined,
  297. type: undefined,
  298. reason: undefined,
  299. id: undefined,
  300. })
  301. const formRef = ref()
  302. const { appContext } = getCurrentInstance()
  303. const t = appContext.config.globalProperties.$t
  304. const rules = reactive({
  305. assigneeUserId: { rules: [{ required: true, errorMessage: t('message.form.errorHint1') }] },
  306. userIds: { rules: [{ required: true, errorMessage: t('message.form.errorHint6') }] }, // 加签处理人
  307. type: { rules: [{ required: true, errorMessage: t('message.form.errorHint2') }] },
  308. reason: { rules: [{ required: true, errorMessage: t('message.form.errorHint4') }] },
  309. })
  310. const cancel = () => dispatchUserPopup.value.close('bottom')
  311. const handleClick = async (sign) => {
  312. try {
  313. const valid = await formRef.value.validate()
  314. if (!valid) return
  315. if (!form.reason) {
  316. form.reason = form.reason || ''
  317. }
  318. let code = -1
  319. if (clickedButtonIndex.value === '1') { // 分配责任人
  320. code = (await updateFaultProcess(faultId.value, form.type, form.assigneeUserId)).code
  321. code = (await approvalTask(taskId.value, form.reason)).code
  322. } else if (clickedButtonIndex.value === '2') { // 拒绝
  323. code = (await rejectTask(taskId.value, form.reason)).code
  324. } else if (clickedButtonIndex.value === '3') { // 转办
  325. code = (await transferTask(taskId.value, form.assigneeUserId, form.reason)).code
  326. } else if (clickedButtonIndex.value === '4') { // 委派
  327. code = (await delegateTask(taskId.value, form.assigneeUserId, form.reason)).code
  328. } else if (clickedButtonIndex.value === '5') { // 加签
  329. code = (await createSignTask(taskId.value, form.userIds, sign, form.reason)).code
  330. } else if (clickedButtonIndex.value === '7') { // 退回
  331. code = (await cancelTask(processId.value, form.reason)).code
  332. }
  333. if (code === 0) { // 成功时返回
  334. uni.showToast({ title: t('operation.success'), icon: 'none' })
  335. uni.$emit('update')
  336. uni.navigateBack()
  337. }
  338. } catch (e) {
  339. console.log(e)
  340. }
  341. }
  342. const processId = ref('')
  343. const taskId = ref('')
  344. const faultId = ref('')
  345. const { loadDataDictList, getDataDictList } = useDataDictStore()
  346. onLoad(async (options) => {
  347. await reloginByUserId(options.reloginUserId)
  348. taskId.value = options.id
  349. processId.value = options.processInstanceId
  350. statusList.value = getDataDictList('crm_audit_status') // 审批状态列表
  351. repairTypeList.value = getDataDictList('pms_main_type') // 维修类型列表
  352. faultStatusList.value = getDataDictList('pms_failure_status') // 故障状态列表
  353. yesOrNo.value = getDataDictList('infra_boolean_string') // 是或否
  354. if (repairTypeList.value.length === 0) {
  355. await loadDataDictList()
  356. statusList.value = getDataDictList('crm_audit_status') // 审批状态列表
  357. repairTypeList.value = getDataDictList('pms_main_type') // 维修类型列表
  358. faultStatusList.value = getDataDictList('pms_failure_status') // 故障状态列表
  359. yesOrNo.value = getDataDictList('infra_boolean_string') // 是或否
  360. }
  361. data.value = (await getApprovalDetail(options)).data
  362. faultId.value = data.value.processInstance.businessKey
  363. if (processId.value.startsWith('GZ')) {
  364. faultInfo.value = (await getFaultDetail({ id: faultId.value })).data
  365. } else {
  366. faultInfo.value = (await getRepairDetail({ id: faultId.value})).data
  367. }
  368. setButtonList(data.value)
  369. let userId
  370. if (data.value.todoTask) {
  371. userId = data.value.todoTask.assigneeUser.id
  372. if (!taskId.value) {
  373. taskId.value = data.value.todoTask.id
  374. }
  375. } else {
  376. userId = data.value.processInstance.startUser.id
  377. }
  378. userList.value = (await getUserList(userId)).data.map(item => ({
  379. value: item.id,
  380. text: item.nickname,
  381. label: item.nickname,
  382. }))
  383. getUserName(faultInfo.value?.maintainPerson)
  384. })
  385. </script>
  386. <style scoped lang="scss">
  387. .item {
  388. margin: 10px 0;
  389. background-color: white;
  390. border-radius: 0 0 6px 6px;
  391. }
  392. .item-process-id {
  393. padding: 10px;
  394. background: linear-gradient( 270deg, #FFFFFF 0%, #8EBEFF 100%);
  395. border-radius: 6px 6px 0 0;
  396. }
  397. .item-content {
  398. padding: 15px 20px 12px 10px;
  399. font-size: 14px;
  400. color: #333333;
  401. }
  402. .mt-15 {
  403. margin-top: 15px;
  404. }
  405. .mt-27 {
  406. margin-top: 27px;
  407. }
  408. .outline-button {
  409. border: 1px #004098 solid;
  410. border-radius: 3px;
  411. color: #004098;
  412. font-size: 14px;
  413. min-width: 90px;
  414. height: 32px;
  415. line-height: 32px;
  416. margin: 0;
  417. }
  418. .fill-button {
  419. background-color: #004098;
  420. color: white;
  421. font-size: 14px;
  422. min-width: 90px;
  423. height: 32px;
  424. line-height: 32px;
  425. margin: 0;
  426. padding: 0;
  427. }
  428. .popup {
  429. padding: 10px;
  430. }
  431. </style>