5 天以前 f51c5018dc9088f393f34e3e2508d7caf80002c4
src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
@@ -173,41 +173,43 @@
      </div>
      <el-form :model="{ activities }" ref="formRef" label-position="top">
        <el-steps :active="getActiveStep()" finish-status="success" process-status="process" align-center direction="vertical">
                <el-steps :active="getActiveStep()" finish-status="success" process-status="process" align-center direction="vertical">
          <el-step
            v-for="(activity, index) in activities"
            :key="index"
                  finish-status="success"
            :title="getNodeTitle(index, activities.length)"
            :description="activity.approveNodeUser"
            :icon="getNodeIcon(activity, index)"
            v-for="(group, gIndex) in stepGroups"
            :key="gIndex"
            finish-status="success"
            :title="getNodeTitle(gIndex, stepGroups.length)"
            :icon="getNodeIcon(group)"
          >
                  <template #icon>
                     <el-icon v-if="activity.approveNodeStatus === 2" color="red" :size="22"><WarningFilled /></el-icon>
                     <el-icon v-else-if="activity.isShen" color="#1890ff" :size="22"><Edit /></el-icon>
                     <el-icon v-else-if="activity.approveNodeStatus === 1" color="#67C23A" :size="26"><Check /></el-icon>
                     <el-icon v-else color="#C0C4CC" :size="22"><MoreFilled /></el-icon>
                  </template>
            <template #icon>
              <el-icon v-if="group.some(a => a.approveNodeStatus === 2)" color="red" :size="22"><WarningFilled /></el-icon>
              <el-icon v-else-if="group.some(a => a.isShen)" color="#1890ff" :size="22"><Edit /></el-icon>
              <el-icon v-else-if="group.every(a => a.approveNodeStatus === 1)" color="#67C23A" :size="26"><Check /></el-icon>
              <el-icon v-else color="#C0C4CC" :size="22"><MoreFilled /></el-icon>
            </template>
            <template #title>
              <span style="color: #000000">{{ getNodeTitle(index, activities.length) }}</span>
              <span style="color: #000000">{{ getNodeTitle(gIndex, stepGroups.length) }}</span>
              <el-tag :type="group[0]?.approveMode === 'and' ? 'warning' : 'info'" size="small" style="margin-left: 6px">{{ group[0]?.approveMode === 'and' ? '会签' : '或签' }}</el-tag>
            </template>
            <template #description>
              <div class="node-user">
                <div class="avatar-wrapper">
                  <img :src="userStore.avatar" class="user-avatar" alt=""/>
              <div v-for="(activity, aIndex) in group" :key="activity.id || aIndex" class="node-user-item">
                <div class="node-user">
                  <div class="avatar-wrapper">
                    <img :src="userStore.avatar" class="user-avatar" alt=""/>
                  </div>
                  <span style="color: #000000">{{ activity.approveNodeUser }}({{ activity.isApproval }})</span>
                </div>
                <span style="color: #000000">{{ activity.approveNodeUser }}-{{activity.isApproval}}</span>
              </div>
              <div v-if="!activity.isShen" class="node-reason">
                <span>审批意见:</span>{{ activity.approveNodeReason }}
              </div>
              <div v-else-if="activity.isShen">
                <el-form-item
                  :prop="'activities.' + index + '.approveNodeReason'"
                  :rules="[{ required: true, message: '审批意见不能为空', trigger: 'blur' }]"
                >
                  <el-input v-model="activity.approveNodeReason" clearable type="textarea" :disabled="operationType === 'view'"></el-input>
                </el-form-item>
                <div v-if="!activity.isShen" class="node-reason">
                  <span>审批意见:</span>{{ activity.approveNodeReason }}
                </div>
                <div v-else-if="activity.isShen">
                  <el-form-item
                    :prop="'activities.' + getActivityIndex(activity) + '.approveNodeReason'"
                    :rules="[{ required: true, message: '审批意见不能为空', trigger: 'blur' }]"
                  >
                    <el-input v-model="activity.approveNodeReason" clearable type="textarea" :disabled="operationType === 'view'"></el-input>
                  </el-form-item>
                </div>
              </div>
            </template>
          </el-step>
@@ -281,19 +283,31 @@
  return '审批';
};
// 获取当前激活步骤
// 获取当前激活步骤(分组后:含待审人的组下标,无则返回组总数=全部完成)
const getActiveStep = () => {
  // 如果所有 isShen 都为 false,返回最后一个步骤(全部完成)
  const hasActive = activities.value.some(a => a.isShen === true);
  if (!hasActive) return activities.value.length;
  // 当前节点索引
  return activities.value.findIndex(a => a.isShen  == true);
  const idx = stepGroups.value.findIndex(group => group.some(a => a.isShen === true));
  if (idx === -1) return stepGroups.value.length;
  return idx;
};
// 步骤icon
const getNodeIcon = (activity, index) => {
  if (activity.approveNodeStatus === 2) return 'el-icon-warning'; // 不通过
  if (activity.isShen) return 'Edit';
// 步骤icon(组级:任一人驳回/任一人待审)
const getNodeIcon = (group) => {
  if (group.some(a => a.approveNodeStatus === 2)) return 'el-icon-warning'; // 不通过
  if (group.some(a => a.isShen)) return 'Edit';
  return '';
};
// 审批节点分组(同一 approveNodeOrder = 同一节点的多名审批人,或签/会签)
const stepGroups = computed(() => {
  const map = new Map();
  (activities.value || []).forEach(a => {
    const order = a.approveNodeOrder;
    if (!map.has(order)) map.set(order, []);
    map.get(order).push(a);
  });
  return Array.from(map.values());
});
// 获取节点成员在 activities 中的索引(用于表单校验 prop)
const getActivityIndex = (activity) => {
  return activities.value.findIndex(a => a.id === activity.id);
};
// 打开弹框
@@ -445,9 +459,8 @@
    return;
  }
  currentActivity.approveNodeStatus = status;
  // 判断是否为最后一步
  const isLast = activities.value.findIndex(a => a.isShen) === activities.value.length-1;
  updateApproveNode({ ...currentActivity, isLast }).then(() => {
  // 流转判断由后端完成,前端不再传 isLast
  updateApproveNode({ ...currentActivity }).then(() => {
    proxy.$modal.msgSuccess("提交成功");
    closeDia();
  });
@@ -479,6 +492,9 @@
  align-items: center;
  gap: 8px;
}
.node-user-item {
  margin: 8px 0;
}
.node-status {
  color: #1890ff;
  margin-left: 8px;