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** 方可生效。
+45
View File
@@ -0,0 +1,45 @@
# 组织管理 · 关联物料分类
面向联调/产品:编辑组织弹窗右侧「关联物料分类」的实现说明。与 **应用内更新说明**`src/data/appChangelog.js`)及根目录 **`PROJECT_OVERVIEW.md` →「8. showtime_weihai」** 同日(2026-05-10)条目对齐。
---
## 1. 接口约定
| 用途 | 方法 | 路径 | Body 要点 |
|------|------|------|-----------|
| 当前组织已关联的物料分类 | POST | `/api/company/category_listed` | `{ company_code }` |
| 新增关联 | POST | `/api/company/link_category` | `{ company_code, category_code }` |
| 解除关联 | POST | `/api/company/unlink_category` | `{ company_code, category_code }` |
| 全量物料分类树(勾选用 + 路径索引) | POST | `/api/category/listed` | `{}` |
响应解析:关联列表兼容 `data` 为数组或 `list` / `rows` / `categories` 等字段;分类树与物料分类页一致,节点映射为 `id``category_code`)、`label``children`
---
## 2. 交互流程
1. **编辑组织**(已有 `company_code`):打开弹窗后请求 `category_listed`,并行请求 `category/listed` 构建 **code →「父 / 子 / …」** 路径表;列表每项上方展示灰色路径行,下方为名称与编码。
2. **新建组织**:无组织编码,右侧仅说明文案,不调列表与维护接口。
3. **管理关联**:点击「管理关联」加载树,预勾选当前已关联节点;用户勾选/取消勾选后点「确认」,与进入管理时的勾选快照 diff,分别调用 `link_category``unlink_category`
4. **加载文案**:列表与树加载态为「加载中」;提交关联过程遮罩为 **「关联中」**。
5. **说明文案**:标题行右侧橘色小字提示进入管理后勾选 / 取消勾选与确认的含义(无编辑权限时仍可看到说明,可无按钮)。
---
## 3. 布局与样式(OrgManage.vue
- 弹窗宽度约 **1200px**`el-dialog__body` **固定高度**`min(68vh, 720px)`),避免树数据加载后整窗被撑高。
- 左侧表单区、右侧关联区 **内部纵向滚动**;分类票据双列、关联列表与树区域 **禁止横向滚动条**(树标签省略号截断)。
- 右侧虚线容器内:列表模式与管理模式(搜索 + 树 + 取消/确认)切换,高度在固定窗体内分配。
---
## 4. 代码位置
| 项 | 路径 |
|----|------|
| 页面 | `src/views/base/OrgManage.vue` |
| 权限 | `usePagePower('company')``canUpdate` 控制「管理关联」按钮 |
同名能力(**部门 `dept_code`**、页签入口)见 **`docs/部门管理_关联物料分类.md`**。
+44
View File
@@ -0,0 +1,44 @@
# 部门管理 · 关联物料分类
面向联调/产品:**部门管理** 右侧顶栏页签 **「关联物料分类」** 的实现说明。交互与 **组织管理** 弹窗内「关联物料分类」一致(已关联列表、路径行、「管理关联」全树勾选、确认 diff 保存),差异在于主键为 **部门 `dept_code`**、入口为页签而非弹窗侧栏。与 **应用内更新说明**`src/data/appChangelog.js`**2026-05-10** 条目对齐(与 `docs/组织管理_关联物料分类.md` 同日)。
---
## 1. 接口约定
| 用途 | 方法 | 路径 | Body 要点 |
|------|------|------|-----------|
| 当前部门已关联的物料分类 | POST | `/api/dept/category_listed` | `{ dept_code }` |
| 新增关联 | POST | `/api/dept/link_category` | `{ dept_code, category_code }` |
| 解除关联 | POST | `/api/dept/unlink_category` | `{ dept_code, category_code }` |
| 全量物料分类树(勾选用 + 路径索引) | POST | `/api/category/listed` | `{}` |
响应解析:关联列表兼容 `data` 为数组,或对象内 `list` / `rows` / `categories` / `data` 等字段;分类树与组织侧一致,节点映射为 `id``category_code`)、`label``children`
---
## 2. 交互流程
1. **选择部门**:左侧部门树选中节点后,若当前页签为 **「关联物料分类」**,请求 `category_listed``dept_code`),并行请求 `category/listed` 构建 **code →「父 / 子 / …」** 路径表;列表项上方为灰色路径行,下方为名称与编码。
2. **未选部门**:右侧工作区提示先选部门,不调列表与维护接口。
3. **切换页签**:切回「角色列表」时退出物料分类管理态(取消编辑中的树);切至「关联物料分类」且已有选中部门时刷新已关联列表。
4. **切换部门**:在「关联物料分类」下更换部门时退出管理态并重新拉取该部门的关联列表。
5. **管理关联**:点击「管理关联」加载树,预勾选当前已关联节点;勾选/取消后点「确认」,与进入管理时的快照 diff,分别调用 `link_category``unlink_category`
6. **加载文案**:列表与树加载态为「加载中」;提交关联过程遮罩为 **「关联中」**。
7. **权限**`usePagePower('dept')``canUpdate` 控制「管理关联」按钮(无编辑权限时仍可看到橘色说明文案)。
---
## 3. 布局与样式(DeptManage.vue
- 右侧 **`dept-right-stack`**:顶栏 **「角色列表 | 关联物料分类」**,下方整块切换;**不** 把页签放在左侧部门栏。
- 「关联物料分类」:`dept-mc-workspace` 占满页签下方区域;有部门时为虚线框 **`dept-mc-bordered`** 包一层,内层 **`dept-mc-panel`** 与组织侧 `org-mc-*` 规则对齐(列表滚动区、管理态搜索 + 树 + 取消/确认;树标签省略、内部纵向滚动)。
---
## 4. 代码与文档对照
| 项 | 路径 |
|----|------|
| 页面 | `src/views/base/DeptManage.vue` |
| 类似实现(组织 + `company_code` | `src/views/base/OrgManage.vue``docs/组织管理_关联物料分类.md` |