@steedos-labs/plugin-workflow 3.0.46 → 3.0.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/designer/dist/amis-renderer/amis-renderer.css +1 -1
  2. package/designer/dist/amis-renderer/amis-renderer.js +1 -1
  3. package/designer/dist/assets/index-5LmRPj9U.js +952 -0
  4. package/designer/dist/assets/index-KzcJ7tj0.css +1 -0
  5. package/designer/dist/index.html +2 -2
  6. package/main/default/manager/import.js +20 -2
  7. package/main/default/objects/instances/buttons/instance_delete.button.yml +1 -1
  8. package/main/default/objects/instances/buttons/instance_related.button.yml +5 -2
  9. package/main/default/objects/instances/buttons/instance_submit.button.yml +0 -3
  10. package/main/default/routes/api_workflow_ai_form_design.router.js +5 -2
  11. package/main/default/routes/api_workflow_ai_form_design_stream.router.js +5 -2
  12. package/main/default/routes/flow_form_design.ejs +8 -0
  13. package/main/default/routes/flow_form_design.router.js +1 -1
  14. package/main/default/test/FORMULA_SCAN_GUIDE.md +258 -0
  15. package/main/default/test/prompt-formula-analyze.md +59 -0
  16. package/main/default/test/prompt-formula-fix.md +75 -0
  17. package/main/default/test/reports/formula-scan/.gitkeep +0 -0
  18. package/main/default/test/reports/formula-scan/SCAN_HISTORY.md +165 -0
  19. package/main/default/test/reports/formula-scan/scan-result-v6-20260324.json +31846 -0
  20. package/main/default/test/reports/formula-scan/scan-result-v7-20260324.json +31543 -0
  21. package/main/default/test/run_approval_comments_upgrade.js +135 -0
  22. package/main/default/test/scan_production_formulas.js +573 -0
  23. package/main/default/test/test_formula_compat.js +38 -0
  24. package/main/default/utils/designerManager.js +1 -0
  25. package/main/default/utils/formula-compat.js +8 -0
  26. package/package.json +1 -1
  27. package/public/amis-renderer/amis-renderer.css +1 -1
  28. package/public/amis-renderer/amis-renderer.js +1 -1
  29. package/public/workflow/index.css +4 -0
  30. package/designer/dist/assets/index-BNKlgpz1.js +0 -943
  31. package/designer/dist/assets/index-D7JdeS9f.css +0 -1
