vue2-client 1.15.14 → 1.15.15

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.
@@ -90,6 +90,40 @@
90
90
  @x-form-item-emit-func="formItemEmitFunc"
91
91
  @onSubmit="submitForm"/>
92
92
  <a-divider/>
93
+
94
+ <!-- 分支节点状态提示 -->
95
+ <a-alert
96
+ v-if="isBranchLastNode.isBranchNode && !isBranchLastNode.isLastBranch"
97
+ type="info"
98
+ show-icon
99
+ style="margin-bottom: 16px"
100
+ >
101
+ <template slot="message">
102
+ <span style="font-weight: bold;">分支节点等待中</span>
103
+ </template>
104
+ <template slot="description">
105
+ <div>当前为分支节点,其他分支仍在进行中。完成当前分支后将等待其他分支完成,然后自动汇合到下一环节。</div>
106
+ <div style="margin-top: 8px; color: #666; font-size: 12px;">
107
+ <a-icon type="info-circle" style="margin-right: 4px;" />
108
+ 提示:此操作无需选择下一环节负责人,系统将自动处理流程流转。
109
+ </div>
110
+ </template>
111
+ </a-alert>
112
+
113
+ <a-alert
114
+ v-if="isBranchLastNode.isBranchNode && isBranchLastNode.isLastBranch"
115
+ type="success"
116
+ show-icon
117
+ style="margin-bottom: 16px"
118
+ >
119
+ <template slot="message">
120
+ <span style="font-weight: bold;">分支汇合节点</span>
121
+ </template>
122
+ <template slot="description">
123
+ <div>您正在处理最后一个未完成的分支节点,完成后将触发分支汇合并进入下一环节。</div>
124
+ </template>
125
+ </a-alert>
126
+
93
127
  <a-form v-show="!lastStep" label-align="left" :label-col="{ span: 3 }" :wrapper-col="{ span: 13 }">
94
128
  <a-form-item v-if="showStepNextBtn" label="操作类型" required>
95
129
  <a-radio-group v-model="operationType" @change="handleOperationTypeChange">
@@ -97,9 +131,14 @@
97
131
  <a-radio value="skip">{{ stepNextBtnTitle }}</a-radio>
98
132
  </a-radio-group>
99
133
  </a-form-item>
100
- <!-- 智能分支人员选择组件 -->
101
- <WorkflowPersonSelector ref="personSelector"/>
134
+
135
+ <!-- 智能分支人员选择组件 - 只有非分支节点或最后一个分支才显示 -->
136
+ <WorkflowPersonSelector
137
+ v-if="!isBranchLastNode.isBranchNode || isBranchLastNode.isLastBranch"
138
+ ref="personSelector"/>
139
+
102
140
  <a-form-item
141
+ v-if="!isBranchLastNode.isBranchNode || isBranchLastNode.isLastBranch"
103
142
  label="下一环节截止时间"
104
143
  :validate-status="deadlineValidateStatus"
105
144
  :help="deadlineHelp"
@@ -142,7 +181,13 @@
142
181
  <template>
143
182
  <a-popover v-if="operationType === 'submit'">
144
183
  <template slot="content">
145
- <p>{{ nextBtnTitle }}</p>
184
+ <p v-if="isBranchLastNode.isBranchNode && !isBranchLastNode.isLastBranch">
185
+ 完成当前分支,等待其他分支完成后自动汇合
186
+ </p>
187
+ <p v-else-if="isBranchLastNode.isBranchNode && isBranchLastNode.isLastBranch">
188
+ 完成最后一个分支并触发汇合到下一环节
189
+ </p>
190
+ <p v-else>{{ nextBtnTitle }}</p>
146
191
  </template>
147
192
  <a-button
148
193
  v-show="!lastStep"
@@ -262,6 +307,55 @@ export default {
262
307
  return this
263
308
  },
264
309
  ...mapState('account', { currUser: 'user' }),
