编辑 | blame | 历史 | 原始文档

审批流程支持或签/会签模式

涉及页面

  • 审批管理配置页:collaborativeApproval/approvalManagement/index.vue
  • 审批列表页(协同审批):collaborativeApproval/approvalProcess/index.vue
  • 审批列表页(危险作业 type 8):safeProduction/safeWorkApproval/index.vue
  • 审批弹框(协同审批):collaborativeApproval/approvalProcess/components/approvalDia.vue
  • 审批弹框(危险作业 type 8):safeProduction/safeWorkApproval/components/approvalDia.vue

API

方法 路径 说明
GET /approveProcessConfigNode/listNode 查询审批节点配置(响应新增 approveMode 字段)
POST /approveProcessConfigNode/addApproveProcessConfigNodes 保存节点配置(每行一个审批人,同一 nodeOrder 多行即同一节点多人,需传 approveMode
POST /approveProcess/addApprove 发起审批(新增响应/快照字段 approve_node_config,节点含多人时写入 approve_user_current_ids/names
GET /approveProcess/details 审批详情(节点列表新增 approveMode 字段;isShen 仅当前待审节点且当前登录人可审时返回 true)
POST /approveNode/updateApproveNode 提交审批(**不再需要 isLast 参数**,流转判断由后端按节点模式完成)

节点配置保存请求参数(addApproveProcessConfigNodes)

同一节点多审批人通过多条记录表达,nodeOrder 相同、approveMode 标识模式:

[
  { "approveType": 1, "nodeOrder": 1, "approverId": 11, "approverName": "张三", "approveMode": "or" },
  { "approveType": 1, "nodeOrder": 1, "approverId": 12, "approverName": "李四", "approveMode": "or" },
  { "approveType": 1, "nodeOrder": 2, "approverId": 21, "approverName": "王五", "approveMode": "and" },
  { "approveType": 1, "nodeOrder": 2, "approverId": 22, "approverName": "赵六", "approveMode": "and" }
]
  • approveModeor=或签(任一人通过即流转),and=会签(需所有人通过才流转)
  • 任一审批人拒绝 → 整个流程立即驳回(或签/会签一致,一票否决)

审批详情响应(details)新增字段

每个节点新增:

字段 类型 说明
approveMode String 节点审批模式:or / and
approveNodeOrder Integer 节点序号(同一节点的多人记录相同)
isShen Boolean 是否为当前登录人的待审节点

流程级新增(列表接口返回):approveUserCurrentIdsapproveUserCurrentNames(当前节点全部待审人)。

前端修改点

1. 配置页:节点卡片支持多审批人 + 或签/会签

collaborativeApproval/approvalManagement/index.vue

审批人改为多选,新增模式单选:

<el-form-item label="审批人">
  <el-select v-model="item.approverIds" multiple filterable placeholder="选择审批人(可多选)">
    <el-option v-for="u in allUsers" :key="u.userId" :label="u.nickName" :value="u.userId" />
  </el-select>
</el-form-item>
<el-form-item label="审批模式">
  <el-radio-group v-model="item.approveMode">
    <el-radio-button value="or">或签(任意一人通过)</el-radio-button>
    <el-radio-button value="and">会签(需所有人通过)</el-radio-button>
  </el-radio-group>
</el-form-item>

loadData:将接口扁平配置按 nodeOrder 合并为卡片数据:

const groupMap = new Map();
(res.data || []).forEach(r => {
  const order = r.nodeOrder;
  if (!groupMap.has(order)) groupMap.set(order, { nodeOrder: order, approverIds: [], approverNames: [], approveMode: r.approveMode || 'or' });
  const g = groupMap.get(order);
  if (!g.approverIds.includes(r.approverId)) {
    g.approverIds.push(r.approverId);
    g.approverNames.push(r.approverName);
  }
});
nodeCards.value = Array.from(groupMap.values()).sort((a, b) => a.nodeOrder - b.nodeOrder);

handleSave:每张卡片按审批人展开成多行 payload:

const list = [];
nodeCards.value.forEach(card => {
  card.approverIds.forEach((uid, i) => {
    list.push({
      approveType: currentType,
      nodeOrder: card.nodeOrder,
      approverId: uid,
      approverName: card.approverNames[i],
      approveMode: card.approveMode || 'or',
    });
  });
});
await addApproveProcessConfigNodes(list);

2. 列表页:当前审批人列 + 审核按钮权限

collaborativeApproval/approvalProcess/index.vuesafeProduction/safeWorkApproval/index.vue

当前审批人列展示同节点全部待审人,富化行数据:

tableData.value = (res.data.records || []).map(r => ({
  ...r,
  currentApproverNames: r.approveUserCurrentNames || r.approveUserCurrentName || '-',
  _canApprove:
    String(r.approveUserCurrentIds ?? '').split(',').filter(Boolean).includes(String(userStore.id)) ||
    r.approveUserCurrentId === userStore.id,
}));

审核按钮禁用条件:

disabled: row =>
  row.approveStatus == 2 || row.approveStatus == 3 || row.approveStatus == 4 || !row._canApprove,

3. 审批弹框:按节点分组展示

collaborativeApproval/approvalProcess/components/approvalDia.vuesafeProduction/safeWorkApproval/components/approvalDia.vue

新增分组计算属性,同一 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());
});

