Files
shanxia2.0/docs/superpowers/specs/2026-08-16-quote-list-column-stats-design.md
T
2026-08-17 09:22:31 +08:00

5.9 KiB
Raw Blame History

报价单列表 · 可配置列统计行

日期: 2026-08-16
状态: 已实现(V1.5:6ce755455 / 072790989 / 42ad89645)
范围: web-admin 报价单管理主列表(/#/crm/quote)
非目标: 后端聚合、跨页统计、ListTable 通用能力、展开行产品子表、其它业务列表


1. 背景与目标

客户希望在【报价单管理】列表底部增加一行统计区:默认无数据;用户按列选择统计方式后,对当前页数据即时计算并展示。统计方式支持求和、平均、最大值、最小值。

后续其它列表将逐页单独改造(不先做全站通用组件),本设计仅覆盖报价单页,逻辑可放在报价单目录内小文件,便于以后复制或再抽离。

2. 已确认决策

项 决策
数据范围 仅当前页 quoteList,前端计算
交互 点击合计行对应单元格 → 下拉选择统计方式 → 同格显示结果
列范围 所有业务列均可配置(统一交互)
无法计算 显示 -,不报错
持久化 localStorage,仅当前浏览器
展示格式 前缀 + 数值,如 求和 12,345.00、平均 -
推广策略 一页一改;本次只改报价单

3. 界面与交互

3.1 位置

主表 ListTable(table-key="crm-quote")与分页条之间,增加自定义合计行(不使用 Element Plus show-summary,因其难以承载可点选下拉)。

┌─────────────────────────────────────┐
│  筛选 / 工具栏                        │
├─────────────────────────────────────┤
│  ListTable 主表(当前页)              │
├─────────────────────────────────────┤
│  自定义列统计行(可点选)               │
├─────────────────────────────────────┤
│  分页                                 │
└─────────────────────────────────────┘

3.2 单元格行为

  • 展开列、勾选列:固定空白,不可配置。
  • 其余业务列(含列设置显隐控制的列):与主表可见列同步;隐藏列不展示对应统计格。
  • 未选择 / 选「无」:单元格为空(可点击以打开下拉)。
  • 已选择:显示 {方式标签} {结果},例如 求和 12,345.00、最大值 张三、平均 -。
  • 下拉选项:无、求和、平均、最大值、最小值(文案固定为上述中文)。

3.3 视觉

对齐 Fresh Mint 合计行约定(见 docs/web-admin-ui-spec-fresh-mint.md):浅绿背景(--primary-bg / 等价 token)、主色顶边、字重加粗;不引入新的高饱和色。

横向滚动时,合计行应与主表列对齐(实现上采用与主表相同的列定义顺序与宽度策略,避免错位)。

4. 计算规则

对当前页每一行的该列取值进行聚合;空值、无法参与的值按下列规则跳过或导致 -。

方式 规则
无 不展示结果
求和 仅对可解析为有限数字的值求和;若本列没有任何有效数字 → -
平均 对有效数字求算术平均(分母为有效数字个数);无有效数字 → -
最大值 若存在有效数字,取数值最大;否则对非空字符串做字典序最大;皆无 → -
最小值 对称于最大值

说明:

  • 「可解析为有限数字」:去掉常见金额前缀/千分位后 Number 为有限数(含 0)。
  • 折扣率等带 % 的展示值:从原始行字段取数(如 discountRate),不要从已格式化 DOM 文案解析。
  • finalAmount 等与列表展示一致:使用与列表相同的取值函数(如 getQuoteFinalAmount),再参与聚合。
  • 状态、客户名等非数值列:求和/平均通常为 -;最大/最小可对字符串生效。

金额类结果的数字部分格式与列表金额展示习惯一致(千分位等);前缀与数字之间一个空格。非金额数值(如查看次数)按普通数字格式化即可。

5. 本机持久化

  • Storage key: crm-quote-column-stats
  • Value: JSON 对象,{ [columnProp: string]: 'sum' | 'avg' | 'max' | 'min' }
  • 选「无」或清空时删除该 prop 的键。
  • 进入页面时读取;切换统计方式时写入。
  • 换页 / 刷新后:恢复各列已选方式,并对新的当前页数据重新计算。

不与账号、租户、后端同步。

6. 实现边界(代码落点)

位置 职责
web-admin/src/views/crm/quote/quoteListColumnStats.ts(新建) 类型、聚合计算、展示文案、localStorage 读写
web-admin/src/views/crm/quote/QuoteListPage.vue(修改) 渲染合计行、绑定列显隐与当前页数据、点选下拉

不修改:

  • ListTable 组件
  • 后端 API / SQL
  • 展开行内产品子表
  • 报销/地磅等现有只读 show-summary 页

7. 验收要点

  1. 进入报价单列表:合计行存在,默认各业务格为空。
  2. 对金额列选「求和」:显示 求和 …,数值等于当前页该列之和。
  3. 对客户名称选「求和」:显示 求和 -;选「最大值」:显示字典序最大的非空客户名(有数据时)。
  4. 切换分页:已选方式保留,数值按新页重算。
  5. 刷新浏览器:方式从 localStorage 恢复。
  6. 列设置隐藏某列:合计行对应格消失;再显示后若曾配置过方式则恢复展示。
  7. 展开列 / 勾选列无下拉、无统计文案。

8. 后续(本设计之外)

其它列表需要同类能力时,复制本页模式单独接入;若多页稳定后再评估是否抽公共组件。不在本变更范围。