vue2-client 1.15.86 → 1.15.88

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 (377) hide show
  1. package/.editorconfig +9 -9
  2. package/.env +20 -20
  3. package/.env.development +1 -1
  4. package/.env.iot +19 -19
  5. package/.env.message +19 -19
  6. package/.env.revenue +19 -19
  7. package/.env.runtime +19 -19
  8. package/.eslintrc.json +5 -5
  9. package/CLAUDE.md +89 -89
  10. package/README.md +65 -65
  11. package/babel.config.js +21 -21
  12. package/docs/Logic/345/207/275/346/225/260/344/275/277/347/224/250/347/233/270/345/205/263.md +46 -46
  13. package/docs/notice.md +22 -22
  14. package/docs//345/207/275/346/225/260/344/275/277/347/224/250/347/233/270/345/205/263.md +179 -179
  15. package/jest.config.js +22 -22
  16. package/package.json +111 -111
  17. package/src/App.vue +196 -196
  18. package/src/ReportView.js +13 -13
  19. package/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox.vue +532 -532
  20. package/src/base-client/components/common/AddressSearchCombobox/index.js +3 -3
  21. package/src/base-client/components/common/AmapMarker/index.js +3 -3
  22. package/src/base-client/components/common/CitySelect/CitySelect.vue +376 -376
  23. package/src/base-client/components/common/CitySelect/demo.vue +43 -43
  24. package/src/base-client/components/common/ColorPickerCombobox/ColorPickerCombobox.vue +99 -99
  25. package/src/base-client/components/common/ColorPickerCombobox/demo.vue +34 -34
  26. package/src/base-client/components/common/FormGroupEdit/FormGroupEdit.vue +146 -146
  27. package/src/base-client/components/common/JSONToTree/index.js +3 -3
  28. package/src/base-client/components/common/Upload/Upload.vue +323 -323
  29. package/src/base-client/components/common/XAddForm/index.js +3 -3
  30. package/src/base-client/components/common/XAddForm/index.md +61 -61
  31. package/src/base-client/components/common/XAddNativeForm/XAddNativeForm.vue +1169 -1169
  32. package/src/base-client/components/common/XAddNativeForm/demo.vue +54 -54
  33. package/src/base-client/components/common/XAddNativeForm/index.js +3 -3
  34. package/src/base-client/components/common/XAddReport/XAddReport.vue +212 -212
  35. package/src/base-client/components/common/XBadge/index.js +3 -3
  36. package/src/base-client/components/common/XBadge/index.md +39 -39
  37. package/src/base-client/components/common/XButtons/XButtons.vue +284 -284
  38. package/src/base-client/components/common/XCalendar/XCalendar.vue +369 -369
  39. package/src/base-client/components/common/XCalendar/index.md +284 -284
  40. package/src/base-client/components/common/XCard/index.js +3 -3
  41. package/src/base-client/components/common/XCard/index.md +43 -43
  42. package/src/base-client/components/common/XCardSet/XCardSet.vue +300 -300
  43. package/src/base-client/components/common/XCollapse/XCollapse.vue +354 -354
  44. package/src/base-client/components/common/XConversation/XConversation.vue +576 -576
  45. package/src/base-client/components/common/XConversation/XConversationDemo.vue +28 -28
  46. package/src/base-client/components/common/XDataCard/XDataCard.vue +629 -629
  47. package/src/base-client/components/common/XDatePicker/index.vue +276 -276
  48. package/src/base-client/components/common/XDescriptions/XDescriptions.vue +174 -174
  49. package/src/base-client/components/common/XDescriptions/XDescriptionsGroup.vue +314 -314
  50. package/src/base-client/components/common/XDescriptions/demo.vue +51 -51
  51. package/src/base-client/components/common/XForm/XForm.vue +420 -420
  52. package/src/base-client/components/common/XForm/XFormItem.vue +1474 -1474
  53. package/src/base-client/components/common/XForm/XTreeSelect.vue +276 -276
  54. package/src/base-client/components/common/XForm/demo.vue +105 -105
  55. package/src/base-client/components/common/XForm/index.js +3 -3
  56. package/src/base-client/components/common/XFormCol/XFormCol.vue +157 -157
  57. package/src/base-client/components/common/XFormCol/index.js +3 -3
  58. package/src/base-client/components/common/XFormCol/index.md +35 -35
  59. package/src/base-client/components/common/XFormGroup/XFormGroup.vue +301 -301
  60. package/src/base-client/components/common/XFormGroup/demo.vue +41 -41
  61. package/src/base-client/components/common/XFormTable/XFormTable.vue +938 -938
  62. package/src/base-client/components/common/XFormTable/demo.vue +87 -87
  63. package/src/base-client/components/common/XFormTable/index.js +3 -3
  64. package/src/base-client/components/common/XImportExcel/XImportExcel.vue +174 -174
  65. package/src/base-client/components/common/XImportExcel/index.js +3 -3
  66. package/src/base-client/components/common/XImportExcel/index.md +38 -38
  67. package/src/base-client/components/common/XInput/XInput.vue +128 -128
  68. package/src/base-client/components/common/XInput/index.js +3 -3
  69. package/src/base-client/components/common/XInput/index.md +97 -97
  70. package/src/base-client/components/common/XIntervalPicker/XIntervalPicker.vue +121 -121
  71. package/src/base-client/components/common/XLicensePlate/index.js +3 -3
  72. package/src/base-client/components/common/XLicensePlate/index.md +38 -38
  73. package/src/base-client/components/common/XPrint/Demo.vue +41 -41
  74. package/src/base-client/components/common/XPrint/PrintBill.vue +308 -308
  75. package/src/base-client/components/common/XRate/demo.vue +102 -102
  76. package/src/base-client/components/common/XRate/index.vue +149 -149
  77. package/src/base-client/components/common/XReport/XReport.vue +963 -963
  78. package/src/base-client/components/common/XReport/XReportDemo.vue +70 -70
  79. package/src/base-client/components/common/XReport/XReportTrGroup.vue +1005 -1005
  80. package/src/base-client/components/common/XReport/index.md +103 -103
  81. package/src/base-client/components/common/XReportDrawer/XReportDrawer.vue +201 -201
  82. package/src/base-client/components/common/XReportGrid/XReport.vue +1075 -1075
  83. package/src/base-client/components/common/XReportGrid/XReportDemo.vue +44 -44
  84. package/src/base-client/components/common/XReportGrid/XReportDesign.vue +620 -620
  85. package/src/base-client/components/common/XReportGrid/XReportTrGroup.vue +723 -723
  86. package/src/base-client/components/common/XReportGrid/print.js +184 -184
  87. package/src/base-client/components/common/XTab/XTab.vue +299 -299
  88. package/src/base-client/components/common/XTable/ExportExcel.vue +283 -283
  89. package/src/base-client/components/common/XTable/XTable.vue +1599 -1599
  90. package/src/base-client/components/common/XTable/XTableWrapper.vue +597 -597
  91. package/src/base-client/components/common/XTable/index.js +3 -3
  92. package/src/base-client/components/common/XTimeline/XTimeline.vue +358 -358
  93. package/src/base-client/components/common/XTimeline/index.md +191 -191
  94. package/src/base-client/components/common/XTree/XTreePro.vue +452 -452
  95. package/src/base-client/components/common/XTreeOne/index.js +3 -3
  96. package/src/base-client/components/common/XUploadFilesView/index.vue +485 -485
  97. package/src/base-client/components/his/XCharge/XCharge.vue +238 -238
  98. package/src/base-client/components/his/XCheckbox/XCheckbox.vue +105 -105
  99. package/src/base-client/components/his/XCheckbox/index.md +253 -253
  100. package/src/base-client/components/his/XHDescriptions/XHDescriptions.vue +430 -430
  101. package/src/base-client/components/his/XHDescriptions/index.md +217 -217
  102. package/src/base-client/components/his/XHisEditor/XHisEditor.vue +629 -629
  103. package/src/base-client/components/his/XHisEditor/diagnosisAutocomplete.js +263 -263
  104. package/src/base-client/components/his/XList/XList.vue +495 -495
  105. package/src/base-client/components/his/XQuestionnaire/XQuestionnaire.json +3 -3
  106. package/src/base-client/components/his/XQuestionnaire/XQuestionnaire.vue +106 -106
  107. package/src/base-client/components/his/XQuestionnaire/XQuestionnaireDemo.vue +51 -51
  108. package/src/base-client/components/his/XQuestionnaire/XQuestionnaireItem.vue +269 -269
  109. package/src/base-client/components/his/XRadio/XRadio.vue +125 -125
  110. package/src/base-client/components/his/XRadio/index.md +234 -234
  111. package/src/base-client/components/his/XSelect/XSelect.vue +72 -72
  112. package/src/base-client/components/his/XShiftSchedule/XShiftSchedule.vue +234 -234
  113. package/src/base-client/components/his/XShiftSchedule/dome.vue +29 -29
  114. package/src/base-client/components/his/XSidebar/XSidebar.vue +240 -240
  115. package/src/base-client/components/his/XTextCard/XTextCard.vue +207 -207
  116. package/src/base-client/components/his/XTimeSelect/XTimeSelect.vue +162 -162
  117. package/src/base-client/components/his/XTimeSelect/XTimeSelectDemo.vue +23 -23
  118. package/src/base-client/components/his/XTitle/README.md +113 -113
  119. package/src/base-client/components/his/XTitle/XTitle.vue +123 -123
  120. package/src/base-client/components/his/XTreeRows/TreeNode.vue +107 -107
  121. package/src/base-client/components/his/XTreeRows/XTreeRows.vue +307 -307
  122. package/src/base-client/components/his/threeTestOrders/dome.vue +68 -68
  123. package/src/base-client/components/his/threeTestOrders/editor.vue +111 -111
  124. package/src/base-client/components/his/threeTestOrders/textBox.vue +457 -457
  125. package/src/base-client/components/his/threeTestOrders/threeTestOrders.vue +475 -475
  126. package/src/base-client/components/layout/XPageView/RenderRow.vue +88 -88
  127. package/src/base-client/components/layout/XPageView/XErrorView.vue +22 -22
  128. package/src/base-client/components/layout/XPageView/XPageRowTemplate.vue +37 -37
  129. package/src/base-client/components/layout/XPageView/XPageView.vue +223 -223
  130. package/src/base-client/components/layout/XPageView/XTab/XTab.vue +96 -96
  131. package/src/base-client/components/layout/XPageView/XTab/index.js +3 -3
  132. package/src/base-client/components/layout/XPageView/componentTypes.js +22 -22
  133. package/src/base-client/components/layout/XPageView/index.js +2 -2
  134. package/src/base-client/components/layout/XPageView/index.md +96 -96
  135. package/src/base-client/components/system/DictionaryDetailsView/index.js +3 -3
  136. package/src/base-client/components/system/DictionaryDetailsView/index.md +41 -41
  137. package/src/base-client/components/system/LogDetailsView/LogDetailsView.vue +376 -376
  138. package/src/base-client/components/system/LogDetailsView/index.js +3 -3
  139. package/src/base-client/components/system/LogDetailsView/index.md +41 -41
  140. package/src/base-client/components/system/QueryParamsDetailsView/index.js +3 -3
  141. package/src/base-client/components/ticket/TicketDetailsView/TicketDetailsView.vue +807 -807
  142. package/src/base-client/components/ticket/TicketDetailsView/index.js +3 -3
  143. package/src/base-client/components/ticket/TicketDetailsView/index.md +29 -29
  144. package/src/base-client/components/ticket/TicketDetailsView/part/TicketDetailsFlow.vue +260 -260
  145. package/src/base-client/components/ticket/TicketDetailsView/part/index.js +3 -3
  146. package/src/base-client/components/ticket/TicketSubmitSuccessView/TicketSubmitSuccessView.vue +532 -532
  147. package/src/base-client/components/ticket/TicketSubmitSuccessView/index.js +3 -3
  148. package/src/base-client/components/ticket/TicketSubmitSuccessView/index.md +29 -29
  149. package/src/base-client/plugins/AppData.js +126 -126
  150. package/src/base-client/plugins/PagedList.js +177 -177
  151. package/src/base-client/plugins/__tests__/selectValueTypeHelper.test.js +154 -154
  152. package/src/base-client/plugins/authority-plugin.js +167 -167
  153. package/src/base-client/plugins/compatible/LoginServiceOA.js +20 -20
  154. package/src/base-client/plugins/i18n-extend.js +32 -32
  155. package/src/base-client/plugins/moment.js +8 -8
  156. package/src/base-client/plugins/selectValueTypeHelper.js +281 -281
  157. package/src/bootstrap.js +51 -51
  158. package/src/components/Ellipsis/Ellipsis.vue +65 -65
  159. package/src/components/Ellipsis/index.js +3 -3
  160. package/src/components/Ellipsis/index.md +38 -38
  161. package/src/components/FileImageItem/FileItem.vue +320 -320
  162. package/src/components/FileImageItem/FileItemGroup.vue +197 -197
  163. package/src/components/FileImageItem/ImageItem.vue +107 -107
  164. package/src/components/FileImageItem/index.js +4 -4
  165. package/src/components/FilePreview/FilePreview.vue +181 -181
  166. package/src/components/FilePreview/FilePreviewDemo.vue +30 -30
  167. package/src/components/FilePreview/index.js +3 -3
  168. package/src/components/HeightScanner/index.vue +615 -615
  169. package/src/components/STable/README.md +341 -341
  170. package/src/components/STable/index.js +558 -558
  171. package/src/components/TableSetting/TableSetting.vue +143 -143
  172. package/src/components/TableSetting/index.js +3 -3
  173. package/src/components/Trend/Trend.vue +41 -41
  174. package/src/components/Trend/index.js +3 -3
  175. package/src/components/Trend/index.less +41 -41
  176. package/src/components/Trend/index.md +45 -45
  177. package/src/components/_util/util.js +46 -46
  178. package/src/components/cache/AKeepAlive.js +179 -179
  179. package/src/components/exception/typeConfig.js +19 -19
  180. package/src/components/form/FormRow.vue +52 -52
  181. package/src/components/index.less +5 -5
  182. package/src/components/menu/Contextmenu.vue +84 -84
  183. package/src/components/menu/index.less +38 -38
  184. package/src/components/page/header/PageHeader.vue +64 -64
  185. package/src/components/page/header/index.less +40 -40
  186. package/src/components/result/Result.vue +77 -77
  187. package/src/components/setting/SettingItem.vue +26 -26
  188. package/src/components/setting/i18n.js +117 -117
  189. package/src/components/table/StandardTable.vue +141 -141
  190. package/src/components/table/advance/ActionColumns.vue +158 -158
  191. package/src/components/table/advance/ActionSize.vue +45 -45
  192. package/src/components/table/advance/AdvanceTable.vue +275 -275
  193. package/src/components/table/advance/SearchArea.vue +355 -355
  194. package/src/components/table/advance/index.js +2 -2
  195. package/src/components/table/api/ApiTable.vue +50 -50
  196. package/src/components/task/TaskGroup.vue +80 -80
  197. package/src/components/task/TaskItem.vue +26 -26
  198. package/src/components/tool/AvatarList.vue +68 -68
  199. package/src/components/tool/DetailList.vue +157 -157
  200. package/src/components/tool/Drawer.vue +142 -142
  201. package/src/components/tool/FooterToolBar.vue +30 -30
  202. package/src/components/tool/HeadInfo.vue +35 -35
  203. package/src/components/tool/TagSelect.vue +83 -83
  204. package/src/components/tool/TagSelectOption.vue +33 -33
  205. package/src/components/transition/PageToggleTransition.vue +97 -97
  206. package/src/config/default/admin.config.js +18 -18
  207. package/src/config/default/animate.config.js +21 -21
  208. package/src/config/default/index.js +6 -6
  209. package/src/config/index.js +3 -3
  210. package/src/config/replacer/index.js +10 -10
  211. package/src/config/replacer/resolve.config.js +67 -67
  212. package/src/expression/ExpressionRunner.js +26 -26
  213. package/src/expression/TestExpression.js +509 -509
  214. package/src/expression/core/Delegate.js +115 -115
  215. package/src/expression/core/Expression.js +1358 -1358
  216. package/src/expression/core/Program.js +932 -932
  217. package/src/expression/core/Token.js +27 -27
  218. package/src/expression/enums/ExpressionType.js +81 -81
  219. package/src/expression/enums/TokenType.js +11 -11
  220. package/src/expression/exception/BreakWayException.js +2 -2
  221. package/src/expression/exception/ContinueWayException.js +2 -2
  222. package/src/expression/exception/ExpressionException.js +28 -28
  223. package/src/expression/exception/ReturnWayException.js +14 -14
  224. package/src/expression/exception/ServiceException.js +22 -22
  225. package/src/expression/instances/LogicConsole.js +44 -44
  226. package/src/expression/ts/ExpressionRunner.ts +28 -28
  227. package/src/expression/ts/TestExpression.ts +509 -509
  228. package/src/expression/ts/core/Delegate.ts +114 -114
  229. package/src/expression/ts/core/Expression.ts +1309 -1309
  230. package/src/expression/ts/core/Program.ts +950 -950
  231. package/src/expression/ts/core/Token.ts +29 -29
  232. package/src/expression/ts/enums/ExpressionType.ts +81 -81
  233. package/src/expression/ts/enums/TokenType.ts +13 -13
  234. package/src/expression/ts/exception/BreakWayException.ts +2 -2
  235. package/src/expression/ts/exception/ContinueWayException.ts +2 -2
  236. package/src/expression/ts/exception/ExpressionException.ts +28 -28
  237. package/src/expression/ts/exception/ReturnWayException.ts +14 -14
  238. package/src/expression/ts/exception/ServiceException.ts +22 -22
  239. package/src/expression/ts/instances/JSONArray.ts +48 -48
  240. package/src/expression/ts/instances/JSONObject.ts +109 -109
  241. package/src/expression/ts/instances/LogicConsole.ts +32 -32
  242. package/src/layouts/AdminLayout.vue +176 -176
  243. package/src/layouts/BlankView.vue +79 -79
  244. package/src/layouts/ComponentLayoutOne.vue +47 -47
  245. package/src/layouts/GridView.vue +43 -43
  246. package/src/layouts/PageView.vue +55 -55
  247. package/src/layouts/footer/PageFooter.vue +49 -49
  248. package/src/layouts/header/HeaderAvatar.vue +64 -64
  249. package/src/layouts/header/HeaderSearch.vue +67 -67
  250. package/src/layouts/header/index.less +92 -92
  251. package/src/layouts/tabs/TabsView.vue +383 -383
  252. package/src/layouts/tabs/i18n.js +25 -25
  253. package/src/layouts/tabs/index.js +2 -2
  254. package/src/logic/LogicRunner.js +62 -62
  255. package/src/logic/TestLogic.js +13 -13
  256. package/src/logic/plugins/common/DateTools.js +35 -35
  257. package/src/logic/plugins/common/VueTools.js +30 -30
  258. package/src/logic/plugins/index.js +7 -7
  259. package/src/logic/ts/LogicRunner.ts +67 -67
  260. package/src/logic/ts/TestLogic.ts +13 -13
  261. package/src/main.js +33 -33
  262. package/src/mixins/formValidationMixin.js +46 -46
  263. package/src/mock/common/activityData.js +32 -32
  264. package/src/mock/common/index.js +89 -89
  265. package/src/mock/common/reportData.js +20 -20
  266. package/src/mock/common/tableData.js +118 -118
  267. package/src/mock/index.js +12 -12
  268. package/src/mock/project/index.js +17 -17
  269. package/src/mock/user/current.js +13 -13
  270. package/src/mock/user/login.js +39 -39
  271. package/src/mock/user/routes.js +61 -61
  272. package/src/mock/workplace/index.js +15 -15
  273. package/src/pages/LogicCallExample/index.vue +46 -46
  274. package/src/pages/ReportGrid/index.vue +76 -76
  275. package/src/pages/ReportView.vue +50 -50
  276. package/src/pages/WorkflowDetail/WorkFlowDemo.vue +47 -47
  277. package/src/pages/WorkflowDetail/WorkFlowDemo2.vue +204 -204
  278. package/src/pages/WorkflowDetail/WorkFlowDemo3.vue +203 -203
  279. package/src/pages/WorkflowDetail/WorkflowDetail.vue +391 -391
  280. package/src/pages/WorkflowDetail/WorkflowPageDetail/LeaveMessage.vue +388 -388
  281. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowBaseInformation.vue +415 -415
  282. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowHandle.vue +1766 -1766
  283. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowHandleReso.vue +975 -975
  284. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowPreview.vue +109 -109
  285. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowTimeline.vue +929 -929
  286. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkOrderParentDetails.vue +222 -222
  287. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkflowDetailResso.vue +243 -243
  288. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkflowLog.vue +188 -188
  289. package/src/pages/WorkflowDetail/WorkflowPageDetail/components/WorkflowPersonSelector.vue +109 -109
  290. package/src/pages/WorkflowDetail/WorkflowPageDetail/worklog.vue +97 -97
  291. package/src/pages/XPageViewExample/index.vue +149 -149
  292. package/src/pages/addressSelect/addressDemo.vue +24 -24
  293. package/src/pages/addressSelect/index.vue +270 -270
  294. package/src/pages/dashboard/workplace/i18n.js +40 -40
  295. package/src/pages/dashboard/workplace/index.js +2 -2
  296. package/src/pages/dashboard/workplace/index.less +59 -59
  297. package/src/pages/exception/403.vue +21 -21
  298. package/src/pages/exception/404.vue +24 -24
  299. package/src/pages/exception/500.vue +21 -21
  300. package/src/pages/login/index.js +2 -2
  301. package/src/pages/report/ReportTableHome.vue +28 -28
  302. package/src/pages/resourceManage/depListManage.vue +23 -23
  303. package/src/pages/resourceManage/funListManage.vue +23 -23
  304. package/src/pages/resourceManage/index.js +15 -15
  305. package/src/pages/resourceManage/resourceManageMain.vue +57 -57
  306. package/src/pages/resourceManage/roleListManage.vue +23 -23
  307. package/src/pages/resourceManage/staffListManage.vue +23 -23
  308. package/src/pages/system/file/Info.vue +56 -56
  309. package/src/pages/system/file/index.vue +317 -317
  310. package/src/pages/system/settings/index.vue +126 -126
  311. package/src/pages/userInfoDetailManage/FillCardRecordQuery/index.vue +77 -77
  312. package/src/pages/userInfoDetailManage/FillGasRecordQuery/index.vue +75 -75
  313. package/src/pages/userInfoDetailManage/InsuranceDetailQuery/index.vue +64 -64
  314. package/src/pages/userInfoDetailManage/MachineRecordQuery/index.vue +75 -75
  315. package/src/pages/userInfoDetailManage/OtherChargeRecordQuery/index.vue +75 -75
  316. package/src/pages/userInfoDetailManage/PriceAdjustments/index.vue +64 -64
  317. package/src/pages/userInfoDetailManage/UserChargeRecordQuery/index.vue +94 -94
  318. package/src/pages/userInfoDetailManage/UserException/index.vue +64 -64
  319. package/src/pages/userInfoDetailManage/UserHandRecordQuery/index.vue +87 -87
  320. package/src/pages/userInfoDetailManage/UserRecordQuery/index.vue +74 -74
  321. package/src/pages/userInfoDetailManage/index.vue +290 -290
  322. package/src/pages/userInfoDetailManage/uploadFilesHistory/ImagePreview.vue +101 -101
  323. package/src/pages/userInfoDetailManage/uploadFilesHistory/index.vue +129 -129
  324. package/src/pages/userInfoDetailManage/userInfoDetailQueryTabs.vue +144 -144
  325. package/src/plugins/HiPrintPlugin.js +164 -164
  326. package/src/router/async/router.map.js +126 -126
  327. package/src/router/guards.js +262 -262
  328. package/src/router/i18n.js +57 -57
  329. package/src/router.js +17 -17
  330. package/src/services/api/DictionaryDetailsViewApi.js +6 -6
  331. package/src/services/api/LogDetailsViewApi.js +10 -10
  332. package/src/services/api/QueryParamsDetailsViewApi.js +6 -6
  333. package/src/services/api/logininfor/index.js +6 -6
  334. package/src/services/api/manage.js +8 -8
  335. package/src/services/api/restTools.js +215 -215
  336. package/src/services/api/workFlow.js +57 -57
  337. package/src/services/apiService.js +16 -16
  338. package/src/services/dataSource.js +12 -12
  339. package/src/services/index.js +7 -7
  340. package/src/services/user.js +92 -92
  341. package/src/services/v3Api.js +116 -116
  342. package/src/store/index.js +5 -5
  343. package/src/store/mutation-types.js +4 -4
  344. package/src/theme/antd/ant-menu.less +2 -2
  345. package/src/theme/antd/ant-message.less +3 -3
  346. package/src/theme/antd/ant-table.less +22 -22
  347. package/src/theme/antd/ant-time-picker.less +3 -3
  348. package/src/theme/antd/index.less +3 -3
  349. package/src/theme/default/color.less +43 -43
  350. package/src/theme/default/index.less +3 -3
  351. package/src/theme/default/nprogress.less +76 -76
  352. package/src/theme/global.less +279 -279
  353. package/src/theme/index.less +5 -5
  354. package/src/theme/reportTable.less +58 -58
  355. package/src/theme/theme.less +1 -1
  356. package/src/utils/EncryptUtil.js +162 -162
  357. package/src/utils/Objects.js +25 -25
  358. package/src/utils/axios-interceptors.js +100 -100
  359. package/src/utils/colors.js +107 -107
  360. package/src/utils/common.js +10 -10
  361. package/src/utils/excel/Blob.js +180 -180
  362. package/src/utils/excel/Export2Excel.js +141 -141
  363. package/src/utils/filter.js +21 -21
  364. package/src/utils/i18n.js +80 -80
  365. package/src/utils/indexedDB.js +549 -549
  366. package/src/utils/microAppUtils.js +49 -49
  367. package/src/utils/request.js +395 -395
  368. package/src/utils/routerUtil.js +553 -553
  369. package/src/utils/themeUtil.js +100 -100
  370. package/test/Tree.spec.js +168 -168
  371. package/test/myDialog.spec.js +47 -47
  372. package/test/request.test.js +17 -17
  373. package/test/util.test.js +53 -53
  374. package/test/v3Api.test.js +1984 -1984
  375. package/tests/unit/ReportTable.spec.js +16 -16
  376. package/vue.config.js +222 -222
  377. package/.claude/settings.local.json +0 -12
