weaver-e10-builder 1.6.9 → 1.6.11
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.
- package/dist/commands/form-data.d.ts.map +1 -1
- package/dist/commands/form-data.js +4 -1
- package/dist/commands/form-data.js.map +1 -1
- package/dist/commands/report-admin.d.ts.map +1 -1
- package/dist/commands/report-admin.js +378 -2
- package/dist/commands/report-admin.js.map +1 -1
- package/dist/commands/report-validate.d.ts.map +1 -1
- package/dist/commands/report-validate.js +1066 -3
- package/dist/commands/report-validate.js.map +1 -1
- package/dist/commands/report.d.ts.map +1 -1
- package/dist/commands/report.js +341 -3
- package/dist/commands/report.js.map +1 -1
- package/dist/commands/workflow-after-submit-comment.d.ts +3 -0
- package/dist/commands/workflow-after-submit-comment.d.ts.map +1 -0
- package/dist/commands/workflow-after-submit-comment.js +56 -0
- package/dist/commands/workflow-after-submit-comment.js.map +1 -0
- package/dist/commands/workflow-setting.d.ts.map +1 -1
- package/dist/commands/workflow-setting.js +2 -67
- package/dist/commands/workflow-setting.js.map +1 -1
- package/dist/services/action-detail.d.ts.map +1 -1
- package/dist/services/action-detail.js +1 -17
- package/dist/services/action-detail.js.map +1 -1
- package/dist/services/actionflow/components/action_eb_update_compiler.d.ts.map +1 -1
- package/dist/services/actionflow/components/action_eb_update_compiler.js +6 -2
- package/dist/services/actionflow/components/action_eb_update_compiler.js.map +1 -1
- package/dist/services/actionflow/components/custom_trigger.js +1 -1
- package/dist/services/actionflow/components/custom_trigger.js.map +1 -1
- package/dist/services/actionflow/components/dml_execute.js +1 -1
- package/dist/services/actionflow/components/dml_execute.js.map +1 -1
- package/dist/services/actionflow/components/document_actions.js +1 -2
- package/dist/services/actionflow/components/document_actions.js.map +1 -1
- package/dist/services/actionflow/components/eb_get_data_by_id.d.ts.map +1 -1
- package/dist/services/actionflow/components/eb_get_data_by_id.js +2 -2
- package/dist/services/actionflow/components/eb_get_data_by_id.js.map +1 -1
- package/dist/services/actionflow/components/form_data_builder.d.ts.map +1 -1
- package/dist/services/actionflow/components/form_data_builder.js +18 -10
- package/dist/services/actionflow/components/form_data_builder.js.map +1 -1
- package/dist/services/actionflow/components/hrm_actions.js +0 -1
- package/dist/services/actionflow/components/hrm_actions.js.map +1 -1
- package/dist/services/actionflow/components/webhook_trigger.js +3 -3
- package/dist/services/actionflow/components/webhook_trigger.js.map +1 -1
- package/dist/services/actionflow/components/workflow_actions.js +3 -2
- package/dist/services/actionflow/components/workflow_actions.js.map +1 -1
- package/dist/services/actionflow/filter_rules.d.ts.map +1 -1
- package/dist/services/actionflow/filter_rules.js +15 -13
- package/dist/services/actionflow/filter_rules.js.map +1 -1
- package/dist/services/actionflow/form_source.d.ts.map +1 -1
- package/dist/services/actionflow/form_source.js +59 -11
- package/dist/services/actionflow/form_source.js.map +1 -1
- package/dist/services/actionflow/formula_service.d.ts.map +1 -1
- package/dist/services/actionflow/formula_service.js +4 -1
- package/dist/services/actionflow/formula_service.js.map +1 -1
- package/dist/services/actionflow/option_field_types.d.ts +5 -0
- package/dist/services/actionflow/option_field_types.d.ts.map +1 -0
- package/dist/services/actionflow/option_field_types.js +20 -0
- package/dist/services/actionflow/option_field_types.js.map +1 -0
- package/dist/services/actionflow/param_group_dto.d.ts.map +1 -1
- package/dist/services/actionflow/param_group_dto.js +7 -3
- package/dist/services/actionflow/param_group_dto.js.map +1 -1
- package/dist/services/actionflow/preflight_service.d.ts.map +1 -1
- package/dist/services/actionflow/preflight_service.js +42 -18
- package/dist/services/actionflow/preflight_service.js.map +1 -1
- package/dist/services/actionflow/webhook_source.d.ts.map +1 -1
- package/dist/services/actionflow/webhook_source.js +9 -4
- package/dist/services/actionflow/webhook_source.js.map +1 -1
- package/dist/services/actionflow/workflow_compiler.d.ts.map +1 -1
- package/dist/services/actionflow/workflow_compiler.js +11 -8
- package/dist/services/actionflow/workflow_compiler.js.map +1 -1
- package/dist/services/report/blueprint.d.ts +109 -0
- package/dist/services/report/blueprint.d.ts.map +1 -0
- package/dist/services/report/blueprint.js +322 -0
- package/dist/services/report/blueprint.js.map +1 -0
- package/dist/services/report/build.d.ts.map +1 -1
- package/dist/services/report/build.js +8 -3
- package/dist/services/report/build.js.map +1 -1
- package/dist/services/report/card.d.ts +65 -0
- package/dist/services/report/card.d.ts.map +1 -0
- package/dist/services/report/card.js +151 -0
- package/dist/services/report/card.js.map +1 -0
- package/dist/services/report/copy-health.d.ts +31 -0
- package/dist/services/report/copy-health.d.ts.map +1 -0
- package/dist/services/report/copy-health.js +87 -0
- package/dist/services/report/copy-health.js.map +1 -0
- package/dist/services/report/dataset-heal.d.ts +64 -0
- package/dist/services/report/dataset-heal.d.ts.map +1 -0
- package/dist/services/report/dataset-heal.js +89 -0
- package/dist/services/report/dataset-heal.js.map +1 -0
- package/dist/services/report/dataset-ids.d.ts +70 -0
- package/dist/services/report/dataset-ids.d.ts.map +1 -0
- package/dist/services/report/dataset-ids.js +149 -0
- package/dist/services/report/dataset-ids.js.map +1 -0
- package/dist/services/report/dataset.d.ts.map +1 -1
- package/dist/services/report/dataset.js +3 -1
- package/dist/services/report/dataset.js.map +1 -1
- package/dist/services/report/empty-dataset.d.ts +51 -0
- package/dist/services/report/empty-dataset.d.ts.map +1 -0
- package/dist/services/report/empty-dataset.js +213 -0
- package/dist/services/report/empty-dataset.js.map +1 -0
- package/dist/services/report/field-binding.d.ts +75 -0
- package/dist/services/report/field-binding.d.ts.map +1 -0
- package/dist/services/report/field-binding.js +160 -0
- package/dist/services/report/field-binding.js.map +1 -0
- package/dist/services/report/forms.d.ts +32 -0
- package/dist/services/report/forms.d.ts.map +1 -1
- package/dist/services/report/forms.js +90 -0
- package/dist/services/report/forms.js.map +1 -1
- package/dist/services/report/formula-parent.d.ts +25 -0
- package/dist/services/report/formula-parent.d.ts.map +1 -0
- package/dist/services/report/formula-parent.js +116 -0
- package/dist/services/report/formula-parent.js.map +1 -0
- package/dist/services/report/locate.d.ts +40 -0
- package/dist/services/report/locate.d.ts.map +1 -0
- package/dist/services/report/locate.js +122 -0
- package/dist/services/report/locate.js.map +1 -0
- package/dist/services/report/reports.d.ts +4 -0
- package/dist/services/report/reports.d.ts.map +1 -1
- package/dist/services/report/reports.js +4 -2
- package/dist/services/report/reports.js.map +1 -1
- package/dist/services/report/scene.d.ts +22 -0
- package/dist/services/report/scene.d.ts.map +1 -0
- package/dist/services/report/scene.js +145 -0
- package/dist/services/report/scene.js.map +1 -0
- package/dist/services/report/types.d.ts +28 -0
- package/dist/services/report/types.d.ts.map +1 -1
- package/dist/services/report/verify.d.ts +24 -0
- package/dist/services/report/verify.d.ts.map +1 -1
- package/dist/services/report/verify.js +115 -2
- package/dist/services/report/verify.js.map +1 -1
- package/dist/services/report/workbook.d.ts +12 -1
- package/dist/services/report/workbook.d.ts.map +1 -1
- package/dist/services/report/workbook.js +107 -8
- package/dist/services/report/workbook.js.map +1 -1
- package/dist/services/workflow-after-submit-comment.d.ts +20 -0
- package/dist/services/workflow-after-submit-comment.d.ts.map +1 -0
- package/dist/services/workflow-after-submit-comment.js +81 -0
- package/dist/services/workflow-after-submit-comment.js.map +1 -0
- package/ecodecmd/src/build.js +36 -12
- package/package.json +1 -1
- package/skill-docs/SKILL.md +4 -4
- package/skill-docs/_catalog.md +10 -1
- package/skill-docs/actionflows/SKILL.md +1 -0
- package/skill-docs/actionflows/references/components/ebuilder/EnquiryForm.md +2 -2
- package/skill-docs/actionflows/references/components/trigger/CustomTrigger.md +2 -0
- package/skill-docs/actionflows/references/components/trigger/WebHookTrigger.md +19 -1
- package/skill-docs/references/coding/guide-form-crud.md +2 -0
- package/skill-docs/references/coding/guide-page-code.md +108 -0
- package/skill-docs/references/components/ref-component-common.md +98 -0
- package/skill-docs/references/report/add-dataset-registration-guide.md +44 -22
- package/skill-docs/references/report/advanced-crosstab-tree-guide.md +82 -0
- package/skill-docs/references/report/ai-report-workflow.md +100 -100
- package/skill-docs/references/report/api-auth-headers.md +129 -0
- package/skill-docs/references/report/api-report-build-fast-path.md +274 -275
- package/skill-docs/references/report/app-datasource-lookup-guide.md +230 -230
- package/skill-docs/references/report/branch-scene-guide.md +293 -0
- package/skill-docs/references/report/build-resilience-guide.md +99 -0
- package/skill-docs/references/report/card-report-guide.md +110 -0
- package/skill-docs/references/report/cell-config-echo-guide.md +44 -9
- package/skill-docs/references/report/cell-transform-guide.md +9 -9
- package/skill-docs/references/report/column-split-report-guide.md +96 -0
- package/skill-docs/references/report/condition-format-guide.md +49 -24
- package/skill-docs/references/report/cross-dataset-filter-guide.md +180 -69
- package/skill-docs/references/report/crosstab-raw-workbook-guide.md +265 -0
- package/skill-docs/references/report/dataset-query-filter-guide.md +231 -235
- package/skill-docs/references/report/dataset-sidebar-ops-guide.md +75 -34
- package/skill-docs/references/report/dataset-table-field-contract-guide.md +196 -46
- package/skill-docs/references/report/datasource-metadata-guide.md +128 -119
- package/skill-docs/references/report/datasource-selection-and-parent-filter-guide.md +183 -148
- package/skill-docs/references/report/date-range-query-reference.md +97 -102
- package/skill-docs/references/report/default-header-style-guide.md +8 -8
- package/skill-docs/references/report/designer-blank-prevention-guide.md +8 -8
- package/skill-docs/references/report/dossier-report-guide.md +69 -0
- package/skill-docs/references/report/drilldown-report-guide.md +59 -0
- package/skill-docs/references/report/event-hreflink-guide.md +53 -47
- package/skill-docs/references/report/expansion-block-parent-config-guide.md +208 -0
- package/skill-docs/references/report/failure-cleanup-and-nonblocking-guide.md +183 -0
- package/skill-docs/references/report/field-bind-exact-match-guide.md +208 -208
- package/skill-docs/references/report/financial-stats-report-guide.md +89 -0
- package/skill-docs/references/report/formula-cell-api-guide.md +325 -258
- package/skill-docs/references/report/golden-case-summary-sheet.md +200 -0
- package/skill-docs/references/report/guide-report-build.md +6 -1
- package/skill-docs/references/report/hidden-row-and-header-merge-guide.md +10 -10
- package/skill-docs/references/report/layout-showlocation-freeze-guide.md +39 -10
- package/skill-docs/references/report/multi-report-crosstab-casebook.md +263 -0
- package/skill-docs/references/report/paged-group-report-guide.md +68 -0
- package/skill-docs/references/report/preaggregate-auto-disable-guide.md +24 -13
- package/skill-docs/references/report/query-condition-api-guide.md +145 -125
- package/skill-docs/references/report/ref-report-commands.md +41 -3
- package/skill-docs/references/report/report-baseinfo-defaults-guide.md +117 -117
- package/skill-docs/references/report/report-building-guide.md +52 -52
- package/skill-docs/references/report/report-case-prompts.md +104 -0
- package/skill-docs/references/report/report-config-schema.md +281 -281
- package/skill-docs/references/report/report-create-modes-guide.md +73 -35
- package/skill-docs/references/report/report-data-model.md +131 -131
- package/skill-docs/references/report/report-delivery-contract.md +23 -3
- package/skill-docs/references/report/report-designer-feature-map.md +30 -35
- package/skill-docs/references/report/report-help-guide.md +304 -0
- package/skill-docs/references/report/report-internal-error-guide.md +71 -0
- package/skill-docs/references/report/report-knowledge-base.md +27 -27
- package/skill-docs/references/report/report-lifecycle-api-guide.md +126 -94
- package/skill-docs/references/report/report-list-page-ops-guide.md +54 -8
- package/skill-docs/references/report/report-permission-guide.md +99 -102
- package/skill-docs/references/report/report-requirement-analysis-template.md +93 -29
- package/skill-docs/references/report/report-self-check-guide.md +164 -164
- package/skill-docs/references/report/report-verification-discipline-guide.md +203 -0
- package/skill-docs/references/report/safe-partial-save-guide.md +151 -151
- package/skill-docs/references/report/shard-freeze-report-guide.md +97 -0
- package/skill-docs/references/report/snowflake-id-precision-guide.md +84 -84
- package/skill-docs/references/report/spec-build-schema.md +71 -71
- package/skill-docs/references/report/targeted-fix-guide.md +155 -97
- package/skill-docs/references/report/user-request-scope-only-guide.md +23 -4
- package/skill-docs/references/workflow/guide-after-submit-comment.md +58 -0
- package/skill-docs/references/workflow/guide-workflow.md +6 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> **入口**:报表设计器左侧数据集标题 `…` 菜单
|
|
4
4
|
> **页面例**:`/sp/edc/report/designer/{reportId}`
|
|
5
5
|
> **CLI**:`e10-cli report dataset rename|agg|sort|replace|delete|check-used|preview`
|
|
6
|
-
> **鉴权**:e10-
|
|
6
|
+
> **鉴权**:e10-cli auth 三项头(`api-auth-headers.md`)
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -59,13 +59,13 @@ e10-cli report dataset rename --dataset-id <id> --name "轻资产主表" [--name
|
|
|
59
59
|
|
|
60
60
|
```json
|
|
61
61
|
[
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
{
|
|
63
|
+
"fieldId": "{datasetId}.{tableId}.{fieldName}",
|
|
64
|
+
"countType": "sum",
|
|
65
|
+
"showName": "库存合计",
|
|
66
|
+
"fieldName": "s_sum_field_xxx"
|
|
67
|
+
},
|
|
68
|
+
{ "groupBy": "{datasetId}.{tableId}.{fieldName}" }
|
|
69
69
|
]
|
|
70
70
|
```
|
|
71
71
|
|
|
@@ -108,8 +108,8 @@ e10-cli report dataset agg clear --dataset-id <id>
|
|
|
108
108
|
|
|
109
109
|
```json
|
|
110
110
|
[
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
{ "fieldId": "{datasetId}.{tableId}.{name}", "orderType": "asc" },
|
|
112
|
+
{ "fieldId": "{datasetId}.{tableId}.{name2}", "orderType": "desc" }
|
|
113
113
|
]
|
|
114
114
|
```
|
|
115
115
|
|
|
@@ -132,20 +132,20 @@ Content-Type: application/json
|
|
|
132
132
|
|
|
133
133
|
```json
|
|
134
134
|
{
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
135
|
+
"reportId": 1313049481975267329,
|
|
136
|
+
"builtinId": 旧datasetId,
|
|
137
|
+
"name": "新数据源显示名",
|
|
138
|
+
"sourceType": "LOGIC",
|
|
139
|
+
"sourceId": "新表单sourceId",
|
|
140
|
+
"sourceGroup": "weaver-ebuilder-form-service",
|
|
141
|
+
"appid": "<appId>",
|
|
142
|
+
"fieldMap": [
|
|
143
|
+
{
|
|
144
|
+
"builtinField": "旧字段leaf或度量别名",
|
|
145
|
+
"replaceField": "新字段name",
|
|
146
|
+
"replaceFieldName": "新显示名"
|
|
147
|
+
}
|
|
148
|
+
]
|
|
149
149
|
}
|
|
150
150
|
```
|
|
151
151
|
|
|
@@ -159,6 +159,40 @@ e10-cli report dataset replace --file replace-body.json
|
|
|
159
159
|
|
|
160
160
|
替换后须用新 id 再 `fieldsAndOriginFields` / 必要时 remap 单元格 `dataSetId`/`fieldKey`。
|
|
161
161
|
|
|
162
|
+
### 4.1 ★ replaceDataset 的「原地换型」用法(复制 500 的正解 · 2026-09-15 实证)
|
|
163
|
+
|
|
164
|
+
**场景**:报表「复制」报 500「报表内部错误」→ 根因是数据集 `type` 为大写 `LOGIC`
|
|
165
|
+
(设计器/手动建表写小写 `logic`)。此时**用 `replaceDataset` 指向同一 `sourceId`** 即可原地换型:
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"reportId": "<rid>", "builtinId": "<旧 datasetId>",
|
|
170
|
+
"name": "<原显示名>", "sourceType": "logic",
|
|
171
|
+
"sourceId": "<原 sourceId>", "sourceGroup": "weaver-ebuilder-form-service",
|
|
172
|
+
"appid": "<appId>",
|
|
173
|
+
"fieldMap": [ { "builtinField": "field_x", "replaceField": "field_x", "replaceFieldName": "" } ]
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
- `fieldMap` = 旧字段名 → 同名字段(同源换型时即自映射),逐条来自旧数据集的 `fieldsKey`。
|
|
178
|
+
- **验证服务端会自动把单元格的 `dataSetId` / `fieldKey` 重映射到新数据集**(案例:33 格报表换型后
|
|
179
|
+
格数/类型/公式/父格/合并 完全一致)→ 这两项**不需要**手工 remap。
|
|
180
|
+
- 🔴 **但「零损失」是错的(2026-09-16 更正,注意点 BUILD-31)**:服务端重建绑定时还会**抹掉/降级**一批
|
|
181
|
+
**不在结构骨架里**的属性,`verify contract` / `dump cells` 全绿也查不出来:
|
|
182
|
+
| 键 | 后果 |
|
|
183
|
+
|---|---|
|
|
184
|
+
| `text`(**字段显示名**) | **被清空** → 设计器里字段格没有内容可显示 ⇒ **整行字段格看起来是空的**(用户报「字段值都不展示」) |
|
|
185
|
+
| `allNeedFields` | 被清空(该格的取数字段清单) |
|
|
186
|
+
| `tableName` | 从 `采招-招标项目(业务模块)` 降级成**裸雪花号** `865889931247566866` |
|
|
187
|
+
| `openType`(Const 格) | 被清空 |
|
|
188
|
+
⇒ 换数据集后**必须补跑** `e10-cli report fix field-binding --report-id <rid> --app-id <appId> --apply` 才算收工。
|
|
189
|
+
⚠ 验证心法:**换绑定的保真校验要逐属性 diff**(拿换之前的 `getReportDevInfo.fields` 全量快照对比),
|
|
190
|
+
只比「格数/cellType/公式/父格」会漏掉整类损伤 —— 本包在 BUILD-27(把复制 500 错归给 groupId)上已经犯过同一个错。
|
|
191
|
+
- 幂等封装:**`e10-cli report dataset heal --report-id <rid> --app-id <appId> [--purge] [--apply]`**
|
|
192
|
+
(默认 dry-run;`--purge` 顺带删除 `sourceId` 为空的脏数据集;落库后回读 + 提示跑 `copy-health`)。
|
|
193
|
+
**跑完后接 `fix field-binding`(上表四项)。**
|
|
194
|
+
- ⚠ 共享表应用里数据集 `appId` ≠ 报表 `appId` **属正常**(指向表单归属应用),不要当脏数据删。
|
|
195
|
+
|
|
162
196
|
---
|
|
163
197
|
|
|
164
198
|
## 五、移除(删除数据集)
|
|
@@ -197,10 +231,17 @@ e10-cli report dataset delete --report-id <rid> --dataset-id <did> [--force]
|
|
|
197
231
|
|
|
198
232
|
| 层 | 现象 | 定位接口 |
|
|
199
233
|
|---|---|---|
|
|
200
|
-
| **① 报表挂载了重复数据集** | `dataset/list` 返回 **2 条同 `sourceId
|
|
234
|
+
| **① 报表挂载了重复数据集** | `dataset/list` 返回 **2 条同 `sourceId`** 的数据集记录(`name` 可能相同、也可能一条带后缀一条不带) | `GET /api/bs/edc/dataset/list?hasField=true&reportId=` |
|
|
201
235
|
| **② 画布存在游离单元格** | 某单元格 `dataSetId` 指向第二个数据集,常在**另一张 sheet 或表格远端的孤立格** | 遍历 workbook 全部 sheet 的 `dataTable`,按 `cellType.dataSetId` 统计 |
|
|
236
|
+
| **③ 数据集 `name` 被脚本写进了类型后缀** | 左侧显示 **`采购入库(业务模块)(业务模块)`** 双后缀(看起来像「两条同名分组」) | 读 `dataset/list[].name`:带后缀的那条就是脏值 → `fix dataset-name`(注意点 **BUILD-36**)。**先看后修**:`e10-cli report dataset list --report-id <rid> --app-id <appId>` 现在会逐行**预演**「面板显示名」并给脏名标 ⚠ |
|
|
237
|
+
| **④ 数据集 `name` 被写成裸雪花号**(建表把 `sourceId` 当名字传) | 左侧显示 **`865889931247566866(业务模块)`**(一串数字 + 类型标签),而同行 `originalName` 是可读名 `采招-招标项目` | `dataset list` 标 ⚠「name 是裸雪花号」并打出「应为 `采招-招标项目(业务模块)`」→ `fix dataset-name` 按 `originalName` 还原(注意点 **BUILD-37**)。⛔ 不阻断「复制」 |
|
|
202
238
|
|
|
203
239
|
> **关键陷阱**:游离单元格**不一定在 Sheet1**。本例游标藏在 **Sheet2 的 B3**(`sheetIndex:1, x:2, y:1`),只扫 Sheet1 会漏诊。**必须遍历全部 sheet**。
|
|
240
|
+
>
|
|
241
|
+
> ⚠️ **先分诊再动手(2026-09-16 补充,注意点 BUILD-35)**:`dataset/list?hasField=true&reportId=` 返回**两条**并不等于重复挂载。
|
|
242
|
+
> **每张报表天然就有两条**:主业务数据集(`type=logic`/`form`)+ 系统字段数据集 `dataUpdateTime`(`type=systemField`、0 格引用、平台自动附带)。
|
|
243
|
+
> 判据只看一条:**两条记录的 `sourceId` 是否相同** —— 相同 = 真重复(按本节清);不同 = 正常共存(**勿动**)。
|
|
244
|
+
> `dataUpdateTime` / `数据更新时间` 是**禁止删除**豁免项,删了「数据更新时间」单元格类型就没了。
|
|
204
245
|
|
|
205
246
|
**左侧树显示名的权威来源**:`GET /api/bs/edc/dataset/listWithPageReport?hasField=true&reportId=` → 返回**源级**记录(`id` 是 **sourceId 而非 datasetId**),其 `name`/`tableText` 决定分组显示名。
|
|
206
247
|
- 正常:`name = '事项清单(uf_ydsxqd_1)'`(业务模块名 + 物理表名)
|
|
@@ -219,22 +260,22 @@ e10-cli report dataset delete --report-id <rid> --dataset-id <did> [--force]
|
|
|
219
260
|
```python
|
|
220
261
|
# 1) 先摘除游标:遍历 workbook 全 sheet,删除/改绑指向重复数据集的单元格
|
|
221
262
|
for sheet_name, sh in wb["sheets"].items():
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
263
|
+
dt = (sh.get("data") or {}).get("dataTable") or {}
|
|
264
|
+
for ri in list(dt):
|
|
265
|
+
for ci in list(dt[ri]):
|
|
266
|
+
ct = ((dt[ri][ci].get("style") or {}).get("cellType")) or {}
|
|
267
|
+
if ct.get("dataSetId") == DUP_DS:
|
|
268
|
+
del dt[ri][ci] # 或改绑 KEEP_DS
|
|
228
269
|
|
|
229
270
|
# 2) saveReportDevInfo 落库(提交 workbook,gzip+base64,带 designKey)
|
|
230
271
|
|
|
231
272
|
# 3) 再调用 delDataset 删除重复数据集
|
|
232
|
-
POST /api/bs/edc/report/delDataset
|
|
273
|
+
POST /api/bs/edc/report/delDataset form: reportId=<rid>&sourceIds=<dupDatasetId>
|
|
233
274
|
|
|
234
275
|
# 4) 校验
|
|
235
|
-
dataset/list
|
|
276
|
+
dataset/list → 只剩 1 条同源数据集
|
|
236
277
|
getReportDevInfo.fields → 无任何字段引用 DUP_DS(注意看 sheetIndex 分布)
|
|
237
|
-
列表/面板
|
|
278
|
+
列表/面板 → 顶层分组只剩 1 个
|
|
238
279
|
```
|
|
239
280
|
|
|
240
281
|
> **顺序原因**:被引用时 `delDataset` 会被服务端拒绝(引用检查)。必须先清画布再删数据集。
|
|
@@ -11,17 +11,17 @@
|
|
|
11
11
|
> | `fieldName` | 字段技术名 `field_<id>` | 同上 |
|
|
12
12
|
> | `fieldText` | 字段显示名 | 同上 |
|
|
13
13
|
>
|
|
14
|
-
>
|
|
14
|
+
> 验证证据(同一报表内对照组):
|
|
15
15
|
> - Agent 建的 10 个 Field:`tableName=None`(异常)
|
|
16
16
|
> - 用户在设计器手动绑的 2 个 Field:`tableName='党员发展(业务模块)'`(正确)
|
|
17
17
|
> - 平台原生报表 `772466395278696448`:`tableName='轻资产处理(表单)'`,9/10 非空
|
|
18
18
|
> - 平台原生报表 `799097275701215232`:16/16 非空
|
|
19
19
|
>
|
|
20
20
|
> **根因不是接口、不是服务端** —— 是建表脚本写入的 `cellType` 本身就缺字段。
|
|
21
|
-
>
|
|
21
|
+
>
|
|
22
22
|
> 重构时**未迁移**,导致知识随重构丢失。
|
|
23
23
|
>
|
|
24
|
-
> **⚠️ 2026-09-11
|
|
24
|
+
> **⚠️ 2026-09-11 二次实证校正(重要)**:修复该报表时,从设计器接口返回解出真实 workbook,
|
|
25
25
|
> 对照用户手绑字段发现 —— **`fieldId` / `fieldName` / `fieldText` / `dateTimeProp` 在服务端落库的
|
|
26
26
|
> cellType 里同样是缺失的**(用户手绑字段也没有),它们由设计器**运行时装配**,不属落库契约。
|
|
27
27
|
> **真正需要落库、且能对照验证的只有 `tableName` 一项。** 上表把三件套标为「必需」属过度设计,
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
| `nameIndex` | ✅ | 底层 FORM sourceId | **不是字段 id** |
|
|
70
70
|
| `text` | ✅ | 字段显示名 | |
|
|
71
71
|
| `dataSetId` | ✅ | 报表内部注册 id | `dataset/list` 的 `id` |
|
|
72
|
-
| **`tableName`** | ○ 建议写 | **`数据集名(业务模块)`** |
|
|
72
|
+
| **`tableName`** | ○ 建议写 | **`数据集名(业务模块)`** | 单元格级字段归属标记;**非**面板显示名来源(见开头三次校正)。⚠️ **只有单元格**要带后缀;数据集 `name` 必须裸名(§二 更正框) |
|
|
73
73
|
| `fieldId` | ○ 建议写 | 字段雪花 id | 落库本不含;设计器运行时装配,写入幂等无害 |
|
|
74
74
|
| `fieldName` | ○ 建议写 | `field_<雪花>` | 同上 |
|
|
75
75
|
| `fieldText` | ○ 建议写 | 字段显示名 | 同上 |
|
|
@@ -85,17 +85,42 @@
|
|
|
85
85
|
|----------|------------------------------|------|------|
|
|
86
86
|
| **A(默认)** | `LOGIC` + `weaver-ebuilder-form-service` | **`(业务模块)`** | 普通应用表单 |
|
|
87
87
|
| **B(共享表)** | `form` + `<appId>` | **`(表单)`** | `xxx-共享表` 类应用 |
|
|
88
|
-
| **C(数据加工 SQL 视图)** | `
|
|
88
|
+
| **C(数据加工 SQL 视图)** | `eteams`(**小写 type**) + `sql` | **`(数据加工)`** | 数据集来自「数据加工」SQL 视图 |
|
|
89
89
|
|
|
90
|
-
>
|
|
91
|
-
>
|
|
92
|
-
>
|
|
90
|
+
> **⚠️⚠️ 形态 C 更正(2026-10-09 实证 · 应用 `1323883777452843010` 全量 8 表比对)**:
|
|
91
|
+
> 此前本表把形态 C 写成「无后缀」是**错的** —— 验证「数据加工」数据源的单元格 `tableName`
|
|
92
|
+
> **带 `(数据加工)` 后缀**(= `数据集名(数据加工)`)。
|
|
93
|
+
>
|
|
94
|
+
> | 落库形态(`dataset/list`) | 单元格 `tableName` | 判定 |
|
|
95
|
+
> |---|---|---|
|
|
96
|
+
> | `type=eteams`(小写)+ `sourceGroup=sql` | **`学院表(数据加工)`** | ✅ 数据加工 |
|
|
97
|
+
> | `type=ETEAMS`(大写)+ `sourceGroup=-98` | `学院表(业务模块)` | ❌ 被当成业务模块 |
|
|
98
|
+
>
|
|
99
|
+
> 验证对照(同应用):`eteams`/`sql` 的 5 张表(`培训报表`/`汇总表`/`test`/`12`/新建表)
|
|
100
|
+
> 单元格全是 `X(数据加工)`;`ETEAMS`/`-98` 的 2 张表(`各学院专业人数统计` / `…-chl`)单元格全是 `X(业务模块)`。
|
|
101
|
+
> **口径分水岭就是 `type` 大小写 + `sourceGroup`**,与 `LOGIC`(BUILD-29) 同理 —— 脚本注册
|
|
102
|
+
> 「数据加工」SQL 视图时 `addDataset.sourceType` **必须传小写 `eteams`**、`sourceGroup='sql'`。
|
|
103
|
+
>
|
|
93
104
|
> **判断口径(三条一致即可定值)**:① 设计器里已有手绑单元格 → 用它的 `tableName`;
|
|
94
|
-
> ②
|
|
105
|
+
> ② 否则 `数据集名 + (数据加工)`;③ 都没有才按 `dataset/list[].name`。
|
|
95
106
|
|
|
96
107
|
> 与 `add-dataset-registration-guide.md` §一 的两种注册形态一一对应。
|
|
97
108
|
> **禁止**给共享表硬套 `(业务模块)` —— 后缀必须与注册形态一致。
|
|
98
109
|
|
|
110
|
+
> ⚠️⚠️ **本节只适用于「单元格 `tableName`」(2026-09-16 更正 · 注意点 BUILD-36)**:
|
|
111
|
+
> **数据集自己的 `name`(= `addDataset.sourceName`)绝不能带这个后缀。**
|
|
112
|
+
> 左侧「数据集」面板显示名 = `数据源名 + (添加类型标签)`,那个标签由**平台按数据源的「添加类型」自动拼接**:
|
|
113
|
+
> `业务模块 / 表单 / 数据加工 / 外部数据源 / 内置数据集 / 数据集合 / 系统字段 …`,**不是固定写死的**。
|
|
114
|
+
> 脚本若自行拼一遍 → 面板显示 **`采购入库(业务模块)(业务模块)`**(双后缀)。
|
|
115
|
+
>
|
|
116
|
+
> | 对象 | 后缀 | 谁负责 |
|
|
117
|
+
> |---|---|---|
|
|
118
|
+
> | 单元格 `tableName` | ✅ 要(`X(业务模块)`) | `build_from_spec.resolveTableName()` / `fix field-binding`(写文件时) |
|
|
119
|
+
> | 数据集 `name` / `sourceName` | ❌ 不要(裸名 `X`) | 构建层 / `fix dataset-name`(写 `edc_dataset_dev.name` 时) |
|
|
120
|
+
>
|
|
121
|
+
> 验证对照(报表 `1315265856934289408`,同 sourceId 两条):脚本建 `name="采购入库(业务模块)"` → 双后缀 ❌;
|
|
122
|
+
> 设计器「+」建 `name="采购入库"` → `采购入库(业务模块)` ✅。(`originalName` 两者都是 `采购入库`)
|
|
123
|
+
|
|
99
124
|
**取值优先级**(服务端常不回传,必须脚本兜底):
|
|
100
125
|
|
|
101
126
|
1. `fieldsKey[].tableName`(服务端有则用)
|
|
@@ -103,7 +128,7 @@
|
|
|
103
128
|
3. `datasetLabel + datasetSuffix(sourceType)` ← **兜底,保证恒非空**
|
|
104
129
|
|
|
105
130
|
`datasetLabel` 来自 `dataset/list` 的 `name`(即 `addDataset` 的 `sourceName`),
|
|
106
|
-
由
|
|
131
|
+
由 构建层 回传、`fieldsKeyOf()` 注入到每个字段。
|
|
107
132
|
|
|
108
133
|
---
|
|
109
134
|
|
|
@@ -115,7 +140,7 @@
|
|
|
115
140
|
| `fieldName` | `fieldsKey[].name` |
|
|
116
141
|
| `fieldText` | `fieldsKey[].text`(→ `showName` → 列标题) |
|
|
117
142
|
|
|
118
|
-
`fieldsKey[]`
|
|
143
|
+
`fieldsKey[]` 验证可用键(`fieldsAndOriginFields?isFront=true`):
|
|
119
144
|
|
|
120
145
|
```
|
|
121
146
|
name / text / originName / fieldType / formatType
|
|
@@ -123,7 +148,7 @@ dataSetId / nameIndex / tableId / tableText / datasetName
|
|
|
123
148
|
config{ fieldId, formId, sformId, formName, componentKey, ... }
|
|
124
149
|
```
|
|
125
150
|
|
|
126
|
-
### 三点五、两接口返回格式对照(**以 `fieldsAndOriginFields` 为准** · 2026-09-11
|
|
151
|
+
### 三点五、两接口返回格式对照(**以 `fieldsAndOriginFields` 为准** · 2026-09-11 验证)
|
|
127
152
|
|
|
128
153
|
同一表单 `sourceId=753880319550169088` 双接口 30/30 逐条比对:
|
|
129
154
|
|
|
@@ -140,7 +165,7 @@ config{ fieldId, formId, sformId, formName, componentKey, ... }
|
|
|
140
165
|
**统一归一化入口**:`spec_lib.normalizeFieldList(payload, { datasetId })`
|
|
141
166
|
|
|
142
167
|
```javascript
|
|
143
|
-
const { fields } = normalizeFieldList(res, { datasetId });
|
|
168
|
+
const { fields } = normalizeFieldList(res, { datasetId }); // 冒号:任一接口 → 字段元素数组
|
|
144
169
|
```
|
|
145
170
|
|
|
146
171
|
- 抹平「裸数组 / `{fieldsKey}` 对象 / `{fields}` 对象」三种信封 → 一律返回**字段元素数组**;
|
|
@@ -161,8 +186,8 @@ const { fields } = normalizeFieldList(res, { datasetId }); // 冒号:任一接
|
|
|
161
186
|
const fieldCells = fields.filter((f) => f.cellType === 'Field');
|
|
162
187
|
const missingTableName = fieldCells.filter((f) => !f.tableName);
|
|
163
188
|
if (missingTableName.length) {
|
|
164
|
-
|
|
165
|
-
|
|
189
|
+
console.error(`WARN ${missingTableName.length}/${fieldCells.length} 个 Field 单元格缺 tableName`);
|
|
190
|
+
process.exitCode = 2; // 非零退出,提示需修正
|
|
166
191
|
}
|
|
167
192
|
```
|
|
168
193
|
|
|
@@ -180,13 +205,13 @@ if (missingTableName.length) {
|
|
|
180
205
|
## 四点五、修复存量报表(tableName 缺失)— 最小侵入路径 ✅ 已验证
|
|
181
206
|
|
|
182
207
|
> **场景**:报表已落库,但 `tableName` 缺失(旧脚本产物)。
|
|
183
|
-
> **报表 `1313789294296735745`
|
|
208
|
+
> **报表 `1313789294296735745` 验证修复成功(HTTP 200 + 双向验证通过)。**
|
|
184
209
|
|
|
185
210
|
**关键接口认知(务必先读)**
|
|
186
211
|
|
|
187
212
|
| 接口 | 提交物 | 易错点 |
|
|
188
213
|
|------|--------|--------|
|
|
189
|
-
| `saveReportDevInfo` | **`workbook
|
|
214
|
+
| `saveReportDevInfo` | **`workbook`** | ❌ 用 `fields=<json>` 提交 → **400 Bad Request**。⚠️ 载荷形态**因环境而异**:多数环境 `gzip+base64`,**部分自建环境只认明文 JSON**(传 gzip+b64 → 整表 500「报表内部错误」)。脚本走 构建层 自适应(先 gzip+b64,非 200 回退明文)—— 见 `report-internal-error-guide.md` §三.0 / 注意点 **BUILD-39** |
|
|
190
215
|
| `getReportDevInfo` | 返回 `fields[]` | ⚠️ 只有 `cellType: "Field"/"Const"` **类型标记**,**不含字段绑定明细**;明细只在 workbook 里 |
|
|
191
216
|
|
|
192
217
|
**`saveReportDevInfo` 完整表单(7 字段,multipart)**
|
|
@@ -195,7 +220,7 @@ if (missingTableName.length) {
|
|
|
195
220
|
groupId / appId / reportId / name / nameLabelId / designKey / workbook
|
|
196
221
|
```
|
|
197
222
|
- `designKey` 是**乐观锁**,必须取线上当前值(`getReportDevInfo.data.designKey`),否则拒写
|
|
198
|
-
- `workbook
|
|
223
|
+
- `workbook`(默认口径)= `base64(gzip(json.dumps(workbook), mtime=0))`;**部分环境需明文 JSON**(见上)
|
|
199
224
|
|
|
200
225
|
**获取「当前真实 workbook」(唯一可靠来源)**
|
|
201
226
|
|
|
@@ -210,17 +235,17 @@ groupId / appId / reportId / name / nameLabelId / designKey / workbook
|
|
|
210
235
|
|
|
211
236
|
```python
|
|
212
237
|
wb = json.loads(解码后的workbook)
|
|
213
|
-
dt = wb["sheets"]["Sheet1"]["data"]["dataTable"]
|
|
238
|
+
dt = wb["sheets"]["Sheet1"]["data"]["dataTable"] # {row: {col: {"style": {...}, "tag": {...}}}}
|
|
214
239
|
for r in dt:
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
240
|
+
for c in dt[r]:
|
|
241
|
+
ct = (dt[r][c].get("style") or {}).get("cellType") or {}
|
|
242
|
+
if ct.get("cellType") != "Field": continue
|
|
243
|
+
if str(ct.get("dataSetId")) == DS_OLD and not ct.get("tableName"):
|
|
244
|
+
newct = {}
|
|
245
|
+
for k, v in ct.items(): # 保持键顺序:插在 dataSetId 之后
|
|
246
|
+
newct[k] = v
|
|
247
|
+
if k == "dataSetId": newct["tableName"] = "党员发展(业务模块)"
|
|
248
|
+
dt[r][c]["style"]["cellType"] = newct
|
|
224
249
|
# 重新编码并提交 saveReportDevInfo
|
|
225
250
|
```
|
|
226
251
|
|
|
@@ -231,7 +256,7 @@ for r in dt:
|
|
|
231
256
|
| `getReportDevInfo` 回读 | `fields[]` 中带 `tableName` 的数量 = Field 总数 |
|
|
232
257
|
| 设计器实时 workbook | dataTable 内 `Field` 单元格 `tableName` 缺失数 = 0 |
|
|
233
258
|
|
|
234
|
-
>
|
|
259
|
+
> 验证结果:12/12 带 tableName ✅;设计器实时 workbook 11/11 Field 全齐、0 缺失 ✅
|
|
235
260
|
|
|
236
261
|
---
|
|
237
262
|
|
|
@@ -240,26 +265,26 @@ for r in dt:
|
|
|
240
265
|
> **场景**:整张报表的 Field 单元格 `tableName` 全为空 → 设计器里单元格/属性面板不回显数据集名;
|
|
241
266
|
> 但**孤例**(某个手绑单元格)是对的。用户会说「参考 XX 单元格的规则才对,调整其他字段」。
|
|
242
267
|
>
|
|
243
|
-
> **报表 `1314970921403138199`
|
|
268
|
+
> **报表 `1314970921403138199` 验证成功(2026-09-14)**:
|
|
244
269
|
> 48 个 Field 中 47 个 `tableName=""`,唯 `AM5`(row4,col38)为 `考勤汇总报表(优化)` → 一键补齐。
|
|
245
270
|
|
|
246
|
-
### 为什么优先走这条路(而不是 §四点五 的 CDP
|
|
271
|
+
### 为什么优先走这条路(而不是 §四点五 的 CDP 接口返回)
|
|
247
272
|
|
|
248
273
|
`getReportDevInfo` 的 `workbookProps.sheets` **恒为 `{}`**,拿不到 `dataTable`;
|
|
249
274
|
但它的 **`fields[]` 是服务端对 workbook 的逐单元格回读**,字段足够重建:
|
|
250
275
|
`x/y`、`xCount/yCount`(合并跨度)、`leftX/leftY/topX/topY`(父子格)、`expandType/displayType`、
|
|
251
276
|
`countType`、`style`(整份 style JSON 串)、`name/text/nameIndex/dataSetId/fieldKey/tableName`、`width/height`。
|
|
252
|
-
**→
|
|
277
|
+
**→ 不需要浏览器、不需要按键接口返回**。§四点五 的 CDP 路径仅作兜底。
|
|
253
278
|
|
|
254
279
|
### 重建规则(照抄即可)
|
|
255
280
|
|
|
256
281
|
```
|
|
257
282
|
dataTable[x][y] = { style: { ...JSON.parse(fields[].style), cellType }, tag: { fixed:false, formatterType:['common'] } }
|
|
258
|
-
spans
|
|
259
|
-
columns[c] = fields[].width(该列任一单元格);
|
|
260
|
-
sheet.tag
|
|
261
|
-
|
|
262
|
-
workbook
|
|
283
|
+
spans = 每个 xCount>1 || yCount>1 的单元格 → { row:x, col:y, rowCount:xCount, colCount:yCount }
|
|
284
|
+
columns[c] = fields[].width(该列任一单元格); rows[r] = fields[].height
|
|
285
|
+
sheet.tag = sheetProps[0] 的 childMerge / showLocation / filterSheet / tableNameSuffix
|
|
286
|
+
+ JSON.parse(columnConfig) + JSON.parse(sheetConfig)
|
|
287
|
+
workbook = { version, __scrollbarShowMax, __excelSheet, workbookConfig:{}, sheets }
|
|
263
288
|
cellType 键序 = 设计器真实键序(见 §一,逐字照排)
|
|
264
289
|
```
|
|
265
290
|
|
|
@@ -276,8 +301,8 @@ cellType 键序 = 设计器真实键序(见 §一,逐字照排)
|
|
|
276
301
|
- `fields[].width/height` **可能合法为 0**(Excel 隐藏列,如「人员ID」)→ 不能用 `Number(w) || 40` 兜底,会把 0 吞成 40。
|
|
277
302
|
- 合并区覆盖但**无单元格**的列(日期块被合并掉的第 2/3 列)在 `fields[]` 里不存在 → 沿用左侧最近已知列宽,避免列宽塌成默认值。
|
|
278
303
|
|
|
279
|
-
> ⚠️ **与
|
|
280
|
-
> `gridline` / `__gridline`,注释称「存在即 500
|
|
304
|
+
> ⚠️ **与 `` 的一处分歧**:该脚本的 `stripWorkbookGridlineKeys()` 会删掉
|
|
305
|
+
> `gridline` / `__gridline`,注释称「存在即 500」。**在某自建站点环境(`<自建站点域名>:5001`)验证不成立**:
|
|
281
306
|
> 带 `__gridline: 0` 的 workbook 保存返回 200(报表 `1314970921403138199` 连续两次)。
|
|
282
307
|
> 该断言可能只对某站点成立 —— 保留删除动作更安全,但**不要据此判定其他 500 的成因**。
|
|
283
308
|
|
|
@@ -291,10 +316,10 @@ cellType 键序 = 设计器真实键序(见 §一,逐字照排)
|
|
|
291
316
|
|
|
292
317
|
```bash
|
|
293
318
|
# 默认 dry-run(打印计划 + 保真自检,不落库)
|
|
294
|
-
|
|
295
|
-
|
|
319
|
+
e10-cli report fix table-name --report-id <rid> [--app-id <aid>] \
|
|
320
|
+
[--table-name "<数据集名>"] [--restore-from <备份workbook.json>]
|
|
296
321
|
# 确认后落库
|
|
297
|
-
|
|
322
|
+
e10-cli report fix table-name --report-id <rid> --apply
|
|
298
323
|
```
|
|
299
324
|
- 自动定值:`--table-name` > `fieldsKey[].datasetName` > `dataset/list[].name`
|
|
300
325
|
- `--restore-from`:把备份 workbook 中「线上已不存在」的单元格补回(例如被误删的手绑单元格)
|
|
@@ -306,7 +331,7 @@ node e10-cli report fix table-name --report-id <rid> --apply
|
|
|
306
331
|
```
|
|
307
332
|
保存前 fields = A(含孤例),保存后 fields = B
|
|
308
333
|
diff(A,B) 期望:仅 `tableName` 变化(条数 = 缺失数)+ 可选 `(新增)`(补回的手绑单元格)
|
|
309
|
-
|
|
334
|
+
其余键(cellType/name/dataSetId/父子格/expandType/displayType/style…)必须 0 差异
|
|
310
335
|
```
|
|
311
336
|
|
|
312
337
|
再跑 `e10-cli report verify all <rid> <appId>`(`ok:true, errors:[]`)+ 渲染回读
|
|
@@ -316,18 +341,144 @@ diff(A,B) 期望:仅 `tableName` 变化(条数 = 缺失数)+ 可选 `(新
|
|
|
316
341
|
> 若线上存在「`fields[]` 也看不到」的内容(未知键),重建会丢。故保存前**先把重建出的
|
|
317
342
|
> 『原样 workbook』落一份备份**(本脚本 `--restore-from` 亦依赖它补回被误删的手绑单元格)。
|
|
318
343
|
|
|
319
|
-
|
|
320
344
|
---
|
|
321
345
|
|
|
322
346
|
- ❌ 只在 `fields[]` 回读层「补」tableName —— 必须写入 workbook 的 `cellType`,服务端才会落库
|
|
323
347
|
- ❌ **照抄 `fields[]` 的键集重建 cellType** —— `typeName` 等 6 个键服务端不回传,漏了必 500(见 §四点六 坑 1)
|
|
324
348
|
- ❌ **把服务端派生键回写 cellType**(`dateTimeProps`/`highlightDatas`/`allNeedFields`/`fill*`)—— 必 500(坑 2)
|
|
325
|
-
- ❌ 给共享表(form 契约)写 `(业务模块)`
|
|
349
|
+
- ❌ 给共享表(form 契约)写 `(业务模块)` 后缀;给「数据加工」SQL 视图(`eteams`/`sql`)漏写 `(数据加工)` 后缀
|
|
350
|
+
(此前误写「形态 C 无后缀」——2026-10-09 更正,验证带 `(数据加工)`)
|
|
326
351
|
- ❌ 用 `saveReportDevInfo` 的 `fields[]` 数组下发字段 —— 服务端**只认 workbook**
|
|
327
352
|
- ❌ 重构时把本契约从 references 删除(本事故成因)
|
|
328
353
|
|
|
329
354
|
---
|
|
330
355
|
|
|
356
|
+
## 五、两个「回显不对」症状的字段归属(2026-09-14 实证补录)
|
|
357
|
+
|
|
358
|
+
用户报「回显不对」时,**先分清是哪一种**,两者落库字段不同、修法相同(同一脚本一次修完):
|
|
359
|
+
|
|
360
|
+
| 症状 | 落库字段 | 判据 | 期望形态 |
|
|
361
|
+
|------|----------|------|----------|
|
|
362
|
+
| ①「数据集名称显示不对 / 不回显」 | `tableName` | Field 单元格 `tableName` 为空 | `数据集显示名(业务模块)` / `(表单)` / 裸名(形态C) |
|
|
363
|
+
| ②「字段回显不对,应是『数据集名.字段名』」 | **`fieldKey`** | 非 `dataSetId.nameIndex.name` 三段一致 | `1313903497535856649.865906673130749953.field_xxx` |
|
|
364
|
+
|
|
365
|
+
> **`fieldKey` 契约(本次补录)**:三段 = ①本报表内部 `dataSetId`(`dataset/list[].id`,**不是** sourceId)
|
|
366
|
+
> ②`nameIndex`(底层表单 sourceId)③`name`(`field_<雪花>`,须逐字等于 `fieldsKey[].name`)。
|
|
367
|
+
> **⚠️ 修复时绝不臆造段值**:若某段(如 `name`)在 `cellType` 里本身缺失,宁可留空也不拼接,
|
|
368
|
+
> 否则会造出「看起来有值但绑错字段」的假回显。脚本 `assemble()` 已按此实现(缺段则不重建)。
|
|
369
|
+
|
|
370
|
+
**一次双向修复**:`e10-cli report fix table-name` 的 `assemble()` 同时处理 ①`tableName` ②`fieldKey`;
|
|
371
|
+
dry-run 会分别打印「tableName 缺失 n/N」+「fieldKey 不合规 n/N」+ 将修复的单元格坐标,
|
|
372
|
+
落库后快照 diff 期望仅 `tableName` / `fieldKey` / `(新增)` 三类键变化。
|
|
373
|
+
|
|
374
|
+
### ⚠️⚠️ 重建 workbook 的三个致命坑(2026-09-14 血案 · 报表 1313903497535856640)
|
|
375
|
+
|
|
376
|
+
| # | 坑 | 症状 | 正确做法 |
|
|
377
|
+
|---|----|------|----------|
|
|
378
|
+
| 1 | **`typeName` 必须与 `cellType` 一一对应** | Formula 格被写成 `ConstCellType` → 服务端保存后**静默丢弃**该格 | `Field→FieldCellType`、`Formula→FormulaCellType`、`Const→ConstCellType` |
|
|
379
|
+
| 2 | **`rows[]` 必须覆盖真实工作表行数** | 只按 live `fields[]` 的 maxX 生成 → `rows.length=3`,第 9 行的格子落在声明行数外 → 被丢 | `rowsLen = max(maxX+1, sheetProps.rowCount, 200)`,`rowCount` 同步 |
|
|
380
|
+
| 3 | **同一报表可挂多个数据集** | 全局套一个 `tableName` → 第二数据集的格被写错名 | `tableName` **按每格自身 `dataSetId` 分别解析**(`assemble(f, tnMap)`) |
|
|
381
|
+
|
|
382
|
+
> **`fields[]` 是「不完整视图」**:验证同一报表在两次 GET 之间,
|
|
383
|
+
> `fields[]` 会漏报某些格(如属第二数据集的 `(14,2)`),也会**受上一次保存影响**而增删。
|
|
384
|
+
> **禁止**把 `fields[]` 当作 workbook 的等价物;重建前必须做「期望格集合 == 实际格集合」比对。
|
|
385
|
+
|
|
386
|
+
> **Formula 格无法经重建写入(2026-09-14 双血案后定论)**:
|
|
387
|
+
> 报表 `1313903497535856640`(J3)与 `1313903463073415168`(J3)两起事故,
|
|
388
|
+
> 均为「修 tableName 时重建 workbook → 保存后 Formula 格消失(`fields 23→22`)」。
|
|
389
|
+
> **共穷举 6 种组合全部失败**(服务端一律 code 200 但不落库):
|
|
390
|
+
>
|
|
391
|
+
> | # | 尝试 | 结果 |
|
|
392
|
+
> |---|------|------|
|
|
393
|
+
> | ① | `--restore-from <pre-loss workbook>` 补回 | ❌ 200 但不落库 |
|
|
394
|
+
> | ② | `(2,9).leftX/leftY` 改为紧邻 `(2,8)` | ❌ 同上 |
|
|
395
|
+
> | ③ | `left=(2,8) + expandType=Vertical`(随父链) | ❌ 同上 |
|
|
396
|
+
> | ④ | `left=(2,0) + expandType=Vertical` | ❌ 同上 |
|
|
397
|
+
> | ⑤ | 原样提交(仅补 tableName,其余字段零改动) | ❌ 同上 |
|
|
398
|
+
> | ⑥ | 从 pre-loss workbook 全量重放 | ❌ 同上 |
|
|
399
|
+
>
|
|
400
|
+
> **定论:服务端不接受由 `saveReportDevInfo` 写入的 Formula 格。** 重建式写入**必然丢 Formula 格**。
|
|
401
|
+
> **恢复此类格首选**:CDP 抓设计器真实 workbook(§四点五),或**让用户在设计器手工补一格(最稳)**。
|
|
402
|
+
> **⚠️ 不要反复盲试** —— 每次尝试都是一次真实落库,且失败不报错(静默 200),风险不可控。
|
|
403
|
+
|
|
404
|
+
> **⚠️ 执行纪律(血案后强制)**:对**含 Formula 格的报表**执行 `fix table-name --apply` 前,
|
|
405
|
+
> 必须先向用户明示「本操作会丢失公式格」,取得明确授权;
|
|
406
|
+
> 或改为只读 `verify contract` 出报告 + 由用户在设计器手工修 `tableName`。
|
|
407
|
+
> 判定方法:`verify contract` 输出里 `fields` 总数 > `Const` + `Field` 之和(差额即 Formula 格数)。
|
|
408
|
+
|
|
409
|
+
> **回落路径必须补形态后缀(2026-09-14 补)**:`tableName` 回落取 `dataset/list[].originalName` 时,
|
|
410
|
+
> 拿到的是**裸显示名**(如 `采招-招标项目`),**必须**经 `withFormSuffix()` 拼成 `采招-招标项目(业务模块)`。
|
|
411
|
+
> 否则与「参照单元格路径」「人工手绑」的值不一致 → 设计器仍不回显数据集名。
|
|
412
|
+
> 规则:`sourceType=LOGIC 且 sourceGroup 含 ebuilder/form-service → (业务模块)`;`FORM → (表单)`;
|
|
413
|
+
> `eteams`(小写 type)且 `sourceGroup=sql → (数据加工)`;其它无后缀。
|
|
414
|
+
> ⚠️ 仍是**单元格** `tableName` 的口径。且 `originalName` 本身就是**裸名**(这是对的)——
|
|
415
|
+
> 不要把后缀回写进数据集 `name`(BUILD-36)。回落取值优先级见本节上方。
|
|
416
|
+
|
|
417
|
+
### ⚠️⚠️ 重建 workbook 的第四个致命坑 —— `tag.formatterType`(2026-09-15 血案 · 报表 1315015331503456271)
|
|
418
|
+
|
|
419
|
+
**症状**:`tableName` / `fieldKey` / 字段绑定 / `showLocation` 全对,脚本自报「快照 diff = 0 处」,
|
|
420
|
+
但用户发现**列格式变了** —— 身份证列本该是「文本」格式(防科学计数)变回常规,金额列「数值」格式也没了。
|
|
421
|
+
|
|
422
|
+
**根因**:重建时 `put()` 把每格的 tag 写死:
|
|
423
|
+
|
|
424
|
+
```js
|
|
425
|
+
tag: { fixed: !!f.fixed, formatterType: ['common'] } // ← 每格格式被强制成 common
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
**关键认知 —— 格式存在 `tag` 上,不是 `cellType` 上**:
|
|
429
|
+
|
|
430
|
+
| 位置 | 语义 | 设计器保存值 |
|
|
431
|
+
|------|------|--------------|
|
|
432
|
+
| `cellType.formatterType` | 单元格类型层的占位 | **恒为 `[]`** |
|
|
433
|
+
| **`tag.formatterType`** | **真正的「单元格格式」** | `["common"]` / `["text"]` / `["value"]`… |
|
|
434
|
+
| `fields[].formatterType`(回读顶层) | 由 `tag.formatterType` 映射而来 | 同上 |
|
|
435
|
+
|
|
436
|
+
验证验证:把 `["text"]` 写进 `cellType.formatterType` → 服务端回读**仍是 `["common"]`**(无效写法);
|
|
437
|
+
只有写进 `tag.formatterType` 才生效。**故格式必须落在 `tag` 上。**
|
|
438
|
+
|
|
439
|
+
**修复写法**:
|
|
440
|
+
|
|
441
|
+
```js
|
|
442
|
+
tag: {
|
|
443
|
+
fixed: !!f.fixed,
|
|
444
|
+
formatterType: (Array.isArray(f.formatterType) && f.formatterType.length) ? f.formatterType : ['common'],
|
|
445
|
+
}
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
**为什么自检没抓到**:`CMP_KEYS` 是**白名单**,里面没有 `formatterType`;`diffSnap` 又只遍历它 →
|
|
449
|
+
改坏了照样报绿。**已在保真自检里新增 `tag.formatterType` 逐格比对。**
|
|
450
|
+
|
|
451
|
+
**★ 通用教训**:`CMP_KEYS` 白名单以外的一切键,重建都可能被静默改写而自检仍报绿。
|
|
452
|
+
**动生产报表前必须另做一次「全键独立比对」**:落库前存快照 → 落库后回读 →
|
|
453
|
+
逐格遍历 `Object.keys` 求差集(`updateTime` / `allNeedFields` / `fill*` / `dateTimeProps` 等派生键可白名单排除)。
|
|
454
|
+
本次正是靠这一步才抓到 `formatterType` 被抹。
|
|
455
|
+
|
|
456
|
+
**定点修正命令**(恢复即用它):
|
|
457
|
+
|
|
458
|
+
```bash
|
|
459
|
+
e10-cli report fix parent --report-id <id> --app-id <appId> \
|
|
460
|
+
--set-json '2,1:formatterType:["text"]' \
|
|
461
|
+
--set-json '2,6:formatterType:["value"]' --apply
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
> **配套:`fix parent` 的左父格定点修正**
|
|
465
|
+
> 多数据集「连续同源区域」的**后续字段**被错误指向异源格时:
|
|
466
|
+
> `e10-cli report fix parent --report-id <id> --set-parent "x,y=leftX,leftY" [--apply]`
|
|
467
|
+
> (`x,y` = 目标格,0 基;`x`=行 / `y`=列)。规则见
|
|
468
|
+
> `datasource-selection-and-parent-filter-guide.md` §2.1(强制)/ §2.3(反例)。
|
|
469
|
+
|
|
470
|
+
### 硬门禁(apply 前必须通过)
|
|
471
|
+
|
|
472
|
+
```
|
|
473
|
+
① 重建格数 == fields.length + extraCells.length (防丢格)
|
|
474
|
+
② 每个格的 typeName 与 cellType 匹配 (防服务端静默丢格)
|
|
475
|
+
③ rows.length >= 该 sheet 真实行数 (防越界丢格)
|
|
476
|
+
④ tnMap 覆盖全部用到的 dataSetId (防多源写错名)
|
|
477
|
+
⑤ 保存后快照 diff 仅 tableName/fieldKey/(新增) (防洗数据)
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
331
482
|
## 六、相关文档
|
|
332
483
|
|
|
333
484
|
| 文档 | 关系 |
|
|
@@ -336,4 +487,3 @@ diff(A,B) 期望:仅 `tableName` 变化(条数 = 缺失数)+ 可选 `(新
|
|
|
336
487
|
| `field-bind-exact-match-guide.md` | `name` 逐字匹配 fieldsKey |
|
|
337
488
|
| `spec-build-schema.md` | `build spec` 声明式用法 |
|
|
338
489
|
| `query-condition-api-guide.md` §2.1.2 | `browserType` 富对象(关联浏览分类元数据接口) |
|
|
339
|
-
| 旧包 `data_source_rule.md` §2.2/§2.5 | 本契约原始出处(已迁回本文件) |
|