6 天以前 22229c67d87f0fae4c4bc90db106b8a1e2c49b53
src/views/safeProduction/safeWorkApproval/components/approvalDia.vue
@@ -157,7 +157,7 @@
                <el-descriptions-item label="采购合同号">{{ currentPurchase.purchaseContractNumber }}</el-descriptions-item>
                <el-descriptions-item label="供应商名称">{{ currentPurchase.supplierName }}</el-descriptions-item>
                <el-descriptions-item label="项目名称">{{ currentPurchase.projectName }}</el-descriptions-item>
                <el-descriptions-item label="销售合同号">{{ currentPurchase.salesContractNo }}</el-descriptions-item>
                <el-descriptions-item label="订单编号">{{ currentPurchase.salesContractNo }}</el-descriptions-item>
                <el-descriptions-item label="签订日期">{{ currentPurchase.executionDate }}</el-descriptions-item>
                <el-descriptions-item label="录入日期">{{ currentPurchase.entryDate }}</el-descriptions-item>
                <el-descriptions-item label="付款方式">{{ currentPurchase.paymentMethod }}</el-descriptions-item>
@@ -198,29 +198,28 @@
      <el-form :model="{ activities }"
               ref="formRef"
               label-position="top">
        <el-steps :active="getActiveStep()"
                <el-steps :active="getActiveStep()"
                  finish-status="success"
                  process-status="process"
                  align-center
                  direction="vertical">
          <el-step v-for="(activity, index) in activities"
                   :key="index"
          <el-step v-for="(group, gIndex) in stepGroups"
                   :key="gIndex"
                   finish-status="success"
                   :title="getNodeTitle(index, activities.length)"
                   :description="activity.approveNodeUser"
                   :icon="getNodeIcon(activity, index)">
                   :title="getNodeTitle(gIndex, stepGroups.length)"
                   :icon="getNodeIcon(group)">
            <template #icon>
              <el-icon v-if="activity.approveNodeStatus === 2"
              <el-icon v-if="group.some(a => a.approveNodeStatus === 2)"
                       color="red"
                       :size="22">
                <WarningFilled />
              </el-icon>
              <el-icon v-else-if="activity.isShen"
              <el-icon v-else-if="group.some(a => a.isShen)"
                       color="#1890ff"
                       :size="22">
                <Edit />
              </el-icon>
              <el-icon v-else-if="activity.approveNodeStatus === 1"
              <el-icon v-else-if="group.every(a => a.approveNodeStatus === 1)"
                       color="#67C23A"
                       :size="26">
                <Check />
@@ -232,37 +231,42 @@
              </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-if="!activity.isShen"
                   class="node-reason">
                <span>签名:</span>
                <img :src="activity.urlTem"
                     class="signImg"
                     alt=""
                     v-if="activity.urlTem" />
              </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-if="!activity.isShen"
                     class="node-reason">
                  <span>签名:</span>
                  <img :src="activity.urlTem"
                       class="signImg"
                       alt=""
                       v-if="activity.urlTem" />
                </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>
@@ -348,19 +352,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);
  };
  // 打开弹框
@@ -474,10 +490,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();
    });
@@ -506,6 +520,9 @@
    align-items: center;
    gap: 8px;
  }
  .node-user-item {
    margin: 8px 0;
  }
  .node-status {
    color: #1890ff;
    margin-left: 8px;