From 31052d0b98c2394e4a84cd6a1a198baee1af0970 Mon Sep 17 00:00:00 2001 From: caoxiaozhu Date: Wed, 3 Jun 2026 15:14:44 +0800 Subject: [PATCH] feat(workbench): keep progress detail return context --- .../工作台费用进度详情返回与类型列/CONCEPT.md | 75 +++++++++++++++++++ .../工作台费用进度详情返回与类型列/TODO.md | 25 +++++++ .../personal-workbench-responsive.css | 8 +- .../styles/components/personal-workbench.css | 35 ++++++++- .../components/business/PersonalWorkbench.vue | 7 ++ web/src/composables/useAppShell.js | 35 ++++++++- web/src/utils/workbenchSummary.js | 1 + web/src/views/AppShellRouteView.vue | 12 ++- .../personal-workbench-assistant.test.mjs | 11 ++- web/tests/workbench-detail-return.test.mjs | 31 ++++++++ web/tests/workbench-summary.test.mjs | 1 + 11 files changed, 231 insertions(+), 10 deletions(-) create mode 100644 document/development/工作台费用进度详情返回与类型列/CONCEPT.md create mode 100644 document/development/工作台费用进度详情返回与类型列/TODO.md create mode 100644 web/tests/workbench-detail-return.test.mjs diff --git a/document/development/工作台费用进度详情返回与类型列/CONCEPT.md b/document/development/工作台费用进度详情返回与类型列/CONCEPT.md new file mode 100644 index 0000000..f028dc1 --- /dev/null +++ b/document/development/工作台费用进度详情返回与类型列/CONCEPT.md @@ -0,0 +1,75 @@ +# 工作台费用进度详情返回与类型列概念文档 + +## 功能一句话 + +让用户从首页费用进度进入单据详情后能返回首页,并在费用进度列表中直接看到每笔单据的费用类型。 + +## 背景与问题 + +当前首页费用进度点击单据后进入详情页,但详情页返回按钮默认回到单据中心,破坏了用户从首页查看进度的上下文。同时费用进度行只展示单号、标题、流程、状态和金额,用户需要点进详情才知道单据属于差旅、招待、办公等哪类费用。 + +## 目标与非目标 + +目标: + +- 从首页费用进度进入详情时,详情页返回按钮回到个人工作台。 +- 从单据中心进入详情时,原有返回单据中心逻辑不变。 +- 在首页费用进度行新增“费用类型”列。 +- 费用类型优先使用单据已有类型字段,缺失时按标题、场景和备注轻量归类。 + +非目标: + +- 不修改详情页主体内容。 +- 不新增后端接口。 +- 不改变单据中心列表、审批详情和其他来源的返回逻辑。 + +## 用户与场景 + +个人员工在首页查看最近费用进度,点击某笔单据进入详情核对处理情况。查看完后点击返回,应回到刚才的首页工作台继续看其他进度项,而不是跳到单据中心列表。 + +## 功能能力 + +- 首页打开详情时带入 `returnTo=workbench` 来源标记。 +- 详情页根据来源标记动态显示返回按钮文案并执行返回首页。 +- 费用进度数据新增 `expenseTypeLabel`。 +- 费用类型列在桌面端作为独立列展示,窄屏下按移动端布局折行展示。 + +## 方案设计 + +前端实现: + +- `PersonalWorkbench.vue` 在 `open-document` 事件 payload 中补 `source: 'workbench'` 和 `returnTo: 'workbench'`。 +- `AppShellRouteView.vue` 接收工作台来源并传给 `openRequestDetail`。 +- `useAppShell.js` 在打开详情时写入查询参数,在关闭详情时根据查询参数返回工作台或单据中心。 +- `workbenchSummary.js` 在 `progressItems` 中补费用类型字段。 +- `personal-workbench.css` 与响应式样式新增费用类型列。 + +## 算法与公式 + +当前功能不涉及复杂数学公式。 + +费用类型归类优先级: + +1. 单据显式字段:`expenseCategory`、`expense_type`、`category` 等。 +2. 文本规则:从场景、标题、备注和描述中匹配差旅、招待、办公、培训、市场等关键词。 +3. 兜底为“其他费用”。 + +## 测试方案 + +- 源码测试确认首页费用进度打开详情时带 `returnTo=workbench`。 +- 源码测试确认详情返回文案和关闭逻辑支持工作台来源。 +- 单元测试确认 `progressItems` 输出费用类型字段。 +- 源码测试确认费用进度模板和样式包含费用类型列。 +- 运行前端定向测试与构建。 + +## 指标与验收 + +- 从首页费用进度进入详情后,返回按钮回到个人工作台。 +- 从单据中心进入详情后,返回按钮仍回到单据中心。 +- 首页费用进度行可直接看到费用类型。 +- 相关定向测试与前端构建通过。 + +## 风险与开放问题 + +- 当前费用类型归类仍是前端轻量归类。后续若后端已有稳定 ontology 类型字段,应优先接入 canonical 字段。 +- 路由查询参数只用于详情返回来源,不应影响单据筛选和详情数据加载。 diff --git a/document/development/工作台费用进度详情返回与类型列/TODO.md b/document/development/工作台费用进度详情返回与类型列/TODO.md new file mode 100644 index 0000000..b31ddde --- /dev/null +++ b/document/development/工作台费用进度详情返回与类型列/TODO.md @@ -0,0 +1,25 @@ +# 工作台费用进度详情返回与类型列 TODO + +## 调研与契约 + +- [x] 核对首页费用进度点击链路、详情页返回逻辑和当前进度行样式。[CONCEPT: 方案设计] 证据:已确认 `PersonalWorkbench.vue` 发出 `open-document`,`AppShellRouteView.vue` 转入详情,`useAppShell.js` 默认返回单据中心。 +- [x] 明确来源标记与费用类型字段的前端契约。[CONCEPT: 功能能力] 证据:采用 `returnTo: 'workbench'` 与 `expenseTypeLabel`。 + +## 前端实现 + +- [x] 首页费用进度打开详情时带入工作台返回来源。[CONCEPT: 方案设计] 证据:`PersonalWorkbench.vue` 的 `open-document` payload 已包含 `source` 与 `returnTo`。 +- [x] 详情页关闭逻辑按来源返回工作台或单据中心。[CONCEPT: 功能能力] 证据:`useAppShell.js` 根据 `route.query.returnTo` 选择 `app-workbench` 或 `app-documents`。 +- [x] 工作台进度汇总新增费用类型字段。[CONCEPT: 功能能力] 证据:`workbenchSummary.js` 的 `progressItems` 输出 `expenseTypeLabel`。 +- [x] 首页费用进度行新增费用类型列及响应式样式。[CONCEPT: 指标与验收] 证据:`PersonalWorkbench.vue` 新增 `progress-type`,样式和响应式布局已更新。 + +## 测试与验证 + +- [x] 补充详情返回来源源码测试。[CONCEPT: 测试方案] 证据:`node web/tests/workbench-detail-return.test.mjs` 通过。 +- [x] 补充费用进度类型列源码测试。[CONCEPT: 测试方案] 证据:`node web/tests/personal-workbench-assistant.test.mjs` 通过。 +- [x] 补充工作台汇总单元测试,覆盖费用类型字段。[CONCEPT: 测试方案] 证据:`node web/tests/workbench-summary.test.mjs` 通过。 +- [x] 运行定向测试和前端构建。[CONCEPT: 指标与验收] 证据:以上定向测试和 `npm.cmd --prefix web run build` 均通过。 + +## 交付 + +- [x] 复查暂存范围,避免纳入无关工作区改动。[CONCEPT: 风险与开放问题] 证据:`git diff --cached --name-only` 仅包含本次工作台进度、返回来源、测试和开发文档。 +- [ ] 提交并 push 本次功能分支。[CONCEPT: 指标与验收] diff --git a/web/src/assets/styles/components/personal-workbench-responsive.css b/web/src/assets/styles/components/personal-workbench-responsive.css index 9231a54..af46d9a 100644 --- a/web/src/assets/styles/components/personal-workbench-responsive.css +++ b/web/src/assets/styles/components/personal-workbench-responsive.css @@ -96,7 +96,7 @@ } .progress-row { - grid-template-columns: minmax(72px, 0.42fr) minmax(126px, 0.86fr) minmax(270px, 1.32fr) minmax(86px, auto); + grid-template-columns: minmax(72px, 0.4fr) minmax(122px, 0.72fr) minmax(78px, 0.42fr) minmax(238px, 1.18fr) minmax(86px, auto); gap: 12px; } } @@ -328,6 +328,7 @@ grid-template-columns: minmax(70px, auto) 1fr minmax(74px, auto); grid-template-areas: "time identity result" + "type type type" "steps steps steps"; gap: 8px; padding: 10px 0; @@ -356,6 +357,11 @@ font-size: 11px; } + .progress-type { + grid-area: type; + width: 100%; + } + .progress-result { grid-area: result; width: 100%; diff --git a/web/src/assets/styles/components/personal-workbench.css b/web/src/assets/styles/components/personal-workbench.css index fa4ae32..afa5eb8 100644 --- a/web/src/assets/styles/components/personal-workbench.css +++ b/web/src/assets/styles/components/personal-workbench.css @@ -525,6 +525,38 @@ white-space: nowrap; } +.progress-type { + min-width: 0; + display: grid; + justify-items: start; + gap: 3px; +} + +.progress-type small { + color: var(--workbench-muted); + font-size: 10px; + font-weight: 750; + line-height: 1.2; +} + +.progress-type strong { + max-width: 100%; + overflow: hidden; + display: inline-flex; + align-items: center; + min-height: 22px; + padding: 0 8px; + border: 1px solid rgba(var(--theme-primary-rgb, 58, 124, 165), 0.18); + border-radius: 4px; + background: rgba(var(--theme-primary-rgb, 58, 124, 165), 0.08); + color: var(--workbench-primary-active); + font-size: 11.5px; + font-weight: 850; + line-height: 1.2; + text-overflow: ellipsis; + white-space: nowrap; +} + .progress-status { display: inline-flex; align-items: center; @@ -555,7 +587,7 @@ .progress-row { position: relative; display: grid; - grid-template-columns: minmax(78px, 0.44fr) minmax(138px, 0.86fr) minmax(300px, 1.46fr) minmax(92px, auto); + grid-template-columns: minmax(78px, 0.42fr) minmax(132px, 0.74fr) minmax(84px, 0.42fr) minmax(260px, 1.28fr) minmax(92px, auto); align-items: center; gap: 12px; width: 100%; @@ -605,6 +637,7 @@ .progress-time, .progress-identity, +.progress-type, .progress-result { min-width: 0; display: grid; diff --git a/web/src/components/business/PersonalWorkbench.vue b/web/src/components/business/PersonalWorkbench.vue index ac1c12e..6b360a1 100644 --- a/web/src/components/business/PersonalWorkbench.vue +++ b/web/src/components/business/PersonalWorkbench.vue @@ -215,6 +215,11 @@ {{ item.title }} + + 费用类型 + {{ item.expenseTypeLabel || '其他费用' }} + +