vue2-client 1.15.34 → 1.15.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (691) hide show
  1. package/.cursorrules +19 -19
  2. package/.editorconfig +9 -9
  3. package/.env +20 -20
  4. package/.env.apply +19 -19
  5. package/.env.development +1 -1
  6. package/.env.gaslink +19 -19
  7. package/.env.his +19 -19
  8. package/.env.iot +19 -19
  9. package/.env.liuli +20 -20
  10. package/.env.message +19 -19
  11. package/.env.revenue +19 -19
  12. package/.env.runtime +19 -19
  13. package/.env.scada +19 -19
  14. package/.eslintrc.js +90 -90
  15. package/.eslintrc.json +5 -5
  16. package/CHANGELOG.md +824 -824
  17. package/CLAUDE.md +89 -89
  18. package/Components.md +60 -60
  19. package/README.md +65 -65
  20. package/babel.config.js +21 -21
  21. package/docs/Logic/345/207/275/346/225/260/344/275/277/347/224/250/347/233/270/345/205/263.md +45 -45
  22. package/docs/LowCode/lowcode.md +155 -155
  23. package/docs/LowCode/lowcodeForDeveloper.md +230 -230
  24. package/docs/index.md +30 -30
  25. package/docs/notice.md +22 -22
  26. package/docs//345/207/275/346/225/260/344/275/277/347/224/250/347/233/270/345/205/263.md +177 -177
  27. package/index.js +31 -31
  28. package/jest-transform-stub.js +8 -8
  29. package/jest.config.js +22 -22
  30. package/jest.setup.js +7 -7
  31. package/jsconfig.json +19 -19
  32. package/package.json +110 -110
  33. package/public/his/editor/editor.html +51 -51
  34. package/public/his/editor/mock/bind_data.html +779 -779
  35. package/public/his/editor/mock/data_table.html +40 -40
  36. package/public/his/editor/mock/sign.html +75 -75
  37. package/public/his/editor/vender/JsBarcode.all.js +3669 -3669
  38. package/public/his/editor/vender/date97/My97DatePicker.htm +65 -65
  39. package/public/his/editor/vender/date97/WdatePicker.js +677 -677
  40. package/public/his/editor/vender/date97/calendar.js +4 -4
  41. package/public/his/editor/vender/date97/lang/en.js +13 -13
  42. package/public/his/editor/vender/date97/lang/zh-cn.js +13 -13
  43. package/public/his/editor/vender/date97/lang/zh-tw.js +13 -13
  44. package/public/his/editor/vender/date97/skin/WdatePicker.css +10 -10
  45. package/public/his/editor/vender/date97/skin/default/datepicker.css +328 -328
  46. package/public/his/editor/vender/date97/skin/ext/datepicker.css +308 -308
  47. package/public/his/editor/vender/date97/skin/whyGreen/datepicker.css +255 -255
  48. package/public/his/editor/vender/diff.js +1627 -1627
  49. package/public/his/editor/vender/editor.js +1 -1
  50. package/public/his/editor/vender/fabric.js +31187 -31187
  51. package/public/his/editor/vender/jquery/jquery.base64.js +190 -190
  52. package/public/his/editor/vender/jquery/jquery.js +10872 -10872
  53. package/public/his/editor/vender/jquery/jquery.print.js +255 -255
  54. package/public/his/editor/vender/jquery/zTreeStyle/zTreeStyle.css +96 -96
  55. package/public/his/editor/vender/mui/mui.min.css +4 -4
  56. package/public/his/editor/vender/mui/mui.min.js +5 -5
  57. package/public/his/editor/vender/mui/mui.picker.min.css +6 -6
  58. package/public/his/editor/vender/mui/mui.picker.min.js +6 -6
  59. package/public/his/editor/vender/qrcode.js +7 -7
  60. package/public/his/editor/vender/requirejs/require.js +2145 -2145
  61. package/public/his/editor/vender/signature/jSignature.CompressorSVG.js +518 -518
  62. package/public/his/editor/vender/signature/jSignature.UndoButton.js +164 -164
  63. package/public/his/editor/vender/signature/jSignature.js +1486 -1486
  64. package/public/his/editor/vender/validator.js +5094 -5094
  65. package/public/his/editor/vender/weui/weui.css +5659 -5659
  66. package/public/his/editor/vender/weui/weui.min.css +4 -4
  67. package/public/his/editor/vender/weui/weui.min.js +11 -11
  68. package/public/index.html +27 -27
  69. package/src/App.vue +196 -196
  70. package/src/ReportView.js +13 -13
  71. package/src/assets/img/querySlotDemo.svg +15 -15
  72. package/src/assets/svg/badtwo.svg +1 -1
  73. package/src/assets/svg/goodtwo.svg +1 -1
  74. package/src/base-client/components/AI/AskAiBtn.vue +136 -136
  75. package/src/base-client/components/AI/demo.vue +31 -31
  76. package/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox.vue +532 -532
  77. package/src/base-client/components/common/AddressSearchCombobox/IcMapIcon.vue +16 -16
  78. package/src/base-client/components/common/AddressSearchCombobox/demo.vue +36 -36
  79. package/src/base-client/components/common/AddressSearchCombobox/ic_map.svg +6 -6
  80. package/src/base-client/components/common/AddressSearchCombobox/index.js +3 -3
  81. package/src/base-client/components/common/AmapMarker/AmapPointRendering.vue +120 -120
  82. package/src/base-client/components/common/AmapMarker/index.js +3 -3
  83. package/src/base-client/components/common/CitySelect/CitySelect.vue +365 -365
  84. package/src/base-client/components/common/CitySelect/index.js +3 -3
  85. package/src/base-client/components/common/CitySelect/index.md +109 -109
  86. package/src/base-client/components/common/CreateQuery/CreateQuery.vue +669 -669
  87. package/src/base-client/components/common/CreateQuery/CreateQueryItem.vue +1014 -1014
  88. package/src/base-client/components/common/CreateQuery/index.js +3 -3
  89. package/src/base-client/components/common/CreateQuery/index.md +42 -42
  90. package/src/base-client/components/common/CreateSimpleFormQuery/CreateSimpleFormQuery.vue +452 -452
  91. package/src/base-client/components/common/CreateSimpleFormQuery/CreateSimpleFormQueryItem.vue +511 -511
  92. package/src/base-client/components/common/CreateSimpleFormQuery/index.js +3 -3
  93. package/src/base-client/components/common/CreateSimpleFormQuery/index.md +42 -42
  94. package/src/base-client/components/common/FormGroupEdit/FormGroupEdit.vue +146 -146
  95. package/src/base-client/components/common/FormGroupEdit/index.js +3 -3
  96. package/src/base-client/components/common/FormGroupEdit/index.md +43 -43
  97. package/src/base-client/components/common/FormGroupQuery/FormGroupQuery.vue +166 -166
  98. package/src/base-client/components/common/FormGroupQuery/index.js +3 -3
  99. package/src/base-client/components/common/FormGroupQuery/index.md +43 -43
  100. package/src/base-client/components/common/JSONToTree/index.js +3 -3
  101. package/src/base-client/components/common/JSONToTree/jsontotree.vue +271 -271
  102. package/src/base-client/components/common/LowCodeComponent/LowCodeEditorModal.vue +108 -108
  103. package/src/base-client/components/common/LowCodeComponent/LowCodeEditorPanel.vue +413 -413
  104. package/src/base-client/components/common/LowCodeComponent/LowCodePageOrganization.vue +502 -502
  105. package/src/base-client/components/common/LowCodeComponent/LowCodeRender.vue +728 -728
  106. package/src/base-client/components/common/LowCodeComponent/LowCodeRenderEnter.vue +29 -29
  107. package/src/base-client/components/common/LowCodeComponent/LowCodeUIStore.vue +219 -219
  108. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeAddPageModal.vue +117 -117
  109. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeCustomJSModal.vue +80 -80
  110. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeEventEditorModal.vue +398 -398
  111. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeLifeCycleModal.vue +65 -65
  112. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeLogicCallbackModal.vue +64 -64
  113. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeLogicParamModal.vue +73 -73
  114. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeRunFunctionParamModal.vue +76 -76
  115. package/src/base-client/components/common/PersonSetting/PersonSetting.vue +208 -208
  116. package/src/base-client/components/common/PersonSetting/index.js +3 -3
  117. package/src/base-client/components/common/Recording/Recording.vue +243 -243
  118. package/src/base-client/components/common/Recording/index.js +3 -3
  119. package/src/base-client/components/common/Tree/Tree.vue +149 -149
  120. package/src/base-client/components/common/Tree/index.js +2 -2
  121. package/src/base-client/components/common/Upload/Upload.vue +323 -323
  122. package/src/base-client/components/common/Upload/index.js +3 -3
  123. package/src/base-client/components/common/XAddForm/XAddForm.vue +113 -113
  124. package/src/base-client/components/common/XAddForm/index.js +3 -3
  125. package/src/base-client/components/common/XAddForm/index.md +61 -61
  126. package/src/base-client/components/common/XAddNativeForm/XAddNativeForm.vue +1169 -1169
  127. package/src/base-client/components/common/XAddNativeForm/demo.vue +40 -40
  128. package/src/base-client/components/common/XAddNativeForm/index.js +3 -3
  129. package/src/base-client/components/common/XAddNativeForm/index.md +146 -146
  130. package/src/base-client/components/common/XAddNativeFormOA/XAddNativeFormOA.vue +303 -303
  131. package/src/base-client/components/common/XAddNativeFormOA/index.js +3 -3
  132. package/src/base-client/components/common/XAddNativeFormOA/index.md +146 -146
  133. package/src/base-client/components/common/XAddReport/XAddReport.vue +212 -212
  134. package/src/base-client/components/common/XAddReport/index.js +3 -3
  135. package/src/base-client/components/common/XAddReport/index.md +56 -56
  136. package/src/base-client/components/common/XBadge/XBadge.vue +94 -94
  137. package/src/base-client/components/common/XBadge/index.js +3 -3
  138. package/src/base-client/components/common/XBadge/index.md +39 -39
  139. package/src/base-client/components/common/XButtons/XButtonDemo.vue +28 -28
  140. package/src/base-client/components/common/XButtons/XButtons.vue +71 -71
  141. package/src/base-client/components/common/XButtons/index.js +3 -3
  142. package/src/base-client/components/common/XButtons/index.md +61 -61
  143. package/src/base-client/components/common/XCalendar/XCalendar.vue +369 -369
  144. package/src/base-client/components/common/XCalendar/index.md +284 -284
  145. package/src/base-client/components/common/XCard/XCard.vue +64 -64
  146. package/src/base-client/components/common/XCard/index.js +3 -3
  147. package/src/base-client/components/common/XCard/index.md +43 -43
  148. package/src/base-client/components/common/XCardSet/XCardSet.vue +300 -300
  149. package/src/base-client/components/common/XCheckList/XCheckList.vue +106 -106
  150. package/src/base-client/components/common/XCheckList/XCheckListDemo.vue +41 -41
  151. package/src/base-client/components/common/XCollapse/XCollapse.vue +253 -253
  152. package/src/base-client/components/common/XConversation/XConversation.vue +576 -576
  153. package/src/base-client/components/common/XConversation/XConversationDemo.vue +28 -28
  154. package/src/base-client/components/common/XDataCard/XDataCard.vue +629 -629
  155. package/src/base-client/components/common/XDataCard/index.js +3 -3
  156. package/src/base-client/components/common/XDataCard/index.md +1 -1
  157. package/src/base-client/components/common/XDataDrawer/XDataDrawer.vue +180 -180
  158. package/src/base-client/components/common/XDataDrawer/index.js +3 -3
  159. package/src/base-client/components/common/XDataDrawer/index.md +41 -41
  160. package/src/base-client/components/common/XDatePicker/demo.vue +153 -153
  161. package/src/base-client/components/common/XDatePicker/index.vue +276 -276
  162. package/src/base-client/components/common/XDescriptions/XDescriptions.vue +174 -174
  163. package/src/base-client/components/common/XDescriptions/XDescriptionsGroup.vue +314 -314
  164. package/src/base-client/components/common/XDescriptions/demo.vue +51 -51
  165. package/src/base-client/components/common/XDescriptions/index.js +3 -3
  166. package/src/base-client/components/common/XDescriptions/index.md +83 -83
  167. package/src/base-client/components/common/XDetailsView/XDetailsView.vue +238 -238
  168. package/src/base-client/components/common/XDetailsView/index.js +3 -3
  169. package/src/base-client/components/common/XForm/XForm.vue +420 -420
  170. package/src/base-client/components/common/XForm/XFormItem.vue +1342 -1342
  171. package/src/base-client/components/common/XForm/XStatusButton.vue +54 -54
  172. package/src/base-client/components/common/XForm/XTreeSelect.vue +276 -276
  173. package/src/base-client/components/common/XForm/demo.vue +105 -105
  174. package/src/base-client/components/common/XForm/index.js +3 -3
  175. package/src/base-client/components/common/XForm/index.md +178 -178
  176. package/src/base-client/components/common/XForm/itemComponent/XClickChangeBtn/index.vue +49 -49
  177. package/src/base-client/components/common/XFormCol/XFormCol.vue +157 -157
  178. package/src/base-client/components/common/XFormCol/index.js +3 -3
  179. package/src/base-client/components/common/XFormCol/index.md +35 -35
  180. package/src/base-client/components/common/XFormGroup/XFormGroup.vue +301 -301
  181. package/src/base-client/components/common/XFormGroup/demo.vue +41 -41
  182. package/src/base-client/components/common/XFormGroup/index.js +3 -3
  183. package/src/base-client/components/common/XFormGroup/index.md +38 -38
  184. package/src/base-client/components/common/XFormGroupDetails/XFormGroupDetails.vue +72 -72
  185. package/src/base-client/components/common/XFormGroupDetails/index.js +3 -3
  186. package/src/base-client/components/common/XFormTable/XFormTable.vue +938 -938
  187. package/src/base-client/components/common/XFormTable/demo.vue +87 -87
  188. package/src/base-client/components/common/XFormTable/index.js +3 -3
  189. package/src/base-client/components/common/XFormTable/index.md +92 -92
  190. package/src/base-client/components/common/XImportExcel/XImportExcel.vue +174 -174
  191. package/src/base-client/components/common/XImportExcel/index.js +3 -3
  192. package/src/base-client/components/common/XImportExcel/index.md +38 -38
  193. package/src/base-client/components/common/XInput/XInput.vue +128 -128
  194. package/src/base-client/components/common/XInput/index.js +3 -3
  195. package/src/base-client/components/common/XInput/index.md +97 -97
  196. package/src/base-client/components/common/XIntervalPicker/XIntervalPicker.vue +121 -121
  197. package/src/base-client/components/common/XLabelSelect/XLabelSelect.vue +110 -110
  198. package/src/base-client/components/common/XLabelSelect/XLabelSelectDemo.vue +35 -35
  199. package/src/base-client/components/common/XLicensePlate/XLicensePlate.vue +193 -193
  200. package/src/base-client/components/common/XLicensePlate/XLicensePlateDemo.vue +48 -48
  201. package/src/base-client/components/common/XLicensePlate/index.js +3 -3
  202. package/src/base-client/components/common/XLicensePlate/index.md +38 -38
  203. package/src/base-client/components/common/XPrint/Demo.vue +41 -41
  204. package/src/base-client/components/common/XPrint/OpenInvoice.vue +21 -21
  205. package/src/base-client/components/common/XPrint/PrintBill.vue +304 -304
  206. package/src/base-client/components/common/XPrint/PrintHtml.js +98 -98
  207. package/src/base-client/components/common/XPrint/css/hiPrintCss.js +359 -359
  208. package/src/base-client/components/common/XPrint/css/lodopCss.js +26 -26
  209. package/src/base-client/components/common/XPrint/css/print-lock.css +351 -351
  210. package/src/base-client/components/common/XPrint/index.vue +97 -97
  211. package/src/base-client/components/common/XRate/demo.vue +102 -102
  212. package/src/base-client/components/common/XRate/index.vue +149 -149
  213. package/src/base-client/components/common/XReport/XReport.vue +963 -963
  214. package/src/base-client/components/common/XReport/XReportDemo.vue +70 -70
  215. package/src/base-client/components/common/XReport/XReportDesign.vue +463 -463
  216. package/src/base-client/components/common/XReport/XReportJsonRender.vue +381 -381
  217. package/src/base-client/components/common/XReport/XReportTrGroup.vue +1005 -1005
  218. package/src/base-client/components/common/XReport/index.js +3 -3
  219. package/src/base-client/components/common/XReport/index.md +103 -103
  220. package/src/base-client/components/common/XReport/print.js +186 -186
  221. package/src/base-client/components/common/XReportDrawer/XReportDrawer.vue +201 -201
  222. package/src/base-client/components/common/XReportDrawer/index.js +3 -3
  223. package/src/base-client/components/common/XReportGrid/XReport.vue +1075 -1075
  224. package/src/base-client/components/common/XReportGrid/XReportDemo.vue +44 -44
  225. package/src/base-client/components/common/XReportGrid/XReportDesign.vue +620 -620
  226. package/src/base-client/components/common/XReportGrid/XReportTrGroup.vue +731 -731
  227. package/src/base-client/components/common/XReportGrid/index.js +3 -3
  228. package/src/base-client/components/common/XReportGrid/index.md +44 -44
  229. package/src/base-client/components/common/XReportGrid/print.js +184 -184
  230. package/src/base-client/components/common/XReportSlot/XReportSlot.vue +110 -110
  231. package/src/base-client/components/common/XReportSlot/index.js +3 -3
  232. package/src/base-client/components/common/XReportSlot/index.md +48 -48
  233. package/src/base-client/components/common/XSimpleDescriptions/XSimpleDescriptions.vue +166 -166
  234. package/src/base-client/components/common/XSimpleDescriptions/index.js +3 -3
  235. package/src/base-client/components/common/XSimpleDescriptions/index.md +7 -7
  236. package/src/base-client/components/common/XStepView/XStepView.vue +252 -252
  237. package/src/base-client/components/common/XStepView/index.js +3 -3
  238. package/src/base-client/components/common/XStepView/index.md +31 -31
  239. package/src/base-client/components/common/XTab/XTab.vue +299 -299
  240. package/src/base-client/components/common/XTab/XTabDemo.vue +22 -22
  241. package/src/base-client/components/common/XTab/index.js +3 -3
  242. package/src/base-client/components/common/XTable/CustomFuncCel.vue +51 -51
  243. package/src/base-client/components/common/XTable/ExportExcel.vue +282 -282
  244. package/src/base-client/components/common/XTable/TableCellRenderer.vue +161 -161
  245. package/src/base-client/components/common/XTable/XTable.vue +1613 -1600
  246. package/src/base-client/components/common/XTable/XTableWrapper.vue +584 -584
  247. package/src/base-client/components/common/XTable/index.js +3 -3
  248. package/src/base-client/components/common/XTable/index.md +255 -255
  249. package/src/base-client/components/common/XTagGroup/index.vue +52 -52
  250. package/src/base-client/components/common/XTimeline/XTimeline.vue +358 -358
  251. package/src/base-client/components/common/XTimeline/index.md +191 -191
  252. package/src/base-client/components/common/XTree/XTree.vue +424 -424
  253. package/src/base-client/components/common/XTree/XTreePro.vue +452 -452
  254. package/src/base-client/components/common/XTree/index.js +3 -3
  255. package/src/base-client/components/common/XTree/index.md +36 -36
  256. package/src/base-client/components/common/XTreeOne/XTreeOne.vue +113 -113
  257. package/src/base-client/components/common/XTreeOne/XTreeOnePro.vue +128 -128
  258. package/src/base-client/components/common/XTreeOne/index.js +3 -3
  259. package/src/base-client/components/common/XUploadFilesView/index.vue +485 -485
  260. package/src/base-client/components/common/richTextModal/index.vue +56 -56
  261. package/src/base-client/components/common/richTextModal/richDemo.vue +48 -48
  262. package/src/base-client/components/his/XCharge/XCharge.vue +238 -238
  263. package/src/base-client/components/his/XCheckbox/XCheckbox.vue +105 -105
  264. package/src/base-client/components/his/XCheckbox/index.md +253 -253
  265. package/src/base-client/components/his/XHDescriptions/XHDescriptions.vue +430 -430
  266. package/src/base-client/components/his/XHDescriptions/index.md +217 -217
  267. package/src/base-client/components/his/XHisEditor/XHisEditor.vue +457 -457
  268. package/src/base-client/components/his/XHisEditor/diagnosisAutocomplete.js +263 -263
  269. package/src/base-client/components/his/XHisEditor/index.js +3 -3
  270. package/src/base-client/components/his/XList/XList.vue +306 -306
  271. package/src/base-client/components/his/XQuestionnaire/XQuestionnaire.json +3 -3
  272. package/src/base-client/components/his/XQuestionnaire/XQuestionnaire.vue +89 -89
  273. package/src/base-client/components/his/XQuestionnaire/XQuestionnaireDemo.vue +51 -51
  274. package/src/base-client/components/his/XQuestionnaire/XQuestionnaireItem.vue +252 -252
  275. package/src/base-client/components/his/XRadio/XRadio.vue +125 -125
  276. package/src/base-client/components/his/XRadio/index.md +234 -234
  277. package/src/base-client/components/his/XSelect/XSelect.vue +72 -72
  278. package/src/base-client/components/his/XShiftSchedule/XShiftSchedule.vue +234 -234
  279. package/src/base-client/components/his/XShiftSchedule/dome.vue +29 -29
  280. package/src/base-client/components/his/XSidebar/XSidebar.vue +240 -240
  281. package/src/base-client/components/his/XTextCard/XTextCard.vue +207 -207
  282. package/src/base-client/components/his/XTimeSelect/XTimeSelect.vue +162 -162
  283. package/src/base-client/components/his/XTimeSelect/XTimeSelectDemo.vue +23 -23
  284. package/src/base-client/components/his/XTitle/README.md +113 -113
  285. package/src/base-client/components/his/XTitle/XTitle.vue +123 -123
  286. package/src/base-client/components/his/XTreeRows/TreeNode.vue +100 -100
  287. package/src/base-client/components/his/XTreeRows/XTreeRows.vue +197 -197
  288. package/src/base-client/components/his/threeTestOrders/dome.vue +68 -68
  289. package/src/base-client/components/his/threeTestOrders/editor.vue +111 -111
  290. package/src/base-client/components/his/threeTestOrders/textBox.vue +457 -457
  291. package/src/base-client/components/his/threeTestOrders/threeTestOrders.vue +475 -475
  292. package/src/base-client/components/index.js +51 -51
  293. package/src/base-client/components/layout/XPageView/RenderRow.vue +88 -88
  294. package/src/base-client/components/layout/XPageView/XErrorView.vue +22 -22
  295. package/src/base-client/components/layout/XPageView/XPageRowTemplate.vue +37 -37
  296. package/src/base-client/components/layout/XPageView/XPageView.vue +223 -223
  297. package/src/base-client/components/layout/XPageView/XTab/XTab.vue +96 -96
  298. package/src/base-client/components/layout/XPageView/XTab/index.js +3 -3
  299. package/src/base-client/components/layout/XPageView/componentTypes.js +22 -22
  300. package/src/base-client/components/layout/XPageView/index.js +2 -2
  301. package/src/base-client/components/layout/XPageView/index.md +96 -96
  302. package/src/base-client/components/layout/XTreeView/XTreeView.vue +130 -130
  303. package/src/base-client/components/layout/XTreeView/index.js +3 -3
  304. package/src/base-client/components/layout/XTreeView/index.md +46 -46
  305. package/src/base-client/components/system/DictionaryDetailsView/DictionaryDetailsView.vue +232 -232
  306. package/src/base-client/components/system/DictionaryDetailsView/index.js +3 -3
  307. package/src/base-client/components/system/DictionaryDetailsView/index.md +41 -41
  308. package/src/base-client/components/system/LogDetailsView/LogDetailsView.vue +376 -376
  309. package/src/base-client/components/system/LogDetailsView/index.js +3 -3
  310. package/src/base-client/components/system/LogDetailsView/index.md +41 -41
  311. package/src/base-client/components/system/QueryParamsDetailsView/QueryParamsDetailsView.vue +281 -281
  312. package/src/base-client/components/system/QueryParamsDetailsView/index.js +3 -3
  313. package/src/base-client/components/ticket/TicketDetailsView/TicketDetailsView.vue +807 -807
  314. package/src/base-client/components/ticket/TicketDetailsView/index.js +3 -3
  315. package/src/base-client/components/ticket/TicketDetailsView/index.md +29 -29
  316. package/src/base-client/components/ticket/TicketDetailsView/part/TicketDetailsFlow.vue +260 -260
  317. package/src/base-client/components/ticket/TicketDetailsView/part/index.js +3 -3
  318. package/src/base-client/components/ticket/TicketSubmitSuccessView/TicketSubmitSuccessView.vue +532 -532
  319. package/src/base-client/components/ticket/TicketSubmitSuccessView/index.js +3 -3
  320. package/src/base-client/components/ticket/TicketSubmitSuccessView/index.md +29 -29
  321. package/src/base-client/plugins/AppData.js +126 -126
  322. package/src/base-client/plugins/Config.js +19 -19
  323. package/src/base-client/plugins/GetLoginInfoService.js +183 -183
  324. package/src/base-client/plugins/PagedList.js +177 -177
  325. package/src/base-client/plugins/Recording.js +258 -258
  326. package/src/base-client/plugins/authority-plugin.js +167 -167
  327. package/src/base-client/plugins/compatible/LoginServiceOA.js +20 -20
  328. package/src/base-client/plugins/i18n-extend.js +32 -32
  329. package/src/base-client/plugins/index.js +23 -23
  330. package/src/base-client/plugins/moment.js +8 -8
  331. package/src/base-client/plugins/tabs-page-plugin.js +39 -39
  332. package/src/bootstrap.js +51 -51
  333. package/src/components/Charts/Bar.vue +62 -62
  334. package/src/components/Charts/ChartCard.vue +134 -134
  335. package/src/components/Charts/Liquid.vue +67 -67
  336. package/src/components/Charts/MiniArea.vue +39 -39
  337. package/src/components/Charts/MiniBar.vue +39 -39
  338. package/src/components/Charts/MiniProgress.vue +75 -75
  339. package/src/components/Charts/MiniSmoothArea.vue +40 -40
  340. package/src/components/Charts/Radar.vue +68 -68
  341. package/src/components/Charts/RankList.vue +77 -77
  342. package/src/components/Charts/TagCloud.vue +113 -113
  343. package/src/components/Charts/TransferBar.vue +64 -64
  344. package/src/components/Charts/Trend.vue +82 -82
  345. package/src/components/Charts/chart.less +12 -12
  346. package/src/components/Charts/smooth.area.less +13 -13
  347. package/src/components/CodeMirror/inedx.vue +118 -118
  348. package/src/components/CodeMirror/setting.js +40 -40
  349. package/src/components/Ellipsis/Ellipsis.vue +65 -65
  350. package/src/components/Ellipsis/index.js +3 -3
  351. package/src/components/Ellipsis/index.md +38 -38
  352. package/src/components/FileImageItem/FileItem.vue +305 -305
  353. package/src/components/FileImageItem/FileItemGroup.vue +197 -197
  354. package/src/components/FileImageItem/ImageItem.vue +107 -107
  355. package/src/components/FileImageItem/index.js +4 -4
  356. package/src/components/FilePreview/FilePreview.vue +181 -181
  357. package/src/components/FilePreview/FilePreviewDemo.vue +30 -30
  358. package/src/components/FilePreview/index.js +3 -3
  359. package/src/components/HeightScanner/index.vue +615 -615
  360. package/src/components/NumberInfo/NumberInfo.vue +54 -54
  361. package/src/components/NumberInfo/index.js +3 -3
  362. package/src/components/NumberInfo/index.less +54 -54
  363. package/src/components/NumberInfo/index.md +43 -43
  364. package/src/components/STable/README.md +341 -341
  365. package/src/components/STable/index.js +558 -558
  366. package/src/components/TableSetting/TableSetting.vue +143 -143
  367. package/src/components/TableSetting/index.js +3 -3
  368. package/src/components/Trend/Trend.vue +41 -41
  369. package/src/components/Trend/index.js +3 -3
  370. package/src/components/Trend/index.less +41 -41
  371. package/src/components/Trend/index.md +45 -45
  372. package/src/components/_util/util.js +46 -46
  373. package/src/components/cache/AKeepAlive.js +179 -179
  374. package/src/components/card/ChartCard.vue +79 -79
  375. package/src/components/chart/Bar.vue +60 -60
  376. package/src/components/chart/MiniArea.vue +67 -67
  377. package/src/components/chart/MiniBar.vue +59 -59
  378. package/src/components/chart/MiniProgress.vue +57 -57
  379. package/src/components/chart/Radar.vue +80 -80
  380. package/src/components/chart/RankingList.vue +60 -60
  381. package/src/components/chart/Trend.vue +79 -79
  382. package/src/components/chart/index.less +9 -9
  383. package/src/components/checkbox/ColorCheckbox.vue +157 -157
  384. package/src/components/checkbox/ImgCheckbox.vue +117 -117
  385. package/src/components/checkbox/ImgCheckboxGroup.vue +76 -76
  386. package/src/components/checkbox/index.js +9 -9
  387. package/src/components/exception/ExceptionPage.vue +70 -70
  388. package/src/components/exception/typeConfig.js +19 -19
  389. package/src/components/form/FormRow.vue +52 -52
  390. package/src/components/g2Charts/constants.js +202 -202
  391. package/src/components/g2Charts/demo.vue +808 -808
  392. package/src/components/g2Charts/designer.vue +228 -228
  393. package/src/components/g2Charts/designerBaseConfig.vue +61 -61
  394. package/src/components/g2Charts/designerDataConfig.vue +259 -259
  395. package/src/components/g2Charts/designerStyleConfig.vue +16 -16
  396. package/src/components/g2Charts/index.vue +397 -397
  397. package/src/components/index.js +36 -36
  398. package/src/components/index.less +5 -5
  399. package/src/components/input/IInput.vue +66 -66
  400. package/src/components/menu/Contextmenu.vue +84 -84
  401. package/src/components/menu/SideMenu.vue +75 -75
  402. package/src/components/menu/index.less +38 -38
  403. package/src/components/menu/menu.js +273 -273
  404. package/src/components/page/header/PageHeader.vue +64 -64
  405. package/src/components/page/header/index.less +40 -40
  406. package/src/components/result/Result.vue +77 -77
  407. package/src/components/setting/Setting.vue +234 -234
  408. package/src/components/setting/SettingItem.vue +26 -26
  409. package/src/components/setting/i18n.js +117 -117
  410. package/src/components/table/StandardTable.vue +141 -141
  411. package/src/components/table/advance/ActionColumns.vue +158 -158
  412. package/src/components/table/advance/ActionSize.vue +45 -45
  413. package/src/components/table/advance/AdvanceTable.vue +275 -275
  414. package/src/components/table/advance/SearchArea.vue +355 -355
  415. package/src/components/table/advance/index.js +2 -2
  416. package/src/components/table/api/ApiTable.vue +50 -50
  417. package/src/components/task/TaskGroup.vue +80 -80
  418. package/src/components/task/TaskItem.vue +26 -26
  419. package/src/components/tool/AStepItem.vue +60 -60
  420. package/src/components/tool/AvatarList.vue +68 -68
  421. package/src/components/tool/DetailList.vue +157 -157
  422. package/src/components/tool/Drawer.vue +142 -142
  423. package/src/components/tool/FooterToolBar.vue +30 -30
  424. package/src/components/tool/HeadInfo.vue +35 -35
  425. package/src/components/tool/TagSelect.vue +83 -83
  426. package/src/components/tool/TagSelectOption.vue +33 -33
  427. package/src/components/transition/PageToggleTransition.vue +97 -97
  428. package/src/config/CreateQueryConfig.js +325 -325
  429. package/src/config/default/admin.config.js +18 -18
  430. package/src/config/default/animate.config.js +21 -21
  431. package/src/config/default/antd.config.js +89 -89
  432. package/src/config/default/index.js +6 -6
  433. package/src/config/default/setting.config.js +55 -55
  434. package/src/config/index.js +3 -3
  435. package/src/config/replacer/index.js +10 -10
  436. package/src/config/replacer/resolve.config.js +67 -67
  437. package/src/expression/ExpressionRunner.js +26 -26
  438. package/src/expression/TestExpression.js +509 -509
  439. package/src/expression/core/Delegate.js +115 -115
  440. package/src/expression/core/Expression.js +1358 -1358
  441. package/src/expression/core/Program.js +932 -932
  442. package/src/expression/core/Token.js +27 -27
  443. package/src/expression/enums/ExpressionType.js +81 -81
  444. package/src/expression/enums/TokenType.js +11 -11
  445. package/src/expression/exception/BreakWayException.js +2 -2
  446. package/src/expression/exception/ContinueWayException.js +2 -2
  447. package/src/expression/exception/ExpressionException.js +28 -28
  448. package/src/expression/exception/ReturnWayException.js +14 -14
  449. package/src/expression/exception/ServiceException.js +22 -22
  450. package/src/expression/instances/LogicConsole.js +44 -44
  451. package/src/expression/ts/ExpressionRunner.ts +28 -28
  452. package/src/expression/ts/TestExpression.ts +509 -509
  453. package/src/expression/ts/core/Delegate.ts +114 -114
  454. package/src/expression/ts/core/Expression.ts +1309 -1309
  455. package/src/expression/ts/core/Program.ts +950 -950
  456. package/src/expression/ts/core/Token.ts +29 -29
  457. package/src/expression/ts/enums/ExpressionType.ts +81 -81
  458. package/src/expression/ts/enums/TokenType.ts +13 -13
  459. package/src/expression/ts/exception/BreakWayException.ts +2 -2
  460. package/src/expression/ts/exception/ContinueWayException.ts +2 -2
  461. package/src/expression/ts/exception/ExpressionException.ts +28 -28
  462. package/src/expression/ts/exception/ReturnWayException.ts +14 -14
  463. package/src/expression/ts/exception/ServiceException.ts +22 -22
  464. package/src/expression/ts/instances/JSONArray.ts +48 -48
  465. package/src/expression/ts/instances/JSONObject.ts +109 -109
  466. package/src/expression/ts/instances/LogicConsole.ts +32 -32
  467. package/src/font-style/font.css +4 -4
  468. package/src/layouts/AdminLayout.vue +176 -174
  469. package/src/layouts/BlankView.vue +79 -79
  470. package/src/layouts/CommonLayout.vue +56 -56
  471. package/src/layouts/ComponentLayoutOne.vue +47 -47
  472. package/src/layouts/GridView.vue +43 -43
  473. package/src/layouts/PageLayout.vue +151 -151
  474. package/src/layouts/PageView.vue +55 -55
  475. package/src/layouts/SinglePageView.vue +136 -136
  476. package/src/layouts/footer/PageFooter.vue +49 -49
  477. package/src/layouts/header/AdminHeader.vue +132 -132
  478. package/src/layouts/header/HeaderAvatar.vue +64 -64
  479. package/src/layouts/header/HeaderNotice.vue +177 -177
  480. package/src/layouts/header/HeaderSearch.vue +67 -67
  481. package/src/layouts/header/InstitutionDetail.vue +181 -181
  482. package/src/layouts/header/index.less +92 -92
  483. package/src/layouts/tabs/TabsHead.vue +189 -189
  484. package/src/layouts/tabs/TabsView.vue +383 -389
  485. package/src/layouts/tabs/i18n.js +25 -25
  486. package/src/layouts/tabs/index.js +2 -2
  487. package/src/lib.js +1 -1
  488. package/src/logic/LogicRunner.js +62 -62
  489. package/src/logic/TestLogic.js +13 -13
  490. package/src/logic/plugins/common/DateTools.js +35 -35
  491. package/src/logic/plugins/common/VueTools.js +30 -30
  492. package/src/logic/plugins/index.js +7 -7
  493. package/src/logic/ts/LogicRunner.ts +67 -67
  494. package/src/logic/ts/TestLogic.ts +13 -13
  495. package/src/main.js +33 -33
  496. package/src/mixins/formValidationMixin.js +46 -46
  497. package/src/mock/common/activityData.js +32 -32
  498. package/src/mock/common/index.js +89 -89
  499. package/src/mock/common/reportData.js +20 -20
  500. package/src/mock/common/tableData.js +118 -118
  501. package/src/mock/extend/index.js +84 -84
  502. package/src/mock/goods/index.js +108 -108
  503. package/src/mock/index.js +12 -12
  504. package/src/mock/project/index.js +17 -17
  505. package/src/mock/user/current.js +13 -13
  506. package/src/mock/user/login.js +39 -39
  507. package/src/mock/user/routes.js +61 -61
  508. package/src/mock/workplace/index.js +15 -15
  509. package/src/pages/DefaultExample/index.vue +77 -77
  510. package/src/pages/DynamicStatistics/ChartSelector.vue +331 -331
  511. package/src/pages/DynamicStatistics/DataTabs.vue +83 -83
  512. package/src/pages/DynamicStatistics/DynamicTable.vue +128 -128
  513. package/src/pages/DynamicStatistics/EvaluationArea.vue +69 -69
  514. package/src/pages/DynamicStatistics/FavoriteList.vue +50 -50
  515. package/src/pages/DynamicStatistics/QuestionHistoryAndFavorites.vue +591 -591
  516. package/src/pages/DynamicStatistics/SearchBar.vue +192 -192
  517. package/src/pages/DynamicStatistics/index.vue +282 -282
  518. package/src/pages/Example/childIndex.vue +15 -15
  519. package/src/pages/Example/index.vue +30 -30
  520. package/src/pages/LogicCallExample/index.vue +46 -46
  521. package/src/pages/NewDynamicStatistics/ChartSelector.vue +331 -331
  522. package/src/pages/NewDynamicStatistics/DataTabs.vue +122 -122
  523. package/src/pages/NewDynamicStatistics/DynamicTable.vue +128 -128
  524. package/src/pages/NewDynamicStatistics/EvaluationArea.vue +69 -69
  525. package/src/pages/NewDynamicStatistics/FavoriteList.vue +50 -50
  526. package/src/pages/NewDynamicStatistics/QuestionHistoryAndFavorites.vue +289 -289
  527. package/src/pages/NewDynamicStatistics/SearchBar.vue +193 -193
  528. package/src/pages/NewDynamicStatistics/index.vue +258 -258
  529. package/src/pages/Recording/index.vue +77 -77
  530. package/src/pages/ReportGrid/index.vue +76 -76
  531. package/src/pages/ReportView.vue +50 -50
  532. package/src/pages/ServiceReview/index.vue +284 -284
  533. package/src/pages/SubExample/index.vue +26 -26
  534. package/src/pages/WorkflowDetail/WorkFlowDemo.vue +47 -47
  535. package/src/pages/WorkflowDetail/WorkFlowDemo2.vue +204 -204
  536. package/src/pages/WorkflowDetail/WorkFlowDemo3.vue +203 -204
  537. package/src/pages/WorkflowDetail/WorkflowDetail.vue +379 -399
  538. package/src/pages/WorkflowDetail/WorkflowPageDetail/LeaveMessage.vue +388 -388
  539. package/src/pages/WorkflowDetail/WorkflowPageDetail/TrimTextTail.vue +23 -23
  540. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowBaseInformation.vue +415 -415
  541. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowBaseInformationDetails.vue +276 -276
  542. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowHandle.vue +1757 -1757
  543. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowHandleReso.vue +975 -975
  544. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowPreview.vue +109 -109
  545. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowTimeline.vue +987 -987
  546. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkOrderParentDetails.vue +222 -222
  547. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkflowDetailResso.vue +243 -243
  548. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkflowListResolution.vue +248 -248
  549. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkflowLog.vue +188 -188
  550. package/src/pages/WorkflowDetail/WorkflowPageDetail/components/WorkflowPersonSelector.vue +109 -109
  551. package/src/pages/XPageViewExample/index.vue +149 -149
  552. package/src/pages/XReportView/index.vue +64 -64
  553. package/src/pages/XTreeOneProExample/index.vue +67 -67
  554. package/src/pages/addressSelect/addressDemo.vue +24 -24
  555. package/src/pages/addressSelect/index.vue +270 -270
  556. package/src/pages/dashboard/workplace/WorkPlace.vue +141 -141
  557. package/src/pages/dashboard/workplace/i18n.js +40 -40
  558. package/src/pages/dashboard/workplace/index.js +2 -2
  559. package/src/pages/dashboard/workplace/index.less +59 -59
  560. package/src/pages/exception/403.vue +21 -21
  561. package/src/pages/exception/404.vue +24 -24
  562. package/src/pages/exception/500.vue +21 -21
  563. package/src/pages/login/Login.vue +378 -378
  564. package/src/pages/login/LoginV3.vue +389 -389
  565. package/src/pages/login/index.js +2 -2
  566. package/src/pages/lowCode/lowCodeEditor.vue +1219 -1219
  567. package/src/pages/lowCode/lowCodeRenderPage.vue +43 -43
  568. package/src/pages/report/ReportTable.js +124 -124
  569. package/src/pages/report/ReportTableHome.vue +28 -28
  570. package/src/pages/resourceManage/depListManage.vue +23 -23
  571. package/src/pages/resourceManage/funListManage.vue +23 -23
  572. package/src/pages/resourceManage/index.js +15 -15
  573. package/src/pages/resourceManage/orgListManage.vue +98 -98
  574. package/src/pages/resourceManage/resourceManageMain.vue +57 -57
  575. package/src/pages/resourceManage/roleListManage.vue +23 -23
  576. package/src/pages/resourceManage/staffListManage.vue +23 -23
  577. package/src/pages/system/dictionary/index.vue +44 -44
  578. package/src/pages/system/file/Info.vue +56 -56
  579. package/src/pages/system/file/index.vue +317 -317
  580. package/src/pages/system/monitor/loginInfor/index.vue +37 -37
  581. package/src/pages/system/monitor/operLog/index.vue +37 -37
  582. package/src/pages/system/settings/index.vue +126 -126
  583. package/src/pages/system/settings/modifyPassword.vue +117 -117
  584. package/src/pages/system/ticket/index.vue +480 -480
  585. package/src/pages/system/ticket/submitTicketSuccess.vue +484 -484
  586. package/src/pages/userInfoDetailManage/ChangeMeterRecordQuery/index.vue +64 -64
  587. package/src/pages/userInfoDetailManage/FillCardRecordQuery/index.vue +77 -77
  588. package/src/pages/userInfoDetailManage/FillGasRecordQuery/index.vue +75 -75
  589. package/src/pages/userInfoDetailManage/InfoChangeRecordQuery/index.vue +64 -64
  590. package/src/pages/userInfoDetailManage/InstructRecordQuery/index.vue +64 -64
  591. package/src/pages/userInfoDetailManage/InsuranceDetailQuery/index.vue +64 -64
  592. package/src/pages/userInfoDetailManage/MachineRecordQuery/index.vue +75 -75
  593. package/src/pages/userInfoDetailManage/MeterParamRecordQuery/index.vue +64 -64
  594. package/src/pages/userInfoDetailManage/OtherChargeRecordQuery/index.vue +75 -75
  595. package/src/pages/userInfoDetailManage/PriceAdjustments/index.vue +64 -64
  596. package/src/pages/userInfoDetailManage/TransferRecordQuery/index.vue +66 -66
  597. package/src/pages/userInfoDetailManage/UserChargeRecordQuery/index.vue +94 -94
  598. package/src/pages/userInfoDetailManage/UserException/index.vue +64 -64
  599. package/src/pages/userInfoDetailManage/UserHandRecordQuery/index.vue +87 -87
  600. package/src/pages/userInfoDetailManage/UserRecordQuery/index.vue +74 -74
  601. package/src/pages/userInfoDetailManage/WatchCollectionRecordQuery/index.vue +64 -64
  602. package/src/pages/userInfoDetailManage/index.vue +290 -290
  603. package/src/pages/userInfoDetailManage/uploadFilesHistory/index.vue +120 -120
  604. package/src/pages/userInfoDetailManage/userInfoDetailQueryTabs.vue +144 -144
  605. package/src/plugins/EventLogPlugin.js +33 -33
  606. package/src/plugins/FindParentsData.js +17 -17
  607. package/src/plugins/HiPrintPlugin.js +164 -164
  608. package/src/router/async/config.async.js +35 -35
  609. package/src/router/async/router.map.js +126 -126
  610. package/src/router/guards.js +260 -260
  611. package/src/router/i18n.js +57 -57
  612. package/src/router/index.js +27 -27
  613. package/src/router.js +17 -17
  614. package/src/services/DataModel.js +30 -30
  615. package/src/services/LodopFuncs.js +137 -137
  616. package/src/services/api/DictionaryDetailsViewApi.js +6 -6
  617. package/src/services/api/LogDetailsViewApi.js +10 -10
  618. package/src/services/api/QueryParamsDetailsViewApi.js +6 -6
  619. package/src/services/api/TicketDetailsViewApi.js +46 -46
  620. package/src/services/api/cas.js +79 -79
  621. package/src/services/api/common.js +346 -346
  622. package/src/services/api/entity.js +18 -18
  623. package/src/services/api/index.js +17 -17
  624. package/src/services/api/logininfor/index.js +6 -6
  625. package/src/services/api/manage.js +8 -8
  626. package/src/services/api/restTools.js +215 -215
  627. package/src/services/api/workFlow.js +57 -57
  628. package/src/services/apiService.js +16 -16
  629. package/src/services/dataSource.js +12 -12
  630. package/src/services/index.js +7 -7
  631. package/src/services/user.js +92 -92
  632. package/src/services/v3Api.js +116 -116
  633. package/src/store/index.js +5 -5
  634. package/src/store/modules/account.js +115 -115
  635. package/src/store/modules/index.js +5 -5
  636. package/src/store/modules/lowCode.js +33 -33
  637. package/src/store/modules/setting.js +119 -119
  638. package/src/store/mutation-types.js +4 -4
  639. package/src/theme/antd/ant-menu.less +2 -2
  640. package/src/theme/antd/ant-message.less +3 -3
  641. package/src/theme/antd/ant-table.less +22 -22
  642. package/src/theme/antd/ant-time-picker.less +3 -3
  643. package/src/theme/antd/index.less +3 -3
  644. package/src/theme/default/color.less +43 -43
  645. package/src/theme/default/index.less +3 -3
  646. package/src/theme/default/nprogress.less +76 -76
  647. package/src/theme/default/style.less +58 -58
  648. package/src/theme/global.less +271 -271
  649. package/src/theme/index.less +5 -5
  650. package/src/theme/reportTable.less +58 -58
  651. package/src/theme/theme.less +1 -1
  652. package/src/utils/EncryptUtil.js +75 -75
  653. package/src/utils/Objects.js +25 -25
  654. package/src/utils/authority-utils.js +85 -85
  655. package/src/utils/axios-interceptors.js +100 -100
  656. package/src/utils/colors.js +107 -107
  657. package/src/utils/common.js +10 -10
  658. package/src/utils/errorCode.js +6 -6
  659. package/src/utils/excel/Blob.js +180 -180
  660. package/src/utils/excel/Export2Excel.js +141 -141
  661. package/src/utils/filter.js +21 -21
  662. package/src/utils/formatter.js +74 -74
  663. package/src/utils/htmlToPDF.js +108 -108
  664. package/src/utils/htmlToPDFApi.js +5 -5
  665. package/src/utils/i18n.js +80 -80
  666. package/src/utils/indexedDB.js +549 -549
  667. package/src/utils/login.js +188 -188
  668. package/src/utils/lowcode/lowcodeComponentMixin.js +120 -120
  669. package/src/utils/lowcode/lowcodeLog.js +29 -29
  670. package/src/utils/lowcode/lowcodeUtils.js +373 -373
  671. package/src/utils/lowcode/registerComponentForEditor.js +1 -1
  672. package/src/utils/lowcode/registerComponentForRender.js +11 -11
  673. package/src/utils/map-utils.js +47 -47
  674. package/src/utils/microAppUtils.js +49 -49
  675. package/src/utils/reg.js +95 -95
  676. package/src/utils/request.js +383 -383
  677. package/src/utils/routerUtil.js +553 -553
  678. package/src/utils/runEvalFunction.js +14 -14
  679. package/src/utils/theme-color-replacer-extend.js +92 -92
  680. package/src/utils/themeUtil.js +100 -100
  681. package/src/utils/util.js +329 -329
  682. package/src/utils/waterMark.js +31 -31
  683. package/test/Tree.spec.js +168 -168
  684. package/test/myDialog.spec.js +47 -47
  685. package/test/request.test.js +17 -17
  686. package/test/util.test.js +53 -53
  687. package/test/v3Api.test.js +1984 -1984
  688. package/tests/unit/ReportTable.spec.js +16 -16
  689. package/vue.config.js +222 -222
  690. package//350/277/201/347/247/273/346/227/245/345/277/227.md +15 -15
  691. package/.claude/settings.local.json +0 -9