el-steps 改为遍历 stepGroups,每组一个 el-step,组内循环渲染成员(姓名、状态、意见、签名、待审输入框):

<el-steps :active="getActiveStep()" ...>
  <el-step v-for="(group, gIndex) in stepGroups" :key="gIndex" ...>
    <template #title>
      <span>{{ getNodeTitle(gIndex, stepGroups.length) }}</span>
      <el-tag :type="group[0]?.approveMode === 'and' ? 'warning' : 'info'">
        {{ group[0]?.approveMode === 'and' ? '会签' : '或签' }}
      </el-tag>
    </template>
    <template #description>
      <div v-for="(activity, aIndex) in group" :key="activity.id || aIndex" class="node-user-item">
        <!-- 成员姓名、状态、审批意见;仅 isShen 成员渲染输入框 -->
      </div>
    </template>
  </el-step>
</el-steps>

当前激活步骤取含待审成员的组下标:

const getActiveStep = () => {
  const idx = stepGroups.value.findIndex(group => group.some(a => a.isShen === true));
  if (idx === -1) return stepGroups.value.length;
  return idx;
};

提交审批不再传 isLast

currentActivity.approveNodeStatus = status;
updateApproveNode({ ...currentActivity }).then(() => {
  proxy.$modal.msgSuccess("提交成功");
  closeDia();
});

管理员审批不受审批人限制

管理员账号(角色为 普通2 / admin / 最高1)可审批任意流程,不再受"审批人必须是流程节点配置的审批人"限制。

后端

  • details:管理员对当前待审节点的首个待审记录返回 isShen=true(代审整节点)。
  • updateApproveNode:管理员跳过"无权审批该节点"校验;审批通过时自动将同节点其余待审记录标记为"管理员代审通过"(或签/会签均整节点放行);拒绝仍按一票否决处理。

前端

两个列表页(approvalProcess / safeWorkApproval)新增 isAdminUser 判断:

const isAdminUser = computed(() =>
  ["admin", "普通2", "最高1"].some(r => (userStore.roles || []).includes(r))
);

_canApprove 对管理员恒为 true,审核按钮不再禁用:

_canApprove: isAdminUser.value || String(r.approveUserCurrentIds ?? '').split(',').filter(Boolean).includes(String(userStore.id)) || r.approveUserCurrentId === userStore.id

注意

  • 管理员仍需按节点顺序审批("尚未轮到该节点审批"校验保留)。
  • 管理员拒绝任意节点 = 一票否决,整个流程立即驳回。

注意事项

  • 后端流转判断updateApproveNode 已改为按节点模式(或签/会签)统计同 order 的同意数决定是否流转,前端**必须删除 isLast 传参**,否则旧字段会被忽略(不影响结果,但无意义)。
  • 或签放行:或签任一审批人通过后,同节点其余未审记录会被后端自动标记为"已同意(或签:其他审批人已通过)",前端无需处理。
  • 会签部分通过:节点停留在当前步骤,列表"当前审批人"会更新为剩余未审人员。
  • 历史数据兼容:存量节点 approveMode 为空按"或签"处理;存量流程 approveUserCurrentNames 为空时前端兜底 approveUserCurrentName
  • 编辑重建:流程编辑时后端优先按 approve_node_config 快照重建节点以保持分组与模式,无快照时按"一节点一人 or"回退。
  • 配置页已补充 type 8 危险作业审批 的标签与图标。