gongxiangp2/docs/数据统计-趋势可视化升级设计提案.md
chenpei 6c6c282203 feat: 全站视觉统一白皮书语言 + 个人档案改造 + 顶栏平台化
视觉统一(Zen Minimal × Future Organic 白皮书语言,全站浅色单主题):
- 登录页:品牌→由壹点·品牌中心,白纸底+发丝线+柔光光晕,黑按钮
- 作品过稿:深灰头→白皮书,返回链接→返回创意资产库
- 绩效考核:桌面+移动双头部换白皮书,标题改绩效考核,返回改链接
- 组织架构:BoardShell+页面 76 处调色板全量替换(#eef1f4→#fafafa 等)
- admin 后台:MaterialsHeader(面包屑治理与设置),Tab 栏墨色高亮
- 深色主题废弃:globals.css 移除媒体查询,tailwind darkMode:'class' 不挂 .dark
- 设计文档同步更新:AGENTS.md UI 基线/DESIGN.md/PRODUCT.md/README.md/design-qa.md

个人档案(原个人中心):
- API 合并权威人员档案(getEmployeeByUserId → 花名/工号/部门/职位/M-P等级/主管/状态)
- 页面白皮书化:权威档案卡(只读 HR 字段)+ 账号区(头像上传)+ 素材/收藏

顶栏平台化:
- MaterialsHeader 双模式:首页(五板块导航+全套工具+菜单)/板块(面包屑)
- 菜单重排:我的档案/绩效考核/作品过稿看板‖更新记录/提交反馈‖治理与设置‖退出
- 菜单头身份行:花名+职位·部门(权威档案)
- 首页排序:01 创意资产库(全员)→ 02 组织管理(管理员)→ 03-05 规划中
- 素材库改名创意资产库,全站同步(索引/导航/卡片/按钮/页脚)
- 排行榜换白皮书(白底发丝线+琥珀前三名)

构建修复:
- tsconfig 排除 output/(本地审计临时文件不再卡类型检查)
- 存储边界门禁豁免 output/(与 .dockerignore 对齐)
2026-08-15 14:16:20 +08:00

11 KiB
Raw Blame History

视觉基线更新(2026-08-15):本提案落地时,图表与配色须遵循 DESIGN.md 的白皮书语言(全站浅色单主题),不得引入深色样式。

数据统计页 · 趋势可视化升级 设计提案

创建时间:2026-06-27 范围:仅 components/admin/DataStatisticsTab.tsx 的趋势展示区 + 必要的后端口径微调 原则:只做加法和体验升级,不删任何现有功能;不改数据库、不动业务逻辑


1. 现状诊断(已通过代码摸底确认)

1.1 趋势区当前形态

┌─ 每日趋势(近31天)─────┐  ┌─ 月度趋势 ─────────────┐
│ 纯 <table> 表格          │  │ 纯 <table> 表格          │
│ 日期 | 上传数            │  │ 月份 | 上传数            │
│ 2026-06-01 | 12          │  │ 2026-01 | 320           │
│ 2026-06-02 | 8           │  │ 2026-02 | 410           │
│ ...(最多31行,可滚动) │  │ ...(可滚动)           │
└──────────────────────────┘  └──────────────────────────┘

问题:

  1. 信息密度低:纯表格,看不出趋势走向(涨/跌/峰值/低谷),需要肉眼逐行比对数字
  2. 缺对比基准:只看到绝对值,不知道"这个数是高还是低"——没有环比/同比/均值线
  3. P1-2 bug:每日趋势标题写死"近31天",但数据实际是后端按筛选时间范围返回的日期桶,选"全部"时表格可能是几年前的31天,标题与数据口径不符
  4. 交互弱:不能hover看明细、不能缩放、点击日期不能联动其它图表

1.2 数据基础(已确认)

后端 lib/admin-material-stats.ts 返回的趋势数据:

dailyUploads:  { bucket: '2026-06-01', count: number }[]  // 按筛选范围内的天
monthlyUploads: { bucket: '2026-06', count: number }[]    // 按筛选范围内的月

数据已经是干净的时序数组,无需后端改动即可做折线图。唯一的口径问题是 dailyUploads 只返回"有数据的天"(稀疏),绘图时需要补零。

1.3 技术约束

  • 项目无图表库(recharts/d3/echarts 都没装),现有柱状图是手写 div + height%
  • 引入新库 = 增加 bundle 体积 + 构建依赖。需权衡"自己画 SVG"vs"引库"

2. 设计目标

  1. 一眼看出趋势:用折线/面积图替代表格,涨跌、峰值、低谷立刻可见
  2. 提供对比基准:加环比(vs 上一周期)、移动平均线,让数字有参照系
  3. 修复 P1-2:每日趋势标题与数据口径一致
  4. 保持轻量:不引入重量级图表库,自己用 SVG 画(与现有柱状图风格一致)
  5. 可降级:表格作为辅助视图保留(切换"图表/表格"),照顾想看精确数字的场景

3. 提案:三档方案(成本递增,任选一档)

方案 A:最小改动(推荐先做)

成本:约 1 个前端组件 + 0 后端改动

把"每日趋势"和"月度趋势"两个表格,各替换为自绘 SVG 折线/面积图,并保留一个"切换表格视图"的按钮。

每日趋势                                  [📈 图表] [📊 表格]  ← 切换
┌──────────────────────────────────────────────────────────────┐
│      ╱╲      ╱╲                                             │
│   ╱╳╯  ╲    ╱  ╲     ╱╲    ← 面积折线(sky 渐变填充)       │
│  ╱      ╲__╱    ╲___╱  ╲___                                 │
│ ─────────── 均值线(虚线)─────────────────                  │
│ 06-01        06-10        06-20        06-30  ← x轴         │
│ 峰值 06-08 (42条)  ·  均值 18.3条/天  ·  合计 549条          │ ← 统计摘要
└──────────────────────────────────────────────────────────────┘
hover 任意点 → tooltip 显示 "2026-06-08:42 条"

新增信息(表格完全没有的):

  • 📍 峰值日期标注(哪天最高)
  • 📍 均值参考线(虚线,一眼判断高低)
  • 📍 统计摘要条(峰值/均值/合计/环比%)
  • 📍 hover tooltip(精确值)

修复 P1-2:标题动态显示真实范围,如"每日趋势(2026-06-01 ~ 2026-06-27,共27天)"。

方案 B:中等改动(A + 同比对比)

成本:A + 前端补零逻辑 + 可能的后端口径微调

在方案 A 基础上,给月度趋势加同比折线(今年 vs 去年同期):

月度趋势(含同比)
┌────────────────────────────────────────────────┐
│   ─── 今年(实线)                              │
│   ┄┄┄ 去年同期(虚线)   ← 需后端返回去年同期数据│
│   1月  2月  3月  4月  5月  6月                  │
│   环比 +12.3%  同比 +5.1%                       │
└────────────────────────────────────────────────┘

后端改动(可选):getMaterialUploadStats 增加 previousMonthlyUploads(取筛选范围向前平移一年的同长度区间)。不改表结构,只多一次聚合查询。

方案 C:大改动(B + 交互联动)

成本:B + 图表点击联动 + 时间粒度切换

  • 点击折线上某月 → 自动把上方"部门/素材类型分布"切换到该月范围
  • 加"日/周/月"粒度切换器(当前只有日和月两张表)
  • 区域选择缩放(拖选一段时间放大看)

4. 推荐落地路径

强烈建议先做方案 A,理由:

维度 方案 A 方案 B 方案 C
视觉提升 ★★★★ 大 ★★★★★ 很大 ★★★★★ 很大
信息增量 中(均值/峰值/摘要) 高(同比) 很高(联动)
后端改动 0 小(多一次聚合) 中
新代码量 ~250 行(1个SVG组件) +100 行 +300 行
bundle 体积 0(自己画SVG) 0 0
回归风险 低(纯展示层) 中(碰后端) 高(联动状态多)
用户感知 立竿见影 需有去年数据才显价值 依赖使用习惯

方案 A 的性价比最高:零后端风险、零依赖、视觉提升立竿见影。做完 A 看实际效果,再决定要不要追加 B/C。


5. 方案 A 详细技术设计

5.1 新增组件:TrendLineChart

位置:components/admin/TrendLineChart.tsx(独立出来,便于复用和测试)

Props:

interface TrendPoint { bucket: string; count: number }
interface TrendLineChartProps {
  data: TrendPoint[]              // 后端返回的 dailyUploads / monthlyUploads
  granularity: 'day' | 'month'    // 决定 x 轴标签格式和补零策略
  accent: 'sky' | 'teal'          // 与现有柱状图配色呼应
  startDate?: string              // 用于动态标题和补零范围
  endDate?: string
}

5.2 SVG 折线图核心算法

1. 数据补零:把 data 按 [startDate, endDate] 补齐成连续日期序列
   (后端只返回有数据的天,绘图需要连续 x 轴)
   - day: 按天补,跨度大时自动降采样到"每周一个点"
   - month: 按月补

2. 坐标映射:
   - x = (index / (n-1)) * width
   - y = height - (count / maxCount) * height

3. 路径生成:
   - 折线: M x0,y0 L x1,y1 ...
   - 面积: 折线 + 回到底边的闭合路径,fill 用渐变(opacity 0.15→0)

4. 均值参考线:
   - avg = sum(count) / n
   - y = height - (avg / maxCount) * height
   - 虚线 stroke-dasharray="4 4"

5. 峰值标注:
   - 找 max count 的点,上方画圆点 + 文字标签

6. hover tooltip:
   - 监听 mousemove,找最近的数据点,浮层显示 "日期:N条"

5.3 统计摘要条(图表上方)

峰值 06-08(42条)  ·  均值 18.3条/天  ·  合计 549条  ·  环比 +12.3% ▲
  • 峰值/均值/合计:前端从 data 算
  • 环比:对比"后半段 vs 前半段"的均值变化(无需后端,纯前端切分)

5.4 视图切换

图表右上角 [📈 图表] [📊 表格] 切换按钮(用现有 rounded-apple 风格)。

  • 默认图表视图
  • 切到表格视图 = 当前形态(保留,零删减,满足"都不删")

5.5 标题修复(P1-2)

// 修改前(写死):
<h3>每日趋势(近31天)</h3>

// 修改后(动态):
const dayCount = dailyUploads.length
const rangeText = startDate && endDate 
  ? `${startDate} ~ ${endDate},共${dayCount}天` 
  : `全部时间,共${dayCount}天`
<h3>每日趋势(${rangeText})</h3>

6. 配色与视觉规范(对齐已完成的 UI 重做)

延续上一轮 UI 重做的 Apple 基线:

  • 折线/面积主色:sky-500(每日)/ teal-500(月度),与两个柱状图呼应
  • 面积填充:from-sky-500/20 to-transparent 渐变
  • 均值线:gray-400 虚线
  • 峰值点:sky-600 实心圆 + 白色描边
  • tooltip:rounded-apple 白底 + shadow-apple-lg
  • 字体:tabular-nums(数字等宽对齐)

7. 改动清单(方案 A)

文件 改动 风险
components/admin/TrendLineChart.tsx 新增(~250行 SVG 折线组件) 低,新文件
components/admin/DataStatisticsTab.tsx 引入 TrendLineChart,替换两个趋势表格的渲染,加视图切换按钮,修 P1-2 标题 低,只动渲染层
后端 lib/admin-material-stats.ts 不改 -
数据库 / Prisma 不改 -

不涉及:接口签名、响应结构、权限、数据写入、其它页面。


8. 验证清单(做完后)

  1. npx tsc --noEmit 类型通过
  2. npm test 现有测试不回归
  3. 切换"今天/近7天/近30天/本月/上月/全部"6个预设,图表正确补零、标题正确显示
  4. 表格视图切换正常,数据与图表一致
  5. hover tooltip 正确显示日期和数值
  6. 峰值/均值/合计/环比 4 个摘要数字计算正确
  7. shadow 环境实测视觉

9. 待你确认的开放问题

  1. 方案选 A / B / C?(我推荐 A)
  2. 视图切换默认显示图表还是表格?(我推荐默认图表)
  3. 每日趋势跨度很大时(比如选"全部",跨2年=730天),怎么处理?
    • 选项:(a) 自动降采样到每周一个点 (b) 横向滚动 (c) 强制只显示最近N天
    • 我推荐 (a) 降采样,保证图表可读
  4. 要不要这个提案先作为文档存档,等你 review 后再决定是否实施?