@@ -1,1757 +1,1757 @@
1
- <template>
2
- <div>
3
- <!-- 上方流程显示 -->
4
- <a-card :bordered="false" :loading="loading">
5
- <!-- 项目进度流程 -->
6
- <work-flow-timeline
7
- :current-step-id="currentStepId"
8
- :active-step-id="activeStepId"
9
- :workflow-id="workflowId"
10
- :steps="stepsForChild"
11
- :state="workflowState"
12
- change-able
13
- @activeStep="activeStep"/>
14
- </a-card>
15
- <!-- 无权访问的提示 -->
16
- <a-result v-show="!canSubmit" status="403" title="无权操作" sub-title="您没有访问该步骤的权限.">
17
- </a-result>
18
- <div v-show="canSubmit">
19
- <!-- 流程被退回的提示 -->
20
- <a-alert v-if="currentStep && currentStep.back && !(beforeStepActive || workflowState)" type="info" show-icon style="margin-bottom: 14px">
21
- <div slot="message">
22
- <span style="font-weight: bold">流程被退回</span>
23
- <span style="margin-left: 14px; font-size: 14px; color: rgba(0, 0, 0, 0.65)">请重新填写信息发起提交</span>
24
- </div>
25
- <div slot="description">
26
- <div>操作人:{{
27
- currentStep.back.f_operator
28
- }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;操作时间:{{ currentStep.back.f_date }}
29
- </div>
30
- <div>原因:{{ currentStep.back.f_notes }}</div>
31
- </div>
32
- </a-alert>
33
- <!-- 步骤内容主体 -->
34
- <a-tabs default-active-key="1" @change="note = ''" type="card">
35
- <a-tab-pane key="0" tab="步骤详情" v-if="beforeStepActive || workflowState">
36
- <a-card :bordered="false" :loading="loadingHistory" :body-style="{ paddingTop: 0 }">
37
- <!-- 当前步骤历史记录 -->
38
- <template v-if="showTab">
39
- <x-tab
40
- :compProp="{ buttonState: { add: false, edit: false, delete: false, import: false, extra: false }, disableAction: true }"
41
- :local-config="tabDesigner"
42
- :body-style="{ padding: 0 }"
43
- :tabBarGutter="24"
44
- :extra-data="{ workflowId: workflowId }"
45
- default-active-key="workFlowTab">
46
- <a-tab-pane
47
- :forceRender="true"
48
- v-if="formCompletedDataPreview"
49
- slot="extraBeforeTabs"
50
- key="workFlowTab"
51
- tab="表单"
52
- >
53
- <work-flow-preview :form-completed-data-preview="formCompletedDataPreview"/>
54
- </a-tab-pane>
55
- </x-tab>
56
- </template>
57
- <template v-else-if="formCompletedDataPreview">
58
- <work-flow-preview :form-completed-data-preview="formCompletedDataPreview"/>
59
- </template>
60
- <template v-else>
61
- <a-result status="404" title="暂无数据" sub-title="该步骤暂无数据。">
62
- </a-result>
63
- </template>
64
- </a-card>
65
- </a-tab-pane>
66
- <a-tab-pane key="1" tab="业务操作" v-else v-show="renderCurrentNode">
67
- <a-card :bordered="false" :loading="loadingHistory" :body-style="{ paddingTop: 0 }">
68
- <x-tab
69
- v-if="showTab"
70
- :compProp="{ buttonState: { extra: true }, disableAction: false }"
71
- :local-config="tabDesigner"
72
- :extra-data="{ workflowId:workflowId }"
73
- :body-style="{ padding: 0 }"
74
- :tabBarGutter="24"
75
- default-active-key="workFlowTab">
76
- <a-tab-pane
77
- :forceRender="true"
78
- v-if="showForm"
79
- slot="extraBeforeTabs"
80
- key="workFlowTab"
81
- tab="表单"
82
- >
83
- <x-add-native-form
84
- ref="xAddForm"
85
- @onSubmit="submitForm"/>
86
- </a-tab-pane>
87
- </x-tab>
88
- <x-add-native-form
89
- v-else
90
- ref="xAddForm"
91
- @x-form-item-emit-func="formItemEmitFunc"
92
- @onSubmit="submitForm"/>
93
- <a-divider/>
94
-
95
- <!-- 分支节点状态提示 -->
96
- <a-alert
97
- v-if="isBranchLastNode.isBranchNode && !isBranchLastNode.isLastBranch"
98
- type="info"
99
- show-icon
100
- style="margin-bottom: 16px"
101
- >
102
- <template slot="message">
103
- <span style="font-weight: bold;">分支节点等待中</span>
104
- </template>
105
- <template slot="description">
106
- <div>当前为分支节点,其他分支仍在进行中。完成当前分支后将等待其他分支完成,然后自动汇合到下一环节。</div>
107
- <div style="margin-top: 8px; color: #666; font-size: 12px;">
108
- <a-icon type="info-circle" style="margin-right: 4px;" />
109
- 提示:此操作无需选择下一环节负责人,系统将自动处理流程流转。
110
- </div>
111
- </template>
112
- </a-alert>
113
-
114
- <a-alert
115
- v-if="isBranchLastNode.isBranchNode && isBranchLastNode.isLastBranch"
116
- type="success"
117
- show-icon
118
- style="margin-bottom: 16px"
119
- >
120
- <template slot="message">
121
- <span style="font-weight: bold;">分支汇合节点</span>
122
- </template>
123
- <template slot="description">
124
- <div>您正在处理最后一个未完成的分支节点,完成后将触发分支汇合并进入下一环节。</div>
125
- </template>
126
- </a-alert>
127
-
128
- <a-form v-show="!lastStep" label-align="left" :label-col="{ span: 3 }" :wrapper-col="{ span: 13 }">
129
- <a-form-item v-if="showStepNextBtn" label="操作类型" required>
130
- <a-radio-group v-model="operationType" @change="handleOperationTypeChange">
131
- <a-radio value="submit">到下一步</a-radio>
132
- <a-radio value="skip">{{ stepNextBtnTitle }}</a-radio>
133
- </a-radio-group>
134
- </a-form-item>
135
-
136
- <!-- 智能分支人员选择组件 - 只有非分支节点或最后一个分支才显示 -->
137
- <WorkflowPersonSelector
138
- v-if="!isBranchLastNode.isBranchNode || isBranchLastNode.isLastBranch"
139
- ref="personSelector"/>
140
-
141
- <a-form-item
142
- v-if="!isBranchLastNode.isBranchNode || isBranchLastNode.isLastBranch"
143
- label="下一环节截止时间"
144
- :validate-status="deadlineValidateStatus"
145
- :help="deadlineHelp"
146
- required>
147
- <a-date-picker
148
- :getCalendarContainer="(triggerNode) => triggerNode.parentNode"
149
- v-model="deadline"
150
- value-format="YYYY-MM-DD HH:mm"
151
- format="YYYY-MM-DD HH:mm"
152
- :allow-clear="false"
153
- :show-today="false"
154
- show-time
155
- placeholder="请选择"/>
156
- </a-form-item>
157
- </a-form>
158
- <a-divider/>
159
- <!-- 备注信息 -->
160
- <a-textarea
161
- v-model="note"
162
- :auto-size="{ minRows: 3, maxRows: 5 }"
163
- placeholder="填写本环节备注事项"
164
- />
165
- <!-- 当前步骤完成后,控制流程按钮 -->
166
- <div style="text-align: center">
167
- <a-radio-group style="margin-top: 20px">
168
- <a-space>
169
- <!-- 动态按钮渲染 -->
170
- <template v-if="buttonGroup && buttonGroup.actionArr">
171
- <a-button
172
- v-for="(button, index) in buttonGroup.actionArr"
173
- :key="index"
174
- v-show="checkButtonVisible(button)"
175
- :type="button.type ? button.type : 'default'"
176
- @click="handleCustomButtonClick(button)"
177
- >
178
- {{ button.text }}
179
- </a-button>
180
- </template>
181
- <!-- 原有的按钮逻辑 -->
182
- <template>
183
- <a-popover v-if="operationType === 'submit'">
184
- <template slot="content">
185
- <p v-if="isBranchLastNode.isBranchNode && !isBranchLastNode.isLastBranch">
186
- 完成当前分支,等待其他分支完成后自动汇合
187
- </p>
188
- <p v-else-if="isBranchLastNode.isBranchNode && isBranchLastNode.isLastBranch">
189
- 完成最后一个分支并触发汇合到下一环节
190
- </p>
191
- <p v-else>{{ nextBtnTitle }}</p>
192
- </template>
193
- <a-button
194
- v-if="!lastStep"
195
- :disabled="!showNextBtn && !stepDone"
196
- type="primary"
197
- @click="nextClick"
198
- >
199
- 完成提交
200
- <a-icon type="right"/>
201
- </a-button>
202
- </a-popover>
203
- <a-popover v-else :title="stepNextBtnTitle">
204
- <template slot="content">
205
- <p v-for="(item,index) in stepNextBtnText" :key="index">{{ item }}</p>
206
- </template>
207
- <a-button
208
- v-if="showStepNextBtn && !lastStep"
209
- type="primary"
210
- @click="stepNextClick"
211
- >
212
- 跳过
213
- </a-button>
214
- </a-popover>
215
- <a-button
216
- v-if="lastStep"
217
- type="primary"
218
- @click="lastStepNextClick"
219
- >
220
- 确认完成
221
- </a-button>
222
- </template>
223
- </a-space>
224
- </a-radio-group>
225
- </div>
226
- </a-card>
227
- </a-tab-pane>
228
- <!-- 退回 -->
229
- <a-tab-pane v-if="canSubmit && !beforeStepActive && showPrevBtn && !workflowState" key="2" tab="退回">
230
- <a-form layout="vertical">
231
- <a-form-item label="退回原因" :wrapper-col="{ span: 24 }" required>
232
- <a-textarea
233
- v-model="backNote"
234
- :auto-size="{ minRows: 4, maxRows: 10 }"
235
- placeholder="请填写退回原因 / 备注"
236
- />
237
- </a-form-item>
238
- <a-form-item :wrapper-col="{ offset: 11 }">
239
- <a-popover :title="preBtnTitle">
240
- <template slot="content">
241
- <p v-for="(item,index) in preBtnText" :key="index">{{ item }}</p>
242
- </template>
243
- <a-button
244
- type="danger"
245
- @click="preClick"
246
- >
247
- <a-icon type="left"/>
248
- 退回
249
- </a-button>
250
- </a-popover>
251
- </a-form-item>
252
- </a-form>
253
- </a-tab-pane>
254
- <!-- <a-tab-pane v-if="canSubmit && !beforeStepActive && showPrevBtn && !workflowState" key="3" tab="工单拆分">
255
- &lt;!&ndash; 分配工单 &ndash;&gt;
256
- <workflow-list-resolution :workflow-project-id="workflowId" :details="details"></workflow-list-resolution>
257
- </a-tab-pane>-->
258
- </a-tabs>
259
- </div>
260
- </div>
261
- </template>
262
-
263
- <script>
264
- import XAddNativeForm from '@vue2-client/base-client/components/common/XAddNativeForm'
265
- import XFormTable from '@vue2-client/base-client/components/common/XFormTable/XFormTable'
266
- import XAddForm from '@vue2-client/base-client/components/common/XAddForm/XAddForm'
267
- import { postByServiceName } from '@vue2-client/services/api/restTools'
268
- import { workFlowViewApi } from '@vue2-client/services/api/workFlow'
269
- import { commonApi } from '@vue2-client/services/api'
270
- import { formatDate } from '@vue2-client/utils/util'
271
- import { mapState } from 'vuex'
272
- import moment from 'moment'
273
- import FilePreview from '@vue2-client/components/FilePreview'
274
- import WorkFlowTimeline from './WorkFlowTimeline.vue'
275
- import { FileItem, ImageItem } from '@vue2-client/components/FileImageItem'
276
- import WorkflowListResolution from './WorkflowListResolution'
277
- import { executeStrFunctionByContext } from '@vue2-client/utils/runEvalFunction'
278
- import * as util from '@vue2-client/utils/util'
279
- import { getConfigByNameAsync, runLogic } from '@vue2-client/services/api/common'
280
- import LogicRunner from '@vue2-client/logic/LogicRunner'
281
- import XTab from '@vue2-client/base-client/components/common/XTab/XTab.vue'
282
- import WorkFlowPreview from './WorkFlowPreview'
283
- import WorkflowPersonSelector from './components/WorkflowPersonSelector.vue'
284
-
285
- export default {
286
- name: 'WorkFlowHandle',
287
- provide () {
288
- return {
289
- formDataChange: this.handleFormDataChange,
290
- workflowHandleWrap: this.workflowHandleWrap
291
- }
292
- },
293
- components: {
294
- XTab,
295
- WorkflowListResolution,
296
- XAddNativeForm,
297
- WorkFlowTimeline,
298
- XFormTable,
299
- XAddForm,
300
- FilePreview,
301
- FileItem,
302
- ImageItem,
303
- WorkFlowPreview,
304
- WorkflowPersonSelector
305
- },
306
- computed: {
307
- workflowHandleWrap () {
308
- return this
309
- },
310
- ...mapState('account', { currUser: 'user' }),
311
- // 判断当前节点的分支状态
312
- isBranchLastNode () {
313
- // 默认返回值
314
- const defaultResult = {
315
- isBranchNode: false, // 是否为分支流程中的节点
316
- isLastBranch: false // 是否为最后一个未完成的分支(需要选择下一环节人员)
317
- }
318
-
319
- // 如果是最后一步或没有下一步或者不能提交,则不是分支节点
320
- if (this.lastStep || !this.nextBtnTo || !this.canSubmit) {
321
- return defaultResult
322
- }
323
-
324
- // 检查下一个节点是否为分支退出节点
325
- const nextStep = this.stepsDefine.find(step => step.id === this.nextBtnTo)
326
-
327
- // 如果下一个节点的flowRole不是branchExit,说明不是分支的最后一个节点
328
- if (!nextStep || nextStep.properties?.flowRole !== 'branchExit') {
329
- return defaultResult
330
- }
331
-
332
- // 获取分支退出节点等待的所有分支步骤ID
333
- const waitStepIds = nextStep.properties.waitStepIds || []
334
- if (waitStepIds.length === 0) {
335
- return {
336
- isBranchNode: true,
337
- isLastBranch: true // 如果没有等待步骤配置,默认认为是最后一个
338
- }
339
- }
340
-
341
- // 当前步骤必须在等待列表中才算是分支节点
342
- if (!waitStepIds.includes(this.activeStepId)) {
343
- return defaultResult
344
- }
345
-
346
- // 检查除当前步骤外的其他分支步骤状态
347
- const otherBranchSteps = waitStepIds.filter(stepId => stepId !== this.activeStepId)
348
-
349
- // 判断其他所有分支步骤是否都已完成(状态为2)
350
- const allOtherBranchesCompleted = otherBranchSteps.every(stepId => {
351
- const step = this.stepsForChild.find(s => s.id === stepId)
352
- return step && step.status === 2 // 已处理
353
- })
354
-
355
- return {
356
- isBranchNode: true, // 当前节点是分支流程中的节点
357
- isLastBranch: allOtherBranchesCompleted // 只有当其他所有分支都已完成时,当前分支才是最后一个
358
- }
359
- },
360
- canSubmit () {
361
- // 对于超级管理员直接认为可以提交
362
- if (this.currUser.rolesnames.indexOf('超级管理员') > -1) {
363
- return true
364
- }
365
- // currentStepId可能还没初始化,此处拿不到先返回false
366
- if (!this.currentStepId) {
367
- return false
368
- }
369
- const activeStep = this.stepsForChild.find(item => item.id === this.activeStepId)
370
- // 如果当前选中节点不是正在进行的节点,则判断viewers权限
371
- if (this.activeStepId !== this.currentStepId && activeStep != null && activeStep.status !== 1) {
372
- // 历史节点为当前登录人操作则不做查看数据权限校验
373
- if (activeStep.handler === this.currUser.name) {
374
- return true
375
- }
376
- const viewers = activeStep?.properties?.otherProperty?.viewers ?? []
377
- if (viewers.length > 0) {
378
- // 使用some方法判断当前人员是否满足任一条件
379
- return viewers.some(item => {
380
- if (item.type === 'role') {
381
- // 检查rolestr是否存在并包含指定角色
382
- return this.currUser.rolestr && this.currUser.rolestr.split(',').includes(item.name)
383
- }
384
- if (item.type === 'department') {
385
- // 检查depname是否存在并包含指定部门
386
- return this.currUser.depname && this.currUser.deps.includes(item.name)
387
- }
388
- return false
389
- })
390
- } else {
391
- return true
392
- }
393
- } else {
394
- // 当前进行节点的数据
395
- const step = this.stepsForChild.find(item => item.id === this.activeStepId)
396
- // 检查角色和部门权限
397
- if (step && step.properties && step.properties.chargePerson) {
398
- // 如果当前节点的负责人选项中有设置选择人员 当前节点就只能由上一步设置的负责人操作
399
- if (step.properties.chargePerson.needSelectPerson) {
400
- return step.handler === this.currUser.name
401
- }
402
- if (step.properties.chargePerson.personList && step.properties.chargePerson.personList.length > 0) {
403
- // 使用some方法判断当前人员是否满足任一条件
404
- return step.properties.chargePerson.personList.some(item => {
405
- if (item.type === 'role') {
406
- // 检查rolestr是否存在并包含指定角色
407
- return this.currUser.rolestr && this.currUser.rolestr.split(',').includes(item.name)
408
- }
409
- if (item.type === 'department') {
410
- // 检查parentname是否存在并包含指定部门
411
- return this.currUser.parentname && this.currUser.parentname.includes(item.name)
412
- }
413
- return false
414
- })
415
- }
416
- }
417
-
418
- // 检查handler是否包含当前用户
419
- if (step && step.handler) {
420
- return step.handler.includes(this.currUser.name)
421
- }
422
- }
423
- return false
424
- },
425
- formPreviewNoFileData () {
426
- return this.formCompletedDataPreview.data.filter(item => item.label !== '附件上传')
427
- }
428
- },
429
- data () {
430
- return {
431
- // 显示供用户填写的当前步骤表单
432
- showForm: false,
433
- // 显示步骤的tab页
434
- showTab: false,
435
- // tab页的配置
436
- tabDesigner: undefined,
437
- // 当前步骤表单标题
438
- formTitle: '',
439
- // 当前步骤表单定义Json
440
- stepDefine: [],
441
- // 当前步骤
442
- currentStep: undefined,
443
- // 当前步骤完成状态
444
- stepDone: false,
445
- // 所有节点连通数据
446
- directions: [],
447
- // 所有流程定义数据
448
- stepsDefine: [],
449
- // 当前步骤能通向的节点
450
- currentDirections: [],
451
- // 当前节点id
452
- currentStepId: undefined,
453
- // 当前活动节点 id
454
- activeStepId: 1,
455
- // 下一步按钮显示
456
- showNextBtn: false,
457
- // 回退按钮显示
458
- showPrevBtn: false,
459
- // 跳过按钮显示
460
- showStepNextBtn: false,
461
- // 定义三个按钮气泡提示内容
462
- preBtnTitle: '',
463
- preBtnText: [],
464
- nextBtnTitle: '',
465
- stepNextBtnTitle: '',
466
- stepNextBtnText: [],
467
- // 控制三个按钮跳转目标
468
- preBtnTo: undefined,
469
- nextBtnTo: undefined,
470
- stepNextBtnTo: undefined,
471
- // 控制当前标签页显示
472
- activeKey: '1',
473
- // 之前的节点是否激活
474
- beforeStepActive: false,
475
- // 之前节点中的数据
476
- beforeStepData: [],
477
- // 用于将已有数据,填回x-add表单中
478
- formCompletedData: {},
479
- // 用于展示提交的数据
480
- formCompletedDataPreview: null,
481
- // 切换至目标流程时,目标流程定义
482
- targetStepDefine: [],
483
- // 控制历史记录加载
484
- loadingHistory: true,
485
- // 控制表单校验
486
- formValid: false,
487
- // 备忘
488
- note: '',
489
- backNote: '', // 新增退回原因专用变量
490
- // 是否是最后一步
491
- lastStep: false,
492
- // 存储每一步骤填表人和时间数据
493
- stepsExtraInfo: [],
494
- // 控制基础信息页流程展示加载
495
- loading: true,
496
- createQueryVisible: false,
497
- // 激活的步骤名
498
- activeStepName: '',
499
- stepsParse: undefined,
500
- // 下一步处理人选择框数据
501
- chargePersonOptions: [],
502
- // 已选择下一步处理人
503
- checkedChargePerson: undefined,
504
- // 下一步截止时间
505
- deadline: this.getDefaultDeadline(),
506
- deadlineValidateStatus: '',
507
- deadlineHelp: '',
508
- // 当前任务是否延期
509
- // taskIsOverdue: moment().isAfter(this.completeTime, 'day'),
510
- // 操作类型,提交到下一步或跳过
511
- operationType: 'submit',
512
- // 获取微信推送是否成功信息
513
- information: [],
514
- // 是否需要选择人员
515
- needSelectPerson: true,
516
- // 下一环节人员信息
517
- chargePerson: {},
518
- // 动态按钮配置
519
- buttonGroup: null,
520
- // 分支节点相关数据
521
- branchNodes: [], // 需要选择人员的分支节点列表
522
- branchChargePersons: {}, // 分支节点人员选择 格式:{stepId: personId}
523
- needMultipleBranchSelection: false, // 是否需要为多个分支节点预先选择人员(包含WF_RESULT的条件分支或并行分支)
524
- calculatedTargetNode: null, // 前台计算出的目标节点
525
- currentBranchActions: null // 缓存当前的分支动作,避免重复调用
526
- }
527
- },
528
- async mounted () {
529
- await this.init()
530
- // this.checkDeadline()
531
- },
532
- props: {
533
- workflowId: {
534
- type: [String, Number],
535
- required: true
536
- },
537
- visible: {
538
- type: Boolean,
539
- default: false
540
- },
541
- stepsForChild: {
542
- type: Array,
543
- required: true
544
- },
545
- workflowState: {
546
- type: [Boolean, Number],
547
- required: true
548
- },
549
- completeTime: {
550
- type: String,
551
- required: true
552
- },
553
- taskName: {
554
- type: String,
555
- required: true
556
- },
557
- details: {
558
- type: Object,
559
- required: true
560
- },
561
- // 展开详情初始化的节点
562
- // 适用于不让第一个节点默认展示的情况
563
- initStepId: {
564
- type: [String, Number],
565
- required: false,
566
- default: null
567
- },
568
- renderCurrentNode: {
569
- type: Boolean,
570
- default: true
571
- }
572
- },
573
- methods: {
574
- init () {
575
- this.getCurrentStep()
576
- },
577
- onClose () {
578
- this.activeStepId = this.currentStepId
579
- this.checkedChargePerson = undefined
580
- this.loadingHistory = true
581
- this.currentStepId = undefined
582
- this.directions = []
583
- this.currentDirections = []
584
- this.preBtnText = []
585
- this.stepNextBtnText = []
586
- this.stepsExtraInfo = []
587
- this.loading = true
588
- this.showNextBtn = false
589
- this.showStepNextBtn = false
590
- this.showPrevBtn = false
591
- this.stepDone = false
592
- this.formCompletedData = {}
593
- this.formCompletedDataPreview = null
594
- this.operationType = 'submit'
595
-
596
- // 清理分支节点相关数据
597
- this.branchNodes = []
598
- this.branchChargePersons = {}
599
- this.needMultipleBranchSelection = false
600
- this.calculatedTargetNode = null
601
- this.currentBranchActions = null
602
- },
603
- async showQueryFormItemFunc () {
604
- if (this.attr.showQueryFormItemFunc) {
605
- const obj = executeStrFunctionByContext(this, this.attr.showQueryFormItemFunc, [this.form, this.setForm, this.attr, util, this.mode])
606
- // 判断是 bool 还是 obj 兼容
607
- if (typeof obj === 'boolean') {
608
- this.show = obj
609
- } else if (obj && typeof obj === 'object') {
610
- // obj 是一个对象,并且不是数组
611
- this.show = obj?.show
612
- this.readOnly = obj?.readOnly
613
- }
614
- } else {
615
- this.show = true
616
- }
617
- },
618
- // 获取单个步骤的定义
619
- getSingleStepDefine (name) {
620
- for (const step of this.stepsDefine) {
621
- if (name === step.name) {
622
- return step.properties.form
623
- }
624
- }
625
- },
626
- // 日期格式化
627
- format (date, format) {
628
- return formatDate(date, format)
629
- },
630
- // 获取当前步骤
631
- getCurrentStep () {
632
- return postByServiceName(workFlowViewApi.getWorkFlowCurrentSubState, {
633
- workflowId: this.workflowId
634
- })
635
- .then(res => {
636
- // 优先级:主动传入的 > 获取到的
637
- this.currentStepId = this.initStepId || res.id
638
-
639
- // 如果指定了具体节点,同时设置activeStepId
640
- if (this.initStepId) {
641
- this.activeStepId = this.initStepId
642
- }
643
-
644
- const currentStep = this.stepsForChild.find(item => item.id === this.currentStepId)
645
- res.state = currentStep.name
646
- // 获取到当前步骤后复制下一步时间
647
- this.deadline = this.getDefaultDeadline(currentStep.properties?.otherProperty?.nextNodeInterval)
648
- this.currentStep = res
649
- this.getDirection()
650
- }, err => {
651
- console.log(err)
652
- })
653
- },
654
- // 完工按钮
655
- async lastStepNextClick () {
656
- this.$refs.xAddForm.asyncSubmit().then((res) => {
657
- this.submitForm(res).then(_ => {
658
- postByServiceName(workFlowViewApi.afterWorkFlowFinalStepSubmit, {
659
- workflowId: this.workflowId,
660
- stepId: this.currentStepId,
661
- submitUser: this.currUser.name,
662
- submitUserId: this.currUser.id
663
- }).then(_res => {
664
- this.saveWorkflowLog('确认完工', '最后一步: ' + this.getStepNameByStepId(this.currentStepId), { notes: this.note.trim() })
665
- this.$message.success('已完工!')
666
- this.loading = true
667
- this.loadingHistory = true
668
- this.onClose()
669
- this.$emit('success', { note: this.note.trim(), form: res.realForm, workflowId: this.workflowId })
670
- },
671
- () => {
672
- this.$message.error('提交失败!')
673
- }
674
- )
675
- })
676
- }).catch(err => {
677
- if (err && err.message === 'Form validation failed') {
678
- this.$message.error('请检查表单必填项!')
679
- } else {
680
- // 对于其他错误,继续向上抛出
681
- throw err
682
- }
683
- })
684
- },
685
- // 三个按钮点击后逻辑
686
- async nextClick () {
687
- // 检查是否为非最后分支节点
688
- const branchStatus = this.isBranchLastNode
689
- const isWaitingBranch = branchStatus.isBranchNode && !branchStatus.isLastBranch
690
-
691
- const extraData = this.getApplyStepExtraData(this.nextBtnTo)
692
- if (!extraData) {
693
- return
694
- }
695
-
696
- // 确认对话框
697
- const confirmContent = isWaitingBranch
698
- ? '确定完成当前分支么?完成后将等待其他分支,不会立即流转到下一环节。'
699
- : '确定提交么?提交之后数据不可更改!'
700
-
701
- await new Promise(resolve => {
702
- this.$confirm({
703
- title: '提交确认',
704
- content: confirmContent,
705
- onOk () {
706
- resolve()
707
- return Promise.resolve()
708
- }
709
- })
710
- })
711
-
712
- this.$refs.xAddForm.asyncSubmit().then(res => {
713
- this.submitForm(res).then(_ => {
714
- postByServiceName(workFlowViewApi.submitToNextStep, extraData)
715
- .then(
716
- () => {
717
- let successMessage = '提交成功'
718
-
719
- // 只有非等待分支节点才保存工作流日志
720
- if (!isWaitingBranch) {
721
- const branchStatus = this.isBranchLastNode
722
- const operation = branchStatus.isBranchNode && branchStatus.isLastBranch ? '分支汇合' : '提交'
723
-
724
- const extra = {
725
- setHandler: this.getStepHandler(),
726
- setDeadline: this.deadline,
727
- notes: this.note.trim()
728
- }
729
- this.saveWorkflowLog(operation, this.generateBranchStepChangeText(this.currentStepId), extra)
730
- } else {
731
- successMessage = '分支完成,等待其他分支完成后自动汇合'
732
- }
733
-
734
- this.$message.success(successMessage)
735
- this.loading = true
736
- this.loadingHistory = true
737
- this.$emit('nextClick', {
738
- note: this.note.trim(),
739
- form: res.realForm,
740
- workflowId: this.workflowId,
741
- isBranchWaiting: isWaitingBranch, // 标记是否为分支等待状态
742
- ...this.generateStepChange(this.currentStepId, this.nextBtnTo)
743
- })
744
- this.$emit('refresh')
745
- this.onClose()
746
- this.init()
747
- },
748
- err => {
749
- this.$message.error('提交失败!')
750
- console.log(err)
751
- }
752
- )
753
- })
754
- }).catch((err) => {
755
- if (err && err.message === 'Form validation failed') {
756
- this.$message.error('请检查表单必填项!')
757
- } else {
758
- // 对于其他错误,继续向上抛出
759
- throw err
760
- }
761
- })
762
- },
763
- async preClick () {
764
- const notes = this.backNote.trim()
765
- if (!notes) {
766
- this.$message.error('退回请在备注中填写理由')
767
- return
768
- }
769
- return postByServiceName(workFlowViewApi.updateWorkFlowState, {
770
- stepId: this.preBtnTo,
771
- workflowId: this.workflowId,
772
- type: 'back'
773
- })
774
- .then(
775
- res => {
776
- this.saveWorkflowLog('退回', this.generateStepChangeText(this.currentStepId, this.preBtnTo), { notes })
777
- this.$message.success('退回成功')
778
- this.backNote = '' // 退回成功后清空退回原因
779
- this.loading = true
780
- this.loadingHistory = true
781
- this.currentStepId = this.preBtnTo
782
- this.activeStepId = this.preBtnTo
783
-
784
- // 新增:重置按钮状态
785
- this.stepDone = false
786
- this.beforeStepActive = false
787
- this.operationType = 'submit'
788
-
789
- this.$emit('refresh')
790
- this.onClose()
791
- this.init()
792
- },
793
- err => {
794
- this.$message.error('退回失败!')
795
- console.log(err)
796
- }
797
- )
798
- },
799
- async stepNextClick () {
800
- const extraData = this.getApplyStepExtraData(this.stepNextBtnTo)
801
- if (!extraData) {
802
- return
803
- }
804
- this.$refs.xAddForm.asyncSubmit().then(res => {
805
- this.submitForm(res).then(_ => {
806
- postByServiceName(workFlowViewApi.submitToNextStep, extraData)
807
- .then(
808
- () => {
809
- const extra = {
810
- setHandler: this.getStepHandler(),
811
- setDeadline: this.deadline,
812
- notes: this.note.trim()
813
- }
814
- this.saveWorkflowLog('跳过', this.generateBranchStepChangeText(this.currentStepId), extra)
815
- this.$message.success('提交成功')
816
- this.$emit('nextClick', {
817
- note: this.note.trim(),
818
- form: res.realForm,
819
- workflowId: this.workflowId,
820
- ...this.generateStepChange(this.currentStepId, this.stepNextBtnTo)
821
- })
822
- this.loading = true
823
- this.loadingHistory = true
824
- this.$emit('refresh')
825
- this.onClose()
826
- this.init()
827
- },
828
- err => {
829
- this.$message.error('提交失败!')
830
- console.log(err)
831
- }
832
- )
833
- })
834
- }).catch(err => {
835
- if (err && err.message === 'Form validation failed') {
836
- this.$message.error('请检查表单必填项!')
837
- } else {
838
- // 对于其他错误,继续向上抛出
839
- throw err
840
- }
841
- })
842
- },
843
- // 获取当前步骤节点,连通的节点
844
- async getDirection () {
845
- // 获取流程定义
846
- return postByServiceName(workFlowViewApi.getWorkFlowDefine, {
847
- id: this.workflowId
848
- })
849
- .then(async res => {
850
- this.directions = []
851
- this.stepsDefine = res.steps
852
- await this.resolveDirections()
853
- this.resolveStep()
854
- }, err => {
855
- console.log(err)
856
- })
857
- },
858
- // 分析当前节点,能通向的节点
859
- async resolveDirections () {
860
- const currentStep = this.stepsForChild.find(item => item.id === this.activeStepId)
861
- if (currentStep?.properties?.actions) {
862
- this.currentDirections = currentStep.properties.actions
863
- }
864
- // 判断是否是最后ige节点
865
- this.lastStep = (currentStep?.properties?.actions || []).filter(item => {
866
- return item.type !== 'back'
867
- }).length === 0
868
-
869
- // 处理跳转按钮
870
- this.workflowControl()
871
-
872
- if (!this.lastStep) {
873
- // 分析分支节点并设置智能人员选择
874
- await this.analyzeBranchNodes()
875
- }
876
- },
877
- // 根据步骤id获取步骤名称
878
- getStepNameByStepId (stepId) {
879
- return this.stepsDefine.find(item => item.id === stepId)?.name
880
- },
881
- // 根据步骤id获取步骤状态
882
- getStepStatusByStepId (stepId) {
883
- return this.stepsForChild.find(item => item.id === stepId)?.status
884
- },
885
- // 表单提交的回调
886
- submitForm (obj) {
887
- this.formValid = true
888
- const formData = obj.realForm
889
- const time = this.format(new Date(), 'yyyy-MM-dd hh:mm:ss')
890
- return postByServiceName(workFlowViewApi.saveWorkFlowStepFormData, {
891
- workflowId: this.workflowId,
892
- stepId: this.activeStepId,
893
- form: formData,
894
- data: time,
895
- handler: this.currUser.name,
896
- note: this.note.trim()
897
- })
898
- .then(
899
- res => {
900
- console.log('表单提交成功')
901
- this.note = ''
902
- this.showForm = false
903
- this.stepDone = true
904
- },
905
- err => {
906
- this.$message.error('保存失败,请检查后重试')
907
- console.log(err)
908
- }
909
- )
910
- },
911
- // 获取当前步骤定义内容,构建组件
912
- async buildComp (stepId) {
913
- const properties = this.stepsDefine.find(item => item.id === stepId).properties
914
- // 表单的渲染
915
- if (properties.form && properties.form.formJson) {
916
- this.stepDefine = properties.form.formJson
917
- this.showForm = true
918
- this.$nextTick(() => {
919
- this.$refs.xAddForm && this.$refs.xAddForm.init({
920
- ...properties.form,
921
- businessType: '修改',
922
- formItems: this.stepDefine,
923
- layout: properties.form.xAddFormLayout,
924
- showSubmitBtn: false
925
- })
926
- })
927
- } else {
928
- this.showForm = false
929
- }
930
- // Tab的渲染
931
- this.tabDesigner = properties.tabDesigner
932
- this.showTab = !!this.tabDesigner
933
- // 以当前激活节点分析节点
934
- await this.resolveDirections()
935
- this.resolveStep()
936
- },
937
- // 根据当前节点,判断之后流程,以及按钮的显示
938
- workflowControl () {
939
- // 重置所有控制数据为默认值,避免之前状态的影响
940
- this.showNextBtn = false
941
- this.nextBtnTo = undefined
942
- this.nextBtnTitle = ''
943
- this.showStepNextBtn = false
944
- this.stepNextBtnTo = undefined
945
- this.stepNextBtnTitle = ''
946
- this.stepNextBtnText = []
947
- this.showPrevBtn = false
948
- this.preBtnTo = undefined
949
- this.preBtnTitle = ''
950
- this.preBtnText = []
951
-
952
- // 分类收集不同类型的actions
953
- const submitActions = this.currentDirections.filter(item => item.type === 'submit')
954
- const conditionalActions = this.currentDirections.filter(item => item.type === 'conditionalBranch')
955
- const parallelActions = this.currentDirections.filter(item => item.type === 'parallelBranch')
956
- const skipActions = this.currentDirections.filter(item => item.type === 'skip')
957
- const backActions = this.currentDirections.filter(item => item.type === 'back')
958
-
959
- // 处理提交按钮 - 优先级:submit > conditionalBranch > parallelBranch
960
- if (submitActions.length > 0) {
961
- this.showNextBtn = true
962
- this.nextBtnTo = submitActions[0].to // 如果有多个submit,取第一个作为主要跳转目标
963
- if (submitActions.length === 1) {
964
- this.nextBtnTitle = '进行下一环节:' + this.getStepNameByStepId(submitActions[0].to)
965
- } else {
966
- this.nextBtnTitle = '将进入以下环节:' + submitActions.map(item => this.getStepNameByStepId(item.to)).join(' , ')
967
- }
968
- } else if (conditionalActions.length > 0) {
969
- this.showNextBtn = true
970
- this.nextBtnTo = conditionalActions[0].to // 条件分支的第一个作为主要跳转目标
971
- const targetSteps = conditionalActions.map(item => this.getStepNameByStepId(item.to)).join(' , ')
972
- this.nextBtnTitle = '后台判断后跳转到:' + targetSteps
973
- } else if (parallelActions.length > 0) {
974
- this.showNextBtn = true
975
- this.nextBtnTo = parallelActions[0].to // 并行分支的第一个作为主要跳转目标
976
- const targetSteps = parallelActions.map(item => this.getStepNameByStepId(item.to)).join(' , ')
977
- this.nextBtnTitle = '将并行进入以下分支:' + targetSteps
978
- }
979
-
980
- // 处理跳过按钮
981
- if (skipActions.length > 0) {
982
- this.showStepNextBtn = true
983
- this.stepNextBtnTo = skipActions[0].to
984
- if (skipActions.length === 1) {
985
- this.stepNextBtnTitle = '跳至:' + this.getStepNameByStepId(skipActions[0].to) + '环节'
986
- this.stepNextBtnText.push('将跳过以下环节:')
987
- for (let i = this.currentStepId; i < skipActions[0].to - 1; i++) {
988
- this.stepNextBtnText.push(this.stepsDefine[i].name)
989
- }
990
- } else {
991
- const targetSteps = skipActions.map(item => this.getStepNameByStepId(item.to)).join(' , ')
992
- this.stepNextBtnTitle = '跳至:' + targetSteps
993
- }
994
- }
995
-
996
- // 处理退回按钮
997
- if (backActions.length > 0) {
998
- const backAction = backActions[0] // 通常只有一个back action
999
- for (let i = this.currentStepId - 1; i > 0; i--) {
1000
- if (backAction.to >= i && this.stepsForChild.find(item => item.id === i)?.handler) {
1001
- this.preBtnTo = i
1002
- this.preBtnTitle = '回退至:' + this.getStepNameByStepId(i) + '环节'
1003
- this.showPrevBtn = true
1004
- break
1005
- } else {
1006
- this.preBtnText.push(this.getStepNameByStepId(i))
1007
- }
1008
- }
1009
- if (this.preBtnText.length) {
1010
- this.preBtnText.unshift('将跳过以下环节:')
1011
- }
1012
- }
1013
- },
1014
- // 获取表单字段实际值
1015
- getRealKey (key, isHandleFormKey) {
1016
- if (key === 'selected_id') return key
1017
- if (isHandleFormKey) {
1018
- return key.substring(key.indexOf('_') + 1)
1019
- } else {
1020
- return key
1021
- }
1022
- },
1023
- // 加载完成
1024
- resolveStep () {
1025
- // 获取当前步骤的按钮组配置
1026
- const currentStep = this.stepsDefine.find(item => item.id === this.activeStepId)
1027
- if (currentStep && currentStep.properties && currentStep.properties.buttonGroup) {
1028
- this.buttonGroup = currentStep.properties.buttonGroup
1029
- } else {
1030
- this.buttonGroup = null
1031
- }
1032
- this.loading = false
1033
- },
1034
- // 流程图组件给当前组件传值用,stepNo为用户点击的非当前步骤
1035
- async activeStep (stepId) {
1036
- // 开启加载
1037
- this.loadingHistory = true
1038
- this.activeStepId = stepId
1039
- // 获取激活节点的步骤名
1040
- this.activeStepName = this.getStepNameByStepId(stepId)
1041
- const status = this.getStepStatusByStepId(stepId)
1042
- // 清空回显数据
1043
- this.formCompletedData = {}
1044
- let formCompletedDataPreview = null
1045
- this.getStepDefine(stepId)
1046
- // 判断激活的节点,是不是待完成节点 (当前节点或者 当前节点状态是1的)
1047
- if ((this.activeStepName !== this.currentStep.state && status !== 1) || this.workflowState) {
1048
- // 获取激活节点历史数据,和字段定义
1049
- await this.getCompletedFormData(stepId)
1050
- // 将回显数据拷贝,避免引用传递
1051
- formCompletedDataPreview = JSON.parse(JSON.stringify(this.formCompletedData))
1052
- // 使用字段定义中内容,将回显数据的列名,替换为定义的中文名
1053
- // 调整逻辑:formData中只显示流程配置表单中定义过的显示列,多余冗余的存储列不进行页面展示
1054
- const formDataArr = []
1055
- const dataObj = formCompletedDataPreview.data || {}
1056
- const currentStepDefine = this.stepsDefine.find(item => item.id === stepId)
1057
- const isKeyHandle = currentStepDefine?.properties?.form?.isKeyHandle || false
1058
- for (let i = 0; i < this.targetStepDefine.length; i++) {
1059
- const stepDefine = this.targetStepDefine[i]
1060
- const key = this.getRealKey(stepDefine.model, isKeyHandle)
1061
- if (Object.prototype.hasOwnProperty.call(dataObj, key)) {
1062
- // 历史表单内容根据流程中配置的表单项顺序进行渲染,需要兼容表单项展示函数
1063
- if (stepDefine.showFormItemFunc && !(await this.showFormItemFunc(stepDefine.showFormItemFunc, dataObj))) {
1064
- continue
1065
- }
1066
- let value = dataObj[key]
1067
- // 字典值处理
1068
- if (stepDefine.formType === 'select' && stepDefine.selectType === 'key') {
1069
- const dictList = this.$appdata.getDictionaryList(stepDefine.selectKey)
1070
- const dictItem = dictList.find(item => item.value === value)
1071
- value = dictItem ? dictItem.label : value
1072
- }
1073
- formDataArr.push({ label: stepDefine.name, value })
1074
- }
1075
- }
1076
- // 如果一个都没匹配上,兼容旧逻辑:把原对象转成数组
1077
- if (formDataArr.length === 0 && dataObj && typeof dataObj === 'object') {
1078
- for (const key in dataObj) {
1079
- if (Object.prototype.hasOwnProperty.call(dataObj, key)) {
1080
- formDataArr.push({ label: key, value: dataObj[key] })
1081
- }
1082
- }
1083
- }
1084
- formCompletedDataPreview.data = formDataArr.length > 0 ? formDataArr : null
1085
- if (!formCompletedDataPreview.data) {
1086
- formCompletedDataPreview.data = null
1087
- }
1088
- // 备注
1089
- formCompletedDataPreview.note = this.stepsForChild.find(item => item.id === stepId)?.note
1090
- if (!formCompletedDataPreview.data && !formCompletedDataPreview.files.length && !formCompletedDataPreview.images.length && !formCompletedDataPreview.note) {
1091
- formCompletedDataPreview = {}
1092
- }
1093
- this.formCompletedDataPreview = formCompletedDataPreview
1094
- // 渲染已完成步骤的Tab
1095
- const properties = this.stepsDefine.find(item => item.id === stepId).properties
1096
- this.tabDesigner = properties.tabDesigner
1097
- this.showTab = !!this.tabDesigner
1098
- // 完成
1099
- this.loadingHistory = false
1100
- this.beforeStepActive = this.activeStepName !== this.currentStep.state
1101
- } else {
1102
- this.loadingHistory = false
1103
- this.beforeStepActive = false
1104
- if (!this.renderCurrentNode) {
1105
- this.formCompletedDataPreview = null
1106
- this.showTab = false
1107
- this.beforeStepActive = true
1108
- return
1109
- }
1110
- await this.buildComp(this.activeStepId)
1111
- }
1112
- },
1113
- // 获取已经完成步骤的数据
1114
- getCompletedFormData (stepId) {
1115
- return postByServiceName(workFlowViewApi.getWorkFlowCompletedStepData, {
1116
- workflowId: this.workflowId,
1117
- stepId: stepId
1118
- })
1119
- .then(
1120
- res => {
1121
- this.formCompletedData = res
1122
- },
1123
- err => {
1124
- console.log(err)
1125
- }
1126
- )
1127
- },
1128
- // 获取步骤定义表中,当前步骤定义
1129
- getStepDefine (stepId) {
1130
- const stepName = this.getStepNameByStepId(stepId)
1131
- this.targetStepDefine = this.getSingleStepDefine(stepName).formJson
1132
- },
1133
- // 获取提交步骤的额外数据
1134
- getApplyStepExtraData (stepId) {
1135
- // 验证人员选择 - 只有在需要显示人员选择器的情况下才验证
1136
- // 判断条件与模板中的 WorkflowPersonSelector 显示条件保持一致
1137
- const shouldShowPersonSelector = !this.isBranchLastNode.isBranchNode || this.isBranchLastNode.isLastBranch
1138
-
1139
- if (shouldShowPersonSelector && this.needSelectPerson) {
1140
- if (this.needMultipleBranchSelection) {
1141
- // 多分支情况:检查是否所有需要的分支都选择了人员
1142
- const missingSelections = this.branchNodes.filter(node => !this.branchChargePersons[node.stepId])
1143
- if (missingSelections.length > 0) {
1144
- const missingNames = missingSelections.map(node => node.stepName).join('、')
1145
- this.$message.error(`请设置以下节点的处理人:${missingNames}`)
1146
- return false
1147
- }
1148
- } else {
1149
- // 单分支情况:检查是否选择了处理人
1150
- if (!this.checkedChargePerson) {
1151
- this.$message.error('请设置下一环节处理人')
1152
- return false
1153
- }
1154
- }
1155
- }
1156
-
1157
- // 统一获取目标步骤IDs
1158
- let stepIds = []
1159
- if (this.needMultipleBranchSelection) {
1160
- // 多分支选择:获取所有分支的目标stepId(包括不需要选择人员的)
1161
- if (!this.currentBranchActions) {
1162
- this.currentBranchActions = this.getBranchActions()
1163
- }
1164
- stepIds = this.currentBranchActions.allBranchActions.map(action => action.to)
1165
- } else if (this.calculatedTargetNode) {
1166
- // 条件判断节点:使用计算出的目标节点
1167
- stepIds = [this.calculatedTargetNode]
1168
- } else {
1169
- // 普通节点:使用传入的stepId
1170
- stepIds = [stepId]
1171
- }
1172
- // 处理bug 有的时候没带到 branchChargePersons 先循环在同一地方处理
1173
- stepIds.forEach(stepItemId => {
1174
- if (!this.branchChargePersons[stepItemId]) {
1175
- const chargePerson = this.stepsForChild.find(item => item.id === stepItemId)?.properties?.chargePerson
1176
- this.branchChargePersons[stepItemId] = this.normalizeChargePersonFormat(chargePerson)
1177
- }
1178
- })
1179
-
1180
- return {
1181
- workflowId: this.workflowId,
1182
- activeStepId: this.activeStepId,
1183
- stepId, // 当前步骤ID
1184
- stepIds, // 目标步骤IDs数组(统一格式)
1185
- name: this.getStepNameByStepId(stepId),
1186
- handler: this.getStepHandler(),
1187
- handlerId: this.checkedChargePerson,
1188
- needSelectPerson: this.needSelectPerson,
1189
- personList: this.chargePerson.personList,
1190
- deadline: this.deadline,
1191
- submitUser: this.currUser.name,
1192
- submitUserId: this.currUser.id,
1193
- branchChargePersons: this.branchChargePersons
1194
- }
1195
- },
1196
-
1197
- // 获取当前选择的负责人
1198
- getStepHandler () {
1199
- let stepHandler
1200
-
1201
- if (this.needMultipleBranchSelection) {
1202
- // 多分支情况:返回所有分支的人员信息
1203
- const selectedHandlers = []
1204
- for (const node of this.branchNodes) {
1205
- const branchData = this.branchChargePersons[node.stepId]
1206
-
1207
- if (node.needSelectPerson && branchData) {
1208
- // 需要选择人员的分支:显示选中的人员
1209
- const personName = this.getBranchPersonName(node.stepId)
1210
- selectedHandlers.push(`${node.stepName}:${personName}`)
1211
- } else if (!node.needSelectPerson && branchData) {
1212
- // 不需要选择人员的分支:显示角色/部门配置
1213
- if (branchData.personList && branchData.personList.length > 0) {
1214
- const personNames = branchData.personList.map(item => item.name).join(',')
1215
- selectedHandlers.push(`${node.stepName}:${personNames}`)
1216
- }
1217
- }
1218
- }
1219
- stepHandler = selectedHandlers.join(';')
1220
- } else {
1221
- // 单分支情况:原有逻辑
1222
- if (this.checkedChargePerson) {
1223
- // 使用 value 找到对应的 label
1224
- stepHandler = this.chargePersonOptions.find(item => item.value === this.checkedChargePerson)?.label
1225
- } else if (this.chargePerson.personList && this.chargePerson.personList.length > 0) {
1226
- stepHandler = this.chargePerson.personList.map(item => item.name).join(',')
1227
- }
1228
- }
1229
-
1230
- return stepHandler
1231
- },
1232
-
1233
- // 获取分支节点选择的人员姓名
1234
- getBranchPersonName (stepId) {
1235
- const personId = this.branchChargePersons[stepId]
1236
- if (!personId) return ''
1237
-
1238
- const node = this.branchNodes.find(n => n.stepId === stepId)
1239
- if (!node) return ''
1240
-
1241
- const person = node.chargePersonOptions.find(p => p.value === personId)
1242
- return person ? person.label : ''
1243
- },
1244
- // 生成工作流日志步骤变化描述
1245
- generateStepChangeText (fromStepId, toStepId) {
1246
- // 如果是多分支场景,toStepId可能是数组或字符串
1247
- if (this.needMultipleBranchSelection && Array.isArray(toStepId)) {
1248
- const targetSteps = toStepId.map(id => `第${id}步: ${this.getStepNameByStepId(id)}`).join('、')
1249
- return `第${fromStepId}步: ${this.getStepNameByStepId(fromStepId)} --> ${targetSteps}`
1250
- } else if (this.needMultipleBranchSelection && typeof toStepId === 'string') {
1251
- // 如果传入的是目标步骤名称字符串
1252
- return `第${fromStepId}步: ${this.getStepNameByStepId(fromStepId)} --> ${toStepId}`
1253
- } else {
1254
- // 单步骤场景
1255
- return `第${fromStepId}步: ${this.getStepNameByStepId(fromStepId)} --> 第${toStepId}步: ${this.getStepNameByStepId(toStepId)}`
1256
- }
1257
- },
1258
-
1259
- // 生成多分支场景的步骤变化描述
1260
- generateBranchStepChangeText (fromStepId) {
1261
- if (!this.needMultipleBranchSelection) {
1262
- return this.generateStepChangeText(fromStepId, this.nextBtnTo)
1263
- }
1264
-
1265
- // 使用所有分支节点生成描述
1266
- const targetSteps = this.branchNodes.map(node => `第${node.stepId}步: ${node.stepName}`).join('、')
1267
- return `第${fromStepId}步: ${this.getStepNameByStepId(fromStepId)} --> ${targetSteps}`
1268
- },
1269
-
1270
- generateStepChange (fromStepId, toStepId) {
1271
- // 获取目标步骤IDs数组
1272
- let stepIds = []
1273
-
1274
- if (this.needMultipleBranchSelection) {
1275
- // 多分支选择:获取所有分支的目标stepId(包括不需要选择人员的)
1276
- if (!this.currentBranchActions) {
1277
- this.currentBranchActions = this.getBranchActions()
1278
- }
1279
- stepIds = this.currentBranchActions.allBranchActions.map(action => action.to)
1280
- } else if (this.calculatedTargetNode) {
1281
- // 条件判断节点:使用计算出的目标节点
1282
- stepIds = [this.calculatedTargetNode]
1283
- } else {
1284
- // 普通节点:使用传入的stepId
1285
- stepIds = [toStepId]
1286
- }
1287
-
1288
- return {
1289
- formStepId: fromStepId,
1290
- fromStepId,
1291
- stepId: toStepId,
1292
- stepIds: stepIds,
1293
- formStep: this.getStepNameByStepId(fromStepId),
1294
- fromStep: this.getStepNameByStepId(fromStepId),
1295
- toStep: this.getStepNameByStepId(stepIds[0]),
1296
- successStepId: this.stepsDefine[this.stepsDefine.length - 1].id,
1297
- successStep: this.stepsDefine[this.stepsDefine.length - 1].name
1298
- }
1299
- },
1300
- // 保存工作流日志
1301
- saveWorkflowLog (operation, desc, extra) {
1302
- postByServiceName(workFlowViewApi.saveWorkFlowLog, {
1303
- workflowId: this.workflowId,
1304
- operation,
1305
- desc,
1306
- operator: this.currUser.name,
1307
- notes: '',
1308
- setHandler: '',
1309
- setDeadline: '',
1310
- ...extra
1311
- })
1312
- },
1313
- // 获取默认截止时间
1314
- getDefaultDeadline (day = 1) {
1315
- const date = new Date()
1316
- date.setDate(date.getDate() + day)
1317
- date.setHours(date.getHours() + 2)
1318
- return formatDate(date, 'yyyy-MM-dd hh:mm')
1319
- },
1320
- // 验证截止时间
1321
- checkDeadline (alert) {
1322
- const deadline = moment(this.deadline)
1323
- if (deadline.isAfter(this.completeTime, 'day')) {
1324
- this.deadlineValidateStatus = 'error'
1325
- this.deadlineHelp = '不能超过任务限定完成时间'
1326
- if (alert) {
1327
- this.$message.error('下一环节截止时间不能超过任务限定完成时间,如需设置,请联系发起人修改任务完成时间', 5)
1328
- }
1329
- return false
1330
- }
1331
- if (deadline.diff(moment(), 'hours') < 1) {
1332
- this.deadlineValidateStatus = 'error'
1333
- this.deadlineHelp = '下一环节截止时间只能在1小时之后'
1334
- return false
1335
- }
1336
- this.deadlineValidateStatus = 'success'
1337
- this.deadlineHelp = ''
1338
- return true
1339
- },
1340
- // 操作类型单选按钮改变时重新设置负责人选择框
1341
- async handleOperationTypeChange (event) {
1342
- this.checkedChargePerson = undefined
1343
- this.branchChargePersons = {}
1344
- // 重新分析分支节点
1345
- await this.analyzeBranchNodes()
1346
- },
1347
-
1348
- // 处理动态按钮点击
1349
- handleCustomButtonClick (button) {
1350
- try {
1351
- // 执行自定义函数
1352
- if (button.func) {
1353
- const result = executeStrFunctionByContext(this, button.func, [this.details, this.$refs.xAddForm.form, util, runLogic, getConfigByNameAsync])
1354
- if (result) {
1355
- // 如果返回true,执行对应的操作
1356
- if (button.text === '提交') {
1357
- this.nextClick()
1358
- } else if (button.text === '取消') {
1359
- this.$emit('cancel')
1360
- }
1361
- }
1362
- }
1363
- } catch (error) {
1364
- console.error('执行自定义按钮函数失败:', error)
1365
- this.$message.error('执行操作失败')
1366
- }
1367
- },
1368
- // 表单项展示函数--用来渲染历史节点数据时和填写表单显示内容同步
1369
- async showFormItemFunc (func, form) {
1370
- try {
1371
- if (func) {
1372
- // 一般展示项函数中不应该存在setForm函数 先屏蔽this.setForm和this.attr的传递还有在this上下文指向不同可能存在异常 流程表单的展示项函数尽量功能单一。有异常默认进行展示(先兼容到这后续有问题进行调整)
1373
- const obj = executeStrFunctionByContext(this, func, [form, null, null, util, '新增/修改'])
1374
- // 判断是 bool 还是 obj 兼容
1375
- if (typeof obj === 'boolean') {
1376
- return obj
1377
- } else if (obj && typeof obj === 'object') {
1378
- // obj 是一个对象,并且不是数组
1379
- return obj?.show
1380
- }
1381
- } else {
1382
- return true
1383
- }
1384
- } catch (e) {
1385
- return true
1386
- }
1387
- },
1388
- // 检查按钮是否显示
1389
- checkButtonVisible (button) {
1390
- try {
1391
- if (button.customFunction) {
1392
- return executeStrFunctionByContext(this, button.customFunction, [this.details, this.$refs.xAddForm.form, util, runLogic, getConfigByNameAsync])
1393
- }
1394
- return true
1395
- } catch (error) {
1396
- console.error('执行按钮显示函数失败:', error)
1397
- return false
1398
- }
1399
- },
1400
- formItemEmitFunc (func, data, value) {
1401
- this.$emit('x-form-item-emit-func', func, data, value)
1402
- },
1403
- // 检查条件表达式是否包含WF_RESULT
1404
- checkIfContainsWfResult () {
1405
- const conditionalActions = this.currentDirections.filter(action => action.type === 'conditionalBranch')
1406
- if (conditionalActions.length === 0) return false
1407
-
1408
- return conditionalActions.some(action => {
1409
- return action.expression && action.expression.includes('WF_RESULT')
1410
- })
1411
- },
1412
-
1413
- // 分析分支节点并设置选择框
1414
- async analyzeBranchNodes () {
1415
- try {
1416
- // 初始化状态
1417
- this.resetBranchSelection()
1418
-
1419
- // 获取所有类型的分支动作并缓存
1420
- this.currentBranchActions = this.getBranchActions()
1421
-
1422
- // 如果没有任何分支,处理普通流程
1423
- if (!this.currentBranchActions.hasAnyBranch) {
1424
- await this.handleNormalFlow()
1425
- return
1426
- }
1427
-
1428
- // 判断是否需要多分支选择
1429
- this.needMultipleBranchSelection = this.shouldUseMultipleBranchSelection(this.currentBranchActions)
1430
-
1431
- if (this.needMultipleBranchSelection) {
1432
- // 需要为多个分支预先选择人员
1433
- await this.setupMultipleBranchSelection(this.currentBranchActions.allBranchActions)
1434
- } else {
1435
- // 可以前台实时计算的条件分支
1436
- await this.calculateTargetNodeFromForm(this.currentBranchActions.conditionalActions)
1437
- }
1438
- } catch (error) {
1439
- console.error('分析分支节点失败:', error)
1440
- this.$message.error('工作流分支配置异常,请联系管理员')
1441
- // 降级处理:使用普通流程
1442
- await this.handleNormalFlow()
1443
- }
1444
- },
1445
-
1446
- // 重置分支选择状态
1447
- resetBranchSelection () {
1448
- this.branchNodes = []
1449
- this.branchChargePersons = {}
1450
- this.needMultipleBranchSelection = false
1451
- this.calculatedTargetNode = null
1452
- this.currentBranchActions = null
1453
- },
1454
-
1455
- // 获取分支动作分类
1456
- getBranchActions () {
1457
- const conditionalActions = this.currentDirections.filter(action => action.type === 'conditionalBranch')
1458
- const parallelActions = this.currentDirections.filter(action => action.type === 'parallelBranch')
1459
- const allBranchActions = [...conditionalActions, ...parallelActions]
1460
-
1461
- return {
1462
- conditionalActions,
1463
- parallelActions,
1464
- allBranchActions,
1465
- hasAnyBranch: allBranchActions.length > 0
1466
- }
1467
- },
1468
-
1469
- // 判断是否应该使用多分支选择模式
1470
- shouldUseMultipleBranchSelection (branchActions) {
1471
- // 情况1: 有并行分支
1472
- if (branchActions.parallelActions.length > 0) {
1473
- return true
1474
- }
1475
-
1476
- // 情况2: 条件分支包含WF_RESULT(后台结果决定)
1477
- if (branchActions.conditionalActions.length > 0) {
1478
- return this.checkIfContainsWfResult()
1479
- }
1480
-
1481
- return false
1482
- },
1483
-
1484
- // 根据表单数据计算目标节点
1485
- async calculateTargetNodeFromForm (conditionalActions = null) {
1486
- if (!conditionalActions) {
1487
- conditionalActions = this.currentDirections.filter(action => action.type === 'conditionalBranch')
1488
- }
1489
-
1490
- if (conditionalActions.length === 0) {
1491
- // 如果当前节点不是在分支流程中,才清空人员选择
1492
- // 避免在并行分支节点中误清除人员选择框
1493
- const currentStep = this.stepsForChild.find(item => item.id === this.activeStepId)
1494
- const isInBranch = currentStep?.properties?.branchPath
1495
-
1496
- if (!isInBranch) {
1497
- this.clearPersonSelection()
1498
- }
1499
- return
1500
- }
1501
-
1502
- try {
1503
- const formData = this.$refs.xAddForm?.form || {}
1504
-
1505
- // 遍历条件找到匹配的
1506
- for (const action of conditionalActions) {
1507
- if (action.expression) {
1508
- const result = await this.evaluateExpression(action.expression, formData)
1509
- if (result) {
1510
- this.calculatedTargetNode = action.to
1511
- await this.setupSingleTargetPersonSelection(action.to)
1512
- return
1513
- }
1514
- }
1515
- }
1516
- console.log('this.calculatedTargetNode', this.calculatedTargetNode)
1517
- // 如果没有匹配的条件,清空选择
1518
- this.clearPersonSelection()
1519
- } catch (error) {
1520
- console.warn('计算目标节点失败:', error)
1521
- this.clearPersonSelection()
1522
- }
1523
- },
1524
-
1525
- // 清空人员选择
1526
- clearPersonSelection () {
1527
- this.calculatedTargetNode = null
1528
- this.needSelectPerson = false
1529
- this.chargePersonOptions = []
1530
- this.checkedChargePerson = undefined
1531
- },
1532
-
1533
- // 设置单个目标节点的人员选择
1534
- async setupSingleTargetPersonSelection (stepId) {
1535
- const stepDefine = this.stepsDefine.find(step => step.id === stepId)
1536
-
1537
- if (!stepDefine?.properties?.chargePerson?.needSelectPerson) {
1538
- this.needSelectPerson = false
1539
- this.chargePersonOptions = []
1540
- return
1541
- }
1542
-
1543
- // 设置人员选择
1544
- this.chargePerson = stepDefine.properties.chargePerson
1545
- this.checkedChargePerson = undefined
1546
- this.chargePersonOptions = await this.getChargePersonOptionsForStep(stepId)
1547
-
1548
- // 如果只有一个选项,自动选中
1549
- if (this.chargePersonOptions.length === 1) {
1550
- this.checkedChargePerson = this.chargePersonOptions[0].value
1551
- }
1552
-
1553
- this.needSelectPerson = true
1554
- },
1555
-
1556
- // 表单数据变化处理函数(将通过provide传递给表单组件)
1557
- async handleFormDataChange (formData) {
1558
- // 只有在不是多分支选择模式且当前活动步骤有条件分支动作时才重新计算
1559
- if (!this.needMultipleBranchSelection && this.currentDirections.some(action => action.type === 'conditionalBranch')) {
1560
- await this.calculateTargetNodeFromForm()
1561
- }
1562
- },
1563
-
1564
- // 表达式评估 - 使用 LogicRunner
1565
- async evaluateExpression (expression, formData) {
1566
- try {
1567
- // 构建参数对象,传递当前表单数据
1568
- const params = {
1569
- WF_FORM: { ...formData }
1570
- }
1571
-
1572
- // 使用 LogicRunner 执行表达式
1573
- const result = await LogicRunner.runExpression(expression, params)
1574
- return result
1575
- } catch (error) {
1576
- console.warn('表达式评估失败:', expression, error)
1577
- return false
1578
- }
1579
- },
1580
-
1581
- // 获取指定步骤的人员选项
1582
- async getChargePersonOptionsForStep (stepId) {
1583
- const define = this.stepsDefine.find(item => item.id === stepId)
1584
- if (!define?.properties?.chargePerson) return []
1585
-
1586
- const chargePerson = define.properties.chargePerson
1587
- this.chargePerson = this.normalizeChargePersonFormat(chargePerson)
1588
-
1589
- if (!chargePerson.needSelectPerson || !chargePerson.personList) return []
1590
-
1591
- // 获取所有用户信息
1592
- const allUser = await postByServiceName(commonApi.getAllUserOptionList, {})
1593
-
1594
- // 根据配置筛选用户
1595
- const options = this.filterUsersByPersonConfig(chargePerson.personList, allUser)
1596
-
1597
- // 去重处理
1598
- return Array.from(new Map(options.map(item => [item.value, item])).values())
1599
- },
1600
-
1601
- // 标准化人员配置格式(兼容旧格式)
1602
- normalizeChargePersonFormat (chargePerson) {
1603
- if (chargePerson.role || chargePerson.department) {
1604
- chargePerson.needSelectPerson = true
1605
- chargePerson.personList = [{
1606
- type: chargePerson.role ? 'role' : 'department',
1607
- name: chargePerson.role || chargePerson.department
1608
- }]
1609
- }
1610
- return chargePerson
1611
- },
1612
-
1613
- // 根据人员配置筛选用户
1614
- filterUsersByPersonConfig (personList, allUsers) {
1615
- return personList.reduce((acc, personItem) => {
1616
- let filteredUsers = []
1617
-
1618
- if (personItem.type === 'role') {
1619
- filteredUsers = allUsers.filter(user =>
1620
- user.rolestr && user.rolestr.split(',').includes(personItem.name)
1621
- ).map(user => ({
1622
- label: user.label,
1623
- value: user.value
1624
- }))
1625
- } else if (personItem.type === 'department') {
1626
- filteredUsers = allUsers.filter(user =>
1627
- user.depname === personItem.name
1628
- ).map(user => ({
1629
- label: user.label,
1630
- value: user.value
1631
- }))
1632
- }
1633
-
1634
- return [...acc, ...filteredUsers]
1635
- }, [])
1636
- },
1637
-
1638
- // 设置多分支人员选择
1639
- async setupMultipleBranchSelection (branchActions) {
1640
- this.branchNodes = []
1641
- this.branchChargePersons = {}
1642
- let hasPersonSelection = false
1643
-
1644
- for (const action of branchActions) {
1645
- const stepDefine = this.stepsDefine.find(step => step.id === action.to)
1646
- const chargePerson = stepDefine?.properties?.chargePerson
1647
-
1648
- // 所有分支节点都加入branchNodes,保持数据结构完整
1649
- const nodeData = {
1650
- stepId: action.to,
1651
- stepName: this.getStepNameByStepId(action.to),
1652
- chargePerson: chargePerson,
1653
- needSelectPerson: chargePerson?.needSelectPerson || false,
1654
- chargePersonOptions: []
1655
- }
1656
-
1657
- if (chargePerson?.needSelectPerson) {
1658
- // 需要选择人员的分支
1659
- const chargePersonOptions = await this.getChargePersonOptionsForStep(action.to)
1660
- nodeData.chargePersonOptions = chargePersonOptions
1661
-
1662
- // 初始化选择值
1663
- this.branchChargePersons[action.to] = undefined
1664
- hasPersonSelection = true
1665
- } else {
1666
- // 不需要选择人员的分支,直接存储配置
1667
- this.branchChargePersons[action.to] = chargePerson
1668
- }
1669
-
1670
- this.branchNodes.push(nodeData)
1671
- }
1672
-
1673
- // 只有当存在需要选择人员的分支时才显示选择区域
1674
- this.needSelectPerson = hasPersonSelection
1675
- },
1676
-
1677
- // 处理普通单线流程(没有分支的情况)
1678
- async handleNormalFlow () {
1679
- const targetStepId = this.operationType === 'skip' ? this.stepNextBtnTo : this.nextBtnTo
1680
-
1681
- this.calculatedTargetNode = targetStepId
1682
- const stepDefine = this.stepsDefine.find(step => step.id === targetStepId)
1683
-
1684
- if (!stepDefine) {
1685
- console.warn('未找到目标步骤定义:', targetStepId)
1686
- this.clearPersonSelection()
1687
- return
1688
- }
1689
-
1690
- const defineProperties = stepDefine.properties
1691
- this.chargePerson = defineProperties?.chargePerson
1692
-
1693
- // 兼容旧格式
1694
- if (defineProperties.chargePerson) {
1695
- defineProperties.chargePerson = this.normalizeChargePersonFormat(defineProperties.chargePerson)
1696
- }
1697
-
1698
- if (defineProperties?.chargePerson?.needSelectPerson) {
1699
- await this.setupSingleTargetPersonSelection(targetStepId)
1700
- // 确保 branchChargePersons 中有该节点的数据结构
1701
- this.branchChargePersons[targetStepId] = {
1702
- handler: '',
1703
- handlerId: undefined,
1704
- ...defineProperties.chargePerson
1705
- }
1706
- } else {
1707
- // 不需要选择人员的情况,直接存储配置
1708
- this.branchChargePersons[targetStepId] = defineProperties?.chargePerson || {}
1709
- this.needSelectPerson = false
1710
- this.chargePersonOptions = []
1711
- }
1712
- }
1713
- },
1714
- watch: {}
1715
- }
1716
- </script>
1717
- <style lang="less" scoped>
1718
- .complete-data-title {
1719
- margin-top: 8px;
1720
- margin-bottom: 8px;
1721
- }
1722
-
1723
- :deep(.ant-result) {
1724
- padding: 0;
1725
- }
1726
-
1727
- .descriptionPreviewItem {
1728
- margin-bottom: 22px;
1729
-
1730
- :deep(.ant-descriptions-view) {
1731
- overflow: visible;
1732
- }
1733
- }
1734
-
1735
- .allWidth {
1736
- :deep(.ant-descriptions-item-content) {
1737
- width: 100%;
1738
- }
1739
- }
1740
-
1741
- .descriptionTitle {
1742
- position: relative;
1743
- padding-left: 12px;
1744
-
1745
- &::before {
1746
- content: '';
1747
- position: absolute;
1748
- left: 0;
1749
- top: 50%;
1750
- transform: translateY(-50%);
1751
- width: 4px;
1752
- height: 16px;
1753
- background-color: @primary-color;
1754
- border-radius: 2px;
1755
- }
1756
- }
1757
- </style>
1
+ <template>
2
+ <div>
3
+ <!-- 上方流程显示 -->
4
+ <a-card :bordered="false" :loading="loading">
5
+ <!-- 项目进度流程 -->
6
+ <work-flow-timeline
7
+ :current-step-id="currentStepId"
8
+ :active-step-id="activeStepId"
9
+ :workflow-id="workflowId"
10
+ :steps="stepsForChild"
11
+ :state="workflowState"
12
+ change-able
13
+ @activeStep="activeStep"/>
14
+ </a-card>
15
+ <!-- 无权访问的提示 -->
16
+ <a-result v-show="!canSubmit" status="403" title="无权操作" sub-title="您没有访问该步骤的权限.">
17
+ </a-result>
18
+ <div v-show="canSubmit">
19
+ <!-- 流程被退回的提示 -->
20
+ <a-alert v-if="currentStep && currentStep.back && !(beforeStepActive || workflowState)" type="info" show-icon style="margin-bottom: 14px">
21
+ <div slot="message">
22
+ <span style="font-weight: bold">流程被退回</span>
23
+ <span style="margin-left: 14px; font-size: 14px; color: rgba(0, 0, 0, 0.65)">请重新填写信息发起提交</span>
24
+ </div>
25
+ <div slot="description">
26
+ <div>操作人:{{
27
+ currentStep.back.f_operator
28
+ }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;操作时间:{{ currentStep.back.f_date }}
29
+ </div>
30
+ <div>原因:{{ currentStep.back.f_notes }}</div>
31
+ </div>
32
+ </a-alert>
33
+ <!-- 步骤内容主体 -->
34
+ <a-tabs default-active-key="1" @change="note = ''" type="card">
35
+ <a-tab-pane key="0" tab="步骤详情" v-if="beforeStepActive || workflowState">
36
+ <a-card :bordered="false" :loading="loadingHistory" :body-style="{ paddingTop: 0 }">
37
+ <!-- 当前步骤历史记录 -->
38
+ <template v-if="showTab">
39
+ <x-tab
40
+ :compProp="{ buttonState: { add: false, edit: false, delete: false, import: false, extra: false }, disableAction: true }"
41
+ :local-config="tabDesigner"
42
+ :body-style="{ padding: 0 }"
43
+ :tabBarGutter="24"
44
+ :extra-data="{ workflowId: workflowId }"
45
+ default-active-key="workFlowTab">
46
+ <a-tab-pane
47
+ :forceRender="true"
48
+ v-if="formCompletedDataPreview"
49
+ slot="extraBeforeTabs"
50
+ key="workFlowTab"
51
+ tab="表单"
52
+ >
53
+ <work-flow-preview :form-completed-data-preview="formCompletedDataPreview"/>
54
+ </a-tab-pane>
55
+ </x-tab>
56
+ </template>
57
+ <template v-else-if="formCompletedDataPreview">
58
+ <work-flow-preview :form-completed-data-preview="formCompletedDataPreview"/>
59
+ </template>
60
+ <template v-else>
61
+ <a-result status="404" title="暂无数据" sub-title="该步骤暂无数据。">
62
+ </a-result>
63
+ </template>
64
+ </a-card>
65
+ </a-tab-pane>
66
+ <a-tab-pane key="1" tab="业务操作" v-else v-show="renderCurrentNode">
67
+ <a-card :bordered="false" :loading="loadingHistory" :body-style="{ paddingTop: 0 }">
68
+ <x-tab
69
+ v-if="showTab"
70
+ :compProp="{ buttonState: { extra: true }, disableAction: false }"
71
+ :local-config="tabDesigner"
72
+ :extra-data="{ workflowId:workflowId }"
73
+ :body-style="{ padding: 0 }"
74
+ :tabBarGutter="24"
75
+ default-active-key="workFlowTab">
76
+ <a-tab-pane
77
+ :forceRender="true"
78
+ v-if="showForm"
79
+ slot="extraBeforeTabs"
80
+ key="workFlowTab"
81
+ tab="表单"
82
+ >
83
+ <x-add-native-form
84
+ ref="xAddForm"
85
+ @onSubmit="submitForm"/>
86
+ </a-tab-pane>
87
+ </x-tab>
88
+ <x-add-native-form
89
+ v-else
90
+ ref="xAddForm"
91
+ @x-form-item-emit-func="formItemEmitFunc"
92
+ @onSubmit="submitForm"/>
93
+ <a-divider/>
94
+
95
+ <!-- 分支节点状态提示 -->
96
+ <a-alert
97
+ v-if="isBranchLastNode.isBranchNode && !isBranchLastNode.isLastBranch"
98
+ type="info"
99
+ show-icon
100
+ style="margin-bottom: 16px"
101
+ >
102
+ <template slot="message">
103
+ <span style="font-weight: bold;">分支节点等待中</span>
104
+ </template>
105
+ <template slot="description">
106
+ <div>当前为分支节点,其他分支仍在进行中。完成当前分支后将等待其他分支完成,然后自动汇合到下一环节。</div>
107
+ <div style="margin-top: 8px; color: #666; font-size: 12px;">
108
+ <a-icon type="info-circle" style="margin-right: 4px;" />
109
+ 提示:此操作无需选择下一环节负责人,系统将自动处理流程流转。
110
+ </div>
111
+ </template>
112
+ </a-alert>
113
+
114
+ <a-alert
115
+ v-if="isBranchLastNode.isBranchNode && isBranchLastNode.isLastBranch"
116
+ type="success"
117
+ show-icon
118
+ style="margin-bottom: 16px"
119
+ >
120
+ <template slot="message">
121
+ <span style="font-weight: bold;">分支汇合节点</span>
122
+ </template>
123
+ <template slot="description">
124
+ <div>您正在处理最后一个未完成的分支节点,完成后将触发分支汇合并进入下一环节。</div>
125
+ </template>
126
+ </a-alert>
127
+
128
+ <a-form v-show="!lastStep" label-align="left" :label-col="{ span: 3 }" :wrapper-col="{ span: 13 }">
129
+ <a-form-item v-if="showStepNextBtn" label="操作类型" required>
130
+ <a-radio-group v-model="operationType" @change="handleOperationTypeChange">
131
+ <a-radio value="submit">到下一步</a-radio>
132
+ <a-radio value="skip">{{ stepNextBtnTitle }}</a-radio>
133
+ </a-radio-group>
134
+ </a-form-item>
135
+
136
+ <!-- 智能分支人员选择组件 - 只有非分支节点或最后一个分支才显示 -->
137
+ <WorkflowPersonSelector
138
+ v-if="!isBranchLastNode.isBranchNode || isBranchLastNode.isLastBranch"
139
+ ref="personSelector"/>
140
+
141
+ <a-form-item
142
+ v-if="!isBranchLastNode.isBranchNode || isBranchLastNode.isLastBranch"
143
+ label="下一环节截止时间"
144
+ :validate-status="deadlineValidateStatus"
145
+ :help="deadlineHelp"
146
+ required>
147
+ <a-date-picker
148
+ :getCalendarContainer="(triggerNode) => triggerNode.parentNode"
149
+ v-model="deadline"
150
+ value-format="YYYY-MM-DD HH:mm"
151
+ format="YYYY-MM-DD HH:mm"
152
+ :allow-clear="false"
153
+ :show-today="false"
154
+ show-time
155
+ placeholder="请选择"/>
156
+ </a-form-item>
157
+ </a-form>
158
+ <a-divider/>
159
+ <!-- 备注信息 -->
160
+ <a-textarea
161
+ v-model="note"
162
+ :auto-size="{ minRows: 3, maxRows: 5 }"
163
+ placeholder="填写本环节备注事项"
164
+ />
165
+ <!-- 当前步骤完成后,控制流程按钮 -->
166
+ <div style="text-align: center">
167
+ <a-radio-group style="margin-top: 20px">
168
+ <a-space>
169
+ <!-- 动态按钮渲染 -->
170
+ <template v-if="buttonGroup && buttonGroup.actionArr">
171
+ <a-button
172
+ v-for="(button, index) in buttonGroup.actionArr"
173
+ :key="index"
174
+ v-show="checkButtonVisible(button)"
175
+ :type="button.type ? button.type : 'default'"
176
+ @click="handleCustomButtonClick(button)"
177
+ >
178
+ {{ button.text }}
179
+ </a-button>
180
+ </template>
181
+ <!-- 原有的按钮逻辑 -->
182
+ <template>
183
+ <a-popover v-if="operationType === 'submit'">
184
+ <template slot="content">
185
+ <p v-if="isBranchLastNode.isBranchNode && !isBranchLastNode.isLastBranch">
186
+ 完成当前分支,等待其他分支完成后自动汇合
187
+ </p>
188
+ <p v-else-if="isBranchLastNode.isBranchNode && isBranchLastNode.isLastBranch">
189
+ 完成最后一个分支并触发汇合到下一环节
190
+ </p>
191
+ <p v-else>{{ nextBtnTitle }}</p>
192
+ </template>
193
+ <a-button
194
+ v-if="!lastStep"
195
+ :disabled="!showNextBtn && !stepDone"
196
+ type="primary"
197
+ @click="nextClick"
198
+ >
199
+ 完成提交
200
+ <a-icon type="right"/>
201
+ </a-button>
202
+ </a-popover>
203
+ <a-popover v-else :title="stepNextBtnTitle">
204
+ <template slot="content">
205
+ <p v-for="(item,index) in stepNextBtnText" :key="index">{{ item }}</p>
206
+ </template>
207
+ <a-button
208
+ v-if="showStepNextBtn && !lastStep"
209
+ type="primary"
210
+ @click="stepNextClick"
211
+ >
212
+ 跳过
213
+ </a-button>
214
+ </a-popover>
215
+ <a-button
216
+ v-if="lastStep"
217
+ type="primary"
218
+ @click="lastStepNextClick"
219
+ >
220
+ 确认完成
221
+ </a-button>
222
+ </template>
223
+ </a-space>
224
+ </a-radio-group>
225
+ </div>
226
+ </a-card>
227
+ </a-tab-pane>
228
+ <!-- 退回 -->
229
+ <a-tab-pane v-if="canSubmit && !beforeStepActive && showPrevBtn && !workflowState" key="2" tab="退回">
230
+ <a-form layout="vertical">
231
+ <a-form-item label="退回原因" :wrapper-col="{ span: 24 }" required>
232
+ <a-textarea
233
+ v-model="backNote"
234
+ :auto-size="{ minRows: 4, maxRows: 10 }"
235
+ placeholder="请填写退回原因 / 备注"
236
+ />
237
+ </a-form-item>
238
+ <a-form-item :wrapper-col="{ offset: 11 }">
239
+ <a-popover :title="preBtnTitle">
240
+ <template slot="content">
241
+ <p v-for="(item,index) in preBtnText" :key="index">{{ item }}</p>
242
+ </template>
243
+ <a-button
244
+ type="danger"
245
+ @click="preClick"
246
+ >
247
+ <a-icon type="left"/>
248
+ 退回
249
+ </a-button>
250
+ </a-popover>
251
+ </a-form-item>
252
+ </a-form>
253
+ </a-tab-pane>
254
+ <!-- <a-tab-pane v-if="canSubmit && !beforeStepActive && showPrevBtn && !workflowState" key="3" tab="工单拆分">
255
+ &lt;!&ndash; 分配工单 &ndash;&gt;
256
+ <workflow-list-resolution :workflow-project-id="workflowId" :details="details"></workflow-list-resolution>
257
+ </a-tab-pane>-->
258
+ </a-tabs>
259
+ </div>
260
+ </div>
261
+ </template>
262
+
263
+ <script>
264
+ import XAddNativeForm from '@vue2-client/base-client/components/common/XAddNativeForm'
265
+ import XFormTable from '@vue2-client/base-client/components/common/XFormTable/XFormTable'
266
+ import XAddForm from '@vue2-client/base-client/components/common/XAddForm/XAddForm'
267
+ import { postByServiceName } from '@vue2-client/services/api/restTools'
268
+ import { workFlowViewApi } from '@vue2-client/services/api/workFlow'
269
+ import { commonApi } from '@vue2-client/services/api'
270
+ import { formatDate } from '@vue2-client/utils/util'
271
+ import { mapState } from 'vuex'
272
+ import moment from 'moment'
273
+ import FilePreview from '@vue2-client/components/FilePreview'
274
+ import WorkFlowTimeline from './WorkFlowTimeline.vue'
275
+ import { FileItem, ImageItem } from '@vue2-client/components/FileImageItem'
276
+ import WorkflowListResolution from './WorkflowListResolution'
277
+ import { executeStrFunctionByContext } from '@vue2-client/utils/runEvalFunction'
278
+ import * as util from '@vue2-client/utils/util'
279
+ import { getConfigByNameAsync, runLogic } from '@vue2-client/services/api/common'
280
+ import LogicRunner from '@vue2-client/logic/LogicRunner'
281
+ import XTab from '@vue2-client/base-client/components/common/XTab/XTab.vue'
282
+ import WorkFlowPreview from './WorkFlowPreview'
283
+ import WorkflowPersonSelector from './components/WorkflowPersonSelector.vue'
284
+
285
+ export default {
286
+ name: 'WorkFlowHandle',
287
+ provide () {
288
+ return {
289
+ formDataChange: this.handleFormDataChange,
290
+ workflowHandleWrap: this.workflowHandleWrap
291
+ }
292
+ },
293
+ components: {
294
+ XTab,
295
+ WorkflowListResolution,
296
+ XAddNativeForm,
297
+ WorkFlowTimeline,
298
+ XFormTable,
299
+ XAddForm,
300
+ FilePreview,
301
+ FileItem,
302
+ ImageItem,
303
+ WorkFlowPreview,
304
+ WorkflowPersonSelector
305
+ },
306
+ computed: {
307
+ workflowHandleWrap () {
308
+ return this
309
+ },
310
+ ...mapState('account', { currUser: 'user' }),
311
+ // 判断当前节点的分支状态
312
+ isBranchLastNode () {
313
+ // 默认返回值
314
+ const defaultResult = {
315
+ isBranchNode: false, // 是否为分支流程中的节点
316
+ isLastBranch: false // 是否为最后一个未完成的分支(需要选择下一环节人员)
317
+ }
318
+
319
+ // 如果是最后一步或没有下一步或者不能提交,则不是分支节点
320
+ if (this.lastStep || !this.nextBtnTo || !this.canSubmit) {
321
+ return defaultResult
322
+ }
323
+
324
+ // 检查下一个节点是否为分支退出节点
325
+ const nextStep = this.stepsDefine.find(step => step.id === this.nextBtnTo)
326
+
327
+ // 如果下一个节点的flowRole不是branchExit,说明不是分支的最后一个节点
328
+ if (!nextStep || nextStep.properties?.flowRole !== 'branchExit') {
329
+ return defaultResult
330
+ }
331
+
332
+ // 获取分支退出节点等待的所有分支步骤ID
333
+ const waitStepIds = nextStep.properties.waitStepIds || []
334
+ if (waitStepIds.length === 0) {
335
+ return {
336
+ isBranchNode: true,
337
+ isLastBranch: true // 如果没有等待步骤配置,默认认为是最后一个
338
+ }
339
+ }
340
+
341
+ // 当前步骤必须在等待列表中才算是分支节点
342
+ if (!waitStepIds.includes(this.activeStepId)) {
343
+ return defaultResult
344
+ }
345
+
346
+ // 检查除当前步骤外的其他分支步骤状态
347
+ const otherBranchSteps = waitStepIds.filter(stepId => stepId !== this.activeStepId)
348
+
349
+ // 判断其他所有分支步骤是否都已完成(状态为2)
350
+ const allOtherBranchesCompleted = otherBranchSteps.every(stepId => {
351
+ const step = this.stepsForChild.find(s => s.id === stepId)
352
+ return step && step.status === 2 // 已处理
353
+ })
354
+
355
+ return {
356
+ isBranchNode: true, // 当前节点是分支流程中的节点
357
+ isLastBranch: allOtherBranchesCompleted // 只有当其他所有分支都已完成时,当前分支才是最后一个
358
+ }
359
+ },
360
+ canSubmit () {
361
+ // 对于超级管理员直接认为可以提交
362
+ if (this.currUser.rolesnames.indexOf('超级管理员') > -1) {
363
+ return true
364
+ }
365
+ // currentStepId可能还没初始化,此处拿不到先返回false
366
+ if (!this.currentStepId) {
367
+ return false
368
+ }
369
+ const activeStep = this.stepsForChild.find(item => item.id === this.activeStepId)
370
+ // 如果当前选中节点不是正在进行的节点,则判断viewers权限
371
+ if (this.activeStepId !== this.currentStepId && activeStep != null && activeStep.status !== 1) {
372
+ // 历史节点为当前登录人操作则不做查看数据权限校验
373
+ if (activeStep.handler === this.currUser.name) {
374
+ return true
375
+ }
376
+ const viewers = activeStep?.properties?.otherProperty?.viewers ?? []
377
+ if (viewers.length > 0) {
378
+ // 使用some方法判断当前人员是否满足任一条件
379
+ return viewers.some(item => {
380
+ if (item.type === 'role') {
381
+ // 检查rolestr是否存在并包含指定角色
382
+ return this.currUser.rolestr && this.currUser.rolestr.split(',').includes(item.name)
383
+ }
384
+ if (item.type === 'department') {
385
+ // 检查depname是否存在并包含指定部门
386
+ return this.currUser.depname && this.currUser.deps.includes(item.name)
387
+ }
388
+ return false
389
+ })
390
+ } else {
391
+ return true
392
+ }
393
+ } else {
394
+ // 当前进行节点的数据
395
+ const step = this.stepsForChild.find(item => item.id === this.activeStepId)
396
+ // 检查角色和部门权限
397
+ if (step && step.properties && step.properties.chargePerson) {
398
+ // 如果当前节点的负责人选项中有设置选择人员 当前节点就只能由上一步设置的负责人操作
399
+ if (step.properties.chargePerson.needSelectPerson) {
400
+ return step.handler === this.currUser.name
401
+ }
402
+ if (step.properties.chargePerson.personList && step.properties.chargePerson.personList.length > 0) {
403
+ // 使用some方法判断当前人员是否满足任一条件
404
+ return step.properties.chargePerson.personList.some(item => {
405
+ if (item.type === 'role') {
406
+ // 检查rolestr是否存在并包含指定角色
407
+ return this.currUser.rolestr && this.currUser.rolestr.split(',').includes(item.name)
408
+ }
409
+ if (item.type === 'department') {
410
+ // 检查parentname是否存在并包含指定部门
411
+ return this.currUser.parentname && this.currUser.parentname.includes(item.name)
412
+ }
413
+ return false
414
+ })
415
+ }
416
+ }
417
+
418
+ // 检查handler是否包含当前用户
419
+ if (step && step.handler) {
420
+ return step.handler.includes(this.currUser.name)
421
+ }
422
+ }
423
+ return false
424
+ },
425
+ formPreviewNoFileData () {
426
+ return this.formCompletedDataPreview.data.filter(item => item.label !== '附件上传')
427
+ }
428
+ },
429
+ data () {
430
+ return {
431
+ // 显示供用户填写的当前步骤表单
432
+ showForm: false,
433
+ // 显示步骤的tab页
434
+ showTab: false,
435
+ // tab页的配置
436
+ tabDesigner: undefined,
437
+ // 当前步骤表单标题
438
+ formTitle: '',
439
+ // 当前步骤表单定义Json
440
+ stepDefine: [],
441
+ // 当前步骤
442
+ currentStep: undefined,
443
+ // 当前步骤完成状态
444
+ stepDone: false,
445
+ // 所有节点连通数据
446
+ directions: [],
447
+ // 所有流程定义数据
448
+ stepsDefine: [],
449
+ // 当前步骤能通向的节点
450
+ currentDirections: [],
451
+ // 当前节点id
452
+ currentStepId: undefined,
453
+ // 当前活动节点 id
454
+ activeStepId: 1,
455
+ // 下一步按钮显示
456
+ showNextBtn: false,
457
+ // 回退按钮显示
458
+ showPrevBtn: false,
459
+ // 跳过按钮显示
460
+ showStepNextBtn: false,
461
+ // 定义三个按钮气泡提示内容
462
+ preBtnTitle: '',
463
+ preBtnText: [],
464
+ nextBtnTitle: '',
465
+ stepNextBtnTitle: '',
466
+ stepNextBtnText: [],
467
+ // 控制三个按钮跳转目标
468
+ preBtnTo: undefined,
469
+ nextBtnTo: undefined,
470
+ stepNextBtnTo: undefined,
471
+ // 控制当前标签页显示
472
+ activeKey: '1',
473
+ // 之前的节点是否激活
474
+ beforeStepActive: false,
475
+ // 之前节点中的数据
476
+ beforeStepData: [],
477
+ // 用于将已有数据,填回x-add表单中
478
+ formCompletedData: {},
479
+ // 用于展示提交的数据
480
+ formCompletedDataPreview: null,
481
+ // 切换至目标流程时,目标流程定义
482
+ targetStepDefine: [],
483
+ // 控制历史记录加载
484
+ loadingHistory: true,
485
+ // 控制表单校验
486
+ formValid: false,
487
+ // 备忘
488
+ note: '',
489
+ backNote: '', // 新增退回原因专用变量
490
+ // 是否是最后一步
491
+ lastStep: false,
492
+ // 存储每一步骤填表人和时间数据
493
+ stepsExtraInfo: [],
494
+ // 控制基础信息页流程展示加载
495
+ loading: true,
496
+ createQueryVisible: false,
497
+ // 激活的步骤名
498
+ activeStepName: '',
499
+ stepsParse: undefined,
500
+ // 下一步处理人选择框数据
501
+ chargePersonOptions: [],
502
+ // 已选择下一步处理人
503
+ checkedChargePerson: undefined,
504
+ // 下一步截止时间
505
+ deadline: this.getDefaultDeadline(),
506
+ deadlineValidateStatus: '',
507
+ deadlineHelp: '',
508
+ // 当前任务是否延期
509
+ // taskIsOverdue: moment().isAfter(this.completeTime, 'day'),
510
+ // 操作类型,提交到下一步或跳过
511
+ operationType: 'submit',
512
+ // 获取微信推送是否成功信息
513
+ information: [],
514
+ // 是否需要选择人员
515
+ needSelectPerson: true,
516
+ // 下一环节人员信息
517
+ chargePerson: {},
518
+ // 动态按钮配置
519
+ buttonGroup: null,
520
+ // 分支节点相关数据
521
+ branchNodes: [], // 需要选择人员的分支节点列表
522
+ branchChargePersons: {}, // 分支节点人员选择 格式:{stepId: personId}
523
+ needMultipleBranchSelection: false, // 是否需要为多个分支节点预先选择人员(包含WF_RESULT的条件分支或并行分支)
524
+ calculatedTargetNode: null, // 前台计算出的目标节点
525
+ currentBranchActions: null // 缓存当前的分支动作,避免重复调用
526
+ }
527
+ },
528
+ async mounted () {
529
+ await this.init()
530
+ // this.checkDeadline()
531
+ },
532
+ props: {
533
+ workflowId: {
534
+ type: [String, Number],
535
+ required: true
536
+ },
537
+ visible: {
538
+ type: Boolean,
539
+ default: false
540
+ },
541
+ stepsForChild: {
542
+ type: Array,
543
+ required: true
544
+ },
545
+ workflowState: {
546
+ type: [Boolean, Number],
547
+ required: true
548
+ },
549
+ completeTime: {
550
+ type: String,
551
+ required: true
552
+ },
553
+ taskName: {
554
+ type: String,
555
+ required: true
556
+ },
557
+ details: {
558
+ type: Object,
559
+ required: true
560
+ },
561
+ // 展开详情初始化的节点
562
+ // 适用于不让第一个节点默认展示的情况
563
+ initStepId: {
564
+ type: [String, Number],
565
+ required: false,
566
+ default: null
567
+ },
568
+ renderCurrentNode: {
569
+ type: Boolean,
570
+ default: true
571
+ }
572
+ },
573
+ methods: {
574
+ init () {
575
+ this.getCurrentStep()
576
+ },
577
+ onClose () {
578
+ this.activeStepId = this.currentStepId
579
+ this.checkedChargePerson = undefined
580
+ this.loadingHistory = true
581
+ this.currentStepId = undefined
582
+ this.directions = []
583
+ this.currentDirections = []
584
+ this.preBtnText = []
585
+ this.stepNextBtnText = []
586
+ this.stepsExtraInfo = []
587
+ this.loading = true
588
+ this.showNextBtn = false
589
+ this.showStepNextBtn = false
590
+ this.showPrevBtn = false
591
+ this.stepDone = false
592
+ this.formCompletedData = {}
593
+ this.formCompletedDataPreview = null
594
+ this.operationType = 'submit'
595
+
596
+ // 清理分支节点相关数据
597
+ this.branchNodes = []
598
+ this.branchChargePersons = {}
599
+ this.needMultipleBranchSelection = false
600
+ this.calculatedTargetNode = null
601
+ this.currentBranchActions = null
602
+ },
603
+ async showQueryFormItemFunc () {
604
+ if (this.attr.showQueryFormItemFunc) {
605
+ const obj = executeStrFunctionByContext(this, this.attr.showQueryFormItemFunc, [this.form, this.setForm, this.attr, util, this.mode])
606
+ // 判断是 bool 还是 obj 兼容
607
+ if (typeof obj === 'boolean') {
608
+ this.show = obj
609
+ } else if (obj && typeof obj === 'object') {
610
+ // obj 是一个对象,并且不是数组
611
+ this.show = obj?.show
612
+ this.readOnly = obj?.readOnly
613
+ }
614
+ } else {
615
+ this.show = true
616
+ }
617
+ },
618
+ // 获取单个步骤的定义
619
+ getSingleStepDefine (name) {
620
+ for (const step of this.stepsDefine) {
621
+ if (name === step.name) {
622
+ return step.properties.form
623
+ }
624
+ }
625
+ },
626
+ // 日期格式化
627
+ format (date, format) {
628
+ return formatDate(date, format)
629
+ },
630
+ // 获取当前步骤
631
+ getCurrentStep () {
632
+ return postByServiceName(workFlowViewApi.getWorkFlowCurrentSubState, {
633
+ workflowId: this.workflowId
634
+ })
635
+ .then(res => {
636
+ // 优先级:主动传入的 > 获取到的
637
+ this.currentStepId = this.initStepId || res.id
638
+
639
+ // 如果指定了具体节点,同时设置activeStepId
640
+ if (this.initStepId) {
641
+ this.activeStepId = this.initStepId
642
+ }
643
+
644
+ const currentStep = this.stepsForChild.find(item => item.id === this.currentStepId)
645
+ res.state = currentStep.name
646
+ // 获取到当前步骤后复制下一步时间
647
+ this.deadline = this.getDefaultDeadline(currentStep.properties?.otherProperty?.nextNodeInterval)
648
+ this.currentStep = res
649
+ this.getDirection()
650
+ }, err => {
651
+ console.log(err)
652
+ })
653
+ },
654
+ // 完工按钮
655
+ async lastStepNextClick () {
656
+ this.$refs.xAddForm.asyncSubmit().then((res) => {
657
+ this.submitForm(res).then(_ => {
658
+ postByServiceName(workFlowViewApi.afterWorkFlowFinalStepSubmit, {
659
+ workflowId: this.workflowId,
660
+ stepId: this.currentStepId,
661
+ submitUser: this.currUser.name,
662
+ submitUserId: this.currUser.id
663
+ }).then(_res => {
664
+ this.saveWorkflowLog('确认完工', '最后一步: ' + this.getStepNameByStepId(this.currentStepId), { notes: this.note.trim() })
665
+ this.$message.success('已完工!')
666
+ this.loading = true
667
+ this.loadingHistory = true
668
+ this.onClose()
669
+ this.$emit('success', { note: this.note.trim(), form: res.realForm, workflowId: this.workflowId })
670
+ },
671
+ () => {
672
+ this.$message.error('提交失败!')
673
+ }
674
+ )
675
+ })
676
+ }).catch(err => {
677
+ if (err && err.message === 'Form validation failed') {
678
+ this.$message.error('请检查表单必填项!')
679
+ } else {
680
+ // 对于其他错误,继续向上抛出
681
+ throw err
682
+ }
683
+ })
684
+ },
685
+ // 三个按钮点击后逻辑
686
+ async nextClick () {
687
+ // 检查是否为非最后分支节点
688
+ const branchStatus = this.isBranchLastNode
689
+ const isWaitingBranch = branchStatus.isBranchNode && !branchStatus.isLastBranch
690
+
691
+ const extraData = this.getApplyStepExtraData(this.nextBtnTo)
692
+ if (!extraData) {
693
+ return
694
+ }
695
+
696
+ // 确认对话框
697
+ const confirmContent = isWaitingBranch
698
+ ? '确定完成当前分支么?完成后将等待其他分支,不会立即流转到下一环节。'
699
+ : '确定提交么?提交之后数据不可更改!'
700
+
701
+ await new Promise(resolve => {
702
+ this.$confirm({
703
+ title: '提交确认',
704
+ content: confirmContent,
705
+ onOk () {
706
+ resolve()
707
+ return Promise.resolve()
708
+ }
709
+ })
710
+ })
711
+
712
+ this.$refs.xAddForm.asyncSubmit().then(res => {
713
+ this.submitForm(res).then(_ => {
714
+ postByServiceName(workFlowViewApi.submitToNextStep, extraData)
715
+ .then(
716
+ () => {
717
+ let successMessage = '提交成功'
718
+
719
+ // 只有非等待分支节点才保存工作流日志
720
+ if (!isWaitingBranch) {
721
+ const branchStatus = this.isBranchLastNode
722
+ const operation = branchStatus.isBranchNode && branchStatus.isLastBranch ? '分支汇合' : '提交'
723
+
724
+ const extra = {
725
+ setHandler: this.getStepHandler(),
726
+ setDeadline: this.deadline,
727
+ notes: this.note.trim()
728
+ }
729
+ this.saveWorkflowLog(operation, this.generateBranchStepChangeText(this.currentStepId), extra)
730
+ } else {
731
+ successMessage = '分支完成,等待其他分支完成后自动汇合'
732
+ }
733
+
734
+ this.$message.success(successMessage)
735
+ this.loading = true
736
+ this.loadingHistory = true
737
+ this.$emit('nextClick', {
738
+ note: this.note.trim(),
739
+ form: res.realForm,
740
+ workflowId: this.workflowId,
741
+ isBranchWaiting: isWaitingBranch, // 标记是否为分支等待状态
742
+ ...this.generateStepChange(this.currentStepId, this.nextBtnTo)
743
+ })
744
+ this.$emit('refresh')
745
+ this.onClose()
746
+ this.init()
747
+ },
748
+ err => {
749
+ this.$message.error('提交失败!')
750
+ console.log(err)
751
+ }
752
+ )
753
+ })
754
+ }).catch((err) => {
755
+ if (err && err.message === 'Form validation failed') {
756
+ this.$message.error('请检查表单必填项!')
757
+ } else {
758
+ // 对于其他错误,继续向上抛出
759
+ throw err
760
+ }
761
+ })
762
+ },
763
+ async preClick () {
764
+ const notes = this.backNote.trim()
765
+ if (!notes) {
766
+ this.$message.error('退回请在备注中填写理由')
767
+ return
768
+ }
769
+ return postByServiceName(workFlowViewApi.updateWorkFlowState, {
770
+ stepId: this.preBtnTo,
771
+ workflowId: this.workflowId,
772
+ type: 'back'
773
+ })
774
+ .then(
775
+ res => {
776
+ this.saveWorkflowLog('退回', this.generateStepChangeText(this.currentStepId, this.preBtnTo), { notes })
777
+ this.$message.success('退回成功')
778
+ this.backNote = '' // 退回成功后清空退回原因
779
+ this.loading = true
780
+ this.loadingHistory = true
781
+ this.currentStepId = this.preBtnTo
782
+ this.activeStepId = this.preBtnTo
783
+
784
+ // 新增:重置按钮状态
785
+ this.stepDone = false
786
+ this.beforeStepActive = false
787
+ this.operationType = 'submit'
788
+
789
+ this.$emit('refresh')
790
+ this.onClose()
791
+ this.init()
792
+ },
793
+ err => {
794
+ this.$message.error('退回失败!')
795
+ console.log(err)
796
+ }
797
+ )
798
+ },
799
+ async stepNextClick () {
800
+ const extraData = this.getApplyStepExtraData(this.stepNextBtnTo)
801
+ if (!extraData) {
802
+ return
803
+ }
804
+ this.$refs.xAddForm.asyncSubmit().then(res => {
805
+ this.submitForm(res).then(_ => {
806
+ postByServiceName(workFlowViewApi.submitToNextStep, extraData)
807
+ .then(
808
+ () => {
809
+ const extra = {
810
+ setHandler: this.getStepHandler(),
811
+ setDeadline: this.deadline,
812
+ notes: this.note.trim()
813
+ }
814
+ this.saveWorkflowLog('跳过', this.generateBranchStepChangeText(this.currentStepId), extra)
815
+ this.$message.success('提交成功')
816
+ this.$emit('nextClick', {
817
+ note: this.note.trim(),
818
+ form: res.realForm,
819
+ workflowId: this.workflowId,
820
+ ...this.generateStepChange(this.currentStepId, this.stepNextBtnTo)
821
+ })
822
+ this.loading = true
823
+ this.loadingHistory = true
824
+ this.$emit('refresh')
825
+ this.onClose()
826
+ this.init()
827
+ },
828
+ err => {
829
+ this.$message.error('提交失败!')
830
+ console.log(err)
831
+ }
832
+ )
833
+ })
834
+ }).catch(err => {
835
+ if (err && err.message === 'Form validation failed') {
836
+ this.$message.error('请检查表单必填项!')
837
+ } else {
838
+ // 对于其他错误,继续向上抛出
839
+ throw err
840
+ }
841
+ })
842
+ },
843
+ // 获取当前步骤节点,连通的节点
844
+ async getDirection () {
845
+ // 获取流程定义
846
+ return postByServiceName(workFlowViewApi.getWorkFlowDefine, {
847
+ id: this.workflowId
848
+ })
849
+ .then(async res => {
850
+ this.directions = []
851
+ this.stepsDefine = res.steps
852
+ await this.resolveDirections()
853
+ this.resolveStep()
854
+ }, err => {
855
+ console.log(err)
856
+ })
857
+ },
858
+ // 分析当前节点,能通向的节点
859
+ async resolveDirections () {
860
+ const currentStep = this.stepsForChild.find(item => item.id === this.activeStepId)
861
+ if (currentStep?.properties?.actions) {
862
+ this.currentDirections = currentStep.properties.actions
863
+ }
864
+ // 判断是否是最后ige节点
865
+ this.lastStep = (currentStep?.properties?.actions || []).filter(item => {
866
+ return item.type !== 'back'
867
+ }).length === 0
868
+
869
+ // 处理跳转按钮
870
+ this.workflowControl()
871
+
872
+ if (!this.lastStep) {
873
+ // 分析分支节点并设置智能人员选择
874
+ await this.analyzeBranchNodes()
875
+ }
876
+ },
877
+ // 根据步骤id获取步骤名称
878
+ getStepNameByStepId (stepId) {
879
+ return this.stepsDefine.find(item => item.id === stepId)?.name
880
+ },
881
+ // 根据步骤id获取步骤状态
882
+ getStepStatusByStepId (stepId) {
883
+ return this.stepsForChild.find(item => item.id === stepId)?.status
884
+ },
885
+ // 表单提交的回调
886
+ submitForm (obj) {
887
+ this.formValid = true
888
+ const formData = obj.realForm
889
+ const time = this.format(new Date(), 'yyyy-MM-dd hh:mm:ss')
890
+ return postByServiceName(workFlowViewApi.saveWorkFlowStepFormData, {
891
+ workflowId: this.workflowId,
892
+ stepId: this.activeStepId,
893
+ form: formData,
894
+ data: time,
895
+ handler: this.currUser.name,
896
+ note: this.note.trim()
897
+ })
898
+ .then(
899
+ res => {
900
+ console.log('表单提交成功')
901
+ this.note = ''
902
+ this.showForm = false
903
+ this.stepDone = true
904
+ },
905
+ err => {
906
+ this.$message.error('保存失败,请检查后重试')
907
+ console.log(err)
908
+ }
909
+ )
910
+ },
911
+ // 获取当前步骤定义内容,构建组件
912
+ async buildComp (stepId) {
913
+ const properties = this.stepsDefine.find(item => item.id === stepId).properties
914
+ // 表单的渲染
915
+ if (properties.form && properties.form.formJson) {
916
+ this.stepDefine = properties.form.formJson
917
+ this.showForm = true
918
+ this.$nextTick(() => {
919
+ this.$refs.xAddForm && this.$refs.xAddForm.init({
920
+ ...properties.form,
921
+ businessType: '修改',
922
+ formItems: this.stepDefine,
923
+ layout: properties.form.xAddFormLayout,
924
+ showSubmitBtn: false
925
+ })
926
+ })
927
+ } else {
928
+ this.showForm = false
929
+ }
930
+ // Tab的渲染
931
+ this.tabDesigner = properties.tabDesigner
932
+ this.showTab = !!this.tabDesigner
933
+ // 以当前激活节点分析节点
934
+ await this.resolveDirections()
935
+ this.resolveStep()
936
+ },
937
+ // 根据当前节点,判断之后流程,以及按钮的显示
938
+ workflowControl () {
939
+ // 重置所有控制数据为默认值,避免之前状态的影响
940
+ this.showNextBtn = false
941
+ this.nextBtnTo = undefined
942
+ this.nextBtnTitle = ''
943
+ this.showStepNextBtn = false
944
+ this.stepNextBtnTo = undefined
945
+ this.stepNextBtnTitle = ''
946
+ this.stepNextBtnText = []
947
+ this.showPrevBtn = false
948
+ this.preBtnTo = undefined
949
+ this.preBtnTitle = ''
950
+ this.preBtnText = []
951
+
952
+ // 分类收集不同类型的actions
953
+ const submitActions = this.currentDirections.filter(item => item.type === 'submit')
954
+ const conditionalActions = this.currentDirections.filter(item => item.type === 'conditionalBranch')
955
+ const parallelActions = this.currentDirections.filter(item => item.type === 'parallelBranch')
956
+ const skipActions = this.currentDirections.filter(item => item.type === 'skip')
957
+ const backActions = this.currentDirections.filter(item => item.type === 'back')
958
+
959
+ // 处理提交按钮 - 优先级:submit > conditionalBranch > parallelBranch
960
+ if (submitActions.length > 0) {
961
+ this.showNextBtn = true
962
+ this.nextBtnTo = submitActions[0].to // 如果有多个submit,取第一个作为主要跳转目标
963
+ if (submitActions.length === 1) {
964
+ this.nextBtnTitle = '进行下一环节:' + this.getStepNameByStepId(submitActions[0].to)
965
+ } else {
966
+ this.nextBtnTitle = '将进入以下环节:' + submitActions.map(item => this.getStepNameByStepId(item.to)).join(' , ')
967
+ }
968
+ } else if (conditionalActions.length > 0) {
969
+ this.showNextBtn = true
970
+ this.nextBtnTo = conditionalActions[0].to // 条件分支的第一个作为主要跳转目标
971
+ const targetSteps = conditionalActions.map(item => this.getStepNameByStepId(item.to)).join(' , ')
972
+ this.nextBtnTitle = '后台判断后跳转到:' + targetSteps
973
+ } else if (parallelActions.length > 0) {
974
+ this.showNextBtn = true
975
+ this.nextBtnTo = parallelActions[0].to // 并行分支的第一个作为主要跳转目标
976
+ const targetSteps = parallelActions.map(item => this.getStepNameByStepId(item.to)).join(' , ')
977
+ this.nextBtnTitle = '将并行进入以下分支:' + targetSteps
978
+ }
979
+
980
+ // 处理跳过按钮
981
+ if (skipActions.length > 0) {
982
+ this.showStepNextBtn = true
983
+ this.stepNextBtnTo = skipActions[0].to
984
+ if (skipActions.length === 1) {
985
+ this.stepNextBtnTitle = '跳至:' + this.getStepNameByStepId(skipActions[0].to) + '环节'
986
+ this.stepNextBtnText.push('将跳过以下环节:')
987
+ for (let i = this.currentStepId; i < skipActions[0].to - 1; i++) {
988
+ this.stepNextBtnText.push(this.stepsDefine[i].name)
989
+ }
990
+ } else {
991
+ const targetSteps = skipActions.map(item => this.getStepNameByStepId(item.to)).join(' , ')
992
+ this.stepNextBtnTitle = '跳至:' + targetSteps
993
+ }
994
+ }
995
+
996
+ // 处理退回按钮
997
+ if (backActions.length > 0) {
998
+ const backAction = backActions[0] // 通常只有一个back action
999
+ for (let i = this.currentStepId - 1; i > 0; i--) {
1000
+ if (backAction.to >= i && this.stepsForChild.find(item => item.id === i)?.handler) {
1001
+ this.preBtnTo = i
1002
+ this.preBtnTitle = '回退至:' + this.getStepNameByStepId(i) + '环节'
1003
+ this.showPrevBtn = true
1004
+ break
1005
+ } else {
1006
+ this.preBtnText.push(this.getStepNameByStepId(i))
1007
+ }
1008
+ }
1009
+ if (this.preBtnText.length) {
1010
+ this.preBtnText.unshift('将跳过以下环节:')
1011
+ }
1012
+ }
1013
+ },
1014
+ // 获取表单字段实际值
1015
+ getRealKey (key, isHandleFormKey) {
1016
+ if (key === 'selected_id') return key
1017
+ if (isHandleFormKey) {
1018
+ return key.substring(key.indexOf('_') + 1)
1019
+ } else {
1020
+ return key
1021
+ }
1022
+ },
1023
+ // 加载完成
1024
+ resolveStep () {
1025
+ // 获取当前步骤的按钮组配置
1026
+ const currentStep = this.stepsDefine.find(item => item.id === this.activeStepId)
1027
+ if (currentStep && currentStep.properties && currentStep.properties.buttonGroup) {
1028
+ this.buttonGroup = currentStep.properties.buttonGroup
1029
+ } else {
1030
+ this.buttonGroup = null
1031
+ }
1032
+ this.loading = false
1033
+ },
1034
+ // 流程图组件给当前组件传值用,stepNo为用户点击的非当前步骤
1035
+ async activeStep (stepId) {
1036
+ // 开启加载
1037
+ this.loadingHistory = true
1038
+ this.activeStepId = stepId
1039
+ // 获取激活节点的步骤名
1040
+ this.activeStepName = this.getStepNameByStepId(stepId)
1041
+ const status = this.getStepStatusByStepId(stepId)
1042
+ // 清空回显数据
1043
+ this.formCompletedData = {}
1044
+ let formCompletedDataPreview = null
1045
+ this.getStepDefine(stepId)
1046
+ // 判断激活的节点,是不是待完成节点 (当前节点或者 当前节点状态是1的)
1047
+ if ((this.activeStepName !== this.currentStep.state && status !== 1) || this.workflowState) {
1048
+ // 获取激活节点历史数据,和字段定义
1049
+ await this.getCompletedFormData(stepId)
1050
+ // 将回显数据拷贝,避免引用传递
1051
+ formCompletedDataPreview = JSON.parse(JSON.stringify(this.formCompletedData))
1052
+ // 使用字段定义中内容,将回显数据的列名,替换为定义的中文名
1053
+ // 调整逻辑:formData中只显示流程配置表单中定义过的显示列,多余冗余的存储列不进行页面展示
1054
+ const formDataArr = []
1055
+ const dataObj = formCompletedDataPreview.data || {}
1056
+ const currentStepDefine = this.stepsDefine.find(item => item.id === stepId)
1057
+ const isKeyHandle = currentStepDefine?.properties?.form?.isKeyHandle || false
1058
+ for (let i = 0; i < this.targetStepDefine.length; i++) {
1059
+ const stepDefine = this.targetStepDefine[i]
1060
+ const key = this.getRealKey(stepDefine.model, isKeyHandle)
1061
+ if (Object.prototype.hasOwnProperty.call(dataObj, key)) {
1062
+ // 历史表单内容根据流程中配置的表单项顺序进行渲染,需要兼容表单项展示函数
1063
+ if (stepDefine.showFormItemFunc && !(await this.showFormItemFunc(stepDefine.showFormItemFunc, dataObj))) {
1064
+ continue
1065
+ }
1066
+ let value = dataObj[key]
1067
+ // 字典值处理
1068
+ if (stepDefine.formType === 'select' && stepDefine.selectType === 'key') {
1069
+ const dictList = this.$appdata.getDictionaryList(stepDefine.selectKey)
1070
+ const dictItem = dictList.find(item => item.value === value)
1071
+ value = dictItem ? dictItem.label : value
1072
+ }
1073
+ formDataArr.push({ label: stepDefine.name, value })
1074
+ }
1075
+ }
1076
+ // 如果一个都没匹配上,兼容旧逻辑:把原对象转成数组
1077
+ if (formDataArr.length === 0 && dataObj && typeof dataObj === 'object') {
1078
+ for (const key in dataObj) {
1079
+ if (Object.prototype.hasOwnProperty.call(dataObj, key)) {
1080
+ formDataArr.push({ label: key, value: dataObj[key] })
1081
+ }
1082
+ }
1083
+ }
1084
+ formCompletedDataPreview.data = formDataArr.length > 0 ? formDataArr : null
1085
+ if (!formCompletedDataPreview.data) {
1086
+ formCompletedDataPreview.data = null
1087
+ }
1088
+ // 备注
1089
+ formCompletedDataPreview.note = this.stepsForChild.find(item => item.id === stepId)?.note
1090
+ if (!formCompletedDataPreview.data && !formCompletedDataPreview.files.length && !formCompletedDataPreview.images.length && !formCompletedDataPreview.note) {
1091
+ formCompletedDataPreview = {}
1092
+ }
1093
+ this.formCompletedDataPreview = formCompletedDataPreview
1094
+ // 渲染已完成步骤的Tab
1095
+ const properties = this.stepsDefine.find(item => item.id === stepId).properties
1096
+ this.tabDesigner = properties.tabDesigner
1097
+ this.showTab = !!this.tabDesigner
1098
+ // 完成
1099
+ this.loadingHistory = false
1100
+ this.beforeStepActive = this.activeStepName !== this.currentStep.state
1101
+ } else {
1102
+ this.loadingHistory = false
1103
+ this.beforeStepActive = false
1104
+ if (!this.renderCurrentNode) {
1105
+ this.formCompletedDataPreview = null
1106
+ this.showTab = false
1107
+ this.beforeStepActive = true
1108
+ return
1109
+ }
1110
+ await this.buildComp(this.activeStepId)
1111
+ }
1112
+ },
1113
+ // 获取已经完成步骤的数据
1114
+ getCompletedFormData (stepId) {
1115
+ return postByServiceName(workFlowViewApi.getWorkFlowCompletedStepData, {
1116
+ workflowId: this.workflowId,
1117
+ stepId: stepId
1118
+ })
1119
+ .then(
1120
+ res => {
1121
+ this.formCompletedData = res
1122
+ },
1123
+ err => {
1124
+ console.log(err)
1125
+ }
1126
+ )
1127
+ },
1128
+ // 获取步骤定义表中,当前步骤定义
1129
+ getStepDefine (stepId) {
1130
+ const stepName = this.getStepNameByStepId(stepId)
1131
+ this.targetStepDefine = this.getSingleStepDefine(stepName).formJson
1132
+ },
1133
+ // 获取提交步骤的额外数据
1134
+ getApplyStepExtraData (stepId) {
1135
+ // 验证人员选择 - 只有在需要显示人员选择器的情况下才验证
1136
+ // 判断条件与模板中的 WorkflowPersonSelector 显示条件保持一致
1137
+ const shouldShowPersonSelector = !this.isBranchLastNode.isBranchNode || this.isBranchLastNode.isLastBranch
1138
+
1139
+ if (shouldShowPersonSelector && this.needSelectPerson) {
1140
+ if (this.needMultipleBranchSelection) {
1141
+ // 多分支情况:检查是否所有需要的分支都选择了人员
1142
+ const missingSelections = this.branchNodes.filter(node => !this.branchChargePersons[node.stepId])
1143
+ if (missingSelections.length > 0) {
1144
+ const missingNames = missingSelections.map(node => node.stepName).join('、')
1145
+ this.$message.error(`请设置以下节点的处理人:${missingNames}`)
1146
+ return false
1147
+ }
1148
+ } else {
1149
+ // 单分支情况:检查是否选择了处理人
1150
+ if (!this.checkedChargePerson) {
1151
+ this.$message.error('请设置下一环节处理人')
1152
+ return false
1153
+ }
1154
+ }
1155
+ }
1156
+
1157
+ // 统一获取目标步骤IDs
1158
+ let stepIds = []
1159
+ if (this.needMultipleBranchSelection) {
1160
+ // 多分支选择:获取所有分支的目标stepId(包括不需要选择人员的)
1161
+ if (!this.currentBranchActions) {
1162
+ this.currentBranchActions = this.getBranchActions()
1163
+ }
1164
+ stepIds = this.currentBranchActions.allBranchActions.map(action => action.to)
1165
+ } else if (this.calculatedTargetNode) {
1166
+ // 条件判断节点:使用计算出的目标节点
1167
+ stepIds = [this.calculatedTargetNode]
1168
+ } else {
1169
+ // 普通节点:使用传入的stepId
1170
+ stepIds = [stepId]
1171
+ }
1172
+ // 处理bug 有的时候没带到 branchChargePersons 先循环在同一地方处理
1173
+ stepIds.forEach(stepItemId => {
1174
+ if (!this.branchChargePersons[stepItemId]) {
1175
+ const chargePerson = this.stepsForChild.find(item => item.id === stepItemId)?.properties?.chargePerson
1176
+ this.branchChargePersons[stepItemId] = this.normalizeChargePersonFormat(chargePerson)
1177
+ }
1178
+ })
1179
+
1180
+ return {
1181
+ workflowId: this.workflowId,
1182
+ activeStepId: this.activeStepId,
1183
+ stepId, // 当前步骤ID
1184
+ stepIds, // 目标步骤IDs数组(统一格式)
1185
+ name: this.getStepNameByStepId(stepId),
1186
+ handler: this.getStepHandler(),
1187
+ handlerId: this.checkedChargePerson,
1188
+ needSelectPerson: this.needSelectPerson,
1189
+ personList: this.chargePerson.personList,
1190
+ deadline: this.deadline,
1191
+ submitUser: this.currUser.name,
1192
+ submitUserId: this.currUser.id,
1193
+ branchChargePersons: this.branchChargePersons
1194
+ }
1195
+ },
1196
+
1197
+ // 获取当前选择的负责人
1198
+ getStepHandler () {
1199
+ let stepHandler
1200
+
1201
+ if (this.needMultipleBranchSelection) {
1202
+ // 多分支情况:返回所有分支的人员信息
1203
+ const selectedHandlers = []
1204
+ for (const node of this.branchNodes) {
1205
+ const branchData = this.branchChargePersons[node.stepId]
1206
+
1207
+ if (node.needSelectPerson && branchData) {
1208
+ // 需要选择人员的分支:显示选中的人员
1209
+ const personName = this.getBranchPersonName(node.stepId)
1210
+ selectedHandlers.push(`${node.stepName}:${personName}`)
1211
+ } else if (!node.needSelectPerson && branchData) {
1212
+ // 不需要选择人员的分支:显示角色/部门配置
1213
+ if (branchData.personList && branchData.personList.length > 0) {
1214
+ const personNames = branchData.personList.map(item => item.name).join(',')
1215
+ selectedHandlers.push(`${node.stepName}:${personNames}`)
1216
+ }
1217
+ }
1218
+ }
1219
+ stepHandler = selectedHandlers.join(';')
1220
+ } else {
1221
+ // 单分支情况:原有逻辑
1222
+ if (this.checkedChargePerson) {
1223
+ // 使用 value 找到对应的 label
1224
+ stepHandler = this.chargePersonOptions.find(item => item.value === this.checkedChargePerson)?.label
1225
+ } else if (this.chargePerson.personList && this.chargePerson.personList.length > 0) {
1226
+ stepHandler = this.chargePerson.personList.map(item => item.name).join(',')
1227
+ }
1228
+ }
1229
+
1230
+ return stepHandler
1231
+ },
1232
+
1233
+ // 获取分支节点选择的人员姓名
1234
+ getBranchPersonName (stepId) {
1235
+ const personId = this.branchChargePersons[stepId]
1236
+ if (!personId) return ''
1237
+
1238
+ const node = this.branchNodes.find(n => n.stepId === stepId)
1239
+ if (!node) return ''
1240
+
1241
+ const person = node.chargePersonOptions.find(p => p.value === personId)
1242
+ return person ? person.label : ''
1243
+ },
1244
+ // 生成工作流日志步骤变化描述
1245
+ generateStepChangeText (fromStepId, toStepId) {
1246
+ // 如果是多分支场景,toStepId可能是数组或字符串
1247
+ if (this.needMultipleBranchSelection && Array.isArray(toStepId)) {
1248
+ const targetSteps = toStepId.map(id => `第${id}步: ${this.getStepNameByStepId(id)}`).join('、')
1249
+ return `第${fromStepId}步: ${this.getStepNameByStepId(fromStepId)} --> ${targetSteps}`
1250
+ } else if (this.needMultipleBranchSelection && typeof toStepId === 'string') {
1251
+ // 如果传入的是目标步骤名称字符串
1252
+ return `第${fromStepId}步: ${this.getStepNameByStepId(fromStepId)} --> ${toStepId}`
1253
+ } else {
1254
+ // 单步骤场景
1255
+ return `第${fromStepId}步: ${this.getStepNameByStepId(fromStepId)} --> 第${toStepId}步: ${this.getStepNameByStepId(toStepId)}`
1256
+ }
1257
+ },
1258
+
1259
+ // 生成多分支场景的步骤变化描述
1260
+ generateBranchStepChangeText (fromStepId) {
1261
+ if (!this.needMultipleBranchSelection) {
1262
+ return this.generateStepChangeText(fromStepId, this.nextBtnTo)
1263
+ }
1264
+
1265
+ // 使用所有分支节点生成描述
1266
+ const targetSteps = this.branchNodes.map(node => `第${node.stepId}步: ${node.stepName}`).join('、')
1267
+ return `第${fromStepId}步: ${this.getStepNameByStepId(fromStepId)} --> ${targetSteps}`
1268
+ },
1269
+
1270
+ generateStepChange (fromStepId, toStepId) {
1271
+ // 获取目标步骤IDs数组
1272
+ let stepIds = []
1273
+
1274
+ if (this.needMultipleBranchSelection) {
1275
+ // 多分支选择:获取所有分支的目标stepId(包括不需要选择人员的)
1276
+ if (!this.currentBranchActions) {
1277
+ this.currentBranchActions = this.getBranchActions()
1278
+ }
1279
+ stepIds = this.currentBranchActions.allBranchActions.map(action => action.to)
1280
+ } else if (this.calculatedTargetNode) {
1281
+ // 条件判断节点:使用计算出的目标节点
1282
+ stepIds = [this.calculatedTargetNode]
1283
+ } else {
1284
+ // 普通节点:使用传入的stepId
1285
+ stepIds = [toStepId]
1286
+ }
1287
+
1288
+ return {
1289
+ formStepId: fromStepId,
1290
+ fromStepId,
1291
+ stepId: toStepId,
1292
+ stepIds: stepIds,
1293
+ formStep: this.getStepNameByStepId(fromStepId),
1294
+ fromStep: this.getStepNameByStepId(fromStepId),
1295
+ toStep: this.getStepNameByStepId(stepIds[0]),
1296
+ successStepId: this.stepsDefine[this.stepsDefine.length - 1].id,
1297
+ successStep: this.stepsDefine[this.stepsDefine.length - 1].name
1298
+ }
1299
+ },
1300
+ // 保存工作流日志
1301
+ saveWorkflowLog (operation, desc, extra) {
1302
+ postByServiceName(workFlowViewApi.saveWorkFlowLog, {
1303
+ workflowId: this.workflowId,
1304
+ operation,
1305
+ desc,
1306
+ operator: this.currUser.name,
1307
+ notes: '',
1308
+ setHandler: '',
1309
+ setDeadline: '',
1310
+ ...extra
1311
+ })
1312
+ },
1313
+ // 获取默认截止时间
1314
+ getDefaultDeadline (day = 1) {
1315
+ const date = new Date()
1316
+ date.setDate(date.getDate() + day)
1317
+ date.setHours(date.getHours() + 2)
1318
+ return formatDate(date, 'yyyy-MM-dd hh:mm')
1319
+ },
1320
+ // 验证截止时间
1321
+ checkDeadline (alert) {
1322
+ const deadline = moment(this.deadline)
1323
+ if (deadline.isAfter(this.completeTime, 'day')) {
1324
+ this.deadlineValidateStatus = 'error'
1325
+ this.deadlineHelp = '不能超过任务限定完成时间'
1326
+ if (alert) {
1327
+ this.$message.error('下一环节截止时间不能超过任务限定完成时间,如需设置,请联系发起人修改任务完成时间', 5)
1328
+ }
1329
+ return false
1330
+ }
1331
+ if (deadline.diff(moment(), 'hours') < 1) {
1332
+ this.deadlineValidateStatus = 'error'
1333
+ this.deadlineHelp = '下一环节截止时间只能在1小时之后'
1334
+ return false
1335
+ }
1336
+ this.deadlineValidateStatus = 'success'
1337
+ this.deadlineHelp = ''
1338
+ return true
1339
+ },
1340
+ // 操作类型单选按钮改变时重新设置负责人选择框
1341
+ async handleOperationTypeChange (event) {
1342
+ this.checkedChargePerson = undefined
1343
+ this.branchChargePersons = {}
1344
+ // 重新分析分支节点
1345
+ await this.analyzeBranchNodes()
1346
+ },
1347
+
1348
+ // 处理动态按钮点击
1349
+ handleCustomButtonClick (button) {
1350
+ try {
1351
+ // 执行自定义函数
1352
+ if (button.func) {
1353
+ const result = executeStrFunctionByContext(this, button.func, [this.details, this.$refs.xAddForm.form, util, runLogic, getConfigByNameAsync])
1354
+ if (result) {
1355
+ // 如果返回true,执行对应的操作
1356
+ if (button.text === '提交') {
1357
+ this.nextClick()
1358
+ } else if (button.text === '取消') {
1359
+ this.$emit('cancel')
1360
+ }
1361
+ }
1362
+ }
1363
+ } catch (error) {
1364
+ console.error('执行自定义按钮函数失败:', error)
1365
+ this.$message.error('执行操作失败')
1366
+ }
1367
+ },
1368
+ // 表单项展示函数--用来渲染历史节点数据时和填写表单显示内容同步
1369
+ async showFormItemFunc (func, form) {
1370
+ try {
1371
+ if (func) {
1372
+ // 一般展示项函数中不应该存在setForm函数 先屏蔽this.setForm和this.attr的传递还有在this上下文指向不同可能存在异常 流程表单的展示项函数尽量功能单一。有异常默认进行展示(先兼容到这后续有问题进行调整)
1373
+ const obj = executeStrFunctionByContext(this, func, [form, null, null, util, '新增/修改'])
1374
+ // 判断是 bool 还是 obj 兼容
1375
+ if (typeof obj === 'boolean') {
1376
+ return obj
1377
+ } else if (obj && typeof obj === 'object') {
1378
+ // obj 是一个对象,并且不是数组
1379
+ return obj?.show
1380
+ }
1381
+ } else {
1382
+ return true
1383
+ }
1384
+ } catch (e) {
1385
+ return true
1386
+ }
1387
+ },
1388
+ // 检查按钮是否显示
1389
+ checkButtonVisible (button) {
1390
+ try {
1391
+ if (button.customFunction) {
1392
+ return executeStrFunctionByContext(this, button.customFunction, [this.details, this.$refs.xAddForm.form, util, runLogic, getConfigByNameAsync])
1393
+ }
1394
+ return true
1395
+ } catch (error) {
1396
+ console.error('执行按钮显示函数失败:', error)
1397
+ return false
1398
+ }
1399
+ },
1400
+ formItemEmitFunc (func, data, value) {
1401
+ this.$emit('x-form-item-emit-func', func, data, value)
1402
+ },
1403
+ // 检查条件表达式是否包含WF_RESULT
1404
+ checkIfContainsWfResult () {
1405
+ const conditionalActions = this.currentDirections.filter(action => action.type === 'conditionalBranch')
1406
+ if (conditionalActions.length === 0) return false
1407
+
1408
+ return conditionalActions.some(action => {
1409
+ return action.expression && action.expression.includes('WF_RESULT')
1410
+ })
1411
+ },
1412
+
1413
+ // 分析分支节点并设置选择框
1414
+ async analyzeBranchNodes () {
1415
+ try {
1416
+ // 初始化状态
1417
+ this.resetBranchSelection()
1418
+
1419
+ // 获取所有类型的分支动作并缓存
1420
+ this.currentBranchActions = this.getBranchActions()
1421
+
1422
+ // 如果没有任何分支,处理普通流程
1423
+ if (!this.currentBranchActions.hasAnyBranch) {
1424
+ await this.handleNormalFlow()
1425
+ return
1426
+ }
1427
+
1428
+ // 判断是否需要多分支选择
1429
+ this.needMultipleBranchSelection = this.shouldUseMultipleBranchSelection(this.currentBranchActions)
1430
+
1431
+ if (this.needMultipleBranchSelection) {
1432
+ // 需要为多个分支预先选择人员
1433
+ await this.setupMultipleBranchSelection(this.currentBranchActions.allBranchActions)
1434
+ } else {
1435
+ // 可以前台实时计算的条件分支
1436
+ await this.calculateTargetNodeFromForm(this.currentBranchActions.conditionalActions)
1437
+ }
1438
+ } catch (error) {
1439
+ console.error('分析分支节点失败:', error)
1440
+ this.$message.error('工作流分支配置异常,请联系管理员')
1441
+ // 降级处理:使用普通流程
1442
+ await this.handleNormalFlow()
1443
+ }
1444
+ },
1445
+
1446
+ // 重置分支选择状态
1447
+ resetBranchSelection () {
1448
+ this.branchNodes = []
1449
+ this.branchChargePersons = {}
1450
+ this.needMultipleBranchSelection = false
1451
+ this.calculatedTargetNode = null
1452
+ this.currentBranchActions = null
1453
+ },
1454
+
1455
+ // 获取分支动作分类
1456
+ getBranchActions () {
1457
+ const conditionalActions = this.currentDirections.filter(action => action.type === 'conditionalBranch')
1458
+ const parallelActions = this.currentDirections.filter(action => action.type === 'parallelBranch')
1459
+ const allBranchActions = [...conditionalActions, ...parallelActions]
1460
+
1461
+ return {
1462
+ conditionalActions,
1463
+ parallelActions,
1464
+ allBranchActions,
1465
+ hasAnyBranch: allBranchActions.length > 0
1466
+ }
1467
+ },
1468
+
1469
+ // 判断是否应该使用多分支选择模式
1470
+ shouldUseMultipleBranchSelection (branchActions) {
1471
+ // 情况1: 有并行分支
1472
+ if (branchActions.parallelActions.length > 0) {
1473
+ return true
1474
+ }
1475
+
1476
+ // 情况2: 条件分支包含WF_RESULT(后台结果决定)
1477
+ if (branchActions.conditionalActions.length > 0) {
1478
+ return this.checkIfContainsWfResult()
1479
+ }
1480
+
1481
+ return false
1482
+ },
1483
+
1484
+ // 根据表单数据计算目标节点
1485
+ async calculateTargetNodeFromForm (conditionalActions = null) {
1486
+ if (!conditionalActions) {
1487
+ conditionalActions = this.currentDirections.filter(action => action.type === 'conditionalBranch')
1488
+ }
1489
+
1490
+ if (conditionalActions.length === 0) {
1491
+ // 如果当前节点不是在分支流程中,才清空人员选择
1492
+ // 避免在并行分支节点中误清除人员选择框
1493
+ const currentStep = this.stepsForChild.find(item => item.id === this.activeStepId)
1494
+ const isInBranch = currentStep?.properties?.branchPath
1495
+
1496
+ if (!isInBranch) {
1497
+ this.clearPersonSelection()
1498
+ }
1499
+ return
1500
+ }
1501
+
1502
+ try {
1503
+ const formData = this.$refs.xAddForm?.form || {}
1504
+
1505
+ // 遍历条件找到匹配的
1506
+ for (const action of conditionalActions) {
1507
+ if (action.expression) {
1508
+ const result = await this.evaluateExpression(action.expression, formData)
1509
+ if (result) {
1510
+ this.calculatedTargetNode = action.to
1511
+ await this.setupSingleTargetPersonSelection(action.to)
1512
+ return
1513
+ }
1514
+ }
1515
+ }
1516
+ console.log('this.calculatedTargetNode', this.calculatedTargetNode)
1517
+ // 如果没有匹配的条件,清空选择
1518
+ this.clearPersonSelection()
1519
+ } catch (error) {
1520
+ console.warn('计算目标节点失败:', error)
1521
+ this.clearPersonSelection()
1522
+ }
1523
+ },
1524
+
1525
+ // 清空人员选择
1526
+ clearPersonSelection () {
1527
+ this.calculatedTargetNode = null
1528
+ this.needSelectPerson = false
1529
+ this.chargePersonOptions = []
1530
+ this.checkedChargePerson = undefined
1531
+ },
1532
+
1533
+ // 设置单个目标节点的人员选择
1534
+ async setupSingleTargetPersonSelection (stepId) {
1535
+ const stepDefine = this.stepsDefine.find(step => step.id === stepId)
1536
+
1537
+ if (!stepDefine?.properties?.chargePerson?.needSelectPerson) {
1538
+ this.needSelectPerson = false
1539
+ this.chargePersonOptions = []
1540
+ return
1541
+ }
1542
+
1543
+ // 设置人员选择
1544
+ this.chargePerson = stepDefine.properties.chargePerson
1545
+ this.checkedChargePerson = undefined
1546
+ this.chargePersonOptions = await this.getChargePersonOptionsForStep(stepId)
1547
+
1548
+ // 如果只有一个选项,自动选中
1549
+ if (this.chargePersonOptions.length === 1) {
1550
+ this.checkedChargePerson = this.chargePersonOptions[0].value
1551
+ }
1552
+
1553
+ this.needSelectPerson = true
1554
+ },
1555
+
1556
+ // 表单数据变化处理函数(将通过provide传递给表单组件)
1557
+ async handleFormDataChange (formData) {
1558
+ // 只有在不是多分支选择模式且当前活动步骤有条件分支动作时才重新计算
1559
+ if (!this.needMultipleBranchSelection && this.currentDirections.some(action => action.type === 'conditionalBranch')) {
1560
+ await this.calculateTargetNodeFromForm()
1561
+ }
1562
+ },
1563
+
1564
+ // 表达式评估 - 使用 LogicRunner
1565
+ async evaluateExpression (expression, formData) {
1566
+ try {
1567
+ // 构建参数对象,传递当前表单数据
1568
+ const params = {
1569
+ WF_FORM: { ...formData }
1570
+ }
1571
+
1572
+ // 使用 LogicRunner 执行表达式
1573
+ const result = await LogicRunner.runExpression(expression, params)
1574
+ return result
1575
+ } catch (error) {
1576
+ console.warn('表达式评估失败:', expression, error)
1577
+ return false
1578
+ }
1579
+ },
1580
+
1581
+ // 获取指定步骤的人员选项
1582
+ async getChargePersonOptionsForStep (stepId) {
1583
+ const define = this.stepsDefine.find(item => item.id === stepId)
1584
+ if (!define?.properties?.chargePerson) return []
1585
+
1586
+ const chargePerson = define.properties.chargePerson
1587
+ this.chargePerson = this.normalizeChargePersonFormat(chargePerson)
1588
+
1589
+ if (!chargePerson.needSelectPerson || !chargePerson.personList) return []
1590
+
1591
+ // 获取所有用户信息
1592
+ const allUser = await postByServiceName(commonApi.getAllUserOptionList, {})
1593
+
1594
+ // 根据配置筛选用户
1595
+ const options = this.filterUsersByPersonConfig(chargePerson.personList, allUser)
1596
+
1597
+ // 去重处理
1598
+ return Array.from(new Map(options.map(item => [item.value, item])).values())
1599
+ },
1600
+
1601
+ // 标准化人员配置格式(兼容旧格式)
1602
+ normalizeChargePersonFormat (chargePerson) {
1603
+ if (chargePerson.role || chargePerson.department) {
1604
+ chargePerson.needSelectPerson = true
1605
+ chargePerson.personList = [{
1606
+ type: chargePerson.role ? 'role' : 'department',
1607
+ name: chargePerson.role || chargePerson.department
1608
+ }]
1609
+ }
1610
+ return chargePerson
1611
+ },
1612
+
1613
+ // 根据人员配置筛选用户
1614
+ filterUsersByPersonConfig (personList, allUsers) {
1615
+ return personList.reduce((acc, personItem) => {
1616
+ let filteredUsers = []
1617
+
1618
+ if (personItem.type === 'role') {
1619
+ filteredUsers = allUsers.filter(user =>
1620
+ user.rolestr && user.rolestr.split(',').includes(personItem.name)
1621
+ ).map(user => ({
1622
+ label: user.label,
1623
+ value: user.value
1624
+ }))
1625
+ } else if (personItem.type === 'department') {
1626
+ filteredUsers = allUsers.filter(user =>
1627
+ user.depname === personItem.name
1628
+ ).map(user => ({
1629
+ label: user.label,
1630
+ value: user.value
1631
+ }))
1632
+ }
1633
+
1634
+ return [...acc, ...filteredUsers]
1635
+ }, [])
1636
+ },
1637
+
1638
+ // 设置多分支人员选择
1639
+ async setupMultipleBranchSelection (branchActions) {
1640
+ this.branchNodes = []
1641
+ this.branchChargePersons = {}
1642
+ let hasPersonSelection = false
1643
+
1644
+ for (const action of branchActions) {
1645
+ const stepDefine = this.stepsDefine.find(step => step.id === action.to)
1646
+ const chargePerson = stepDefine?.properties?.chargePerson
1647
+
1648
+ // 所有分支节点都加入branchNodes,保持数据结构完整
1649
+ const nodeData = {
1650
+ stepId: action.to,
1651
+ stepName: this.getStepNameByStepId(action.to),
1652
+ chargePerson: chargePerson,
1653
+ needSelectPerson: chargePerson?.needSelectPerson || false,
1654
+ chargePersonOptions: []
1655
+ }
1656
+
1657
+ if (chargePerson?.needSelectPerson) {
1658
+ // 需要选择人员的分支
1659
+ const chargePersonOptions = await this.getChargePersonOptionsForStep(action.to)
1660
+ nodeData.chargePersonOptions = chargePersonOptions
1661
+
1662
+ // 初始化选择值
1663
+ this.branchChargePersons[action.to] = undefined
1664
+ hasPersonSelection = true
1665
+ } else {
1666
+ // 不需要选择人员的分支,直接存储配置
1667
+ this.branchChargePersons[action.to] = chargePerson
1668
+ }
1669
+
1670
+ this.branchNodes.push(nodeData)
1671
+ }
1672
+
1673
+ // 只有当存在需要选择人员的分支时才显示选择区域
1674
+ this.needSelectPerson = hasPersonSelection
1675
+ },
1676
+
1677
+ // 处理普通单线流程(没有分支的情况)
1678
+ async handleNormalFlow () {
1679
+ const targetStepId = this.operationType === 'skip' ? this.stepNextBtnTo : this.nextBtnTo
1680
+
1681
+ this.calculatedTargetNode = targetStepId
1682
+ const stepDefine = this.stepsDefine.find(step => step.id === targetStepId)
1683
+
1684
+ if (!stepDefine) {
1685
+ console.warn('未找到目标步骤定义:', targetStepId)
1686
+ this.clearPersonSelection()
1687
+ return
1688
+ }
1689
+
1690
+ const defineProperties = stepDefine.properties
1691
+ this.chargePerson = defineProperties?.chargePerson
1692
+
1693
+ // 兼容旧格式
1694
+ if (defineProperties.chargePerson) {
1695
+ defineProperties.chargePerson = this.normalizeChargePersonFormat(defineProperties.chargePerson)
1696
+ }
1697
+
1698
+ if (defineProperties?.chargePerson?.needSelectPerson) {
1699
+ await this.setupSingleTargetPersonSelection(targetStepId)
1700
+ // 确保 branchChargePersons 中有该节点的数据结构
1701
+ this.branchChargePersons[targetStepId] = {
1702
+ handler: '',
1703
+ handlerId: undefined,
1704
+ ...defineProperties.chargePerson
1705
+ }
1706
+ } else {
1707
+ // 不需要选择人员的情况,直接存储配置
1708
+ this.branchChargePersons[targetStepId] = defineProperties?.chargePerson || {}
1709
+ this.needSelectPerson = false
1710
+ this.chargePersonOptions = []
1711
+ }
1712
+ }
1713
+ },
1714
+ watch: {}
1715
+ }
1716
+ </script>
1717
+ <style lang="less" scoped>
1718
+ .complete-data-title {
1719
+ margin-top: 8px;
1720
+ margin-bottom: 8px;
1721
+ }
1722
+
1723
+ :deep(.ant-result) {
1724
+ padding: 0;
1725
+ }
1726
+
1727
+ .descriptionPreviewItem {
1728
+ margin-bottom: 22px;
1729
+
1730
+ :deep(.ant-descriptions-view) {
1731
+ overflow: visible;
1732
+ }
1733
+ }
1734
+
1735
+ .allWidth {
1736
+ :deep(.ant-descriptions-item-content) {
1737
+ width: 100%;
1738
+ }
1739
+ }
1740
+
1741
+ .descriptionTitle {
1742
+ position: relative;
1743
+ padding-left: 12px;
1744
+
1745
+ &::before {
1746
+ content: '';
1747
+ position: absolute;
1748
+ left: 0;
1749
+ top: 50%;
1750
+ transform: translateY(-50%);
1751
+ width: 4px;
1752
+ height: 16px;
1753
+ background-color: @primary-color;
1754
+ border-radius: 2px;
1755
+ }
1756
+ }
1757
+ </style>