spec.md 与 tasks.md。forge-admin-ui/src/views/flow/design.vueforge-admin-ui/src/components/flow-designer/DingFlowDesigner.vueforge-admin-ui/src/components/flow-designer/panel/NodeConfigDrawer.vueforge-admin-ui/src/components/flow-designer/panel/ConditionConfig.vueforge-admin-ui/src/components/flow-designer/panel/__tests__/ConditionConfig.spec.jsgit diff --check -- <本轮相关文件>:通过,无输出。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec eslint --fix <本轮前端文件>:通过,无输出。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec vitest run src/components/flow-designer/panel/__tests__/ConditionConfig.spec.js src/components/flow-designer/__tests__/DingFlowDesigner.spec.js:通过,2 个测试文件、15 个用例全部通过。source ~/.nvm/nvm.sh && nvm use v20.19.0 && NODE_OPTIONS=--max-old-space-size=8192 pnpm --dir forge-admin-ui build:通过,✓ built in 53.47s。http://127.0.0.1:5188/condition-preview.html,确认字段条件 UI 可见,输入 3000 后页面包含 ${amount == 3000},控制台错误数为 0,截图保存在 /private/tmp/flow_condition_preview.png。pnpm build 存在项目既有告警:CSS 中 //padding 注释、src/store/index.js 同时被动态和静态导入;未阻断构建,非本轮新增。EMFILE: too many open files, watch,已使用 ulimit -n 65535 和 CHOKIDAR_USEPOLLING=true 解决。curl -I http://127.0.0.1:5188/condition-preview.html 返回 curl: (7) Failed to connect,确认 5188 端口无服务。forge-admin-ui/condition-preview.html、forge-admin-ui/src/condition-preview.js 和 /private/tmp/verify_flow_condition_preview.py 已删除。design.vue 原本的 resolveLocalFormFieldCatalog() 只解析 formSchema 第一层字段。fieldRegistry,前端没有从已加载的 formSchema 递归兜底。children 嵌套、_forge.fieldBinding.fieldCode 业务组件绑定和 ref_ 临时字段。forge-admin-ui/src/views/flow/utils/form-field-catalog.js,按后端字段目录规则递归解析动态表单 Schema。design.vue 改为使用 buildLocalFormFieldCatalog(),并在远端字段目录为空时回退本地 schema 解析。forge-admin-ui/src/views/flow/utils/__tests__/form-field-catalog.spec.js 覆盖嵌套字段、业务组件绑定、ref_ 临时字段过滤。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec vitest run src/views/flow/utils/__tests__/form-field-catalog.spec.js src/components/flow-designer/panel/__tests__/ConditionConfig.spec.js src/components/flow-designer/__tests__/DingFlowDesigner.spec.js:通过,3 个测试文件、18 个用例全部通过。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec eslint --fix src/views/flow/design.vue src/views/flow/utils/form-field-catalog.js src/views/flow/utils/__tests__/form-field-catalog.spec.js src/components/flow-designer/panel/ConditionConfig.vue src/components/flow-designer/panel/__tests__/ConditionConfig.spec.js src/components/flow-designer/DingFlowDesigner.vue src/components/flow-designer/panel/NodeConfigDrawer.vue:通过,无输出。git diff --check -- <本轮前端相关文件>:通过,无输出。source ~/.nvm/nvm.sh && nvm use v20.19.0 && NODE_OPTIONS=--max-old-space-size=8192 pnpm --dir forge-admin-ui build:通过,最终复跑结果 ✓ built in 44.24s。pnpm build 仍存在项目既有告警:CSS 中 //padding 注释、src/store/index.js 同时被动态和静态导入;未阻断构建,非本轮新增。DingFlowDesigner.vue 增加 drawerFocusEdgeId,分支标签点击时携带 edgeId 打开抽屉,点击网关节点时清空聚焦状态。NodeConfigDrawer.vue 透传 focusEdgeId 给网关配置组件。ConditionConfig.vue 在聚焦状态下只渲染对应分支;删除最后一条规则后保留空状态并清空 edge.condition;规则行改为两列容器,表达式预览和高级表达式输入支持换行/局部滚动,避免横向溢出。ConditionConfig.spec.js 与 DingFlowDesigner.spec.js 覆盖聚焦分支、规则清空和网关恢复全部分支。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec vitest run src/views/flow/utils/__tests__/form-field-catalog.spec.js src/components/flow-designer/panel/__tests__/ConditionConfig.spec.js src/components/flow-designer/__tests__/DingFlowDesigner.spec.js:通过,3 个测试文件、21 个用例全部通过。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec eslint --fix src/components/flow-designer/DingFlowDesigner.vue src/components/flow-designer/panel/NodeConfigDrawer.vue src/components/flow-designer/panel/ConditionConfig.vue src/components/flow-designer/panel/__tests__/ConditionConfig.spec.js src/components/flow-designer/__tests__/DingFlowDesigner.spec.js:通过,无输出。git diff --check -- <本轮前端相关文件>:通过,无输出。source ~/.nvm/nvm.sh && nvm use v20.19.0 && NODE_OPTIONS=--max-old-space-size=8192 pnpm --dir forge-admin-ui build:通过,✓ built in 59.14s。pnpm build 仍存在项目既有告警:CSS 中 //padding 注释、src/store/index.js 同时被动态和静态导入;未阻断构建,非本轮新增。ConditionConfig.vue 设置默认分支时不再清空 edge.condition;默认分支仍显示字段条件/高级表达式配置。ConditionConfig.vue 规则配置行改为字段、关系、取值三列对齐,并增加表头;空值运算符显示“无需填写”占位,保持列宽一致。BranchHeader.vue、EdgePath.vue 在默认分支有条件时展示“默认 · 条件摘要”,避免画布只显示“默认”。json-to-bpmn.js 默认边存在条件时仍写出 conditionExpression;branch-parser.js 导入 BPMN 时不再清空 default 边已有条件。ConditionConfig.spec.js、EdgePath.spec.js、json-to-bpmn.spec.js、branch-parser.spec.js 相关测试。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec vitest run src/components/flow-designer/panel/__tests__/ConditionConfig.spec.js src/components/flow-designer/canvas/__tests__/EdgePath.spec.js src/components/flow-designer/converter/__tests__/json-to-bpmn.spec.js src/components/flow-designer/converter/__tests__/branch-parser.spec.js src/components/flow-designer/converter/__tests__/roundtrip.spec.js src/components/flow-designer/__tests__/DingFlowDesigner.spec.js:通过,6 个测试文件、48 个用例全部通过。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec eslint --fix src/components/flow-designer/panel/ConditionConfig.vue src/components/flow-designer/panel/__tests__/ConditionConfig.spec.js src/components/flow-designer/canvas/BranchHeader.vue src/components/flow-designer/canvas/EdgePath.vue src/components/flow-designer/canvas/__tests__/EdgePath.spec.js src/components/flow-designer/converter/json-to-bpmn.js src/components/flow-designer/converter/branch-parser.js src/components/flow-designer/converter/__tests__/json-to-bpmn.spec.js src/components/flow-designer/converter/__tests__/branch-parser.spec.js:首次发现 EdgePath.spec.js 直接写 ${...} 触发 no-template-curly-in-string,改为 DOLLAR 常量后复跑通过。git diff --check -- <本轮前端相关文件>:通过,无输出。source ~/.nvm/nvm.sh && nvm use v20.19.0 && NODE_OPTIONS=--max-old-space-size=8192 pnpm --dir forge-admin-ui build:通过,✓ built in 1m 3s。pnpm build 仍存在项目既有告警:CSS 中 //padding 注释、src/store/index.js 同时被动态和静态导入;未阻断构建,非本轮新增。flowable-exclusive-gateway-condition-on-seq-flow: Default sequenceflow has a condition, which is not allowed。根因是上一轮将 default 边上的 edge.condition 也写入了 BPMN conditionExpression。json-to-bpmn.js 恢复 Flowable 合法导出规则:只有非默认边才写 conditionExpression。ConditionConfig.vue 默认分支提示改为明确说明:条件保留在设计器里,但部署导出不会写入该分支。BranchHeader.vue、EdgePath.vue 默认分支即使保留草稿条件,也只展示“默认”,避免误导为条件参与执行。EdgePath.spec.js、json-to-bpmn.spec.js 的断言,覆盖 default 边条件不导出。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec vitest run src/components/flow-designer/panel/__tests__/ConditionConfig.spec.js src/components/flow-designer/canvas/__tests__/EdgePath.spec.js src/components/flow-designer/converter/__tests__/json-to-bpmn.spec.js src/components/flow-designer/converter/__tests__/branch-parser.spec.js src/components/flow-designer/converter/__tests__/roundtrip.spec.js src/components/flow-designer/__tests__/DingFlowDesigner.spec.js:通过,6 个测试文件、48 个用例全部通过。useFlowDesigner.js 新增 addBranch(gatewayId),在既有条件网关上继续追加审批分支,并自动接回已有合流节点。addBranch() 会归一化默认分支:并行网关不处理默认分支;条件/包容网关保留既有 defaultFlowId,没有合法默认时选择一条默认边,避免出现多个默认。ConditionConfig.vue 在条件摘要区新增“添加分支”按钮;点击后通过 NodeConfigDrawer.vue 事件透传到 DingFlowDesigner.vue。DingFlowDesigner.vue 添加分支后继续打开当前条件网关抽屉,并聚焦刚新增的分支条件配置。useFlowDesigner.spec.js、ConditionConfig.spec.js、DingFlowDesigner.spec.js,覆盖第三分支、唯一默认分支、事件透传和抽屉聚焦新分支。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec vitest run src/components/flow-designer/composables/__tests__/useFlowDesigner.spec.js src/components/flow-designer/panel/__tests__/ConditionConfig.spec.js src/components/flow-designer/__tests__/DingFlowDesigner.spec.js src/components/flow-designer/converter/__tests__/json-to-bpmn.spec.js:通过,4 个测试文件、55 个用例全部通过。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec eslint --fix src/components/flow-designer/composables/useFlowDesigner.js src/components/flow-designer/composables/__tests__/useFlowDesigner.spec.js src/components/flow-designer/panel/ConditionConfig.vue src/components/flow-designer/panel/NodeConfigDrawer.vue src/components/flow-designer/panel/__tests__/ConditionConfig.spec.js src/components/flow-designer/DingFlowDesigner.vue src/components/flow-designer/__tests__/DingFlowDesigner.spec.js:首次发现 add:branch 事件名不符合 vue/custom-event-name-casing,改为 addBranch 后复跑通过,无输出。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec vitest run src/components/flow-designer/composables/__tests__/useFlowDesigner.spec.js src/components/flow-designer/panel/__tests__/ConditionConfig.spec.js src/components/flow-designer/__tests__/DingFlowDesigner.spec.js src/components/flow-designer/canvas/__tests__/EdgePath.spec.js src/components/flow-designer/converter/__tests__/json-to-bpmn.spec.js src/components/flow-designer/converter/__tests__/branch-parser.spec.js src/components/flow-designer/converter/__tests__/roundtrip.spec.js:通过,7 个测试文件、74 个用例全部通过。source ~/.nvm/nvm.sh && nvm use v20.19.0 && NODE_OPTIONS=--max-old-space-size=8192 pnpm --dir forge-admin-ui build:通过,✓ built in 51.79s。pnpm build 仍存在项目既有告警:CSS 中 //padding 注释、src/store/index.js 同时被动态和静态导入;未阻断构建,非本轮新增。BranchAddButton.vue,在条件网关分支连线区域下方渲染“添加分支”按钮。DingFlowDesigner.vue 新增 branchAddButtons 坐标计算,点击画布按钮后调用 designer.addBranch(),并聚焦新分支配置。ConditionConfig.vue 移除抽屉内“添加分支”按钮,右侧面板只保留条件配置。BranchHeader.vue 将画布分支标签改为“条件已设 / N 条条件 / 默认 / 配置条件”摘要,原始 SpEL 仅作为 title 保留。EdgePath.vue 对带 branchId 的网关分支边不再在 SVG 层重复渲染条件标签,避免边上出现多层文本。ConditionConfig.vue 增加表单字段表达式反解析能力,支持常见 ==/!=/>/>=/</<=、区间、包含、不包含、为空、不为空表达式回显为字段条件模式;字段不在当前表单目录里的表达式仍走高级表达式。AddNodeButton.spec.js、EdgePath.spec.js、ConditionConfig.spec.js、DingFlowDesigner.spec.js 覆盖新交互和回显行为。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec vitest run src/components/flow-designer/canvas/__tests__/AddNodeButton.spec.js src/components/flow-designer/canvas/__tests__/EdgePath.spec.js src/components/flow-designer/panel/__tests__/ConditionConfig.spec.js src/components/flow-designer/__tests__/DingFlowDesigner.spec.js src/components/flow-designer/composables/__tests__/useFlowDesigner.spec.js:通过,5 个测试文件、65 个用例全部通过。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec eslint --fix src/components/flow-designer/canvas/BranchAddButton.vue src/components/flow-designer/canvas/BranchHeader.vue src/components/flow-designer/canvas/EdgePath.vue src/components/flow-designer/canvas/__tests__/AddNodeButton.spec.js src/components/flow-designer/canvas/__tests__/EdgePath.spec.js src/components/flow-designer/panel/ConditionConfig.vue src/components/flow-designer/panel/NodeConfigDrawer.vue src/components/flow-designer/panel/__tests__/ConditionConfig.spec.js src/components/flow-designer/DingFlowDesigner.vue src/components/flow-designer/__tests__/DingFlowDesigner.spec.js:首次发现表达式反解析正则存在 regexp/no-super-linear-backtracking 风险,改为“先匹配字段和操作符,再切片取值”后复跑通过。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec vitest run src/components/flow-designer/canvas/__tests__/AddNodeButton.spec.js src/components/flow-designer/canvas/__tests__/EdgePath.spec.js src/components/flow-designer/panel/__tests__/ConditionConfig.spec.js src/components/flow-designer/__tests__/DingFlowDesigner.spec.js src/components/flow-designer/composables/__tests__/useFlowDesigner.spec.js src/components/flow-designer/converter/__tests__/json-to-bpmn.spec.js src/components/flow-designer/converter/__tests__/branch-parser.spec.js src/components/flow-designer/converter/__tests__/roundtrip.spec.js:通过,8 个测试文件、86 个用例全部通过。source ~/.nvm/nvm.sh && nvm use v20.19.0 && NODE_OPTIONS=--max-old-space-size=8192 pnpm --dir forge-admin-ui build:通过,✓ built in 54.73s。pnpm build 仍存在项目既有告警:CSS 中 //padding 注释、src/store/index.js 同时被动态和静态导入;未阻断构建,非本轮新增。BranchAddButton.vue 改为 36px 白底圆形加号按钮,颜色、边框、阴影和 hover 反馈对齐 AddNodeButton.vue。title="添加条件分支" 和 aria-label="添加条件分支",不在画布上显示文字,减少视觉干扰。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec eslint --fix src/components/flow-designer/canvas/BranchAddButton.vue src/components/flow-designer/canvas/__tests__/AddNodeButton.spec.js src/components/flow-designer/__tests__/DingFlowDesigner.spec.js:通过,无输出。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec vitest run src/components/flow-designer/canvas/__tests__/AddNodeButton.spec.js src/components/flow-designer/__tests__/DingFlowDesigner.spec.js:通过,2 个测试文件、22 个用例全部通过。DingFlowDesigner.vue 将 branchAddButtons 的位置从下游节点上方改为网关底部下方,并向右错开 52px,避开分支标签和下游节点点击区域。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec eslint --fix src/components/flow-designer/DingFlowDesigner.vue src/components/flow-designer/__tests__/DingFlowDesigner.spec.js:通过,无输出。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec vitest run src/components/flow-designer/__tests__/DingFlowDesigner.spec.js src/components/flow-designer/canvas/__tests__/AddNodeButton.spec.js:通过,2 个测试文件、22 个用例全部通过。design.vue 新增“审批设置”页,支持配置“允许提交人撤回审批中的申请”和重复审批自动同意策略。DingFlowDesigner.vue、useFlowDesigner.js、json-to-bpmn.js、bpmn-to-json.js 增加流程级 flowJson.config,读写 flowable:allowSubmitterWithdraw、flowable:autoApprovalMode。FormPermissionConfig.vue 改为按全局动态表单字段目录渲染字段权限表,移除手工新增字段行。user-task-writer.js、user-task-parser.js 增加 flowable:formFieldPermissions 持久化和解析。FlowFormCreateRenderer.vue、todo.vue 在待办动态表单中应用字段权限:不可见字段隐藏,只读字段禁用,节点必填字段补校验。TaskFormInfo.java、FlowTaskServiceImpl.java 下发表单字段权限,撤回时校验提交人和流程配置,审批通过后按重复审批策略自动同意后续符合条件的任务。PermissionConfig.vue 将“强制评论”调整为“审批意见”,文案明确同意或驳回时必须填写审批意见。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec vitest run src/components/flow-designer/panel/__tests__/FormPermissionConfig.spec.js src/components/flow-designer/panel/__tests__/ConditionConfig.spec.js src/components/flow-designer/converter/__tests__/json-to-bpmn.spec.js src/components/flow-designer/converter/__tests__/bpmn-to-json-linear.spec.js src/components/flow-designer/converter/__tests__/user-task-parser-permissions.spec.js src/components/flow-designer/__tests__/DingFlowDesigner.spec.js:通过,6 个测试文件、53 个用例全部通过。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec eslint --fix <本轮前端相关文件>:首次发现 user-task-parser.js、user-task-writer.js 中 ${initiator} 等字面量触发 no-template-curly-in-string,改为 DOLLAR 常量拼接后复跑通过。mvn -pl forge-framework/forge-plugin-parent/forge-plugin-flow -am -DskipTests compile:首次失败,原因是当前 shell Java 不支持 target 17:无效的目标发行版: 17。env JAVA_HOME=/opt/homebrew/Cellar/openjdk@17/17.0.13/libexec/openjdk.jdk/Contents/Home mvn -pl forge-framework/forge-plugin-parent/forge-plugin-flow -am -DskipTests compile:通过,forge-plugin-flow 及依赖模块编译成功。source ~/.nvm/nvm.sh && nvm use v20.19.0 && NODE_OPTIONS=--max-old-space-size=8192 pnpm --dir forge-admin-ui build:通过,✓ built in 55.07s。git diff --check:通过,无输出。//padding 注释、src/store/index.js 同时被动态和静态导入。isReadonly 禁用;同时切换到“更多设置”时设计器组件会卸载,直接保存时不能依赖 modelerRef.getXML()。design.vue 移除审批设置上的 isReadonly 禁用,允许前端直接修改提交人撤回和自动审批策略。design.vue 新增 getXmlForSave() / applyProcessConfigToXml(),保存草稿和发布前将当前流程级审批配置合并回 bpmnXml,即使当前停留在“更多设置”页也能保存。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec eslint --fix src/views/flow/design.vue:通过,无输出。source ~/.nvm/nvm.sh && nvm use v20.19.0 && pnpm --dir forge-admin-ui exec vitest run src/components/flow-designer/converter/__tests__/json-to-bpmn.spec.js src/components/flow-designer/converter/__tests__/bpmn-to-json-linear.spec.js src/components/flow-designer/__tests__/DingFlowDesigner.spec.js src/components/flow-designer/panel/__tests__/FormPermissionConfig.spec.js:通过,4 个测试文件、36 个用例全部通过。git diff --check:通过,无输出。ApproverConfig.vue 将页签“审批后操作”改为“审批权限”。source ~/.nvm/nvm.sh && nvm use v20.19.0 >/dev/null && pnpm --dir forge-admin-ui exec eslint --fix src/components/flow-designer/panel/ApproverConfig.vue:通过,无输出。git diff --check:通过,无输出。source ~/.nvm/nvm.sh && nvm use v20.19.0 >/dev/null && NODE_OPTIONS=--max-old-space-size=8192 pnpm --dir forge-admin-ui build:通过,✓ built in 1m 1s。//padding 注释、src/store/index.js 同时被动态和静态导入。