feat(engine): NOTIFY 抄送 + CONDITION 条件路由 + JOIN scope 修复(两批全栈)
build / build-push (push) Successful in 47s

- NOTIFY:TYPE_NOTIFY 瞬时抄送(flw_cc 逐人留痕 + CC_SENT 事件 + 站内通知不加待办角标)、/api/flow/cc/my、轨迹 kind=CC 与 oapi progress 抄送步、示意图青框卡片
- CONDITION:flw_router 判断服务注册 + flw_route_log 决策留痕(REQUIRES_NEW,reroute 回滚不丢失败行)+ 同步判断调用(服务目录寻址 + 平台签名,3s×3 退避重试)+ 失败挂起/管理端重跑(不配默认出口)+ 可选事件 flow.route.decided
- JOIN scope:branch_key 路径前缀编码 + scope 级到齐放行 + DefValidator SPLIT/JOIN 配对与键长守卫(存量无点号键零迁移,历史直连图回退实例级口径)
- 管理端:/api/flow/admin/router/* CRUD + POST /api/flow/admin/instance/{id}/reroute
- 生产 SQL:sql/20260923_create_flw_cc.sql(含 flw_task 时间列升 DATETIME(3))、20260924_create_flw_router_and_route_log.sql
- 测试:全量 125 绿(FlowEngineIT 24,含条件/嵌套并行/退回重走用例)
This commit is contained in:
chenxing
2026-09-24 08:58:26 +08:00
parent f2126cdf32
commit d2bef20e13
34 changed files with 2472 additions and 97 deletions
@@ -52,6 +52,33 @@ public class AssigneeResolver {
return refs;
}
/**
* 抄送接收人解析(NOTIFY 专用,宽容口径):结构不合法照抛(发布期校验本应拦住,属脏定义),
* 但解析不出人(映射被停用/名单为空)只返回空列表由调用方记日志——抄送是知会不是审批,
* 绝不能因抄送对象缺失卡住流程推进。与 {@link #resolve} 的强口径相反。
*/
public List<AssigneeRef> resolveTolerant(Long schId, FlowDefModel.Node node) {
FlowDefModel.Assignee a = node.receivers;
if (a == null || a.type == null) {
throw new BizException(ErrorCode.PARAM_ERROR, "节点缺少抄送对象配置:" + node.id);
}
List<AssigneeRef> refs = new ArrayList<>();
if (FlowDefModel.ASSIGNEE_DEPT_KEY.equals(a.type)) {
for (FlwAssigneeMap m : mapRepository.findEnabled(schId, a.deptKey)) {
refs.add(new AssigneeRef(m.getUserId(), m.getUserName()));
}
} else if (FlowDefModel.ASSIGNEE_USERS.equals(a.type)) {
if (a.userIds != null) {
for (Integer uid : a.userIds) {
refs.add(new AssigneeRef(uid, fetchName(uid)));
}
}
} else {
throw new BizException(ErrorCode.PARAM_ERROR, "不支持抄送对象类型:" + a.type);
}
return refs;
}
private String fetchName(Integer userId) {
try {
BoaUser user = userClient.getUserById(String.valueOf(userId));