@@ -1,929 +1,929 @@
1
- <template>
2
- <div class="timeline-wrapper" ref="timelineContent" style="white-space: nowrap; overflow-x: auto">
3
- <!-- 动态渲染时间轴段落 -->
4
- <template v-for="(segment, segmentIndex) in getTimelineSegments()">
5
-
6
- <!-- 主时间轴段落 -->
7
- <div v-if="segment.type === 'main'" :key="'main-' + segmentIndex" class="timeline-section main-timeline">
8
- <a-steps
9
- :current="getCurrentStepInSection(segment.steps)"
10
- :initial="1">
11
- <template #progressDot="{index}">
12
- <span v-if="!changeAble" class="step-label in-steps"><i :class="['step-icon', getStepIconColor(index, segment.steps)]"></i></span>
13
- <span v-else :key="displayStepId" :class="['step-icon-filled digital', getStepIconColor(index, segment.steps)]">
14
- <a-icon v-if="isStepCompleted(segment.steps[index - 1])" type="check-circle" theme="filled" :class="['step-icon-filled icon', getStepIconColor(index, segment.steps)]" />
15
- <span v-else :class="['step-icon-filled digital', getStepIconColor(index, segment.steps)]">{{ getStepNumber(segmentIndex, index) }}</span>
16
- </span>
17
- </template>
18
-
19
- <a-step
20
- v-for="item in segment.steps"
21
- :key="item.id"
22
- class="step-item"
23
- @click.stop="onStepClick(item.id)"
24
- >
25
- <template #title>
26
- <div class="step-title-container">
27
- <h3 v-if="item.name">{{ item.name }}</h3>
28
- <!-- 判断节点特殊标识 -->
29
- <div v-if="item.type === 'condition'" class="condition-indicators">
30
- <a-tag color="purple" size="small" class="condition-tag">
31
- <a-icon type="branches" /> 条件节点
32
- </a-tag>
33
- <a-tooltip title="此节点根据条件判断后续流程走向">
34
- <a-icon type="question-circle" class="condition-help" />
35
- </a-tooltip>
36
- </div>
37
- </div>
38
- </template>
39
- <template #description>
40
- <div>
41
- <p v-if="item.handler">负责人:
42
- <trim-text-tail :text="item.handler" :length="14"/>
43
- </p>
44
- <p v-if="item.date">填报时间:{{ formatDate(item.date, 'yyyy-MM-dd hh:mm') }}</p>
45
- <p v-if="item.deadline" :class="{ 'text-red': item.id === currentStepId && isOverdue }">截止时间:{{ formatDate(item.deadline, 'yyyy-MM-dd hh:mm') }}</p>
46
- <p v-if="item.note">备注:
47
- <trim-text-tail :text="item.note" :length="15"/>
48
- </p>
49
- </div>
50
- </template>
51
- </a-step>
52
- </a-steps>
53
- </div>
54
-
55
- <!-- 并行分支段落 -->
56
- <div v-else-if="segment.type === 'parallel'" :key="'parallel-' + segmentIndex" class="parallel-section">
57
- <!-- 左侧连接线 -->
58
- <div class="connection-line left-line"></div>
59
-
60
- <!-- 并行分支容器 -->
61
- <div class="parallel-branches-container">
62
- <!-- 并行节点标题 -->
63
- <a-tag color="cyan" size="small" class="parallel-node-title">
64
- <a-icon type="apartment" /> 并行节点
65
- </a-tag>
66
- <!-- 动态渲染并行分支 -->
67
- <div
68
- v-for="(branch, branchIndex) in segment.branches"
69
- :key="'segment-' + segmentIndex + '-branch-' + branchIndex"
70
- class="branch-row">
71
- <!-- 分支时间轴 -->
72
- <div :class="['branch-timeline', getBranchTimelineClass(branch)]">
73
- <a-steps size="small" class="branch-steps">
74
- <a-step
75
- v-for="step in branch"
76
- :key="'segment-' + segmentIndex + '-branch-' + branchIndex + '-step-' + step.id"
77
- :class="['branch-step', getBranchStepClass(step)]"
78
- @click.stop="onStepClick(step.id)">
79
- <template #title>
80
- <a-popover placement="top" trigger="hover" :mouseEnterDelay="0.3">
81
- <template #content>
82
- <div class="branch-step-popover">
83
- <div class="popover-item" v-if="step.handler">
84
- <span class="popover-label">负责人:</span>
85
- <span class="popover-value">{{ step.handler }}</span>
86
- </div>
87
- <div class="popover-item" v-if="step.date">
88
- <span class="popover-label">填报时间:</span>
89
- <span class="popover-value">{{ formatDate(step.date, 'yyyy-MM-dd hh:mm') }}</span>
90
- </div>
91
- <div class="popover-item" v-if="step.deadline">
92
- <span class="popover-label">截止时间:</span>
93
- <span class="popover-value">{{ formatDate(step.deadline, 'yyyy-MM-dd hh:mm') }}</span>
94
- </div>
95
- <div class="popover-item" v-if="step.note">
96
- <span class="popover-label">备注:</span>
97
- <span class="popover-value">{{ step.note }}</span>
98
- </div>
99
- <div class="popover-item no-data" v-if="!step.handler && !step.date && !step.deadline && !step.note">
100
- <span class="popover-value">暂无详细信息</span>
101
- </div>
102
- </div>
103
- </template>
104
- <template #title>
105
- <div class="popover-title">
106
- <a-icon type="info-circle" />
107
- {{ step.name }} - 详细信息
108
- </div>
109
- </template>
110
- <span class="branch-step-title">{{ step.name }}</span>
111
- </a-popover>
112
- </template>
113
- <template #description>
114
- <div class="branch-step-desc">
115
- <p v-if="step.handler">{{ step.handler }}</p>
116
- <p v-if="step.date">{{ formatDate(step.date, 'MM-dd hh:mm') }}</p>
117
- </div>
118
- </template>
119
- </a-step>
120
- </a-steps>
121
- </div>
122
- </div>
123
- </div>
124
-
125
- <!-- 右侧连接线 -->
126
- <div class="connection-line right-line"></div>
127
- </div>
128
-
129
- </template>
130
-
131
- <!-- 当步骤被截断时显示省略状态 -->
132
- <div class="more-steps-section" v-if="hasMoreSteps">
133
- <a-steps :current="1" :initial="1">
134
- <a-step
135
- key="more-steps"
136
- class="step-item more-steps-item">
137
- <template #title>
138
- <div class="more-steps-container">
139
- <h3>后续步骤</h3>
140
- </div>
141
- </template>
142
- <template #description>
143
- <div class="more-steps-desc">
144
- <p>根据上述条件判断结果,将继续执行相应的后续流程</p>
145
- <p class="steps-count">剩余 {{ remainingStepsCount }} 个步骤</p>
146
- </div>
147
- </template>
148
- <template #icon>
149
- <a-icon type="more" style="color: #d9d9d9;" />
150
- </template>
151
- </a-step>
152
- </a-steps>
153
- </div>
154
- </div>
155
- </template>
156
-
157
- <script>
158
- import { formatDate } from '@vue2-client/utils/util'
159
- import TrimTextTail from './TrimTextTail'
160
-
161
- export default {
162
- components: { TrimTextTail },
163
- name: 'WorkFlowTimeline',
164
- props: {
165
- workflowId: {
166
- type: [String, Number],
167
- required: true
168
- },
169
- currentStepId: {
170
- type: Number,
171
- required: false,
172
- default: 1
173
- },
174
- activeStepId: {
175
- type: Number,
176
- required: false,
177
- default: 1
178
- },
179
- state: {
180
- type: [Boolean, Number],
181
- required: false,
182
- default: false
183
- },
184
- steps: {
185
- type: Array,
186
- required: true
187
- },
188
- changeAble: {
189
- type: Boolean,
190
- required: false,
191
- default: false
192
- }
193
- },
194
- data () {
195
- return {
196
- // 当前显示的步骤 id
197
- displayStepId: 1,
198
- // 当前任务是否逾期
199
- isOverdue: false,
200
- // 是否显示所有步骤(包括条件后的步骤)
201
- showAllSteps: false
202
- }
203
- },
204
- computed: {
205
- // 控制显示的步骤:当判断节点未执行时只显示到判断节点,执行后显示包括并行分支的所有步骤
206
- displaySteps () {
207
- const steps = this.steps || []
208
-
209
- // 如果用户选择显示所有步骤,直接返回
210
- if (this.showAllSteps) {
211
- return steps
212
- }
213
-
214
- // 找到第一个判断节点
215
- const firstConditionStepIndex = steps.findIndex(step => step.type === 'condition')
216
-
217
- // 如果没有找到判断节点,显示所有步骤
218
- if (firstConditionStepIndex === -1) {
219
- return steps
220
- }
221
-
222
- const firstConditionStep = steps[firstConditionStepIndex]
223
-
224
- // 如果当前步骤在第一个判断节点之前或等于判断节点,只显示到判断节点
225
- if (this.currentStepId <= firstConditionStep.id) {
226
- return steps.slice(0, firstConditionStepIndex + 1)
227
- }
228
-
229
- // 如果判断节点已经执行,显示所有步骤(包括并行分支)
230
- return steps
231
- },
232
-
233
- // 是否有更多步骤(被条件截断)
234
- hasMoreSteps () {
235
- // 如果已经显示所有步骤,则不显示"更多步骤"
236
- if (this.showAllSteps) return false
237
-
238
- const steps = this.steps || []
239
- const firstConditionStepIndex = steps.findIndex(step => step.type === 'condition')
240
-
241
- if (firstConditionStepIndex === -1) return false
242
-
243
- const firstConditionStep = steps[firstConditionStepIndex]
244
- return this.currentStepId <= firstConditionStep.id && firstConditionStepIndex < steps.length - 1
245
- },
246
-
247
- // 剩余步骤数量
248
- remainingStepsCount () {
249
- const steps = this.steps || []
250
- const firstConditionStepIndex = steps.findIndex(step => step.type === 'condition')
251
-
252
- if (firstConditionStepIndex === -1) return 0
253
-
254
- return steps.length - (firstConditionStepIndex + 1)
255
- }
256
- },
257
- mounted () {
258
- this.init()
259
- const timelineContent = this.$refs.timelineContent
260
- timelineContent.onmousewheel = function (e) {
261
- timelineContent.scrollLeft -= e.wheelDelta
262
- e.preventDefault()
263
- }
264
- },
265
- beforeDestroy () {
266
- this.$refs.timelineContent.onmousewheel = null
267
- },
268
- methods: {
269
- init () {
270
- this.displayStepId = this.activeStepId
271
- const currentStep = this.steps.find(step => step.id === this.currentStepId)
272
- if (currentStep && currentStep.deadline) {
273
- this.isOverdue = !this.state && this.formatDate(new Date(), 'yyyy-MM-dd hh:mm') > currentStep.deadline
274
- }
275
- this.$emit('activeStep', this.displayStepId)
276
- },
277
-
278
- // 获取时间轴段落数据
279
- getTimelineSegments () {
280
- const steps = this.displaySteps
281
- const segments = []
282
- let currentIndex = 0
283
-
284
- while (currentIndex < steps.length) {
285
- // 收集连续的主流程步骤(包括并行分支入口节点)
286
- const mainSteps = []
287
- while (currentIndex < steps.length && !this.isParallelStep(steps[currentIndex])) {
288
- mainSteps.push(steps[currentIndex])
289
-
290
- // 如果当前步骤是并行分支入口,处理完后跳出循环准备处理并行分支
291
- if (this.isParallelBranchEntry(steps[currentIndex])) {
292
- currentIndex++
293
- break
294
- }
295
- currentIndex++
296
- }
297
-
298
- if (mainSteps.length > 0) {
299
- segments.push({
300
- type: 'main',
301
- steps: mainSteps
302
- })
303
- }
304
-
305
- // 检查是否有并行分支需要处理
306
- if (currentIndex > 0 && this.isParallelBranchEntry(steps[currentIndex - 1])) {
307
- // 获取这个并行分支的所有步骤
308
- const branchIndex = steps[currentIndex - 1].properties.branchIndex
309
- const parallelSteps = this.getParallelStepsByBranchIndex(steps, branchIndex)
310
-
311
- if (parallelSteps.length > 0) {
312
- // 按branchPath分组
313
- const branches = this.groupParallelSteps(parallelSteps)
314
- segments.push({
315
- type: 'parallel',
316
- branches: branches
317
- })
318
-
319
- // 跳过已处理的并行步骤
320
- currentIndex = this.skipProcessedParallelSteps(steps, currentIndex, parallelSteps)
321
- }
322
- }
323
- }
324
-
325
- return segments
326
- },
327
-
328
- // 根据branchIndex获取并行步骤
329
- getParallelStepsByBranchIndex (steps, branchIndex) {
330
- return steps.filter(step =>
331
- step.properties &&
332
- step.properties.branchPath &&
333
- step.properties.branchPath.includes(`parallel_${branchIndex}_`)
334
- )
335
- },
336
-
337
- // 将并行步骤按branchPath分组
338
- groupParallelSteps (parallelSteps) {
339
- const branches = {}
340
- parallelSteps.forEach(step => {
341
- const branchPath = step.properties.branchPath
342
- if (!branches[branchPath]) {
343
- branches[branchPath] = []
344
- }
345
- branches[branchPath].push(step)
346
- })
347
-
348
- // 对每个分支内的步骤按id排序
349
- Object.keys(branches).forEach(branchPath => {
350
- branches[branchPath].sort((a, b) => a.id - b.id)
351
- })
352
-
353
- return Object.values(branches)
354
- },
355
-
356
- // 跳过已处理的并行步骤
357
- skipProcessedParallelSteps (steps, currentIndex, processedSteps) {
358
- const processedIds = new Set(processedSteps.map(step => step.id))
359
- while (currentIndex < steps.length && processedIds.has(steps[currentIndex].id)) {
360
- currentIndex++
361
- }
362
- return currentIndex
363
- },
364
-
365
- // 判断是否为并行分支入口
366
- isParallelBranchEntry (step) {
367
- return step.properties &&
368
- step.properties.branchType === 'parallelBranch'
369
- },
370
-
371
- // 判断是否为分支汇合节点
372
- isBranchExit (step) {
373
- return step.properties &&
374
- step.properties.flowRole === 'branchExit'
375
- },
376
-
377
- // 获取在某个section中的当前步骤索引
378
- getCurrentStepInSection (sectionSteps) {
379
- if (!sectionSteps || sectionSteps.length === 0) return 0
380
-
381
- const currentStepIndex = sectionSteps.findIndex(step => step.id === this.currentStepId)
382
- return currentStepIndex >= 0 ? currentStepIndex + 1 : 0
383
- },
384
-
385
- // 获取步骤编号
386
- getStepNumber (segmentIndex, stepIndex) {
387
- const segments = this.getTimelineSegments()
388
- let stepNumber = 0
389
-
390
- // 计算前面所有段落的步骤数
391
- for (let i = 0; i < segmentIndex; i++) {
392
- const segment = segments[i]
393
- if (segment.type === 'main') {
394
- stepNumber += segment.steps.length
395
- } else if (segment.type === 'parallel') {
396
- // 并行分支计算总步骤数
397
- stepNumber += segment.branches.reduce((total, branch) => total + branch.length, 0)
398
- }
399
- }
400
-
401
- return stepNumber + stepIndex
402
- },
403
-
404
- // 判断步骤是否已完成
405
- isStepCompleted (step) {
406
- if (!step) return false
407
- return step.id < this.currentStepId || this.state
408
- },
409
-
410
- // 判断id是否为流程中最后一个
411
- isLastStep (stepId) {
412
- return stepId >= this.steps.length
413
- },
414
-
415
- // 判断是否为并行步骤
416
- isParallelStep (step) {
417
- return step.properties &&
418
- step.properties.branchPath &&
419
- step.properties.branchPath.includes('parallel_')
420
- },
421
-
422
- // 动态展示时间线节点颜色
423
- getStepIconColor (index, sectionSteps) {
424
- if (!sectionSteps || !sectionSteps[index - 1]) return 'gray'
425
-
426
- const stepId = sectionSteps[index - 1].id
427
-
428
- if (this.changeAble && stepId === this.displayStepId) {
429
- return 'yellow'
430
- } else if (!this.changeAble && stepId === this.currentStepId) {
431
- return this.state ? 'blue' : 'green'
432
- }
433
- if (stepId < this.currentStepId || this.state) {
434
- return 'blue'
435
- }
436
- if (stepId === this.currentStepId) {
437
- return this.isOverdue ? 'red' : 'blue'
438
- }
439
- return 'gray'
440
- },
441
-
442
- // 获取分支步骤的CSS类
443
- getBranchStepClass (step) {
444
- if (!step) return 'branch-step-gray'
445
-
446
- // 如果在可编辑状态下且是当前显示的步骤
447
- if (this.changeAble && step.id === this.displayStepId) {
448
- return 'branch-step-yellow'
449
- }
450
-
451
- // 根据 status 判断颜色
452
- switch (step.status) {
453
- case 0: // 未处理
454
- return 'branch-step-gray'
455
- case 1: // 正在处理
456
- // 检查是否逾期
457
- if (step.deadline && !this.state && this.formatDate(new Date(), 'yyyy-MM-dd hh:mm') > step.deadline) {
458
- return 'branch-step-red'
459
- }
460
- return 'branch-step-blue'
461
- case 2: // 已处理
462
- return 'branch-step-green'
463
- default:
464
- return 'branch-step-gray'
465
- }
466
- },
467
-
468
- // 获取分支时间轴的CSS类(根据分支中的步骤状态)
469
- getBranchTimelineClass (branch) {
470
- if (!branch || branch.length === 0) return 'branch-timeline-gray'
471
-
472
- // 检查分支中所有步骤的状态
473
- const hasCompleted = branch.some(step => step.status === 2) // 有已完成的
474
- const hasProcessing = branch.some(step => step.status === 1) // 有正在处理的
475
- const allPending = branch.every(step => step.status === 0 || step.status === undefined) // 全部未处理
476
-
477
- // 优先级:正在处理 > 已完成 > 未处理
478
- if (hasProcessing) {
479
- return 'branch-timeline-blue' // 正在进行
480
- } else if (hasCompleted) {
481
- return 'branch-timeline-green' // 已完成
482
- } else if (allPending) {
483
- return 'branch-timeline-gray' // 未抵达
484
- } else {
485
- return 'branch-timeline-gray' // 默认
486
- }
487
- },
488
-
489
- onStepClick (stepId) {
490
- if (!this.changeAble || stepId === this.displayStepId) {
491
- return
492
- }
493
- const curStep = this.steps.find(item => item.id === stepId)
494
- if (stepId > this.currentStepId && curStep.status !== 1 && curStep.status !== 2) {
495
- return this.$message.warn('请先完成当前步骤')
496
- }
497
- this.$emit('activeStep', stepId)
498
- this.displayStepId = stepId
499
- },
500
-
501
- formatDate,
502
- },
503
- watch: {
504
- activeStepId: function (newVal) {
505
- this.displayStepId = newVal
506
- }
507
- }
508
- }
509
- </script>
510
-
511
- <style lang="less" scoped>
512
- .timeline-wrapper {
513
- display: flex;
514
- align-items: flex-start;
515
- gap: 0;
516
-
517
- .timeline-section {
518
- flex-shrink: 0;
519
-
520
- // 主时间轴自动填充剩余宽度
521
- &.main-timeline {
522
- flex: 1;
523
- }
524
-
525
- /deep/ .ant-steps-dot {
526
- margin-bottom: 6px;
527
- .ant-steps-item-tail {
528
- top: 7px;
529
- margin-left: 106px;
530
- width: calc(100% - 23px);
531
- }
532
- .ant-steps-item-icon {
533
- margin-left: 90px;
534
- width: 8px;
535
- height: 8px;
536
- line-height: 8px;
537
- }
538
- .ant-steps-item-content {
539
- min-width: 195px;
540
- margin-top: 24px;
541
- .ant-steps-item-description {
542
- text-align: left;
543
- background: #fff;
544
- border-radius: 4px;
545
- padding: 12px;
546
- position: relative;
547
-
548
- p {
549
- position: relative;
550
- padding: 8px 0;
551
- margin: 0;
552
- font-size: 13px;
553
- color: #595959;
554
- line-height: 1.5;
555
- white-space: nowrap;
556
- overflow: visible;
557
-
558
- &:first-child {
559
- border-top: 1px dotted #e8e8e8;
560
- }
561
-
562
- &:not(:last-child) {
563
- border-bottom: 1px dashed #f0f0f0;
564
- }
565
-
566
- &:last-child {
567
- padding-bottom: 0;
568
- }
569
- }
570
- }
571
- }
572
- &.ant-steps {
573
- padding-top: 8px;
574
- }
575
- }
576
-
577
- /deep/ .ant-steps-item-title {
578
- font-size: 14px;
579
- h3 {
580
- font-size: 14px;
581
- margin-bottom: 0;
582
- }
583
- }
584
- }
585
-
586
- .parallel-section {
587
- display: flex;
588
- align-items: flex-start;
589
- position: relative;
590
-
591
- .connection-line {
592
- width: 2rem;
593
- height: 0;
594
- flex-shrink: 0;
595
- margin-top: 1rem;
596
-
597
- &.left-line {
598
- margin-right: 0;
599
- position: relative;
600
-
601
- &::before {
602
- content: '';
603
- position: absolute;
604
- left: -4.8rem;
605
- top: -1px;
606
- width: 7rem;
607
- height: 3px;
608
- background: #f0f0f0;
609
- }
610
- }
611
-
612
- &.right-line {
613
- margin-left: 0;
614
- position: relative;
615
-
616
- &::before {
617
- content: '';
618
- position: absolute;
619
- right: -4.6rem;
620
- top: -1px;
621
- width: 6.8rem;
622
- height: 3px;
623
- background: #f0f0f0;
624
- }
625
- }
626
- }
627
-
628
- .parallel-branches-container {
629
- display: flex;
630
- flex-direction: column; /* 竖直排列分支节点 */
631
- gap: 6px; /* 缩小间距 */
632
- align-items: center;
633
- position: relative;
634
- border: 2px dotted #d9d9d9;
635
- border-radius: 8px;
636
- margin: 0 12px;
637
- background: #fff;
638
- padding-bottom: 14px;
639
- width: max-content;
640
-
641
- /* 为并行节点容器添加小标题 */
642
- .parallel-node-title {
643
- position: absolute;
644
- bottom: -10px; /* 调整标题的上下位置 */
645
- left: 50%; /* 水平居中 */
646
- transform: translateX(-50%); /* 精确水平居中 */
647
- background: #fff; /* 背景色与容器一致 */
648
- font-size: 12px; /* 标题的字体大小 */
649
- border-radius: 4px;
650
- }
651
- }
652
-
653
- .branch-row {
654
- display: flex;
655
- flex-direction: column;
656
- align-items: center;
657
- position: relative;
658
- gap: 16px;
659
-
660
- :deep(.ant-steps-item-content) {
661
- text-align: left;
662
- }
663
-
664
- .branch-timeline {
665
- padding: 12px 16px;
666
- position: relative;
667
- min-width: 80px;
668
- text-align: center;
669
- transition: all 0.3s ease; /* 平滑过渡 */
670
- }
671
-
672
- .branch-timeline:hover {
673
- transform: scale(1.01); /* 鼠标悬停时放大 */
674
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
675
- }
676
-
677
- .branch-step-title {
678
- font-size: 14px;
679
- font-weight: 500;
680
- color: #262626;
681
- cursor: pointer;
682
- }
683
-
684
- .branch-step-desc {
685
- p {
686
- margin: 0;
687
- padding: 4px 0;
688
- font-size: 12px;
689
- color: #666;
690
- }
691
- }
692
-
693
- /deep/ .ant-steps-icon {
694
- color: #fefefe;
695
- }
696
-
697
- // 分支步骤节点样式
698
- /deep/ .ant-steps-item-icon {
699
- width: 20px;
700
- height: 20px;
701
- line-height: 20px;
702
- border-radius: 20px;
703
- }
704
-
705
- /deep/ .ant-steps-item-title {
706
- line-height: 20px;
707
- }
708
-
709
- // 分支步骤状态颜色
710
- /deep/ .branch-step-gray .ant-steps-item-icon {
711
- background-color: #bfbfbf !important;
712
- border-color: #bfbfbf !important;
713
- }
714
-
715
- /deep/ .branch-step-blue .ant-steps-item-icon {
716
- background-color: #1890ff !important;
717
- border-color: #1890ff !important;
718
- }
719
-
720
- /deep/ .branch-step-green .ant-steps-item-icon {
721
- background-color: #52c41a !important;
722
- border-color: #52c41a !important;
723
- }
724
-
725
- /deep/ .branch-step-red .ant-steps-item-icon {
726
- background-color: #ff4d4f !important;
727
- border-color: #ff4d4f !important;
728
- }
729
-
730
- /deep/ .branch-step-yellow .ant-steps-item-icon {
731
- background-color: #faad14 !important;
732
- border-color: #faad14 !important;
733
- }
734
- }
735
- }
736
-
737
- @red: rgb(255, 77, 79);
738
-
739
- .step-icon-filled {
740
- position: absolute;
741
- top: -2px;
742
- left: -6px;
743
- @blue: rgb(24, 144, 255);
744
- @yellow: rgb(255, 164, 39);
745
- @gray: rgb(191, 191, 191);
746
- &.digital {
747
- width: 28px;
748
- line-height: 28px;
749
- border-radius: 50%;
750
- color: #ffffff;
751
- &.blue {
752
- background: @blue;
753
- }
754
- &.yellow {
755
- background: @yellow;
756
- }
757
- &.gray {
758
- background: @gray;
759
- }
760
- &.red {
761
- background: @red;
762
- }
763
- }
764
- &.icon {
765
- font-size: 28px;
766
- &.blue {
767
- color: @blue;
768
- }
769
- &.yellow {
770
- color: @yellow;
771
- }
772
- &.gray {
773
- color: @gray;
774
- }
775
- }
776
- }
777
-
778
- .step-item {
779
- cursor: pointer;
780
- &:hover {
781
- .ant-steps-item-description {
782
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
783
- transform: translateY(-1px);
784
- transition: all 0.3s ease;
785
- }
786
- p {
787
- color: #262626;
788
- }
789
- }
790
- .text-red {
791
- color: @red !important;
792
- }
793
- }
794
-
795
- .next-step-overdue {
796
- /deep/ .ant-steps-item-tail::after {
797
- background: @red;
798
- }
799
- }
800
-
801
- // 新增样式:步骤标题容器
802
- .step-title-container {
803
- .condition-indicators {
804
- margin-top: 8px;
805
- display: flex;
806
- align-items: center;
807
- gap: 8px;
808
-
809
- .condition-tag {
810
- margin: 0;
811
- }
812
-
813
- .condition-help {
814
- color: #999;
815
- cursor: pointer;
816
- &:hover {
817
- color: #1890ff;
818
- }
819
- }
820
- }
821
- }
822
-
823
- // 分支信息样式
824
- .branch-info {
825
- margin-top: 8px;
826
- padding: 8px;
827
- background: #f9f9f9;
828
- border-radius: 4px;
829
- border-left: 3px solid #722ed1;
830
-
831
- .branch-title {
832
- margin: 0 0 6px 0 !important;
833
- font-weight: bold;
834
- color: #722ed1;
835
- font-size: 12px;
836
- padding: 0 !important;
837
- border: none !important;
838
- }
839
-
840
- .branch-options {
841
- display: flex;
842
- flex-wrap: wrap;
843
- gap: 4px;
844
-
845
- .branch-option-tag {
846
- margin: 0;
847
- font-size: 11px;
848
- }
849
- }
850
- }
851
-
852
- // 省略步骤样式
853
- .more-steps-section {
854
- flex-shrink: 0;
855
- // margin-top: 24px;
856
-
857
- .more-steps-item {
858
- opacity: 0.7;
859
-
860
- .more-steps-container {
861
- .pending-tag {
862
- margin-top: 8px;
863
- margin-left: 0;
864
- }
865
- }
866
-
867
- .more-steps-desc {
868
- p {
869
- // font-style: italic;
870
- color: #999 !important;
871
-
872
- &.steps-count {
873
- font-weight: bold;
874
- color: #666 !important;
875
- }
876
- }
877
- }
878
- }
879
- }
880
- }
881
-
882
- // 分支步骤 Popover 样式
883
- /deep/ .ant-popover {
884
- .popover-title {
885
- display: flex;
886
- align-items: center;
887
- gap: 6px;
888
- font-weight: 600;
889
- color: #1890ff;
890
-
891
- .anticon {
892
- font-size: 14px;
893
- }
894
- }
895
-
896
- .branch-step-popover {
897
- min-width: 200px;
898
-
899
- .popover-item {
900
- display: flex;
901
- align-items: flex-start;
902
- margin-bottom: 8px;
903
-
904
- &:last-child {
905
- margin-bottom: 0;
906
- }
907
-
908
- &.no-data {
909
- justify-content: center;
910
- font-style: italic;
911
- color: #999;
912
- }
913
-
914
- .popover-label {
915
- font-weight: 600;
916
- color: #262626;
917
- min-width: 70px;
918
- flex-shrink: 0;
919
- }
920
-
921
- .popover-value {
922
- color: #595959;
923
- word-break: break-all;
924
- flex: 1;
925
- }
926
- }
927
- }
928
- }
929
- </style>
1
+ <template>
2
+ <div class="timeline-wrapper" ref="timelineContent" style="white-space: nowrap; overflow-x: auto">
3
+ <!-- 动态渲染时间轴段落 -->
4
+ <template v-for="(segment, segmentIndex) in getTimelineSegments()">
5
+
6
+ <!-- 主时间轴段落 -->
7
+ <div v-if="segment.type === 'main'" :key="'main-' + segmentIndex" class="timeline-section main-timeline">
8
+ <a-steps
9
+ :current="getCurrentStepInSection(segment.steps)"
10
+ :initial="1">
11
+ <template #progressDot="{index}">
12
+ <span v-if="!changeAble" class="step-label in-steps"><i :class="['step-icon', getStepIconColor(index, segment.steps)]"></i></span>
13
+ <span v-else :key="displayStepId" :class="['step-icon-filled digital', getStepIconColor(index, segment.steps)]">
14
+ <a-icon v-if="isStepCompleted(segment.steps[index - 1])" type="check-circle" theme="filled" :class="['step-icon-filled icon', getStepIconColor(index, segment.steps)]" />
15
+ <span v-else :class="['step-icon-filled digital', getStepIconColor(index, segment.steps)]">{{ getStepNumber(segmentIndex, index) }}</span>
16
+ </span>
17
+ </template>
18
+
19
+ <a-step
20
+ v-for="item in segment.steps"
21
+ :key="item.id"
22
+ class="step-item"
23
+ @click.stop="onStepClick(item.id)"
24
+ >
25
+ <template #title>
26
+ <div class="step-title-container">
27
+ <h3 v-if="item.name">{{ item.name }}</h3>
28
+ <!-- 判断节点特殊标识 -->
29
+ <div v-if="item.type === 'condition'" class="condition-indicators">
30
+ <a-tag color="purple" size="small" class="condition-tag">
31
+ <a-icon type="branches" /> 条件节点
32
+ </a-tag>
33
+ <a-tooltip title="此节点根据条件判断后续流程走向">
34
+ <a-icon type="question-circle" class="condition-help" />
35
+ </a-tooltip>
36
+ </div>
37
+ </div>
38
+ </template>
39
+ <template #description>
40
+ <div>
41
+ <p v-if="item.handler">负责人:
42
+ <trim-text-tail :text="item.handler" :length="14"/>
43
+ </p>
44
+ <p v-if="item.date">填报时间:{{ formatDate(item.date, 'yyyy-MM-dd hh:mm') }}</p>
45
+ <p v-if="item.deadline" :class="{ 'text-red': item.id === currentStepId && isOverdue }">截止时间:{{ formatDate(item.deadline, 'yyyy-MM-dd hh:mm') }}</p>
46
+ <p v-if="item.note">备注:
47
+ <trim-text-tail :text="item.note" :length="15"/>
48
+ </p>
49
+ </div>
50
+ </template>
51
+ </a-step>
52
+ </a-steps>
53
+ </div>
54
+
55
+ <!-- 并行分支段落 -->
56
+ <div v-else-if="segment.type === 'parallel'" :key="'parallel-' + segmentIndex" class="parallel-section">
57
+ <!-- 左侧连接线 -->
58
+ <div class="connection-line left-line"></div>
59
+
60
+ <!-- 并行分支容器 -->
61
+ <div class="parallel-branches-container">
62
+ <!-- 并行节点标题 -->
63
+ <a-tag color="cyan" size="small" class="parallel-node-title">
64
+ <a-icon type="apartment" /> 并行节点
65
+ </a-tag>
66
+ <!-- 动态渲染并行分支 -->
67
+ <div
68
+ v-for="(branch, branchIndex) in segment.branches"
69
+ :key="'segment-' + segmentIndex + '-branch-' + branchIndex"
70
+ class="branch-row">
71
+ <!-- 分支时间轴 -->
72
+ <div :class="['branch-timeline', getBranchTimelineClass(branch)]">
73
+ <a-steps size="small" class="branch-steps">
74
+ <a-step
75
+ v-for="step in branch"
76
+ :key="'segment-' + segmentIndex + '-branch-' + branchIndex + '-step-' + step.id"
77
+ :class="['branch-step', getBranchStepClass(step)]"
78
+ @click.stop="onStepClick(step.id)">
79
+ <template #title>
80
+ <a-popover placement="top" trigger="hover" :mouseEnterDelay="0.3">
81
+ <template #content>
82
+ <div class="branch-step-popover">
83
+ <div class="popover-item" v-if="step.handler">
84
+ <span class="popover-label">负责人:</span>
85
+ <span class="popover-value">{{ step.handler }}</span>
86
+ </div>
87
+ <div class="popover-item" v-if="step.date">
88
+ <span class="popover-label">填报时间:</span>
89
+ <span class="popover-value">{{ formatDate(step.date, 'yyyy-MM-dd hh:mm') }}</span>
90
+ </div>
91
+ <div class="popover-item" v-if="step.deadline">
92
+ <span class="popover-label">截止时间:</span>
93
+ <span class="popover-value">{{ formatDate(step.deadline, 'yyyy-MM-dd hh:mm') }}</span>
94
+ </div>
95
+ <div class="popover-item" v-if="step.note">
96
+ <span class="popover-label">备注:</span>
97
+ <span class="popover-value">{{ step.note }}</span>
98
+ </div>
99
+ <div class="popover-item no-data" v-if="!step.handler && !step.date && !step.deadline && !step.note">
100
+ <span class="popover-value">暂无详细信息</span>
101
+ </div>
102
+ </div>
103
+ </template>
104
+ <template #title>
105
+ <div class="popover-title">
106
+ <a-icon type="info-circle" />
107
+ {{ step.name }} - 详细信息
108
+ </div>
109
+ </template>
110
+ <span class="branch-step-title">{{ step.name }}</span>
111
+ </a-popover>
112
+ </template>
113
+ <template #description>
114
+ <div class="branch-step-desc">
115
+ <p v-if="step.handler">{{ step.handler }}</p>
116
+ <p v-if="step.date">{{ formatDate(step.date, 'MM-dd hh:mm') }}</p>
117
+ </div>
118
+ </template>
119
+ </a-step>
120
+ </a-steps>
121
+ </div>
122
+ </div>
123
+ </div>
124
+
125
+ <!-- 右侧连接线 -->
126
+ <div class="connection-line right-line"></div>
127
+ </div>
128
+
129
+ </template>
130
+
131
+ <!-- 当步骤被截断时显示省略状态 -->
132
+ <div class="more-steps-section" v-if="hasMoreSteps">
133
+ <a-steps :current="1" :initial="1">
134
+ <a-step
135
+ key="more-steps"
136
+ class="step-item more-steps-item">
137
+ <template #title>
138
+ <div class="more-steps-container">
139
+ <h3>后续步骤</h3>
140
+ </div>
141
+ </template>
142
+ <template #description>
143
+ <div class="more-steps-desc">
144
+ <p>根据上述条件判断结果,将继续执行相应的后续流程</p>
145
+ <p class="steps-count">剩余 {{ remainingStepsCount }} 个步骤</p>
146
+ </div>
147
+ </template>
148
+ <template #icon>
149
+ <a-icon type="more" style="color: #d9d9d9;" />
150
+ </template>
151
+ </a-step>
152
+ </a-steps>
153
+ </div>
154
+ </div>
155
+ </template>
156
+
157
+ <script>
158
+ import { formatDate } from '@vue2-client/utils/util'
159
+ import TrimTextTail from './TrimTextTail'
160
+
161
+ export default {
162
+ components: { TrimTextTail },
163
+ name: 'WorkFlowTimeline',
164
+ props: {
165
+ workflowId: {
166
+ type: [String, Number],
167
+ required: true
168
+ },
169
+ currentStepId: {
170
+ type: Number,
171
+ required: false,
172
+ default: 1
173
+ },
174
+ activeStepId: {
175
+ type: Number,
176
+ required: false,
177
+ default: 1
178
+ },
179
+ state: {
180
+ type: [Boolean, Number],
181
+ required: false,
182
+ default: false
183
+ },
184
+ steps: {
185
+ type: Array,
186
+ required: true
187
+ },
188
+ changeAble: {
189
+ type: Boolean,
190
+ required: false,
191
+ default: false
192
+ }
193
+ },
194
+ data () {
195
+ return {
196
+ // 当前显示的步骤 id
197
+ displayStepId: 1,
198
+ // 当前任务是否逾期
199
+ isOverdue: false,
200
+ // 是否显示所有步骤(包括条件后的步骤)
201
+ showAllSteps: false
202
+ }
203
+ },
204
+ computed: {
205
+ // 控制显示的步骤:当判断节点未执行时只显示到判断节点,执行后显示包括并行分支的所有步骤
206
+ displaySteps () {
207
+ const steps = this.steps || []
208
+
209
+ // 如果用户选择显示所有步骤,直接返回
210
+ if (this.showAllSteps) {
211
+ return steps
212
+ }
213
+
214
+ // 找到第一个判断节点
215
+ const firstConditionStepIndex = steps.findIndex(step => step.type === 'condition')
216
+
217
+ // 如果没有找到判断节点,显示所有步骤
218
+ if (firstConditionStepIndex === -1) {
219
+ return steps
220
+ }
221
+
222
+ const firstConditionStep = steps[firstConditionStepIndex]
223
+
224
+ // 如果当前步骤在第一个判断节点之前或等于判断节点,只显示到判断节点
225
+ if (this.currentStepId <= firstConditionStep.id) {
226
+ return steps.slice(0, firstConditionStepIndex + 1)
227
+ }
228
+
229
+ // 如果判断节点已经执行,显示所有步骤(包括并行分支)
230
+ return steps
231
+ },
232
+
233
+ // 是否有更多步骤(被条件截断)
234
+ hasMoreSteps () {
235
+ // 如果已经显示所有步骤,则不显示"更多步骤"
236
+ if (this.showAllSteps) return false
237
+
238
+ const steps = this.steps || []
239
+ const firstConditionStepIndex = steps.findIndex(step => step.type === 'condition')
240
+
241
+ if (firstConditionStepIndex === -1) return false
242
+
243
+ const firstConditionStep = steps[firstConditionStepIndex]
244
+ return this.currentStepId <= firstConditionStep.id && firstConditionStepIndex < steps.length - 1
245
+ },
246
+
247
+ // 剩余步骤数量
248
+ remainingStepsCount () {
249
+ const steps = this.steps || []
250
+ const firstConditionStepIndex = steps.findIndex(step => step.type === 'condition')
251
+
252
+ if (firstConditionStepIndex === -1) return 0
253
+
254
+ return steps.length - (firstConditionStepIndex + 1)
255
+ }
256
+ },
257
+ mounted () {
258
+ this.init()
259
+ const timelineContent = this.$refs.timelineContent
260
+ timelineContent.onmousewheel = function (e) {
261
+ timelineContent.scrollLeft -= e.wheelDelta
262
+ e.preventDefault()
263
+ }
264
+ },
265
+ beforeDestroy () {
266
+ this.$refs.timelineContent.onmousewheel = null
267
+ },
268
+ methods: {
269
+ init () {
270
+ this.displayStepId = this.activeStepId
271
+ const currentStep = this.steps.find(step => step.id === this.currentStepId)
272
+ if (currentStep && currentStep.deadline) {
273
+ this.isOverdue = !this.state && this.formatDate(new Date(), 'yyyy-MM-dd hh:mm') > currentStep.deadline
274
+ }
275
+ this.$emit('activeStep', this.displayStepId)
276
+ },
277
+
278
+ // 获取时间轴段落数据
279
+ getTimelineSegments () {
280
+ const steps = this.displaySteps
281
+ const segments = []
282
+ let currentIndex = 0
283
+
284
+ while (currentIndex < steps.length) {
285
+ // 收集连续的主流程步骤(包括并行分支入口节点)
286
+ const mainSteps = []
287
+ while (currentIndex < steps.length && !this.isParallelStep(steps[currentIndex])) {
288
+ mainSteps.push(steps[currentIndex])
289
+
290
+ // 如果当前步骤是并行分支入口,处理完后跳出循环准备处理并行分支
291
+ if (this.isParallelBranchEntry(steps[currentIndex])) {
292
+ currentIndex++
293
+ break
294
+ }
295
+ currentIndex++
296
+ }
297
+
298
+ if (mainSteps.length > 0) {
299
+ segments.push({
300
+ type: 'main',
301
+ steps: mainSteps
302
+ })
303
+ }
304
+
305
+ // 检查是否有并行分支需要处理
306
+ if (currentIndex > 0 && this.isParallelBranchEntry(steps[currentIndex - 1])) {
307
+ // 获取这个并行分支的所有步骤
308
+ const branchIndex = steps[currentIndex - 1].properties.branchIndex
309
+ const parallelSteps = this.getParallelStepsByBranchIndex(steps, branchIndex)
310
+
311
+ if (parallelSteps.length > 0) {
312
+ // 按branchPath分组
313
+ const branches = this.groupParallelSteps(parallelSteps)
314
+ segments.push({
315
+ type: 'parallel',
316
+ branches: branches
317
+ })
318
+
319
+ // 跳过已处理的并行步骤
320
+ currentIndex = this.skipProcessedParallelSteps(steps, currentIndex, parallelSteps)
321
+ }
322
+ }
323
+ }
324
+
325
+ return segments
326
+ },
327
+
328
+ // 根据branchIndex获取并行步骤
329
+ getParallelStepsByBranchIndex (steps, branchIndex) {
330
+ return steps.filter(step =>
331
+ step.properties &&
332
+ step.properties.branchPath &&
333
+ step.properties.branchPath.includes(`parallel_${branchIndex}_`)
334
+ )
335
+ },
336
+
337
+ // 将并行步骤按branchPath分组
338
+ groupParallelSteps (parallelSteps) {
339
+ const branches = {}
340
+ parallelSteps.forEach(step => {
341
+ const branchPath = step.properties.branchPath
342
+ if (!branches[branchPath]) {
343
+ branches[branchPath] = []
344
+ }
345
+ branches[branchPath].push(step)
346
+ })
347
+
348
+ // 对每个分支内的步骤按id排序
349
+ Object.keys(branches).forEach(branchPath => {
350
+ branches[branchPath].sort((a, b) => a.id - b.id)
351
+ })
352
+
353
+ return Object.values(branches)
354
+ },
355
+
356
+ // 跳过已处理的并行步骤
357
+ skipProcessedParallelSteps (steps, currentIndex, processedSteps) {
358
+ const processedIds = new Set(processedSteps.map(step => step.id))
359
+ while (currentIndex < steps.length && processedIds.has(steps[currentIndex].id)) {
360
+ currentIndex++
361
+ }
362
+ return currentIndex
363
+ },
364
+
365
+ // 判断是否为并行分支入口
366
+ isParallelBranchEntry (step) {
367
+ return step.properties &&
368
+ step.properties.branchType === 'parallelBranch'
369
+ },
370
+
371
+ // 判断是否为分支汇合节点
372
+ isBranchExit (step) {
373
+ return step.properties &&
374
+ step.properties.flowRole === 'branchExit'
375
+ },
376
+
377
+ // 获取在某个section中的当前步骤索引
378
+ getCurrentStepInSection (sectionSteps) {
379
+ if (!sectionSteps || sectionSteps.length === 0) return 0
380
+
381
+ const currentStepIndex = sectionSteps.findIndex(step => step.id === this.currentStepId)
382
+ return currentStepIndex >= 0 ? currentStepIndex + 1 : 0
383
+ },
384
+
385
+ // 获取步骤编号
386
+ getStepNumber (segmentIndex, stepIndex) {
387
+ const segments = this.getTimelineSegments()
388
+ let stepNumber = 0
389
+
390
+ // 计算前面所有段落的步骤数
391
+ for (let i = 0; i < segmentIndex; i++) {
392
+ const segment = segments[i]
393
+ if (segment.type === 'main') {
394
+ stepNumber += segment.steps.length
395
+ } else if (segment.type === 'parallel') {
396
+ // 并行分支计算总步骤数
397
+ stepNumber += segment.branches.reduce((total, branch) => total + branch.length, 0)
398
+ }
399
+ }
400
+
401
+ return stepNumber + stepIndex
402
+ },
403
+
404
+ // 判断步骤是否已完成
405
+ isStepCompleted (step) {
406
+ if (!step) return false
407
+ return step.id < this.currentStepId || this.state
408
+ },
409
+
410
+ // 判断id是否为流程中最后一个
411
+ isLastStep (stepId) {
412
+ return stepId >= this.steps.length
413
+ },
414
+
415
+ // 判断是否为并行步骤
416
+ isParallelStep (step) {
417
+ return step.properties &&
418
+ step.properties.branchPath &&
419
+ step.properties.branchPath.includes('parallel_')
420
+ },
421
+
422
+ // 动态展示时间线节点颜色
423
+ getStepIconColor (index, sectionSteps) {
424
+ if (!sectionSteps || !sectionSteps[index - 1]) return 'gray'
425
+
426
+ const stepId = sectionSteps[index - 1].id
427
+
428
+ if (this.changeAble && stepId === this.displayStepId) {
429
+ return 'yellow'
430
+ } else if (!this.changeAble && stepId === this.currentStepId) {
431
+ return this.state ? 'blue' : 'green'
432
+ }
433
+ if (stepId < this.currentStepId || this.state) {
434
+ return 'blue'
435
+ }
436
+ if (stepId === this.currentStepId) {
437
+ return this.isOverdue ? 'red' : 'blue'
438
+ }
439
+ return 'gray'
440
+ },
441
+
442
+ // 获取分支步骤的CSS类
443
+ getBranchStepClass (step) {
444
+ if (!step) return 'branch-step-gray'
445
+
446
+ // 如果在可编辑状态下且是当前显示的步骤
447
+ if (this.changeAble && step.id === this.displayStepId) {
448
+ return 'branch-step-yellow'
449
+ }
450
+
451
+ // 根据 status 判断颜色
452
+ switch (step.status) {
453
+ case 0: // 未处理
454
+ return 'branch-step-gray'
455
+ case 1: // 正在处理
456
+ // 检查是否逾期
457
+ if (step.deadline && !this.state && this.formatDate(new Date(), 'yyyy-MM-dd hh:mm') > step.deadline) {
458
+ return 'branch-step-red'
459
+ }
460
+ return 'branch-step-blue'
461
+ case 2: // 已处理
462
+ return 'branch-step-green'
463
+ default:
464
+ return 'branch-step-gray'
465
+ }
466
+ },
467
+
468
+ // 获取分支时间轴的CSS类(根据分支中的步骤状态)
469
+ getBranchTimelineClass (branch) {
470
+ if (!branch || branch.length === 0) return 'branch-timeline-gray'
471
+
472
+ // 检查分支中所有步骤的状态
473
+ const hasCompleted = branch.some(step => step.status === 2) // 有已完成的
474
+ const hasProcessing = branch.some(step => step.status === 1) // 有正在处理的
475
+ const allPending = branch.every(step => step.status === 0 || step.status === undefined) // 全部未处理
476
+
477
+ // 优先级:正在处理 > 已完成 > 未处理
478
+ if (hasProcessing) {
479
+ return 'branch-timeline-blue' // 正在进行
480
+ } else if (hasCompleted) {
481
+ return 'branch-timeline-green' // 已完成
482
+ } else if (allPending) {
483
+ return 'branch-timeline-gray' // 未抵达
484
+ } else {
485
+ return 'branch-timeline-gray' // 默认
486
+ }
487
+ },
488
+
489
+ onStepClick (stepId) {
490
+ if (!this.changeAble || stepId === this.displayStepId) {
491
+ return
492
+ }
493
+ const curStep = this.steps.find(item => item.id === stepId)
494
+ if (stepId > this.currentStepId && curStep.status !== 1 && curStep.status !== 2) {
495
+ return this.$message.warn('请先完成当前步骤')
496
+ }
497
+ this.$emit('activeStep', stepId)
498
+ this.displayStepId = stepId
499
+ },
500
+
501
+ formatDate,
502
+ },
503
+ watch: {
504
+ activeStepId: function (newVal) {
505
+ this.displayStepId = newVal
506
+ }
507
+ }
508
+ }
509
+ </script>
510
+
511
+ <style lang="less" scoped>
512
+ .timeline-wrapper {
513
+ display: flex;
514
+ align-items: flex-start;
515
+ gap: 0;
516
+
517
+ .timeline-section {
518
+ flex-shrink: 0;
519
+
520
+ // 主时间轴自动填充剩余宽度
521
+ &.main-timeline {
522
+ flex: 1;
523
+ }
524
+
525
+ /deep/ .ant-steps-dot {
526
+ margin-bottom: 6px;
527
+ .ant-steps-item-tail {
528
+ top: 7px;
529
+ margin-left: 106px;
530
+ width: calc(100% - 23px);
531
+ }
532
+ .ant-steps-item-icon {
533
+ margin-left: 90px;
534
+ width: 8px;
535
+ height: 8px;
536
+ line-height: 8px;
537
+ }
538
+ .ant-steps-item-content {
539
+ min-width: 195px;
540
+ margin-top: 24px;
541
+ .ant-steps-item-description {
542
+ text-align: left;
543
+ background: #fff;
544
+ border-radius: 4px;
545
+ padding: 12px;
546
+ position: relative;
547
+
548
+ p {
549
+ position: relative;
550
+ padding: 8px 0;
551
+ margin: 0;
552
+ font-size: 13px;
553
+ color: #595959;
554
+ line-height: 1.5;
555
+ white-space: nowrap;
556
+ overflow: visible;
557
+
558
+ &:first-child {
559
+ border-top: 1px dotted #e8e8e8;
560
+ }
561
+
562
+ &:not(:last-child) {
563
+ border-bottom: 1px dashed #f0f0f0;
564
+ }
565
+
566
+ &:last-child {
567
+ padding-bottom: 0;
568
+ }
569
+ }
570
+ }
571
+ }
572
+ &.ant-steps {
573
+ padding-top: 8px;
574
+ }
575
+ }
576
+
577
+ /deep/ .ant-steps-item-title {
578
+ font-size: 14px;
579
+ h3 {
580
+ font-size: 14px;
581
+ margin-bottom: 0;
582
+ }
583
+ }
584
+ }
585
+
586
+ .parallel-section {
587
+ display: flex;
588
+ align-items: flex-start;
589
+ position: relative;
590
+
591
+ .connection-line {
592
+ width: 2rem;
593
+ height: 0;
594
+ flex-shrink: 0;
595
+ margin-top: 1rem;
596
+
597
+ &.left-line {
598
+ margin-right: 0;
599
+ position: relative;
600
+
601
+ &::before {
602
+ content: '';
603
+ position: absolute;
604
+ left: -4.8rem;
605
+ top: -1px;
606
+ width: 7rem;
607
+ height: 3px;
608
+ background: #f0f0f0;
609
+ }
610
+ }
611
+
612
+ &.right-line {
613
+ margin-left: 0;
614
+ position: relative;
615
+
616
+ &::before {
617
+ content: '';
618
+ position: absolute;
619
+ right: -4.6rem;
620
+ top: -1px;
621
+ width: 6.8rem;
622
+ height: 3px;
623
+ background: #f0f0f0;
624
+ }
625
+ }
626
+ }
627
+
628
+ .parallel-branches-container {
629
+ display: flex;
630
+ flex-direction: column; /* 竖直排列分支节点 */
631
+ gap: 6px; /* 缩小间距 */
632
+ align-items: center;
633
+ position: relative;
634
+ border: 2px dotted #d9d9d9;
635
+ border-radius: 8px;
636
+ margin: 0 12px;
637
+ background: #fff;
638
+ padding-bottom: 14px;
639
+ width: max-content;
640
+
641
+ /* 为并行节点容器添加小标题 */
642
+ .parallel-node-title {
643
+ position: absolute;
644
+ bottom: -10px; /* 调整标题的上下位置 */
645
+ left: 50%; /* 水平居中 */
646
+ transform: translateX(-50%); /* 精确水平居中 */
647
+ background: #fff; /* 背景色与容器一致 */
648
+ font-size: 12px; /* 标题的字体大小 */
649
+ border-radius: 4px;
650
+ }
651
+ }
652
+
653
+ .branch-row {
654
+ display: flex;
655
+ flex-direction: column;
656
+ align-items: center;
657
+ position: relative;
658
+ gap: 16px;
659
+
660
+ :deep(.ant-steps-item-content) {
661
+ text-align: left;
662
+ }
663
+
664
+ .branch-timeline {
665
+ padding: 12px 16px;
666
+ position: relative;
667
+ min-width: 80px;
668
+ text-align: center;
669
+ transition: all 0.3s ease; /* 平滑过渡 */
670
+ }
671
+
672
+ .branch-timeline:hover {
673
+ transform: scale(1.01); /* 鼠标悬停时放大 */
674
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
675
+ }
676
+
677
+ .branch-step-title {
678
+ font-size: 14px;
679
+ font-weight: 500;
680
+ color: #262626;
681
+ cursor: pointer;
682
+ }
683
+
684
+ .branch-step-desc {
685
+ p {
686
+ margin: 0;
687
+ padding: 4px 0;
688
+ font-size: 12px;
689
+ color: #666;
690
+ }
691
+ }
692
+
693
+ /deep/ .ant-steps-icon {
694
+ color: #fefefe;
695
+ }
696
+
697
+ // 分支步骤节点样式
698
+ /deep/ .ant-steps-item-icon {
699
+ width: 20px;
700
+ height: 20px;
701
+ line-height: 20px;
702
+ border-radius: 20px;
703
+ }
704
+
705
+ /deep/ .ant-steps-item-title {
706
+ line-height: 20px;
707
+ }
708
+
709
+ // 分支步骤状态颜色
710
+ /deep/ .branch-step-gray .ant-steps-item-icon {
711
+ background-color: #bfbfbf !important;
712
+ border-color: #bfbfbf !important;
713
+ }
714
+
715
+ /deep/ .branch-step-blue .ant-steps-item-icon {
716
+ background-color: #1890ff !important;
717
+ border-color: #1890ff !important;
718
+ }
719
+
720
+ /deep/ .branch-step-green .ant-steps-item-icon {
721
+ background-color: #52c41a !important;
722
+ border-color: #52c41a !important;
723
+ }
724
+
725
+ /deep/ .branch-step-red .ant-steps-item-icon {
726
+ background-color: #ff4d4f !important;
727
+ border-color: #ff4d4f !important;
728
+ }
729
+
730
+ /deep/ .branch-step-yellow .ant-steps-item-icon {
731
+ background-color: #faad14 !important;
732
+ border-color: #faad14 !important;
733
+ }
734
+ }
735
+ }
736
+
737
+ @red: rgb(255, 77, 79);
738
+
739
+ .step-icon-filled {
740
+ position: absolute;
741
+ top: -2px;
742
+ left: -6px;
743
+ @blue: rgb(24, 144, 255);
744
+ @yellow: rgb(255, 164, 39);
745
+ @gray: rgb(191, 191, 191);
746
+ &.digital {
747
+ width: 28px;
748
+ line-height: 28px;
749
+ border-radius: 50%;
750
+ color: #ffffff;
751
+ &.blue {
752
+ background: @blue;
753
+ }
754
+ &.yellow {
755
+ background: @yellow;
756
+ }
757
+ &.gray {
758
+ background: @gray;
759
+ }
760
+ &.red {
761
+ background: @red;
762
+ }
763
+ }
764
+ &.icon {
765
+ font-size: 28px;
766
+ &.blue {
767
+ color: @blue;
768
+ }
769
+ &.yellow {
770
+ color: @yellow;
771
+ }
772
+ &.gray {
773
+ color: @gray;
774
+ }
775
+ }
776
+ }
777
+
778
+ .step-item {
779
+ cursor: pointer;
780
+ &:hover {
781
+ .ant-steps-item-description {
782
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
783
+ transform: translateY(-1px);
784
+ transition: all 0.3s ease;
785
+ }
786
+ p {
787
+ color: #262626;
788
+ }
789
+ }
790
+ .text-red {
791
+ color: @red !important;
792
+ }
793
+ }
794
+
795
+ .next-step-overdue {
796
+ /deep/ .ant-steps-item-tail::after {
797
+ background: @red;
798
+ }
799
+ }
800
+
801
+ // 新增样式:步骤标题容器
802
+ .step-title-container {
803
+ .condition-indicators {
804
+ margin-top: 8px;
805
+ display: flex;
806
+ align-items: center;
807
+ gap: 8px;
808
+
809
+ .condition-tag {
810
+ margin: 0;
811
+ }
812
+
813
+ .condition-help {
814
+ color: #999;
815
+ cursor: pointer;
816
+ &:hover {
817
+ color: #1890ff;
818
+ }
819
+ }
820
+ }
821
+ }
822
+
823
+ // 分支信息样式
824
+ .branch-info {
825
+ margin-top: 8px;
826
+ padding: 8px;
827
+ background: #f9f9f9;
828
+ border-radius: 4px;
829
+ border-left: 3px solid #722ed1;
830
+
831
+ .branch-title {
832
+ margin: 0 0 6px 0 !important;
833
+ font-weight: bold;
834
+ color: #722ed1;
835
+ font-size: 12px;
836
+ padding: 0 !important;
837
+ border: none !important;
838
+ }
839
+
840
+ .branch-options {
841
+ display: flex;
842
+ flex-wrap: wrap;
843
+ gap: 4px;
844
+
845
+ .branch-option-tag {
846
+ margin: 0;
847
+ font-size: 11px;
848
+ }
849
+ }
850
+ }
851
+
852
+ // 省略步骤样式
853
+ .more-steps-section {
854
+ flex-shrink: 0;
855
+ // margin-top: 24px;
856
+
857
+ .more-steps-item {
858
+ opacity: 0.7;
859
+
860
+ .more-steps-container {
861
+ .pending-tag {
862
+ margin-top: 8px;
863
+ margin-left: 0;
864
+ }
865
+ }
866
+
867
+ .more-steps-desc {
868
+ p {
869
+ // font-style: italic;
870
+ color: #999 !important;
871
+
872
+ &.steps-count {
873
+ font-weight: bold;
874
+ color: #666 !important;
875
+ }
876
+ }
877
+ }
878
+ }
879
+ }
880
+ }
881
+
882
+ // 分支步骤 Popover 样式
883
+ /deep/ .ant-popover {
884
+ .popover-title {
885
+ display: flex;
886
+ align-items: center;
887
+ gap: 6px;
888
+ font-weight: 600;
889
+ color: #1890ff;
890
+
891
+ .anticon {
892
+ font-size: 14px;
893
+ }
894
+ }
895
+
896
+ .branch-step-popover {
897
+ min-width: 200px;
898
+
899
+ .popover-item {
900
+ display: flex;
901
+ align-items: flex-start;
902
+ margin-bottom: 8px;
903
+
904
+ &:last-child {
905
+ margin-bottom: 0;
906
+ }
907
+
908
+ &.no-data {
909
+ justify-content: center;
910
+ font-style: italic;
911
+ color: #999;
912
+ }
913
+
914
+ .popover-label {
915
+ font-weight: 600;
916
+ color: #262626;
917
+ min-width: 70px;
918
+ flex-shrink: 0;
919
+ }
920
+
921
+ .popover-value {
922
+ color: #595959;
923
+ word-break: break-all;
924
+ flex: 1;
925
+ }
926
+ }
927
+ }
928
+ }
929
+ </style>