@steedos-labs/plugin-workflow 3.0.51 → 3.0.53

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.
@@ -183,7 +183,7 @@ router.post('/am/forms', async function (req, res) {
183
183
  });
184
184
  let companyId = currentSpaceUser.company_id;
185
185
  let newForm = {
186
- _id: form["id"],
186
+ _id: form["id"] || form["_id"],
187
187
  name: form["name"],
188
188
  state: "disabled",
189
189
  is_deleted: false,
@@ -204,7 +204,7 @@ router.post('/am/forms', async function (req, res) {
204
204
  newForm.company_id = companyId;
205
205
  }
206
206
  let current = {
207
- _id: form["current"]["id"],
207
+ _id: form["current"]["id"] || form["current"]["_id"],
208
208
  name_forumla: name_forumla,
209
209
  form: newForm._id,
210
210
  _rev: 1,
@@ -274,7 +274,7 @@ router.post('/am/forms', async function (req, res) {
274
274
  let flow = {
275
275
  _id: _makeNewID(),
276
276
  space: form["space"],
277
- form: form["id"],
277
+ form: form["id"] || form["_id"],
278
278
  name_formula: "",
279
279
  code_formula: "",
280
280
  is_valid: true,
@@ -323,7 +323,7 @@ router.post('/am/forms', async function (req, res) {
323
323
  steps: await designerManager.makeSteps(userId, newForm.current.fields, language),
324
324
  _rev: 1,
325
325
  flow: flow._id,
326
- form_version: form["current"]["id"],
326
+ form_version: form["current"]["id"] || form["current"]["_id"],
327
327
  created: now,
328
328
  created_by: userId,
329
329
  modified: now,
@@ -359,7 +359,7 @@ router.put('/am/forms', async function (req, res) {
359
359
  // 执行者的身份校验
360
360
  await designerManager.checkSpaceUserBeforeUpdate(form['space'], userId, req.user.roles)
361
361
  // 更新表单
362
- await designerManager.updateForm(form["id"], form, updatedForms, updatedFlows, userId)
362
+ await designerManager.updateForm(form["id"] || form["_id"], form, updatedForms, updatedFlows, userId)
363
363
  }
364
364
  res.send({
365
365
  "ChangeSet": {
@@ -370,6 +370,7 @@ router.put('/am/forms', async function (req, res) {
370
370
  }
371
371
  });
372
372
  } catch (error) {
373
+ console.log(error)
373
374
  res.status(500).send(error.message)
374
375
  }
375
376
  })
@@ -394,7 +395,7 @@ router.delete('/am/forms', async function (req, res) {
394
395
  let now = new Date();
395
396
  for (let i = 0; i < data['Forms'].length; i++) {
396
397
  let form = data['Forms'][i];
397
- let f = await formCollection.findOne({_id: form["id"]});
398
+ let f = await formCollection.findOne({_id: form["id"] || form["_id"]});
398
399
  // 执行者的身份校验
399
400
  await designerManager.checkSpaceUserBeforeUpdate(f.space, userId, req.user.roles)
400
401
 
@@ -404,7 +405,7 @@ router.delete('/am/forms', async function (req, res) {
404
405
  // 删除表单对应流程
405
406
  let flows = await flowCollection.find({
406
407
  space: spaceId,
407
- form: form["id"]
408
+ form: form["id"] || form["_id"]
408
409
  }).toArray();
409
410
  for (let flow_fd of flows) {
410
411
  let deleted_flow = Object.assign({}, flow_fd);
@@ -419,7 +420,7 @@ router.delete('/am/forms', async function (req, res) {
419
420
  if (recordCollection) {
420
421
  let records = await recordCollection.find({
421
422
  space: spaceId,
422
- form: form["id"]
423
+ form: form["id"] || form["_id"]
423
424
  }).toArray();
424
425
  for (let record_fd of records) {
425
426
  let deleted_record = Object.assign({}, record_fd);
@@ -434,7 +435,7 @@ router.delete('/am/forms', async function (req, res) {
434
435
  // 删除表单对应申请单
435
436
  let instances = await instanceCollection.find({
436
437
  space: spaceId,
437
- form: form["id"]
438
+ form: form["id"] || form["_id"]
438
439
  }).toArray();
439
440
  for (let instance_fd of instances) {
440
441
  let deleted_instance = Object.assign({}, instance_fd);
@@ -446,7 +447,7 @@ router.delete('/am/forms', async function (req, res) {
446
447
  }
447
448
 
448
449
  // 删除instance_tasks
449
- await instanceCollection.deleteMany({ form: form["id"] })
450
+ await instanceCollection.deleteMany({ form: form["id"] || form["_id"] })
450
451
 
451
452
  // 删除表单
452
453
  let deleted_form = Object.assign({}, f);
@@ -454,7 +455,7 @@ router.delete('/am/forms', async function (req, res) {
454
455
  deleted_form['deleted_by'] = userId;
455
456
  await dFormsCollection.insert(deleted_form);
456
457
  deletedForms.push(deleted_form);
457
- await formCollection.deleteOne({_id: form["id"]})
458
+ await formCollection.deleteOne({_id: form["id"] || form["_id"]})
458
459
  }
459
460
 
460
461
  res.send({
@@ -483,7 +484,7 @@ router.put('/am/flows', async function (req, res) {
483
484
  let flowCome = data['Flows'][i];
484
485
  let spaceId = flowCome["space"];
485
486
  let formId = flowCome["form"];
486
- let flowId = flowCome["id"];
487
+ let flowId = flowCome["id"] || flowCome["_id"];
487
488
  let upgraded = flowCome['upgraded'];
488
489
  delete flowCome['decription'];
489
490
  let now = new Date();
@@ -501,7 +502,7 @@ router.put('/am/flows', async function (req, res) {
501
502
  // 某步骤被删除后,删除同流程的“指定历史步骤”属性中被引用的步骤id(仅限于流程的最新版)
502
503
  let clientStepIds = []
503
504
  _.each(flowCome['current']['steps'], function (step) {
504
- clientStepIds.push(step['id']);
505
+ clientStepIds.push(step['_id'] || step['id']);
505
506
  })
506
507
 
507
508
  _.each(flowCome['current']['steps'], function (step) {
@@ -524,12 +525,16 @@ router.put('/am/flows', async function (req, res) {
524
525
 
525
526
  // 由于前台传的是id而非_id,故比较时将id转为_id
526
527
  _.each(flowCome['current']['steps'], function (step) {
527
- step['_id'] = step['id'];
528
- delete step['id'];
528
+ if (step['id']) {
529
+ step['_id'] = step['id'];
530
+ delete step['id'];
531
+ }
529
532
  if (step['lines']) {
530
533
  _.each(step['lines'], function (line) {
531
- line['_id'] = line['id'];
532
- delete line['id'];
534
+ if (line['id']) {
535
+ line['_id'] = line['id'];
536
+ delete line['id'];
537
+ }
533
538
  })
534
539
  }
535
540
  })
@@ -647,6 +652,7 @@ router.put('/am/flows', async function (req, res) {
647
652
  }
648
653
  });
649
654
  } catch (error) {
655
+ console.log(error);
650
656
  res.status(500).send(error.message)
651
657
  }
652
658
  })
@@ -664,7 +670,7 @@ router.put('/am/flows/state', async function (req, res) {
664
670
  let flowCome = data['Flows'][i];
665
671
  let spaceId = flowCome["space"];
666
672
  let formId = flowCome["form"];
667
- let flowId = flowCome["id"];
673
+ let flowId = flowCome["id"] || flowCome["_id"];
668
674
  let now = new Date();
669
675
  let flowUpdateObj = {
670
676
  $set: {}
@@ -39,7 +39,7 @@ router.post('/am/ai/form-design', async function auth(req, res, next) {
39
39
  const baseURL = process.env.WORKFLOW_AI_BASE_URL || 'https://api.openai.com/v1';
40
40
  const model = process.env.WORKFLOW_AI_MODEL || 'gpt-4o';
41
41
 
42
- const { fields, events, userRequest, images, instance_template, form_script, flow_events } = req.body;
42
+ const { fields, events, userRequest, images, instance_template, form_script, flow_events, name_forumla } = req.body;
43
43
 
44
44
  if (!userRequest) {
45
45
  return res.status(400).json({ error: '请输入需求描述' });
@@ -120,6 +120,7 @@ router.post('/am/ai/form-design', async function auth(req, res, next) {
120
120
  - 示例: "\${RMB(assessed_value)}" —— 人民币大写(推荐)
121
121
  - 示例: "\${TEXT(amount, \"rmb\")}" —— 等同于 RMB(),两者都可用,不要用 TEXT(v, "[DBNum2]...") 的 Excel 格式
122
122
  - 注意:公式内字段名直接写,不加 \${} 嵌套,正确:"\${RMB(amount)}",错误:"\${RMB(\${amount})}"
123
+ - ⚠️ 子表字段引用规则:在主表公式中对子表(table)的子字段使用聚合函数时,直接使用子字段名,不需要加子表名前缀。系统会自动从子表数据中提取该列进行聚合。正确:"\${SUM(amount)}"(amount 是子表的子字段名),错误:"\${SUM(items.amount)}"(不要用 子表名.子字段名 的写法)。示例:子表 "items" 有子字段 "unit_price" 和 "quantity",主表求合计公式写 "\${SUM(unit_price)}",不要写 "\${SUM(items.unit_price)}"。
123
124
 
124
125
  - section 类型(分组标题)的额外字段:
125
126
  - colorScheme: 字符串,预设配色方案名称。可选值:"indigo"(靛蓝), "emerald"(翠绿), "amber"(琥珀), "rose"(玫红), "sky"(天蓝), "violet"(紫罗兰), "slate"(石板灰), "orange"(橙色), "teal"(青色)。设置后分组标题会显示对应的主题色
@@ -401,9 +402,29 @@ if (field.name === 'quantity' || field.name === 'unit_price') {
401
402
  "onValueChange": "脚本代码或空字符串",
402
403
  "onSubmit": "脚本代码或空字符串"
403
404
  },
405
+ "nameFormula": "标题公式(仅升级场景,将旧版标题公式中的字段引用更新为新版字段 name)",
404
406
  "migrationLog": ["迁移记录,仅升级场景需要"]
405
407
  }
406
408
 
409
+ ### nameFormula(标题公式,升级场景)
410
+ 当用户提供了旧版标题公式(name_forumla)时,需要将其中的字段引用更新为新版字段 name。
411
+ - 旧版标题公式格式:用 {字段名} 引用字段值,如 "{申请人} 的 {类型} 申请"
412
+ - 升级时**只替换 {旧字段名} → {新字段name}**,如 "{applicant_name} 的 {request_type} 申请"
413
+ - ⚠️ **公式中花括号外的所有字符必须原样保留**,包括但不限于:双引号 "、单引号 '、中文引号""''、括号、标点符号、空格等。只有 {} 内的字段名需要替换,其他一切文本保持不变
414
+ - 示例:旧版 \`"项目" + {项目名称}\` → 新版 \`"项目" + {project_name}\`(注意引号 " 和加号 + 必须保留)
415
+ - 示例:旧版 \`{申请人}"提交的"{类型}"申请"\` → 新版 \`{applicant_name}"提交的"{request_type}"申请"\`(注意引号必须保留)
416
+ - 示例:旧版 \`{项目名称}({申请日期})\` → 新版 \`{project_name}({apply_date})\`(注意中文括号必须保留)
417
+ - 如果用户未提供旧版标题公式,则 nameFormula 字段可省略或返回空字符串
418
+
419
+ #### name_forumla 运行时格式规范
420
+ nameFormula 是一个 JS 表达式,运行时被包装为 \`return <nameFormula>\`,其中 \`{fieldCode}\` 会被替换为 \`(values.fieldCode || '')\`,\`{applicant.xxx}\` 会被替换为 \`(applicant.xxx || '')\`。
421
+ **规则:所有非 {xxx} 的文本(包括中文、符号、空格)必须用引号包裹,多段用 + 拼接。**
422
+ - 正确:\`"合同名称" + {project_name}\`
423
+ - 正确:\`{applicant_name} + "-" + {project_name}\`
424
+ - 错误:\`合同名称{project_name}\` — JS 语法错误
425
+ - 错误:\`合同名称 + {project_name}\` — JS 语法错误
426
+ - 错误:\`{project_name} 审批单\` — JS 语法错误
427
+
407
428
  ### migrationLog(迁移记录)
408
429
  当用户提供了 flow_events、form_script、instance_template 中包含业务逻辑(如校验、赋值、显隐控制等脚本代码)时,必须在 migrationLog 数组中为每条被迁移的逻辑记录一条说明,格式:
409
430
  "<来源>: <原逻辑简述> → <迁移到的具体位置>"
@@ -442,6 +463,9 @@ if (field.name === 'quantity' || field.name === 'unit_price') {
442
463
  if (flow_events) {
443
464
  extraSections += `\n\n## 流程事件 (flow_events)\n\`\`\`javascript\n${flow_events}\n\`\`\``;
444
465
  }
466
+ if (name_forumla) {
467
+ extraSections += `\n\n## 旧版标题公式 (name_forumla)\n${name_forumla}\n\n说明:标题公式用 {字段名} 引用字段值,升级时需将其中的 {旧字段名} 替换为 {新版字段name},输出到 nameFormula 字段。**只替换 {} 花括号内的字段名,花括号外的所有文本(包括引号 "、单引号 '、中文引号""''、括号、其他标点符号和空格等)必须原样保留,禁止增删改。**`;
468
+ }
445
469
 
446
470
  const userContent = `## 当前表单字段
447
471
  ${fieldsJson}
@@ -90,7 +90,7 @@ router.post('/am/ai/form-design-stream', async function auth(req, res, next) {
90
90
  extraSections += `\n\n## 流程事件 (flow_events)\n\`\`\`javascript\n${flow_events}\n\`\`\``;
91
91
  }
92
92
  if (name_forumla) {
93
- extraSections += `\n\n## 旧版标题公式 (name_forumla)\n${name_forumla}\n\n说明:标题公式用 {字段名} 引用字段值,升级时需将其中的 {旧字段名} 替换为 {新版字段name},输出到 nameFormula 字段。`;
93
+ extraSections += `\n\n## 旧版标题公式 (name_forumla)\n${name_forumla}\n\n说明:标题公式用 {字段名} 引用字段值,升级时需将其中的 {旧字段名} 替换为 {新版字段name},输出到 nameFormula 字段。**只替换 {} 花括号内的字段名,花括号外的所有文本(包括引号 \"、单引号 '、中文引号""''、括号、其他标点符号和空格等)必须原样保留,禁止增删改。**`;
94
94
  }
95
95
 
96
96
  const userContent = `## 当前表单字段\n${fieldsJson}\n\n## 当前事件脚本\n${eventsJson}${extraSections}\n\n## 用户需求\n${userRequest}\n\n请返回修改后的完整 JSON 对象(包含 tableColumns、fields 和 events)。`;
@@ -476,6 +476,7 @@ function buildSystemPrompt() {
476
476
  - 示例: "\${RMB(assessed_value)}" —— 人民币大写(推荐)
477
477
  - 示例: "\${TEXT(amount, \\"rmb\\")}" —— 等同于 RMB(),两者都可用,不要用 TEXT(v, "[DBNum2]...") 的 Excel 格式
478
478
  - 注意:公式内字段名直接写,不加 \${} 嵌套,正确:"\${RMB(amount)}",错误:"\${RMB(\${amount})}"
479
+ - ⚠️ 子表字段引用规则:在主表公式中对子表(table)的子字段使用聚合函数时,直接使用子字段名,不需要加子表名前缀。系统会自动从子表数据中提取该列进行聚合。正确:"\${SUM(amount)}"(amount 是子表的子字段名),错误:"\${SUM(items.amount)}"(不要用 子表名.子字段名 的写法)。示例:子表 "items" 有子字段 "unit_price" 和 "quantity",主表求合计公式写 "\${SUM(unit_price)}",不要写 "\${SUM(items.unit_price)}"。
479
480
 
480
481
  - section 类型(分组标题)的额外字段:
481
482
  - colorScheme: 字符串,预设配色方案名称。可选值:"indigo"(靛蓝), "emerald"(翠绿), "amber"(琥珀), "rose"(玫红), "sky"(天蓝), "violet"(紫罗兰), "slate"(石板灰), "orange"(橙色), "teal"(青色)。设置后分组标题会显示对应的主题色
@@ -779,10 +780,22 @@ if (field.name === 'quantity' || field.name === 'unit_price') {
779
780
  ### nameFormula(标题公式,升级场景)
780
781
  当用户提供了旧版标题公式(name_forumla)时,需要将其中的字段引用更新为新版字段 name。
781
782
  - 旧版标题公式格式:用 {字段名} 引用字段值,如 "{申请人} 的 {类型} 申请"
782
- - 升级时将 {旧字段名} 替换为 {新字段name},如 "{applicant_name} 的 {request_type} 申请"
783
- - 公式中的纯文本部分保持不变
783
+ - 升级时**只替换 {旧字段名} {新字段name}**,如 "{applicant_name} 的 {request_type} 申请"
784
+ - ⚠️ **公式中花括号外的所有字符必须原样保留**,包括但不限于:双引号 "、单引号 '、中文引号""''、括号、标点符号、空格等。只有 {} 内的字段名需要替换,其他一切文本保持不变
785
+ - 示例:旧版 \`"项目" + {项目名称}\` → 新版 \`"项目" + {project_name}\`(注意引号 " 和加号 + 必须保留)
786
+ - 示例:旧版 \`{申请人}"提交的"{类型}"申请"\` → 新版 \`{applicant_name}"提交的"{request_type}"申请"\`(注意引号必须保留)
787
+ - 示例:旧版 \`{项目名称}({申请日期})\` → 新版 \`{project_name}({apply_date})\`(注意中文括号必须保留)
784
788
  - 如果用户未提供旧版标题公式,则 nameFormula 字段可省略或返回空字符串
785
789
 
790
+ #### name_forumla 运行时格式规范
791
+ nameFormula 是一个 JS 表达式,运行时被包装为 \`return <nameFormula>\`,其中 \`{fieldCode}\` 会被替换为 \`(values.fieldCode || '')\`,\`{applicant.xxx}\` 会被替换为 \`(applicant.xxx || '')\`。
792
+ **规则:所有非 {xxx} 的文本(包括中文、符号、空格)必须用引号包裹,多段用 + 拼接。**
793
+ - 正确:\`"合同名称" + {project_name}\`
794
+ - 正确:\`{applicant_name} + "-" + {project_name}\`
795
+ - 错误:\`合同名称{project_name}\` — JS 语法错误
796
+ - 错误:\`合同名称 + {project_name}\` — JS 语法错误
797
+ - 错误:\`{project_name} 审批单\` — JS 语法错误
798
+
786
799
  ### migrationLog(迁移记录)
787
800
  当用户提供了 flow_events、form_script、instance_template 中包含业务逻辑(如校验、赋值、显隐控制等脚本代码)时,必须在 migrationLog 数组中为每条被迁移的逻辑记录一条说明,格式:
788
801
  "<来源>: <原逻辑简述> → <迁移到的具体位置>"
@@ -310,7 +310,7 @@ const calcSteps = async function(instance, flow, flowVersionId, formFields, valu
310
310
 
311
311
  _steps.push(step);
312
312
  try {
313
- var nextSteps = await getNextSteps(flow, flowVersionId, instance, step, judge, values, null, null, instance.submitter);
313
+ var nextSteps = await getNextSteps(flow, flowVersionId, instance, step, judge, values, null, true, instance.submitter);
314
314
  const recursiveResults = await Promise.all(nextSteps.map(async (nextStep) => {
315
315
  try {
316
316
  if (!_.includes(track, nextStep._id)) {
@@ -628,7 +628,7 @@
628
628
  for (const sField of field.fields) {
629
629
  if (sField.type != "hidden") {
630
630
  sField.permission = field.permission
631
- const column = await getFieldEditTpl(sField, true);
631
+ const column = await getFieldEditTpl(sField, null);
632
632
  tpl.columns.push(column);
633
633
  }
634
634
  }
@@ -641,7 +641,7 @@
641
641
  tpl.body = []
642
642
  if (field.fields) {
643
643
  for (let i = 0; i < field.fields.length; i++) {
644
- let fieldsItem = await getFieldEditTpl(field.fields[i], true)
644
+ let fieldsItem = await getFieldEditTpl(field.fields[i], tableFieldMap)
645
645
  tpl.body.push(fieldsItem)
646
646
  }
647
647
  }
@@ -205,9 +205,12 @@ reports/formula-scan/
205
205
  | E3 | ERROR | 转换结果中含裸 `{`(非合法 `${...}` 表达式) |
206
206
  | E4 | ERROR | mapFormula 抛出异常 |
207
207
  | E5 | ERROR | 聚合函数引用子表字段但转换结果不含对应 ARRAYMAP(子表识别失败) |
208
+ | E6 | ERROR | section 嵌套公式字段设计器兼容性:引擎转换结果与设计器传参不一致 |
208
209
  | W1 | WARN | 公式含除法且除数是字段引用(除零风险) |
209
210
  | W2 | WARN | 同表单内不同字段 getSafeCode 后结果相同(字段名冲突) |
210
211
 
212
+ > **E6 说明**:检测 `flow_form_design.ejs` 的 section 子字段是否正确传递 `tableFieldMap`。模拟设计器行为(传 `true`)并与正确结果对比,不一致则报 ERROR。详见 SCAN_HISTORY v9→v10。
213
+
211
214
  ---
212
215
 
213
216
  ## 报告结构说明
@@ -197,3 +197,60 @@ v8 与 v7 对比完全一致(0 ERROR),说明:
197
197
  | KNOWN_ISSUE | 4 | 4 |
198
198
  | WARN | 206 | 206 |
199
199
  | PASS | 1949 | 1949 |
200
+
201
+ ---
202
+
203
+ ## v9 → v10:Bug 9 — 设计器 section 子字段未传递 tableFieldMap
204
+
205
+ - **扫描日期**: 2026-03-27
206
+ - **修正前报告**: `scan-result-v9-20260327.json`(6 ERROR, 4 KNOWN_ISSUE, 206 WARN)
207
+ - **修正后报告**: `scan-result-v10-20260327.json`(0 ERROR, 4 KNOWN_ISSUE, 206 WARN)
208
+ - **关联 Issue**: [#538](https://github.com/steedos/steedos-plugins/issues/538)
209
+ - **修改文件**: `flow_form_design.ejs`
210
+
211
+ ### Bug 9 根因
212
+
213
+ `flow_form_design.ejs` 的 `getFieldEditTpl` 函数中:
214
+ - **section case(第 644 行)**:调用 `getFieldEditTpl(field.fields[i], true)` — 传递布尔值 `true` 而非 `tableFieldMap`
215
+ - **table case(第 631 行)**:调用 `getFieldEditTpl(sField, true)` — 同样传递 `true`
216
+
217
+ 在 `_mapFormula` 内部,`tableFieldMap` 为 `true` 时,`true[fieldCode]` 永远返回 `undefined`,导致子表字段识别失败,走了非子表路径(`getSafeCode` 而非 `ARRAYMAP`)。
218
+
219
+ > **为什么之前的扫描器没发现**:扫描器自己通过 `getTableFieldMap(fields)` 构建正确的 `tableFieldMap` 传给 `mapFormula`,测试的是公式引擎本身。但设计器的调用链在 section 递归时传参错误,属于**调用者 bug**而非引擎 bug。
220
+
221
+ ### 修复内容
222
+
223
+ - section case:`getFieldEditTpl(field.fields[i], true)` → `getFieldEditTpl(field.fields[i], tableFieldMap)`
224
+ - table case:`getFieldEditTpl(sField, true)` → `getFieldEditTpl(sField, null)`(子表内字段不需要 tableFieldMap)
225
+
226
+ ### 检测方法(E6 规则,一次性诊断)
227
+
228
+ 为发现此类问题,临时添加 E6 规则到扫描器:
229
+ - 追踪字段是否在 section 内(`inSection` 标志)
230
+ - 对 section 内的公式字段,模拟设计器行为调用 `mapFormula(formula, true)`
231
+ - 比较与正确结果是否一致,不一致则报 ERROR
232
+
233
+ E6 是一次性诊断规则 — 发现问题后修复设计器,然后移除 E6(因为它测试的是调用者行为而非引擎行为)。但 `inSection` 追踪保留在 `collectFormulaFields` 中,供未来诊断使用。
234
+
235
+ ### 修复了 6 个 E6 ERROR
236
+
237
+ | # | 表单名称 | formId | 字段 | 原始公式 | 版本 |
238
+ |---|---------|--------|------|---------|------|
239
+ | 1 | 【公司本部】抚顺石化公司车辆维修审批单 | `9a40a1a2049014ff074a4961` | 配件金额 | `{数量}*{单价}` | history |
240
+ | 2 | 【乙烯部】抚顺石化公司车辆维修审批单 | `2a36450a56ecd64af98506ba` | 配件金额 | `{数量}*{单价}` | history |
241
+ | 3 | 【公司办公室】抚顺石化公司车辆维修费用结算审批单 | `2c3a2c7cbbf618d95a40376b` | 配件金额 | `{数量}*{单价}` | history |
242
+ | 4 | 抚顺石化公司物资采购概预算调整审批单 | `cRJknoGMcLa2raizW` | 拟调整概预算金额合计 | `sum({拟调整概预算金额})` | **current** |
243
+ | 5 | 抚顺石化公司物资采购概预算调整审批单 | `cRJknoGMcLa2raizW` | 拟调整概预算总金额 | `sum({拟调整概预算金额})` | history |
244
+ | 6 | 抚顺石化公司化工三剂采购概预算调整审批单 | `17d3b669d8880cd32b89ebfb` | 拟调整概预算金额合计 | `sum({拟调整概预算金额(元)})` | **current** |
245
+
246
+ > **影响面**: 4 个 history + 2 个 **current**(#4 和 #6 影响在用表单的设计器预览)
247
+
248
+ ### 扫描统计变化
249
+
250
+ | 指标 | v8 | v9(修正前) | v10(修正后) |
251
+ |------|-----|------------|-------------|
252
+ | ERROR | 0 | 6 | 0 |
253
+ | KNOWN_ISSUE | 4 | 4 | 4 |
254
+ | WARN | 206 | 206 | 206 |
255
+ | PASS | 1949 | 1943 | 1949 |
256
+ | current ERROR | 0 | 2 | 0 |