This commit is contained in:
xiaojibeier
2026-07-06 03:36:46 +08:00
parent 300b15aa9f
commit f3726f0810
506 changed files with 221985 additions and 1 deletions
+107
View File
@@ -0,0 +1,107 @@
# 多维表格(MDT)改动纪要
面向产品/联调:本节为多维表与 **配置保存 → 多维表衍生回写** 的技术长文。**按日变更摘录**以仓库根目录 **`PROJECT_OVERVIEW.md` →「8. showtime_weihai」** 为准(与 `src/data/appChangelog.js` 对齐);本文件写实现细节与沿革,避免与总览表格完全重复。
---
## 1. 数据源 listed 与请求策略
| 项 | 说明 |
|----|------|
| 共用模块 | `src/views/material/mdt/dsListedApi.js`:白名单映射 `oa_bank``oa_config``oa_led`ledger)等,未命中时 **`oa_<x>``/api/<x>/listed`** 回退。 |
| 主视图 | `MultiDimensionalTable.vue``getListedApiForDsTable` 从上述模块导入,避免与各处的 listed 路由分叉。 |
| 去重 | `POST /api/excel/dynamic/data_source/listed` 成功后记 `dataSourcesListedLoaded`,并用 inflight Promise 合并并发调用。 |
| 并行 | 关联列 / 数据源列的 `runRefreshLinkDisplayMap` 内对 `fetchLinkDisplay``fetchDsDisplay` 使用 `Promise.all`。 |
| 预取 | `prefetchSideSheetCaches` 对侧表预取并行;`ensureLookupTable` 对同一 `target` 用 Map 合并进行中的请求。 |
---
## 2. LinkPicker(关联记录 / 数据源选择弹窗)
| 项 | 说明 |
|----|------|
| 解析模块 | `src/views/material/mdt/pickerFieldResolve.js``resolvePickerDynLabel` 等对动态表 **`cells`** 按列类型递归解析(查找引用、关联、数据源、单多选等),与主表网格侧语义对齐。 |
| 预热 | `warmupPickerResolveContext`:对列中出现的 `table:` / `ds:` 及直接查表目标做 **BFS**,并合并各层列定义中出现的 **数据源** 以拉 listed 构建 `dsMapsByTarget`。 |
| 动态表判定 | `linkTarget` 规范化(如 `Table:``table:`);仅凭「行内有 `cells` + 已有列定义」也会走格子解析路径,避免误用扁平行而退化为 `row.id`。 |
| 可读标题兜底 | 配置列解析结果为内部 id 时,尝试扫描同类列推断可读文案;占位行号 `#1``#2` 等兜底。 |
| 加载 UX | `element-loading-text="正在加载可选记录…"`。 |
| 刷新 | `pickerViewEpoch` + 列表 `:key`,预热完成后强制刷新列表与已选 chips。 |
| **写回常量不出现在候选列表(2026-05-10)** | 目标为 `oa_config` 时,合并 listed 后 **`filter` 掉** `desc` 命中 `isOaConfigDescFromMdtWriteback` 的行(与多维表 `formatOaConstWriteDesc` 文案一致:`来自多维表格「…」· 列「…」`),防止「表写回的常量」在弹窗再次被关联。实现:`oaConfigListedMerge.js``OA_CONFIG_DESC_FROM_MDT_SUFFIX_RE`)、`LinkPicker.vue`。 |
---
## 3. 查找引用与关联列的体验与样式
| 项 | 说明 |
|----|------|
| 查找引用占位 | 无解析结果时:**「—」+ 「无引用数据」**(小字);整格占位使用 `cell-lookup-placeholder-row`(深灰、`font-style: normal`,与默认浅灰斜体计算列区分)。 |
| 悬停说明 | `buildLookupFailureExplanation` / `getLookupCellTooltip` 用词改为白话(避免「对方表」「该行无录入」等偏开发措辞)。 |
| 关联列 | 标签可带 `title`;有 PK 但尚未解析出可读 tag 时的加载/失败提示文案。 |
---
## 4. 涉及文件一览(数据源于传播与多维表 UX 的早期迭代)
- `src/views/material/MultiDimensionalTable.vue`
- `src/views/material/mdt/LinkPicker.vue`
- `src/views/material/mdt/pickerFieldResolve.js`(新增)
- `src/views/material/mdt/dsListedApi.js`(新增)
---
## 5. 衍生常量传播 · 上游索引(减轻全表 view)
保存配置项或多维表格子写回常量后,`oaConstWritePropagation.js` 会按合并后的 `oa_config` listed 去多维表里找「漂移」并调用 `/api/config/set`。**冷启动仍会逐表 view**,之后便依赖客户端缓存尽量 **少 view**
| 项 | 说明 |
|----|------|
| 静态依赖 | `mdtConstUpstreamDeps.js``computeMdtUpstreamScanHint(columns, rows)`**`oaConstWrite` / `oa_const_write`** 绑定列推断:公式链上的 `ds:oa_config` 格内 PK → Pinia 同款 **sig**;数字列写回 / 链上出现 lookup·link → 该表 **scanAll(保守)**;无任何绑定 → **noDeps**。 |
| 持久化索引 | `mdtUpstreamIndexCache.js``localStorage` **`mdt_const_upstream_idx_v1`**`upsert` / `shouldScanTableForConfigPatch(excel_code, patchSig)`。传播循环里:**无索引或应扫时才 view**;每次 view 后对应该表 **`upsert` hint**。 |
| 表格侧回填 | `MultiDimensionalTable.vue`:换表 **`loadContent`**、**保存成功** 后对本表 **`upsert`**,保证用户在 MDT 里改绑定/公式后索引不陈旧。**从未在本机打开过的表**只能靠传播首轮 view 写入索引。 |
| 补丁 sig | `configConstantSig(classify_code, key)``patchSig` 空时仍可依赖索引 **跳过 noDeps**,避免无写回表的无效请求。 |
| 演进 | 未做服务端依赖索引;日后订单/长连接可替换或补强。 |
**涉及文件**`oaConstWritePropagation.js``mdtConstUpstreamDeps.js``mdtUpstreamIndexCache.js``MultiDimensionalTable.vue`
---
## 6. 配置项管理:`loadCfg` 时机与进行中提示(`ConfigManage.vue`
| 项 | 说明 |
|----|------|
| 二次拉列表 | 保存:`/api/config/set` 成功 → **第一次 `loadCfg`**`propagateMdtDependentConstants`(可能二次 `config/set`)→ **再一次 `loadCfg`**,避免首拉早于衍生落库。 |
| 橘色常驻提示 | 第一次 `loadCfg` 后到传播结束前:`ElMessage.warning``duration: 0`(口语文案,示意「顺带算多维表里绑定的」);**`finally``close`**,再出现绿色的「已按多维表公式同步 N 项…」。 |
---
## 7. 已知产品差异(尚未在本迭代落地)
### 常量 / 「常量信息」数据源(`oa_config`
- 接口 `POST /api/excel/dynamic/data_source/listed`**`table: oa_config`**,下拉展示一般为 **「常量信息」**。
- 「配置项管理」(`ConfigManage.vue` / 菜单「常量管理」)业务流程为:**一级分类 → 子分类 → `/api/config/listed`(带 `classify_code`)→ 每条配置的 `key` / `value` / `desc`**。
- 当前多维表「数据源选择」对 `oa_config` 仍走通用 **扁平 listed +「展示字段」**,与后台分类层级 **不完全同构**;若要「先分类再选常量」,需单独产品方案与前端交互(及部分存盘结构设计,例如 `classify_code + key`),**记入本文档备忘,后续专项做**。
---
## 8. 配置项管理卡片:多维表 desc 分行与阴影
- 多维表写回常量时 `desc` 形态为 **`来自多维表格「表名」· 列「列标题」`**(见 `MultiDimensionalTable.vue``formatOaConstWriteDesc`)。
- `ConfigManage.vue` 若匹配该形态,将 **表来源****`· 列「列名」`** 拆成两行,放在 **Key/Value 与底栏之间的 flex 伸展区**内:同行卡片 **栅格 stretch 等高**;多维表两行用 **`justify-content: space-between`** 把列名行贴在底栏分割线上方,**不依赖再堆一行撑高整卡**;单行 `desc` 仍在区顶,余下空白由 flex 填充。栅格显式 **`column-gap` / `row-gap`**,子卡 **勿设 `width:100%` 顶破轨道** 以免叠层。
---
## 9. 删除常量/删列确认与格内失效展示(2026-05-10)
| 项 | 说明 |
|----|------|
| 配置项删除 | `ConfigManage.vue`:删除前明示页签/物料/多维表可能仍引用、**不自动修改引用**;取消单独捕获。多维表写回的占位项仍禁止在此删除(既有逻辑)。 |
| 删除列 | `MultiDimensionalTable.vue``columnDeleteTouchesOaConst`——列为 **`ds:oa_config`**,或数字/公式列且存在 **`oaConstWrite`** 绑定——删列确认追加文案。 |
| 后台已删常量、格内 PK 仍在 | `resolveDsCell` 无记录时返回 **空串**;格内仍有 PK 时常 **仍渲染数据源外壳、主展示区为空**。 |
---
## 10. 维护说明
- **按日摘录**:根目录 **`PROJECT_OVERVIEW.md`** → **「8. showtime_weihai」**;应用内弹出层 **`src/data/appChangelog.js`** 与总览对齐。
- 修改本纪要、changelog 或总览后,生产环境需重新 **build** 方可生效。