@@ -0,0 +1,258 @@
1
+ # 生产公式扫描操作指南
2
+
3
+ 本指南介绍如何使用 `scan_production_formulas.js` 扫描生产数据库中的工作流表单公式,主动发现 `mapFormula` 未兼容的公式语法,并完成后续 AI 辅助评估与修复。
4
+
5
+ ---
6
+
7
+ ## 前置条件
8
+
9
+ - 本地已安装 Node.js(>=14)
10
+ - 本地 MongoDB 可用(`mongod` 正在运行)
11
+ - 已将生产 `forms` 集合数据还原到本地数据库:
12
+ ```bash
13
+ mongorestore --db <dbname> --collection forms <bson文件路径>
14
+ # 示例
15
+ mongorestore --db prod_backup_20260323 --collection forms ./dump/steedos/forms.bson
16
+ ```
17
+ - 本地已安装 `mongodb` npm 包(若未安装):
18
+ ```bash
19
+ cd steedos-packages/plugin-workflow
20
+ npm install mongodb --no-save
21
+ ```
22
+
23
+ ---
24
+
25
+ ## 完整操作流程
26
+
27
+ ### 步骤 0:执行审批意见字段升级(前置步骤)
28
+
29
+ 备份还原的 forms 库中可能包含老版本的审批意见公式字段(如 `{yijianlan:{step:'部门经理审核',default:'已阅'}}`)。这些字段需要先执行升级转换为 `steedos-field` 类型,否则会被公式扫描误报为 E3 错误。
30
+
31
+ > **说明**:如果目标库来自已执行过"审批意见字段升级"的生产环境,可跳过此步骤。
32
+
33
+ ```bash
34
+ cd steedos-packages/plugin-workflow
35
+
36
+ # 先 dry run 查看影响范围(不修改数据库)
37
+ FORMULA_SCAN_MONGO_URL=mongodb://127.0.0.1:27017/<dbname> \
38
+ DRY_RUN=true \
39
+ node main/default/test/run_approval_comments_upgrade.js
40
+
41
+ # 确认无误后正式执行
42
+ FORMULA_SCAN_MONGO_URL=mongodb://127.0.0.1:27017/<dbname> \
43
+ node main/default/test/run_approval_comments_upgrade.js
44
+ ```
45
+
46
+ 输出示例:
47
+ ```
48
+ 审批意见字段升级完成
49
+ 扫描表单数: 1595
50
+ 升级表单数: 29
51
+ 升级字段数: 1157
52
+ ```
53
+
54
+ 升级脚本复用了 `src/rests/migrateApprovalCommentsField.js` 中的转换逻辑(与"审批意见字段升级控制台"UI 一致),会将 3 种审批意见公式字段转换为 `steedos-field` 类型并清除原有 formula 属性:
55
+
56
+ | 模式 | 示例 |
57
+ |------|------|
58
+ | `{yijianlan:{...}}` | `{yijianlan:{step:'部门经理审核',default:'已阅'}}` |
59
+ | `{signature.traces.步骤名}` | `{signature.traces.部门经理审核}` |
60
+ | `{traces.步骤名}` | `{traces.总经理审批}` |
61
+
62
+ ### 步骤 1:运行扫描脚本
63
+
64
+ ```bash
65
+ cd steedos-packages/plugin-workflow
66
+
67
+ # 基本用法
68
+ FORMULA_SCAN_MONGO_URL=mongodb://127.0.0.1:27017/<dbname> \
69
+ node main/default/test/scan_production_formulas.js
70
+
71
+ # 带标识标签(推荐,便于区分多次扫描结果)
72
+ FORMULA_SCAN_MONGO_URL=mongodb://127.0.0.1:27017/<dbname> \
73
+ SCAN_LABEL=v1 \
74
+ node main/default/test/scan_production_formulas.js
75
+
76
+ # 也可使用 MONGO_URL 回退(若已设置)
77
+ MONGO_URL=mongodb://127.0.0.1:27017/<dbname> \
78
+ node main/default/test/scan_production_formulas.js
79
+ ```
80
+
81
+ 扫描完成后,控制台显示如下统计:
82
+
83
+ ```
84
+ 扫描完成
85
+ 总表单数: 1595
86
+ 含公式字段的表单: 706
87
+ 公式字段总数: 2157
88
+ - formula 字段: 2043
89
+ - default_value 公式字段: 114
90
+ - 来自 current 版本: 1655
91
+ - 来自 history 版本: 502
92
+
93
+ 检测结果:
94
+ ERROR: 4 条(涉及 4 个表单,current: 0,history: 4)
95
+ WARN: 206 条(涉及 114 个表单)
96
+ PASS: 1949 条
97
+
98
+ 报告已输出到: main/default/test/reports/formula-scan/scan-result-v1-20260324.json
99
+ ```
100
+
101
+ 报告文件保存在:
102
+ ```
103
+ main/default/test/reports/formula-scan/scan-result-{SCAN_LABEL}-{YYYYMMDD}.json
104
+ ```
105
+
106
+ ---
107
+
108
+ ### 步骤 2:AI 辅助评估(分类问题根因)
109
+
110
+ 1. 打开生成的 JSON 报告,复制 `errors` 数组内容
111
+ 2. 打开 `main/default/test/prompt-formula-analyze.md`,按其中说明将 errors 填入占位符
112
+ 3. 将拼好的提示词发送给 AI(如 GitHub Copilot Chat / Claude / GPT-4o)
113
+ 4. AI 将对 issues 按根因分组,给出修复策略和优先级
114
+
115
+ ---
116
+
117
+ ### 步骤 3:AI 辅助修复
118
+
119
+ 1. 根据 AI 评估结果,确认需要修复的分组
120
+ 2. 打开 `main/default/test/prompt-formula-fix.md`,按其中说明将需修复的分组填入占位符
121
+ 3. 将拼好的提示词发送给 AI
122
+ 4. AI 将生成:先写测试 → 改代码 → 三处同步 → 运行测试 的完整修复方案
123
+
124
+ ---
125
+
126
+ ### 步骤 4:执行修复并验证
127
+
128
+ 按 AI 给出的方案完成修复后,运行两套测试验证:
129
+
130
+ ```bash
131
+ # plugins 侧回归测试
132
+ cd steedos-packages/plugin-workflow
133
+ node main/default/test/test_formula_compat.js
134
+
135
+ # 重新扫描(使用新版本号),确认 ERROR 数量归零
136
+ FORMULA_SCAN_MONGO_URL=mongodb://127.0.0.1:27017/<dbname> \
137
+ SCAN_LABEL=v<N+1> \
138
+ node main/default/test/scan_production_formulas.js
139
+ ```
140
+
141
+ > widgets 侧单元测试需在 `steedos-widgets` 仓库执行:
142
+ > ```bash
143
+ > cd packages/@steedos-widgets/amis-lib
144
+ > npx jest --verbose
145
+ > ```
146
+
147
+ ### 步骤 5:记录修正过程
148
+
149
+ 每次修复完成后,需要留下完整的修正记录:
150
+
151
+ #### 5.1 给修正前的扫描报告添加 `processedResult`
152
+
153
+ 在修正前的 JSON 报告(如 `scan-result-v6-*.json`)的每个 `errors` 条目中,添加 `processedResult` 字段:
154
+
155
+ ```json
156
+ {
157
+ "level": "ERROR",
158
+ "ruleId": "E1",
159
+ "formId": "...",
160
+ "originalFormula": "sum{金额}",
161
+ "processedResult": {
162
+ "action": "CODE_FIX",
163
+ "bugId": "Bug-8",
164
+ "bugTitle": "聚合函数缺失括号预处理",
165
+ "fixDescription": "sum{金额} 缺少括号,预处理补全为 sum({金额}) 后可正常转换",
166
+ "fixedInVersion": "v7",
167
+ "fixCommit": "3abea58",
168
+ "fixedFiles": ["formula-compat.js", "formula-utils.js"]
169
+ }
170
+ }
171
+ ```
172
+
173
+ `processedResult.action` 取值:
174
+ - `CODE_FIX` — 通过修改公式转换代码解决
175
+ - `KNOWN_ISSUE` — 经分析确认不需要代码修正(附 `category` 和 `resolution`)
176
+
177
+ #### 5.2 更新 SCAN_HISTORY.md
178
+
179
+ 在 `reports/formula-scan/SCAN_HISTORY.md` 中追加本次修正记录,包括:
180
+ - 修正前/后的报告文件名
181
+ - Bug ID 和修改的文件列表
182
+ - 修复的每个 ERROR 的表单名称、formId、字段、原始公式
183
+ - 归类为 knownIssues 的记录及原因
184
+ - 扫描统计对比表
185
+
186
+ #### 5.3 提交产物
187
+
188
+ 每次扫描修正周期应提交到 git 的文件:
189
+
190
+ ```
191
+ reports/formula-scan/
192
+ scan-result-v<N>-YYYYMMDD.json # 修正前(errors 带 processedResult)
193
+ scan-result-v<N+1>-YYYYMMDD.json # 修正后(errors 为空)
194
+ SCAN_HISTORY.md # 追加修正记录
195
+ ```
196
+
197
+ ---
198
+
199
+ ## 检测规则说明
200
+
201
+ | 规则 | 级别 | 触发条件 |
202
+ |------|------|----------|
203
+ | E1 | ERROR | mapFormula 返回 null 但公式含 `{字段名}` 引用 |
204
+ | E2 | ERROR | 转换结果中仍含 `[` 或 `]` |
205
+ | E3 | ERROR | 转换结果中含裸 `{`(非合法 `${...}` 表达式) |
206
+ | E4 | ERROR | mapFormula 抛出异常 |
207
+ | W1 | WARN | 公式含除法且除数是字段引用(除零风险) |
208
+ | W2 | WARN | 同表单内不同字段 getSafeCode 后结果相同(字段名冲突) |
209
+
210
+ ---
211
+
212
+ ## 报告结构说明
213
+
214
+ JSON 报告包含以下顶层字段:
215
+
216
+ | 字段 | 说明 |
217
+ |------|------|
218
+ | `scanDate` | 扫描日期(YYYY-MM-DD) |
219
+ | `mongoUrl` | 已脱敏的连接串 |
220
+ | `summary` | 统计汇总(含 bySource、byVersion、byStatus、errorsByVersion、knownIssueCount) |
221
+ | `errors` | 所有 ERROR 级别问题详情(需要代码修正的公式问题) |
222
+ | `knownIssues` | 经人工审核确认不需要代码修正的问题(附 category 和 resolution) |
223
+ | `warnings` | 所有 WARN 级别问题详情(公式能工作但有风险) |
224
+ | `allFormulas` | 所有含公式字段的完整清单(含 PASS/ERROR/WARN) |
225
+
226
+ **`errors` vs `knownIssues` vs `warnings` 的区别:**
227
+
228
+ | | ERROR | KNOWN_ISSUE | WARN |
229
+ |--|--|--|--|
230
+ | 含义 | 公式**无法正常工作**,需代码修正 | 公式无法转换但**无需代码修正** | 公式**能工作但有风险** |
231
+ | 分类 | — | KNOWN_LIMITATION / BAD_SOURCE_DATA | — |
232
+ | 处理 | AI 辅助分析和修复 | 记录原因后归档 | 通常可批量忽略 |
233
+ | 典型规则 | E1、E2、E3、E4 | E1、E3(经审核) | W1、W2 |
234
+
235
+ `allFormulas` 可用于基线对比:两次扫描结果 diff,快速定位新增问题。
236
+
237
+ `summary.errorsByVersion` 标识 ERROR 来自 current 还是 history 版本,帮助判断优先级——current 版本的 ERROR 影响新审批单,history 版本的 ERROR 只影响已有旧审批单。
238
+
239
+ ---
240
+
241
+ ## 常见问题
242
+
243
+ **Q:脚本报错 `未找到 mongodb 模块`**
244
+ ```bash
245
+ npm install mongodb --no-save
246
+ ```
247
+
248
+ **Q:连接失败 `Authentication failed`**
249
+ 在连接串中加入用户名密码:
250
+ ```
251
+ mongodb://username:password@127.0.0.1:27017/<dbname>
252
+ ```
253
+
254
+ **Q:forms 集合为空**
255
+ 确认 mongorestore 时指定了正确的 `--db` 和 `--collection` 参数,以及 bson 文件路径正确。
256
+
257
+ **Q:WARN 数量很多,是否需要全部修复?**
258
+ W1(除零风险)是运行时风险,建议优先修复;W2(字段名冲突)通常无实际影响,可按业务判断。
@@ -0,0 +1,59 @@
1
+ # AI 提示词:生产公式问题分类评估
2
+
3
+ ## 角色设定
4
+
5
+ 你是 Steedos 工作流公式转换专家,精通老版本工作流表单公式语法与 amis 框架表达式的转换机制。
6
+
7
+ ## 背景
8
+
9
+ Steedos 审批流程(workflow)表单使用老版本 `{字段名}` 语法定义公式,在运行时由 `mapFormula` 函数转换为 amis 框架的 `${表达式}` 语法。
10
+
11
+ 转换规则摘要:
12
+
13
+ | 场景 | 输入示例 | 输出示例 |
14
+ |------|----------|----------|
15
+ | 简单字段引用 | `{月末里程数}` | `${月末里程数}` |
16
+ | 时间函数 | `{now}` | `${NOW()}` |
17
+ | 运算表达式 | `{月末里程数} - {月初里程数}` | `${月末里程数 - 月初里程数}` |
18
+ | 聚合函数 | `sum({出票金额})` | `${SUM(出票金额)}` |
19
+ | 子表聚合 | `sum({出票金额})` (子表字段) | `${SUM(ARRAYMAP(表格, item => item['出票金额']))}` |
20
+ | 上下文变量 | `{applicant}.name` | `${applicant.name}` |
21
+ | 对象字段展开 | `{合同}.name` | `${合同__expand.name}` |
22
+ | 特殊字符字段名 | `{油量(本地)}` | `${油量_本地}` |
23
+ | 方括号分组 | `[{a}+{b}]/{c}` | `${(a+b)/c}` |
24
+ | 大写金额 | `numToRMB({金额})` | `${UPPERMONEY(金额)}` |
25
+
26
+ `getSafeCode` 替换规则(字段名特殊字符转义):
27
+
28
+ | 字符 | 替换为 |
29
+ |------|--------|
30
+ | `(` 全角左括号 | `_` |
31
+ | `)` 全角右括号 | (删除) |
32
+ | `(` 半角左括号 | `_` |
33
+ | `)` 半角右括号 | (删除) |
34
+ | `、` 顿号 | `_` |
35
+ | `,` 全角逗号 | `_` |
36
+ | `%` | `_` |
37
+ | `=` | `_` |
38
+ | `:` 全角冒号 | `_` |
39
+ | `/` | `_` |
40
+ | `-` | `_` |
41
+
42
+ ## 任务
43
+
44
+ 以下是扫描脚本发现的公式 ERROR 列表(`errors` 数组):
45
+
46
+ ```json
47
+ {在此粘贴 scan-result.json 文件中 errors 数组的内容}
48
+ ```
49
+
50
+ 请对上述问题执行分组分析,输出结构化评估报告,每个分组包含:
51
+
52
+ 1. **根因标签**(例如:方括号未转换、字段名含特殊字符、除零风险等)
53
+ 2. **影响范围**(涉及 ERROR/WARN 数量、表单数量)
54
+ 3. **代表性示例**(列出 1-3 个典型 originalFormula 和 convertedResult)
55
+ 4. **修复策略**(代码层面需要改什么)
56
+ 5. **优先级**(Critical / High / Medium / Low)
57
+ 6. **风险评估**(修复后是否可能影响现有正常公式)
58
+
59
+ 最后给出**总体建议**:哪些分组应优先修复,哪些可以延后,哪些是数据问题无需改代码。
@@ -0,0 +1,75 @@
1
+ # AI 提示词:工作流公式转换代码修复
2
+
3
+ ## 角色设定
4
+
5
+ 你是 Steedos 工作流公式转换开发者,负责修复 `mapFormula` 函数中未兼容的公式语法。
6
+
7
+ ## 需要修复的问题分组
8
+
9
+ 以下是经 AI 评估确认、需要修复的问题分组列表:
10
+
11
+ ```
12
+ {在此粘贴 AI 评估确认后需要修复的分组列表}
13
+ ```
14
+
15
+ ## 参考资料
16
+
17
+ 修复前请先阅读以下背景文件,了解公式转换机制和三处同步要求:
18
+
19
+ - `.github/instructions/workflow-formula.instructions.md`(steedos-plugins 仓库)
20
+ - `steedos-packages/plugin-workflow/main/default/utils/formula-compat.js`(当前实现)
21
+ - `steedos-packages/plugin-workflow/main/default/test/test_formula_compat.js`(现有测试)
22
+
23
+ ## 修复要求(5 步流程)
24
+
25
+ ### 步骤 1:先写测试
26
+
27
+ 在 `steedos-packages/plugin-workflow/main/default/test/test_formula_compat.js` 中为每个问题分组添加失败测试用例,确认测试在修复前为红色(失败),修复后为绿色(通过)。
28
+
29
+ ### 步骤 2:改代码
30
+
31
+ 修改 `mapFormula`(或 `getSafeCode`)实现,使新增测试通过,同时保证原有测试不退化。
32
+
33
+ ### 步骤 3:三处同步
34
+
35
+ 公式转换逻辑存在于三个位置,**必须同时更新**:
36
+
37
+ 1. **steedos-widgets 仓库**(主版本,ESM):
38
+ `packages/@steedos-widgets/amis-lib/src/workflow/formula-utils.js`
39
+
40
+ 2. **steedos-plugins 仓库**(CommonJS 镜像):
41
+ `steedos-packages/plugin-workflow/main/default/utils/formula-compat.js`
42
+
43
+ 3. **steedos-plugins 仓库**(内联副本,EJS 模板):
44
+ `steedos-packages/plugin-workflow/main/default/routes/flow_form_design.ejs`
45
+ (内联函数 `_getSafeCode` 和 `_mapFormula`,从第 281 行起)
46
+
47
+ 三处代码逻辑必须完全一致,否则设计器预览与运行时渲染会出现差异。
48
+
49
+ ### 步骤 4:运行测试
50
+
51
+ ```bash
52
+ # plugins 侧回归测试
53
+ cd steedos-packages/plugin-workflow
54
+ node main/default/test/test_formula_compat.js
55
+
56
+ # widgets 侧单元测试(需在 steedos-widgets 仓库执行)
57
+ cd packages/@steedos-widgets/amis-lib
58
+ npx jest --verbose
59
+ ```
60
+
61
+ 所有测试必须通过,才能提交 PR。
62
+
63
+ ### 步骤 5:同步 plugins 侧测试
64
+
65
+ 若 widgets 侧新增了 Jest 测试用例,在 `steedos-packages/plugin-workflow/main/default/test/test_formula_compat.js` 中添加等价测试用例,保持两侧测试覆盖一致。
66
+
67
+ ## 输出格式
68
+
69
+ 请输出:
70
+
71
+ 1. **新增测试用例代码**(`test_formula_compat.js` 中添加的内容)
72
+ 2. **formula-compat.js 的 diff**(精确的代码改动)
73
+ 3. **flow_form_design.ejs 的 diff**(对应的内联函数改动)
74
+ 4. **formula-utils.js 的 diff**(steedos-widgets 仓库)
75
+ 5. **验证说明**:如何手动验证修复效果(可用的测试公式示例)
@@ -0,0 +1,165 @@
1
+ # 公式扫描处理历史 (SCAN_HISTORY)
2
+
3
+ 本文档记录每次生产公式扫描发现的 errors 及其修正过程。
4
+
5
+ > 约定:每次扫描周期产生两个 JSON 文件 —— 修正前(含 `processedResult` 注解)和修正后(干净的 `errors: []`)。
6
+
7
+ ---
8
+
9
+ ## v6 → v7:Bug 8 — 聚合函数全角括号和缺失括号预处理
10
+
11
+ - **扫描日期**: 2026-03-24
12
+ - **修正前报告**: `scan-result-v6-20260324.json`(12 ERROR, 206 WARN)
13
+ - **修正后报告**: `scan-result-v7-20260324.json`(0 ERROR, 4 KNOWN_ISSUE, 206 WARN)
14
+ - **修正提交**: `3abea58` (fix: Bug 8 — 同步聚合函数全角括号和缺失括号预处理 #507)
15
+ - **修改文件**: `formula-compat.js`, `formula-utils.js`, `flow_form_design.ejs`
16
+
17
+ ### Bug 8 修正内容
18
+
19
+ 在 `mapFormula` 转换前新增预处理步骤:
20
+ 1. 将聚合函数的全角括号 `()` 转换为半角 `()`
21
+ 2. 将 `sum{...}` / `average{...}` 等缺失括号的写法补全为 `sum({...})`
22
+
23
+ ### 修复了 8 个 ERROR(均为 E1 规则)
24
+
25
+ | # | 表单名称 | formId | 字段 | 原始公式 | 问题原因 | 版本 |
26
+ |---|---------|--------|------|---------|---------|------|
27
+ | 1 | 抚顺石化公司物资编码替换申请表 | `8f4a6ce7e2dfdf423a28e306` | 合计(替换) | `sum({金额(替换)})` | 全角括号 | history |
28
+ | 2 | 单一来源采购方式报审表 | `dcbqgp5ZCKLdexwpD` | 概算或预估算金额(含税,万元) | `sum{含税金额}` | 缺少括号 | history |
29
+ | 3 | 物资临时领用票 | `gT7bSNfgG9dAd89jk` | 合计金额 | `sum{(金额)}` | 缺少外层括号 | **current** |
30
+ | 4 | 科研项目费用指标控制审批单 | `sS9suXA63oqfot3J2` | 累计支出金额合计 | `sum{累计支出金额}` | 缺少括号 | history |
31
+ | 5 | 质量检验中心应急物资计划审批表 | `RiHrEAqNMKBEwCmXH` | 合计 | `sum{概算总价}` | 缺少括号 | history |
32
+ | 6 | 科研项目费用指标控制审批单 | `Q8WtCbxYb3aAX5KLv` | 项目预算金额合计 | `sum{项目预算金额}` | 缺少括号 | history |
33
+ | 7 | 科研项目费用指标控制审批单 | `Q8WtCbxYb3aAX5KLv` | 本次支出金额合计 | `sum{项目预算金额}` | 缺少括号 | history |
34
+ | 8 | 科研项目费用指标控制审批单 | `Q8WtCbxYb3aAX5KLv` | 累计支出金额合计 | `sum{累计支出金额}` | 缺少括号 | history |
35
+
36
+ > **影响面**: 7 个 history + 1 个 **current**(物资临时领用票),current 版本的修复直接改善了在用表单的公式转换。
37
+
38
+ ### 归类为 knownIssues 的 4 个 ERROR
39
+
40
+ 以下 4 个 ERROR 经分析不需要代码修正,已在 v7 报告中归类到 `knownIssues`。**全部为 history 版本**,不影响新建审批单。
41
+
42
+ | # | 表单名称 | formId | 版本 | 字段 | 原始公式 | 分类 | 原因 |
43
+ |---|---------|--------|------|------|---------|------|------|
44
+ | 1 | 办公桌面问题 | `451766252f8838253eab81f8` | history | 所属信息站 | `judgeIndex({所属部门})` | KNOWN_LIMITATION | 自定义函数,amis 无等价物 |
45
+ | 2 | 工作循环分析计划表 | `9THeSusZyo9E3pe5p` | history | 表名 | `{填报单位}车间{YYYY}年度` | KNOWN_LIMITATION | 文本模板 pattern,无转换路径 |
46
+ | 3 | 员工通勤补贴统计表 | `6d9fe8a132c96a664ca23808` | history | 发放补贴金额(元) | `{发放补贴数量}*{}` | BAD_SOURCE_DATA | 空引用 `{}`,作者漏填 |
47
+ | 4 | 招标结果报审表 | `b9e7465f159b6640bbe49caa` | history | 概算、估算金额(元、大写) | `numToRMB(概算、估算金额{})` | BAD_SOURCE_DATA | 花括号位置写错 |
48
+
49
+ > **生产排查结论**(2026-03-24):4 项均无需处理。第 2、3 项无审批单引用;第 1 项仅 2021 年已完成审批单;第 4 项仅 1 条 draft 草稿。详见 [#511 评论](https://github.com/steedos/steedos-plugins/issues/511#issuecomment-4116293785)。
50
+
51
+ #### 生产数据库排查查询
52
+
53
+ 以下 `mongosh` 命令可直接在终端执行,精确查找**使用了包含问题公式的那些表单版本**创建的审批单。
54
+
55
+ > **查询思路**:
56
+ > 1. 从 `forms` 的 `historys` 数组中,递归查找哪些版本的 `fields` 包含目标公式字段
57
+ > 2. 收集这些版本的 `_id` 列表
58
+ > 3. 用 `form_version: {$in: vids}` 精确匹配 `instances`
59
+ >
60
+ > 这比 `form_version != currentVersionId` 更精确 —— 只命中真正包含问题公式的版本,排除了无关的历史版本。
61
+
62
+ **Issue #1 — 办公桌面问题** (`451766252f8838253eab81f8`,字段 `所属信息站`,公式 `judgeIndex({所属部门})`)
63
+ ```bash
64
+ mongosh "mongodb://127.0.0.1:27017/<dbname>" --eval '
65
+ function find(fields, code, formula) {
66
+ if (!fields) return false;
67
+ for (var f of fields) {
68
+ if (f.code === code && f.formula === formula) return true;
69
+ if (f.fields && find(f.fields, code, formula)) return true;
70
+ }
71
+ return false;
72
+ }
73
+ var form = db.forms.findOne({_id: "451766252f8838253eab81f8"});
74
+ var vids = (form.historys || []).filter(h => find(h.fields, "所属信息站", "judgeIndex({所属部门})")).map(h => h._id);
75
+ print("匹配版本数:", vids.length, "IDs:", JSON.stringify(vids));
76
+ if (vids.length > 0) db.instances.find(
77
+ {form: "451766252f8838253eab81f8", form_version: {$in: vids}},
78
+ {name: 1, form_version: 1, submit_date: 1, state: 1}
79
+ ).sort({submit_date: -1}).limit(10).toArray()
80
+ '
81
+ ```
82
+
83
+ **Issue #2 — 工作循环分析计划表** (`9THeSusZyo9E3pe5p`,字段 `表名`,公式 `{填报单位}车间{YYYY}年度`)
84
+ ```bash
85
+ mongosh "mongodb://127.0.0.1:27017/<dbname>" --eval '
86
+ function find(fields, code, formula) {
87
+ if (!fields) return false;
88
+ for (var f of fields) {
89
+ if (f.code === code && f.formula === formula) return true;
90
+ if (f.fields && find(f.fields, code, formula)) return true;
91
+ }
92
+ return false;
93
+ }
94
+ var form = db.forms.findOne({_id: "9THeSusZyo9E3pe5p"});
95
+ var vids = (form.historys || []).filter(h => find(h.fields, "表名", "{填报单位}车间{YYYY}年度")).map(h => h._id);
96
+ print("匹配版本数:", vids.length, "IDs:", JSON.stringify(vids));
97
+ if (vids.length > 0) db.instances.find(
98
+ {form: "9THeSusZyo9E3pe5p", form_version: {$in: vids}},
99
+ {name: 1, form_version: 1, submit_date: 1, state: 1}
100
+ ).sort({submit_date: -1}).limit(10).toArray()
101
+ '
102
+ ```
103
+
104
+ **Issue #3 — 员工通勤补贴统计表** (`6d9fe8a132c96a664ca23808`,字段 `发放补贴金额(元)`,公式 `{发放补贴数量}*{}`)
105
+ ```bash
106
+ mongosh "mongodb://127.0.0.1:27017/<dbname>" --eval '
107
+ function find(fields, code, formula) {
108
+ if (!fields) return false;
109
+ for (var f of fields) {
110
+ if (f.code === code && f.formula === formula) return true;
111
+ if (f.fields && find(f.fields, code, formula)) return true;
112
+ }
113
+ return false;
114
+ }
115
+ var form = db.forms.findOne({_id: "6d9fe8a132c96a664ca23808"});
116
+ var vids = (form.historys || []).filter(h => find(h.fields, "发放补贴金额(元)", "{发放补贴数量}*{}")).map(h => h._id);
117
+ print("匹配版本数:", vids.length, "IDs:", JSON.stringify(vids));
118
+ if (vids.length > 0) db.instances.find(
119
+ {form: "6d9fe8a132c96a664ca23808", form_version: {$in: vids}},
120
+ {name: 1, form_version: 1, submit_date: 1, state: 1}
121
+ ).sort({submit_date: -1}).limit(10).toArray()
122
+ '
123
+ ```
124
+
125
+ **Issue #4 — 招标结果报审表** (`b9e7465f159b6640bbe49caa`,字段 `概算、估算金额(元、大写)`,公式 `numToRMB(概算、估算金额{})`)
126
+ ```bash
127
+ mongosh "mongodb://127.0.0.1:27017/<dbname>" --eval '
128
+ function find(fields, code, formula) {
129
+ if (!fields) return false;
130
+ for (var f of fields) {
131
+ if (f.code === code && f.formula === formula) return true;
132
+ if (f.fields && find(f.fields, code, formula)) return true;
133
+ }
134
+ return false;
135
+ }
136
+ var form = db.forms.findOne({_id: "b9e7465f159b6640bbe49caa"});
137
+ var vids = (form.historys || []).filter(h => find(h.fields, "概算、估算金额(元、大写)", "numToRMB(概算、估算金额{})")).map(h => h._id);
138
+ print("匹配版本数:", vids.length, "IDs:", JSON.stringify(vids));
139
+ if (vids.length > 0) db.instances.find(
140
+ {form: "b9e7465f159b6640bbe49caa", form_version: {$in: vids}},
141
+ {name: 1, form_version: 1, submit_date: 1, state: 1}
142
+ ).sort({submit_date: -1}).limit(10).toArray()
143
+ '
144
+ ```
145
+
146
+ > **如果是 current 版本的 issue**(本次无此情况,但影响面大 — 所有新建审批单都走此版本):
147
+ > ```bash
148
+ > mongosh "mongodb://127.0.0.1:27017/<dbname>" --eval '
149
+ > var cvid = db.forms.findOne({_id: "<formId>"}).current._id;
150
+ > db.instances.find(
151
+ > {form: "<formId>", form_version: cvid},
152
+ > {name: 1, submit_date: 1, state: 1}
153
+ > ).sort({submit_date: -1}).limit(10).toArray()
154
+ > '
155
+ > ```
156
+
157
+ ### 扫描统计变化
158
+
159
+ | 指标 | v6(修正前) | v7(修正后) |
160
+ |------|------------|------------|
161
+ | ERROR | 12 | 0 |
162
+ | KNOWN_ISSUE | — | 4 |
163
+ | WARN | 206 | 206 |
164
+ | PASS | 1941 | 1949 |
165
+ | current ERROR | 1 | 0 |