310
+ // 判断当前节点的分支状态
311
+ isBranchLastNode () {
312
+ // 默认返回值
313
+ const defaultResult = {
314
+ isBranchNode: false, // 是否为分支流程中的节点
315
+ isLastBranch: false // 是否为最后一个未完成的分支(需要选择下一环节人员)
316
+ }
317
+
318
+ // 如果是最后一步或没有下一步或者不能提交,则不是分支节点
319
+ if (this.lastStep || !this.nextBtnTo || !this.canSubmit) {
320
+ return defaultResult
321
+ }
322
+
323
+ // 检查下一个节点是否为分支退出节点
324
+ const nextStep = this.stepsDefine.find(step => step.id === this.nextBtnTo)
325
+
326
+ // 如果下一个节点的flowRole不是branchExit,说明不是分支的最后一个节点
327
+ if (!nextStep || nextStep.properties?.flowRole !== 'branchExit') {
328
+ return defaultResult
329
+ }
330
+
331
+ // 获取分支退出节点等待的所有分支步骤ID
332
+ const waitStepIds = nextStep.properties.waitStepIds || []
333
+ if (waitStepIds.length === 0) {
334
+ return {
335
+ isBranchNode: true,
336
+ isLastBranch: true // 如果没有等待步骤配置,默认认为是最后一个
337
+ }
338
+ }
339
+
340
+ // 当前步骤必须在等待列表中才算是分支节点
341
+ if (!waitStepIds.includes(this.activeStepId)) {
342
+ return defaultResult
343
+ }
344
+
345
+ // 检查除当前步骤外的其他分支步骤状态
346
+ const otherBranchSteps = waitStepIds.filter(stepId => stepId !== this.activeStepId)
347
+
348
+ // 判断其他所有分支步骤是否都已完成(状态为2)
349
+ const allOtherBranchesCompleted = otherBranchSteps.every(stepId => {
350
+ const step = this.stepsForChild.find(s => s.id === stepId)
351
+ return step && step.status === 2 // 已处理
352
+ })
353
+
354
+ return {
355
+ isBranchNode: true, // 当前节点是分支流程中的节点
356
+ isLastBranch: allOtherBranchesCompleted // 只有当其他所有分支都已完成时,当前分支才是最后一个
357
+ }
358
+ },
265
359
  canSubmit () {
266
360
  // 对于超级管理员直接认为可以提交
267
361
  if (this.currUser.rolesnames.indexOf('超级管理员') > -1) {
@@ -271,10 +365,9 @@ export default {
271
365
  if (!this.currentStepId) {
272
366
  return false
273
367
  }
274
-
368
+ const activeStep = this.stepsForChild.find(item => item.id === this.activeStepId)
275
369
  // 如果当前选中节点不是正在进行的节点,则判断viewers权限
276
- if (this.activeStepId !== this.currentStepId) {
277
- const activeStep = this.stepsForChild.find(item => item.id === this.activeStepId)
370
+ if (this.activeStepId !== this.currentStepId && activeStep != null && activeStep.status !== 1) {
278
371
  // 历史节点为当前登录人操作则不做查看数据权限校验
279
372
  if (activeStep.handler === this.currUser.name) {
280
373
  return true
@@ -297,7 +390,7 @@ export default {
297
390
  return true
298
391
  }
299
392
  } else {
300
- const step = this.stepsForChild.find(item => item.id === this.currentStepId)
393
+ const step = this.stepsForChild.find(item => item.id === this.activeStepId)
301
394
  // 检查角色和部门权限
302
395
  if (step && step.properties && step.properties.chargePerson) {
303
396
  if (step.properties.chargePerson.personList && step.properties.chargePerson.personList.length > 0) {
@@ -420,8 +513,9 @@ export default {
420
513
  // 分支节点相关数据
421
514
  branchNodes: [], // 需要选择人员的分支节点列表
422
515
  branchChargePersons: {}, // 分支节点人员选择 格式:{stepId: personId}
423
- isWfResultBranch: false, // 是否包含WF_RESULT的分支
424
- calculatedTargetNode: null // 前台计算出的目标节点
516
+ needMultipleBranchSelection: false, // 是否需要为多个分支节点预先选择人员(包含WF_RESULT的条件分支或并行分支)
517
+ calculatedTargetNode: null, // 前台计算出的目标节点
518
+ currentBranchActions: null // 缓存当前的分支动作,避免重复调用
425
519
  }
426
520
  },
427
521
  async mounted () {
@@ -456,6 +550,17 @@ export default {
456
550
  details: {
457
551
  type: Object,
458
552
  required: true
553
+ },
554
+ // 展开详情初始化的节点
555
+ // 适用于不让第一个节点默认展示的情况
556
+ initStepId: {
557
+ type: [String, Number],
558
+ required: false,
559
+ default: null
560
+ },
561
+ renderCurrentNode: {
562
+ type: Boolean,
563
+ default: true
459
564
  }
460
565
  },
461
566
  methods: {
@@ -484,8 +589,9 @@ export default {
484
589
  // 清理分支节点相关数据
485
590
  this.branchNodes = []
486
591
  this.branchChargePersons = {}
487
- this.isWfResultBranch = false
592
+ this.needMultipleBranchSelection = false
488
593
  this.calculatedTargetNode = null
594
+ this.currentBranchActions = null
489
595
  },
490
596
  async showQueryFormItemFunc () {
491
597
  if (this.attr.showQueryFormItemFunc) {
@@ -520,8 +626,15 @@ export default {
520
626
  workflowId: this.workflowId
521
627
  })
522
628
  .then(res => {
523
- this.currentStepId = res.id
524
- const currentStep = this.stepsForChild.find(item => item.id === res.id)
629
+ // 优先级:主动传入的 > 获取到的
630
+ this.currentStepId = this.initStepId || res.id
631
+
632
+ // 如果指定了具体节点,同时设置activeStepId
633
+ if (this.initStepId) {
634
+ this.activeStepId = this.initStepId
635
+ }
636
+
637
+ const currentStep = this.stepsForChild.find(item => item.id === this.currentStepId)
525
638
  res.state = currentStep.name
526
639
  // 获取到当前步骤后复制下一步时间
527
640
  this.deadline = this.getDefaultDeadline(currentStep.properties?.otherProperty?.nextNodeInterval)
@@ -553,43 +666,73 @@ export default {
553
666
  }
554
667
  )
555
668
  })
669
+ }).catch(err => {
670
+ if (err && err.message === 'Form validation failed') {
671
+ this.$message.error('请检查表单必填项!')
672
+ } else {
673
+ // 对于其他错误,继续向上抛出
674
+ throw err
675
+ }
556
676
  })
557
677
  },
558
678
  // 三个按钮点击后逻辑
559
679
  async nextClick () {
680
+ // 检查是否为非最后分支节点
681
+ const branchStatus = this.isBranchLastNode
682
+ const isWaitingBranch = branchStatus.isBranchNode && !branchStatus.isLastBranch
683
+
560
684
  const extraData = this.getApplyStepExtraData(this.nextBtnTo)
561
685
  if (!extraData) {
562
686
  return
563
687
  }
688
+
689
+ // 确认对话框
690
+ const confirmContent = isWaitingBranch
691
+ ? '确定完成当前分支么?完成后将等待其他分支,不会立即流转到下一环节。'
692
+ : '确定提交么?提交之后数据不可更改!'
693
+
564
694
  await new Promise(resolve => {
565
695
  this.$confirm({
566
696
  title: '提交确认',
567
- content: '确定提交么?提交之后数据不可更改!',
697
+ content: confirmContent,
568
698
  onOk () {
569
699
  resolve()
570
700
  return Promise.resolve()
571
701
  }
572
702
  })
573
703
  })
704
+
574
705
  this.$refs.xAddForm.asyncSubmit().then(res => {
575
706
  this.submitForm(res).then(_ => {
576
707
  postByServiceName(workFlowViewApi.submitToNextStep, extraData)
577
708
  .then(
578
709
  () => {
579
- const extra = {
580
- setHandler: this.getStepHandler(),
581
- setDeadline: this.deadline,
582
- notes: this.note.trim()
710
+ let successMessage = '提交成功'
711
+
712
+ // 只有非等待分支节点才保存工作流日志
713
+ if (!isWaitingBranch) {
714
+ const branchStatus = this.isBranchLastNode
715
+ const operation = branchStatus.isBranchNode && branchStatus.isLastBranch ? '分支汇合' : '提交'
716
+
717
+ const extra = {
718
+ setHandler: this.getStepHandler(),
719
+ setDeadline: this.deadline,
720
+ notes: this.note.trim()
721
+ }
722
+ this.saveWorkflowLog(operation, this.generateBranchStepChangeText(this.currentStepId), extra)
723
+ } else {
724
+ successMessage = '分支完成,等待其他分支完成后自动汇合'
583
725
  }
584
- this.saveWorkflowLog('提交', this.generateStepChangeText(this.currentStepId, this.nextBtnTo), extra)
585
- this.$message.success('提交成功')
726
+
727
+ this.$message.success(successMessage)
586
728
  this.loading = true
587
729
  this.loadingHistory = true
588
730
  this.$emit('nextClick', {
589
731
  note: this.note.trim(),
590
732
  form: res.realForm,
591
733
  workflowId: this.workflowId,
592
- ...this.generateStepChange(this.currentStepId, this.nextBtnTo)
734
+ isBranchWaiting: isWaitingBranch, // 标记是否为分支等待状态
735
+ ...this.generateStepChange(this.currentStepId, this.nextBtnTo)
593
736
  })
594
737
  this.$emit('refresh')
595
738
  this.onClose()
@@ -601,6 +744,13 @@ export default {
601
744
  }
602
745
  )
603
746
  })
747
+ }).catch((err) => {
748
+ if (err && err.message === 'Form validation failed') {
749
+ this.$message.error('请检查表单必填项!')
750
+ } else {
751
+ // 对于其他错误,继续向上抛出
752
+ throw err
753
+ }
604
754
  })
605
755
  },
606
756
  async preClick () {
@@ -645,13 +795,13 @@ export default {
645
795
  setDeadline: this.deadline,
646
796
  notes: this.note.trim()
647
797
  }
648
- this.saveWorkflowLog('跳过', this.generateStepChangeText(this.currentStepId, this.stepNextBtnTo), extra)
798
+ this.saveWorkflowLog('跳过', this.generateBranchStepChangeText(this.currentStepId), extra)
649
799
  this.$message.success('提交成功')
650
800
  this.$emit('nextClick', {
651
801
  note: this.note.trim(),
652
802
  form: res.realForm,
653
803
  workflowId: this.workflowId,
654
- ...this.generateStepChange(this.currentStepId, this.stepNextBtnTo)
804
+ ...this.generateStepChange(this.currentStepId, this.stepNextBtnTo)
655
805
  })
656
806
  this.loading = true
657
807
  this.loadingHistory = true
@@ -665,6 +815,13 @@ export default {
665
815
  }
666
816
  )
667
817
  })
818
+ }).catch(err => {
819
+ if (err && err.message === 'Form validation failed') {
820
+ this.$message.error('请检查表单必填项!')
821
+ } else {
822
+ // 对于其他错误,继续向上抛出
823
+ throw err
824
+ }
668
825
  })
669
826
  },
670
827
  // 获取当前步骤节点,连通的节点
@@ -674,7 +831,6 @@ export default {
674
831
  id: this.workflowId
675
832
  })
676
833
  .then(async res => {
677
- res = JSON.parse(res.value)
678
834
  this.directions = []
679
835
  this.stepsDefine = res.steps
680
836
  await this.resolveDirections()
@@ -685,7 +841,7 @@ export default {
685
841
  },
686
842
  // 分析当前节点,能通向的节点
687
843
  async resolveDirections () {
688
- const currentStep = this.stepsForChild.find(item => item.id === this.currentStepId)
844
+ const currentStep = this.stepsForChild.find(item => item.id === this.activeStepId)
689
845
  if (currentStep?.properties?.actions) {
690
846
  this.currentDirections = currentStep.properties.actions
691
847
  }
@@ -706,6 +862,10 @@ export default {
706
862
  getStepNameByStepId (stepId) {
707
863
  return this.stepsDefine.find(item => item.id === stepId)?.name
708
864
  },
865
+ // 根据步骤id获取步骤状态
866
+ getStepStatusByStepId (stepId) {
867
+ return this.stepsForChild.find(item => item.id === stepId)?.status
868
+ },
709
869
  // 表单提交的回调
710
870
  submitForm (obj) {
711
871
  this.formValid = true
@@ -713,7 +873,7 @@ export default {
713
873
  const time = this.format(new Date(), 'yyyy-MM-dd hh:mm:ss')
714
874
  return postByServiceName(workFlowViewApi.saveWorkFlowStepFormData, {
715
875
  workflowId: this.workflowId,
716
- stepId: this.currentStepId,
876
+ stepId: this.activeStepId,
717
877
  form: formData,
718
878
  data: time,
719
879
  handler: this.currUser.name,
@@ -733,8 +893,8 @@ export default {
733
893
  )
734
894
  },
735
895
  // 获取当前步骤定义内容,构建组件
736
- buildComp () {
737
- const properties = this.stepsDefine.find(item => item.id === this.currentStep.id).properties
896
+ async buildComp (stepId) {
897
+ const properties = this.stepsDefine.find(item => item.id === stepId).properties
738
898
  // 表单的渲染
739
899
  if (properties.form && properties.form.formJson) {
740
900
  this.stepDefine = properties.form.formJson
@@ -753,11 +913,10 @@ export default {
753
913
  }
754
914
  // Tab的渲染
755
915
  this.tabDesigner = properties.tabDesigner
756
- if (this.tabDesigner) {
757
- this.showTab = true
758
- } else {
759
- this.showTab = false
760
- }
916
+ this.showTab = !!this.tabDesigner
917
+ // 以当前激活节点分析节点
918
+ await this.resolveDirections()
919
+ this.resolveStep()
761
920
  },
762
921
  // 根据当前节点,判断之后流程,以及按钮的显示
763
922
  workflowControl () {
@@ -835,7 +994,7 @@ export default {
835
994
  // 加载完成
836
995
  resolveStep () {
837
996
  // 获取当前步骤的按钮组配置
838
- const currentStep = this.stepsDefine.find(item => item.id === this.currentStepId)
997
+ const currentStep = this.stepsDefine.find(item => item.id === this.activeStepId)
839
998
  if (currentStep && currentStep.properties && currentStep.properties.buttonGroup) {
840
999
  this.buttonGroup = currentStep.properties.buttonGroup
841
1000
  } else {
@@ -845,18 +1004,18 @@ export default {
845
1004
  },
846
1005
  // 流程图组件给当前组件传值用,stepNo为用户点击的非当前步骤
847
1006
  async activeStep (stepId) {
848
- console.log('activeStep', stepId)
849
1007
  // 开启加载
850
1008
  this.loadingHistory = true
851
1009
  this.activeStepId = stepId
852
1010
  // 获取激活节点的步骤名
853
1011
  this.activeStepName = this.getStepNameByStepId(stepId)
1012
+ const status = this.getStepStatusByStepId(stepId)
854
1013
  // 清空回显数据
855
1014
  this.formCompletedData = {}
856
1015
  let formCompletedDataPreview = null
857
1016
  this.getStepDefine(stepId)
858
- // 判断激活的节点,是不是待完成节点
859
- if (this.activeStepName !== this.currentStep.state || this.workflowState) {
1017
+ // 判断激活的节点,是不是待完成节点 (当前节点或者 当前节点状态是1的)
1018
+ if ((this.activeStepName !== this.currentStep.state && status !== 1) || this.workflowState) {
860
1019
  // 获取激活节点历史数据,和字段定义
861
1020
  await this.getCompletedFormData(stepId)
862
1021
  // 将回显数据拷贝,避免引用传递
@@ -914,7 +1073,13 @@ export default {
914
1073
  } else {
915
1074
  this.loadingHistory = false
916
1075
  this.beforeStepActive = false
917
- this.buildComp()
1076
+ if (!this.renderCurrentNode) {
1077
+ this.formCompletedDataPreview = null
1078
+ this.showTab = false
1079
+ this.beforeStepActive = true
1080
+ return
1081
+ }
1082
+ await this.buildComp(this.activeStepId)
918
1083
  }
919
1084
  },
920
1085
  // 获取已经完成步骤的数据
@@ -937,15 +1102,14 @@ export default {
937
1102
  const stepName = this.getStepNameByStepId(stepId)
938
1103
  this.targetStepDefine = this.getSingleStepDefine(stepName).formJson
939
1104
  },
940
- // 获取指定步骤额外数据
1105
+ // 获取提交步骤的额外数据
941
1106
  getApplyStepExtraData (stepId) {
942
- // if (!this.checkDeadline(true)) {
943
- // return false
944
- // }
1107
+ // 验证人员选择 - 只有在需要显示人员选择器的情况下才验证
1108
+ // 判断条件与模板中的 WorkflowPersonSelector 显示条件保持一致
1109
+ const shouldShowPersonSelector = !this.isBranchLastNode.isBranchNode || this.isBranchLastNode.isLastBranch
945
1110
 
946
- // 验证人员选择
947
- if (this.needSelectPerson) {
948
- if (this.isWfResultBranch) {
1111
+ if (shouldShowPersonSelector && this.needSelectPerson) {
1112
+ if (this.needMultipleBranchSelection) {
949
1113
  // 多分支情况:检查是否所有需要的分支都选择了人员
950
1114
  const missingSelections = this.branchNodes.filter(node => !this.branchChargePersons[node.stepId])
951
1115
  if (missingSelections.length > 0) {
@@ -962,35 +1126,66 @@ export default {
962
1126
  }
963
1127
  }
964
1128
 
965
- const stepHandler = this.getStepHandler()
1129
+ // 统一获取目标步骤IDs
1130
+ let stepIds = []
1131
+ if (this.needMultipleBranchSelection) {
1132
+ // 多分支选择:获取所有分支的目标stepId(包括不需要选择人员的)
1133
+ if (!this.currentBranchActions) {
1134
+ this.currentBranchActions = this.getBranchActions()
1135
+ }
1136
+ stepIds = this.currentBranchActions.allBranchActions.map(action => action.to)
1137
+ } else if (this.calculatedTargetNode) {
1138
+ // 条件判断节点:使用计算出的目标节点
1139
+ stepIds = [this.calculatedTargetNode]
1140
+ } else {
1141
+ // 普通节点:使用传入的stepId
1142
+ stepIds = [stepId]
1143
+ }
1144
+ // 处理bug 有的时候没带到 branchChargePersons 先循环在同一地方处理
1145
+ stepIds.forEach(stepItemId => {
1146
+ if (!this.branchChargePersons[stepItemId]) {
1147
+ const chargePerson = this.stepsForChild.find(item => item.id === stepItemId)?.properties?.chargePerson
1148
+ this.branchChargePersons[stepItemId] = this.normalizeChargePersonFormat(chargePerson)
1149
+ }
1150
+ })
966
1151
 
967
1152
  return {
968
1153
  workflowId: this.workflowId,
969
- stepId,
1154
+ activeStepId: this.activeStepId,
1155
+ stepId, // 当前步骤ID
1156
+ stepIds, // 目标步骤IDs数组(统一格式)
970
1157
  name: this.getStepNameByStepId(stepId),
971
- handler: stepHandler,
1158
+ handler: this.getStepHandler(),
972
1159
  handlerId: this.checkedChargePerson,
973
1160
  needSelectPerson: this.needSelectPerson,
974
1161
  personList: this.chargePerson.personList,
975
1162
  deadline: this.deadline,
976
1163
  submitUser: this.currUser.name,
977
1164
  submitUserId: this.currUser.id,
978
- // 新增:分支节点信息
979
1165
  branchChargePersons: this.branchChargePersons
980
1166
  }
981
1167
  },
1168
+
982
1169
  // 获取当前选择的负责人
983
1170
  getStepHandler () {
984
1171
  let stepHandler
985
1172
 
986
- if (this.isWfResultBranch) {
987
- // 多分支情况:返回所有已选择的人员信息
1173
+ if (this.needMultipleBranchSelection) {
1174
+ // 多分支情况:返回所有分支的人员信息
988
1175
  const selectedHandlers = []
989
1176
  for (const node of this.branchNodes) {
990
- const personId = this.branchChargePersons[node.stepId]
991
- if (personId) {
1177
+ const branchData = this.branchChargePersons[node.stepId]
1178
+
1179
+ if (node.needSelectPerson && branchData) {
1180
+ // 需要选择人员的分支:显示选中的人员
992
1181
  const personName = this.getBranchPersonName(node.stepId)
993
1182
  selectedHandlers.push(`${node.stepName}:${personName}`)
1183
+ } else if (!node.needSelectPerson && branchData) {
1184
+ // 不需要选择人员的分支:显示角色/部门配置
1185
+ if (branchData.personList && branchData.personList.length > 0) {
1186
+ const personNames = branchData.personList.map(item => item.name).join(',')
1187
+ selectedHandlers.push(`${node.stepName}:${personNames}`)
1188
+ }
994
1189
  }
995
1190
  }
996
1191
  stepHandler = selectedHandlers.join(';')
@@ -1020,18 +1215,58 @@ export default {
1020
1215
  },
1021
1216
  // 生成工作流日志步骤变化描述
1022
1217
  generateStepChangeText (fromStepId, toStepId) {
1023
- return `第${fromStepId}步: ${this.getStepNameByStepId(fromStepId)} --> 第${toStepId}步: ${this.getStepNameByStepId(toStepId)}`
1218
+ // 如果是多分支场景,toStepId可能是数组或字符串
1219
+ if (this.needMultipleBranchSelection && Array.isArray(toStepId)) {
1220
+ const targetSteps = toStepId.map(id => `第${id}步: ${this.getStepNameByStepId(id)}`).join('、')
1221
+ return `第${fromStepId}步: ${this.getStepNameByStepId(fromStepId)} --> ${targetSteps}`
1222
+ } else if (this.needMultipleBranchSelection && typeof toStepId === 'string') {
1223
+ // 如果传入的是目标步骤名称字符串
1224
+ return `第${fromStepId}步: ${this.getStepNameByStepId(fromStepId)} --> ${toStepId}`
1225
+ } else {
1226
+ // 单步骤场景
1227
+ return `第${fromStepId}步: ${this.getStepNameByStepId(fromStepId)} --> 第${toStepId}步: ${this.getStepNameByStepId(toStepId)}`
1228
+ }
1024
1229
  },
1230
+
1231
+ // 生成多分支场景的步骤变化描述
1232
+ generateBranchStepChangeText (fromStepId) {
1233
+ if (!this.needMultipleBranchSelection) {
1234
+ return this.generateStepChangeText(fromStepId, this.nextBtnTo)
1235
+ }
1236
+
1237
+ // 使用所有分支节点生成描述
1238
+ const targetSteps = this.branchNodes.map(node => `第${node.stepId}步: ${node.stepName}`).join('、')
1239
+ return `第${fromStepId}步: ${this.getStepNameByStepId(fromStepId)} --> ${targetSteps}`
1240
+ },
1241
+
1025
1242
  generateStepChange (fromStepId, toStepId) {
1243
+ // 获取目标步骤IDs数组
1244
+ let stepIds = []
1245
+
1246
+ if (this.needMultipleBranchSelection) {
1247
+ // 多分支选择:获取所有分支的目标stepId(包括不需要选择人员的)
1248
+ if (!this.currentBranchActions) {
1249
+ this.currentBranchActions = this.getBranchActions()
1250
+ }
1251
+ stepIds = this.currentBranchActions.allBranchActions.map(action => action.to)
1252
+ } else if (this.calculatedTargetNode) {
1253
+ // 条件判断节点:使用计算出的目标节点
1254
+ stepIds = [this.calculatedTargetNode]
1255
+ } else {
1256
+ // 普通节点:使用传入的stepId
1257
+ stepIds = [toStepId]
1258
+ }
1259
+
1026
1260
  return {
1027
1261
  formStepId: fromStepId,
1028
1262
  fromStepId,
1029
- toStepId,
1263
+ stepId: toStepId,
1264
+ stepIds: stepIds,
1030
1265
  formStep: this.getStepNameByStepId(fromStepId),
1031
1266
  fromStep: this.getStepNameByStepId(fromStepId),
1032
- toStep: this.getStepNameByStepId(toStepId),
1267
+ toStep: this.getStepNameByStepId(stepIds[0]),
1033
1268
  successStepId: this.stepsDefine[this.stepsDefine.length - 1].id,
1034
- successStep: this.stepsDefine[this.stepsDefine.length - 1].name,
1269
+ successStep: this.stepsDefine[this.stepsDefine.length - 1].name
1035
1270
  }
1036
1271
  },
1037
1272
  // 保存工作流日志
@@ -1129,26 +1364,73 @@ export default {
1129
1364
 
1130
1365
  // 分析分支节点并设置选择框
1131
1366
  async analyzeBranchNodes () {
1132
- const conditionalActions = this.currentDirections.filter(action => action.type === 'conditionalBranch')
1133
- // 如果没有分支节点,处理普通单线流程
1134
- if (conditionalActions.length === 0) {
1135
- this.branchNodes = []
1136
- this.isWfResultBranch = false
1367
+ try {
1368
+ // 初始化状态
1369
+ this.resetBranchSelection()
1370
+
1371
+ // 获取所有类型的分支动作并缓存
1372
+ this.currentBranchActions = this.getBranchActions()
1373
+
1374
+ // 如果没有任何分支,处理普通流程
1375
+ if (!this.currentBranchActions.hasAnyBranch) {
1376
+ await this.handleNormalFlow()
1377
+ return
1378
+ }
1379
+
1380
+ // 判断是否需要多分支选择
1381
+ this.needMultipleBranchSelection = this.shouldUseMultipleBranchSelection(this.currentBranchActions)
1137
1382
 
1383
+ if (this.needMultipleBranchSelection) {
1384
+ // 需要为多个分支预先选择人员
1385
+ await this.setupMultipleBranchSelection(this.currentBranchActions.allBranchActions)
1386
+ } else {
1387
+ // 可以前台实时计算的条件分支
1388
+ await this.calculateTargetNodeFromForm(this.currentBranchActions.conditionalActions)
1389
+ }
1390
+ } catch (error) {
1391
+ console.error('分析分支节点失败:', error)
1392
+ this.$message.error('工作流分支配置异常,请联系管理员')
1393
+ // 降级处理:使用普通流程
1138
1394
  await this.handleNormalFlow()
1139
- return
1140
1395
  }
1396
+ },
1141
1397
 
1142
- this.isWfResultBranch = this.checkIfContainsWfResult()
1398
+ // 重置分支选择状态
1399
+ resetBranchSelection () {
1400
+ this.branchNodes = []
1401
+ this.branchChargePersons = {}
1402
+ this.needMultipleBranchSelection = false
1403
+ this.calculatedTargetNode = null
1404
+ this.currentBranchActions = null
1405
+ },
1143
1406
 
1144
- if (this.isWfResultBranch) {
1145
- // 包含WF_RESULT,需要显示所有可能分支的人员选择
1146
- await this.setupMultipleBranchSelection(conditionalActions)
1147
- } else {
1148
- this.branchNodes = []
1149
- // 不包含WF_RESULT,可以前台实时计算
1150
- await this.calculateTargetNodeFromForm(conditionalActions)
1407
+ // 获取分支动作分类
1408
+ getBranchActions () {
1409
+ const conditionalActions = this.currentDirections.filter(action => action.type === 'conditionalBranch')
1410
+ const parallelActions = this.currentDirections.filter(action => action.type === 'parallelBranch')
1411
+ const allBranchActions = [...conditionalActions, ...parallelActions]
1412
+
1413
+ return {
1414
+ conditionalActions,
1415
+ parallelActions,
1416
+ allBranchActions,
1417
+ hasAnyBranch: allBranchActions.length > 0
1418
+ }
1419
+ },
1420
+
1421
+ // 判断是否应该使用多分支选择模式
1422
+ shouldUseMultipleBranchSelection (branchActions) {
1423
+ // 情况1: 有并行分支
1424
+ if (branchActions.parallelActions.length > 0) {
1425
+ return true
1426
+ }
1427
+
1428
+ // 情况2: 条件分支包含WF_RESULT(后台结果决定)
1429
+ if (branchActions.conditionalActions.length > 0) {
1430
+ return this.checkIfContainsWfResult()
1151
1431
  }
1432
+
1433
+ return false
1152
1434
  },
1153
1435
 
1154
1436
  // 根据表单数据计算目标节点
@@ -1157,7 +1439,17 @@ export default {
1157
1439
  conditionalActions = this.currentDirections.filter(action => action.type === 'conditionalBranch')
1158
1440
  }
1159
1441
 
1160
- if (conditionalActions.length === 0) return
1442
+ if (conditionalActions.length === 0) {
1443
+ // 如果当前节点不是在分支流程中,才清空人员选择
1444
+ // 避免在并行分支节点中误清除人员选择框
1445
+ const currentStep = this.stepsForChild.find(item => item.id === this.activeStepId)
1446
+ const isInBranch = currentStep?.properties?.branchPath
1447
+
1448
+ if (!isInBranch) {
1449
+ this.clearPersonSelection()
1450
+ }
1451
+ return
1452
+ }
1161
1453
 
1162
1454
  try {
1163
1455
  const formData = this.$refs.xAddForm?.form || {}
@@ -1168,32 +1460,56 @@ export default {
1168
1460
  const result = await this.evaluateExpression(action.expression, formData)
1169
1461
  if (result) {
1170
1462
  this.calculatedTargetNode = action.to
1171
- // 设置对应节点的人员选择
1172
- const stepDefine = this.stepsDefine.find(step => step.id === action.to)
1173
- if (stepDefine?.properties?.chargePerson?.needSelectPerson) {
1174
- this.chargePerson = stepDefine?.properties?.chargePerson
1175
- this.checkedChargePerson = undefined
1176
- this.chargePersonOptions = await this.getChargePersonOptionsForStep(action.to)
1177
- // 如果只有一个选项,自动选中
1178
- if (this.chargePersonOptions.length === 1) {
1179
- this.checkedChargePerson = this.chargePersonOptions[0].value
1180
- }
1181
- this.needSelectPerson = true
1182
- } else {
1183
- this.needSelectPerson = false
1184
- this.chargePersonOptions = []
1185
- }
1463
+ await this.setupSingleTargetPersonSelection(action.to)
1186
1464
  return
1187
1465
  }
1188
1466
  }
1189
1467
  }
1468
+ console.log('this.calculatedTargetNode', this.calculatedTargetNode)
1190
1469
  // 如果没有匹配的条件,清空选择
1191
- this.calculatedTargetNode = null
1192
- this.needSelectPerson = false
1193
- this.chargePersonOptions = []
1470
+ this.clearPersonSelection()
1194
1471
  } catch (error) {
1195
1472
  console.warn('计算目标节点失败:', error)
1196
- this.calculatedTargetNode = null
1473
+ this.clearPersonSelection()
1474
+ }
1475
+ },
1476
+
1477
+ // 清空人员选择
1478
+ clearPersonSelection () {
1479
+ this.calculatedTargetNode = null
1480
+ this.needSelectPerson = false
1481
+ this.chargePersonOptions = []
1482
+ this.checkedChargePerson = undefined
1483
+ },
1484
+
1485
+ // 设置单个目标节点的人员选择
1486
+ async setupSingleTargetPersonSelection (stepId) {
1487
+ const stepDefine = this.stepsDefine.find(step => step.id === stepId)
1488
+
1489
+ if (!stepDefine?.properties?.chargePerson?.needSelectPerson) {
1490
+ this.needSelectPerson = false
1491
+ this.chargePersonOptions = []
1492
+ return
1493
+ }
1494
+
1495
+ // 设置人员选择
1496
+ this.chargePerson = stepDefine.properties.chargePerson
1497
+ this.checkedChargePerson = undefined
1498
+ this.chargePersonOptions = await this.getChargePersonOptionsForStep(stepId)
1499
+
1500
+ // 如果只有一个选项,自动选中
1501
+ if (this.chargePersonOptions.length === 1) {
1502
+ this.checkedChargePerson = this.chargePersonOptions[0].value
1503
+ }
1504
+
1505
+ this.needSelectPerson = true
1506
+ },
1507
+
1508
+ // 表单数据变化处理函数(将通过provide传递给表单组件)
1509
+ async handleFormDataChange (formData) {
1510
+ // 只有在不是多分支选择模式且当前活动步骤有条件分支动作时才重新计算
1511
+ if (!this.needMultipleBranchSelection && this.currentDirections.some(action => action.type === 'conditionalBranch')) {
1512
+ await this.calculateTargetNodeFromForm()
1197
1513
  }
1198
1514
  },
1199
1515
 
@@ -1220,8 +1536,22 @@ export default {
1220
1536
  if (!define?.properties?.chargePerson) return []
1221
1537
 
1222
1538
  const chargePerson = define.properties.chargePerson
1223
- this.chargePerson = chargePerson
1224
- // 如果是旧的格式 转换成新的格式
1539
+ this.chargePerson = this.normalizeChargePersonFormat(chargePerson)
1540
+
1541
+ if (!chargePerson.needSelectPerson || !chargePerson.personList) return []
1542
+
1543
+ // 获取所有用户信息
1544
+ const allUser = await postByServiceName(commonApi.getAllUserOptionList, {})
1545
+
1546
+ // 根据配置筛选用户
1547
+ const options = this.filterUsersByPersonConfig(chargePerson.personList, allUser)
1548
+
1549
+ // 去重处理
1550
+ return Array.from(new Map(options.map(item => [item.value, item])).values())
1551
+ },
1552
+
1553
+ // 标准化人员配置格式(兼容旧格式)
1554
+ normalizeChargePersonFormat (chargePerson) {
1225
1555
  if (chargePerson.role || chargePerson.department) {
1226
1556
  chargePerson.needSelectPerson = true
1227
1557
  chargePerson.personList = [{
@@ -1229,25 +1559,23 @@ export default {
1229
1559
  name: chargePerson.role || chargePerson.department
1230
1560
  }]
1231
1561
  }
1562
+ return chargePerson
1563
+ },
1232
1564
 
1233
- if (!chargePerson.needSelectPerson || !chargePerson.personList) return []
1234
-
1235
- // 获取所有用户信息
1236
- const allUser = await postByServiceName(commonApi.getAllUserOptionList, {})
1237
-
1238
- // 使用reduce累积结果
1239
- const options = chargePerson.personList.reduce((acc, personItem) => {
1565
+ // 根据人员配置筛选用户
1566
+ filterUsersByPersonConfig (personList, allUsers) {
1567
+ return personList.reduce((acc, personItem) => {
1240
1568
  let filteredUsers = []
1241
1569
 
1242
1570
  if (personItem.type === 'role') {
1243
- filteredUsers = allUser.filter(user =>
1571
+ filteredUsers = allUsers.filter(user =>
1244
1572
  user.rolestr && user.rolestr.split(',').includes(personItem.name)
1245
1573
  ).map(user => ({
1246
1574
  label: user.label,
1247
1575
  value: user.value
1248
1576
  }))
1249
1577
  } else if (personItem.type === 'department') {
1250
- filteredUsers = allUser.filter(user =>
1578
+ filteredUsers = allUsers.filter(user =>
1251
1579
  user.depname === personItem.name
1252
1580
  ).map(user => ({
1253
1581
  label: user.label,
@@ -1257,84 +1585,83 @@ export default {
1257
1585
 
1258
1586
  return [...acc, ...filteredUsers]
1259
1587
  }, [])
1260
-
1261
- // 去重处理
1262
- return Array.from(new Map(options.map(item => [item.value, item])).values())
1263
1588
  },
1264
1589
 
1265
- // 设置多分支人员选择(包含WF_RESULT的情况)
1266
- async setupMultipleBranchSelection (conditionalActions) {
1590
+ // 设置多分支人员选择
1591
+ async setupMultipleBranchSelection (branchActions) {
1267
1592
  this.branchNodes = []
1268
1593
  this.branchChargePersons = {}
1594
+ let hasPersonSelection = false
1269
1595
 
1270
- for (const action of conditionalActions) {
1596
+ for (const action of branchActions) {
1271
1597
  const stepDefine = this.stepsDefine.find(step => step.id === action.to)
1272
- if (stepDefine?.properties?.chargePerson?.needSelectPerson) {
1273
- // 都使用多分支了 肯定是新数据 那么不用做兼容处理
1274
- this.chargePerson = stepDefine?.properties?.chargePerson
1275
- // 获取这个节点的人员选项
1598
+ const chargePerson = stepDefine?.properties?.chargePerson
1599
+
1600
+ // 所有分支节点都加入branchNodes,保持数据结构完整
1601
+ const nodeData = {
1602
+ stepId: action.to,
1603
+ stepName: this.getStepNameByStepId(action.to),
1604
+ chargePerson: chargePerson,
1605
+ needSelectPerson: chargePerson?.needSelectPerson || false,
1606
+ chargePersonOptions: []
1607
+ }
1608
+
1609
+ if (chargePerson?.needSelectPerson) {
1610
+ // 需要选择人员的分支
1276
1611
  const chargePersonOptions = await this.getChargePersonOptionsForStep(action.to)
1612
+ nodeData.chargePersonOptions = chargePersonOptions
1277
1613
 
1278
- this.branchNodes.push({
1279
- stepId: action.to,
1280
- stepName: this.getStepNameByStepId(action.to),
1281
- chargePerson: stepDefine.properties.chargePerson,
1282
- chargePersonOptions: chargePersonOptions
1283
- })
1284
1614
  // 初始化选择值
1285
1615
  this.branchChargePersons[action.to] = undefined
1616
+ hasPersonSelection = true
1286
1617
  } else {
1287
- this.branchChargePersons[action.to] = stepDefine?.properties?.chargePerson
1618
+ // 不需要选择人员的分支,直接存储配置
1619
+ this.branchChargePersons[action.to] = chargePerson
1288
1620
  }
1621
+
1622
+ this.branchNodes.push(nodeData)
1289
1623
  }
1290
1624
 
1291
- // 如果没有需要选择人员的分支,隐藏选择区域
1292
- this.needSelectPerson = this.branchNodes.length > 0
1625
+ // 只有当存在需要选择人员的分支时才显示选择区域
1626
+ this.needSelectPerson = hasPersonSelection
1293
1627
  },
1294
1628
 
1295
1629
  // 处理普通单线流程(没有分支的情况)
1296
1630
  async handleNormalFlow () {
1297
- let targetStepId = this.nextBtnTo
1298
- if (this.operationType === 'skip') {
1299
- targetStepId = this.stepNextBtnTo
1300
- }
1631
+ const targetStepId = this.operationType === 'skip' ? this.stepNextBtnTo : this.nextBtnTo
1301
1632
 
1302
1633
  this.calculatedTargetNode = targetStepId
1303
1634
  const stepDefine = this.stepsDefine.find(step => step.id === targetStepId)
1635
+
1636
+ if (!stepDefine) {
1637
+ console.warn('未找到目标步骤定义:', targetStepId)
1638
+ this.clearPersonSelection()
1639
+ return
1640
+ }
1641
+
1304
1642
  const defineProperties = stepDefine.properties
1305
1643
  this.chargePerson = defineProperties?.chargePerson
1306
- if (defineProperties.chargePerson?.role || defineProperties.chargePerson?.department) {
1307
- defineProperties.chargePerson.needSelectPerson = true
1308
- defineProperties.chargePerson.personList = [{
1309
- type: defineProperties.chargePerson.role ? 'role' : 'department',
1310
- name: defineProperties.chargePerson.role || defineProperties.chargePerson.department
1311
- }]
1644
+
1645
+ // 兼容旧格式
1646
+ if (defineProperties.chargePerson) {
1647
+ defineProperties.chargePerson = this.normalizeChargePersonFormat(defineProperties.chargePerson)
1312
1648
  }
1313
- console.warn('defineProperties', defineProperties)
1314
1649
 
1315
1650
  if (defineProperties?.chargePerson?.needSelectPerson) {
1316
- // 获取人员选项并设置
1317
- this.checkedChargePerson = undefined
1318
- this.chargePersonOptions = await this.getChargePersonOptionsForStep(targetStepId)
1319
- // 如果只有一个选项,自动选中
1320
- if (this.chargePersonOptions.length === 1) {
1321
- this.checkedChargePerson = this.chargePersonOptions[0].value
1651
+ await this.setupSingleTargetPersonSelection(targetStepId)
1652
+ // 确保 branchChargePersons 中有该节点的数据结构
1653
+ this.branchChargePersons[targetStepId] = {
1654
+ handler: '',
1655
+ handlerId: undefined,
1656
+ ...defineProperties.chargePerson
1322
1657
  }
1323
- this.needSelectPerson = true
1324
- console.warn('设置人员选择,选项数量:', this.chargePersonOptions.length)
1325
1658
  } else {
1326
- this.branchChargePersons[targetStepId] = stepDefine?.properties?.chargePerson
1659
+ // 不需要选择人员的情况,直接存储配置
1660
+ this.branchChargePersons[targetStepId] = defineProperties?.chargePerson || {}
1327
1661
  this.needSelectPerson = false
1328
1662
  this.chargePersonOptions = []
1329
- console.warn('无需选择人员')
1330
- }
1331
- },
1332
- // 表单数据变化处理函数(将通过provide传递给表单组件)
1333
- async handleFormDataChange (formData) {
1334
- if (!this.isWfResultBranch) {
1335
- await this.calculateTargetNodeFromForm()
1336
1663
  }
1337
- },
1664
+ }
1338
1665
  },
1339
1666
  watch: {}
1340
1667
  }