212 lines
9.0 KiB
Markdown
212 lines
9.0 KiB
Markdown
---
|
||
name: dashboard-enrich
|
||
overview: 前后端联动丰富运营仪表盘:后端新增趋势统计接口并扩展 summary 的「内容审核 / VIP / 商品」维度,前端引入 ECharts 用折线图、环形图等呈现。
|
||
design:
|
||
architecture:
|
||
framework: vue
|
||
styleKeywords:
|
||
- 现代清爽
|
||
- 渐变卡片
|
||
- 数据可视化
|
||
- 环形图
|
||
fontSystem:
|
||
fontFamily: PingFang SC
|
||
heading:
|
||
size: 20px
|
||
weight: 700
|
||
subheading:
|
||
size: 15px
|
||
weight: 600
|
||
body:
|
||
size: 13px
|
||
weight: 400
|
||
colorSystem:
|
||
primary:
|
||
- "#4F6EF7"
|
||
- "#6A5CF0"
|
||
- "#8B5CF6"
|
||
background:
|
||
- "#F5F7FB"
|
||
- "#FFFFFF"
|
||
text:
|
||
- "#1F2437"
|
||
- "#5D6685"
|
||
- "#9AA3C0"
|
||
functional:
|
||
- "#22C55E"
|
||
- "#F59E0B"
|
||
- "#EF4444"
|
||
- "#06B6D4"
|
||
todos:
|
||
- id: extend-dashboard-dto
|
||
content: 扩展后端仪表盘 DTO(Content/VIP/Goods/Trend)
|
||
status: completed
|
||
- id: extend-stats-dao
|
||
content: StatsDao 新增内容/VIP/商品/趋势统计方法
|
||
status: completed
|
||
- id: extend-dashboard-service
|
||
content: DashboardService 聚合新维度并实现 Trend 方法
|
||
status: completed
|
||
dependencies:
|
||
- extend-dashboard-dto
|
||
- extend-stats-dao
|
||
- id: add-trend-route
|
||
content: 新增 Trend handler 并注册 dashboard/trends 路由
|
||
status: completed
|
||
dependencies:
|
||
- extend-dashboard-service
|
||
- id: setup-echarts
|
||
content: 安装 echarts 并封装 BaseChart 通用组件
|
||
status: completed
|
||
- id: extend-dashboard-api
|
||
content: 扩展前端 dashboard 类型定义与 API 函数
|
||
status: completed
|
||
dependencies:
|
||
- extend-dashboard-dto
|
||
- id: rebuild-dashboard-view
|
||
content: 重构仪表盘页渲染趋势折线图与三个分布环形图
|
||
status: completed
|
||
dependencies:
|
||
- setup-echarts
|
||
- extend-dashboard-api
|
||
---
|
||
|
||
## 产品概述
|
||
|
||
在现有运营仪表盘基础上进行可视化升级:保留营收、用户、订单概况与待办横幅,新增时间趋势折线图和内容审核、VIP 会员、商品分类三个分布面板,让运营人员一眼掌握核心数据动态。
|
||
|
||
## 核心功能
|
||
|
||
- 近 7/30 天可切换的趋势折线图:新增用户数、已支付订单量、营收金额(双坐标轴)
|
||
- 内容审核概况:穿搭审核状态(待审核/通过/不通过/封禁)、衣物图片处理状态(处理中/成功/失败)、衣柜分享状态(正常/取消/过期/封禁)分布
|
||
- VIP 会员概况:有效会员类型分布(月度/年度/体验)及 7 天内即将到期会员数
|
||
- 商品分类统计:各类型商品数量分布与上架/下架占比
|
||
- 保留现有 summary 各指标与页面布局,新增内容向后兼容、不影响已上线展示
|
||
|
||
## 技术栈
|
||
|
||
- 后端:Go + Gin + GORM(复用现有 StatsDao 直接聚合 MySQL 业务表,不改表结构)
|
||
- 前端:Vue 3 + TypeScript + Element Plus + ECharts(新增 echarts 依赖)
|
||
- 图表:ECharts 折线图 + 环形饼图
|
||
|
||
## 实现方案
|
||
|
||
后端复用现有 `DashboardService` 与 `StatsDao` 模式,将 `GET /dashboard/summary` 的响应扩展出 `content`、`vip`、`goods` 三个子结构(一次请求拿到全部概况),另新增 `GET /dashboard/trends?days=7|30` 返回按天对齐的趋势序列(无数据日期补零)。前端引入 ECharts,封装通用 `BaseChart.vue` 管理实例生命周期,在 DashboardView 内组合趋势折线图与三个环形分布图。
|
||
|
||
关键决策:
|
||
|
||
- **趋势单独一个接口**:summary 保持轻量只做概况,趋势数据按需加载并支持 7/30 天切换,避免每次都聚合全量日期序列。
|
||
- **按天补零在 Go 端完成**:SQL 只 group by 有数据的日期,Go 端从起始日期循环补零,保证折线图 x 轴连续、时区正确。
|
||
- **双 y 轴**:营收(元)与数量量纲不同,趋势图用左轴数量、右轴金额。
|
||
- **向后兼容**:DashboardResponse 只增字段不改字段,前端旧字段继续渲染,新字段独立面板。
|
||
|
||
数据口径:
|
||
|
||
- 趋势新增用户:`users.created_at` 按日计数;订单量:`orders.order_status IN (2,5)` 且按 `pay_time` 计数(与营收同口径);营收:`orders.pay_amount` 求和(分)。
|
||
- VIP 有效会员:`vip_type IN (2,3,4) AND vip_expire > now`;即将到期:`vip_expire BETWEEN now AND now+7*86400`。
|
||
- 内容审核:穿搭按 `audit_status` 与 `status=2` 封禁数;衣物按 `image_process_status` 分组(1/2/3 归为处理中、4 成功、5 失败);分享按 `status` 分组。
|
||
|
||
## 架构设计
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
subgraph Frontend
|
||
DV[DashboardView.vue] --> BC[BaseChart.vue]
|
||
DV --> API[api/dashboard.ts]
|
||
DV --> TYPES[types/dashboard.ts]
|
||
end
|
||
subgraph Backend
|
||
H[SummaryHandler / TrendHandler] --> S[DashboardService]
|
||
S --> DAO[StatsDao]
|
||
DAO --> M[(MySQL 业务表)]
|
||
end
|
||
API -->|GET /dashboard/summary| H
|
||
API -->|GET /dashboard/trends| H
|
||
```
|
||
|
||
## 关键数据结构(后端 dto/dashboard.go 扩展)
|
||
|
||
```
|
||
type DashboardResponse struct {
|
||
Users DashboardUsers `json:"users"`
|
||
Orders DashboardOrders `json:"orders"`
|
||
Revenue DashboardRevenue `json:"revenue"`
|
||
Todo DashboardTodo `json:"todo"`
|
||
Content DashboardContent `json:"content"`
|
||
VIP DashboardVIP `json:"vip"`
|
||
Goods DashboardGoods `json:"goods"`
|
||
}
|
||
|
||
type DashboardContent struct {
|
||
Outfit DashboardOutfitStats `json:"outfit"`
|
||
Clothes DashboardClothesStats `json:"clothes"`
|
||
Share DashboardShareStats `json:"share"`
|
||
}
|
||
|
||
type DashboardVIP struct {
|
||
MemberTotal int64 `json:"member_total"`
|
||
Monthly int64 `json:"monthly"`
|
||
Yearly int64 `json:"yearly"`
|
||
Trial int64 `json:"trial"`
|
||
ExpiringSoon int64 `json:"expiring_soon"`
|
||
}
|
||
|
||
type DashboardGoods struct {
|
||
Total int64 `json:"total"`
|
||
OnShelf int64 `json:"on_shelf"`
|
||
OffShelf int64 `json:"off_shelf"`
|
||
ByType []GoodsTypeCount `json:"by_type"`
|
||
}
|
||
|
||
type TrendPoint struct {
|
||
Date string `json:"date"` // YYYY-MM-DD
|
||
NewUsers int64 `json:"new_users"`
|
||
Orders int64 `json:"orders"`
|
||
Revenue int64 `json:"revenue"` // 分
|
||
}
|
||
```
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
后端 /root/zt-closet-manage-backend/
|
||
├── internal/dto/dashboard.go # [MODIFY] 扩展 Content/VIP/Goods 结构与 Trend 请求/响应结构
|
||
├── internal/mysqldao/stats.go # [MODIFY] 新增 ContentStatsGet/VIPStatsGet/GoodsStatsGet/TrendStatsGet
|
||
├── internal/service/dashboard.go # [MODIFY] Summary 聚合新维度,新增 Trend 方法
|
||
├── internal/routers/api/v1/dashboard.go # [MODIFY] 新增 Trend handler
|
||
└── internal/routers/router.go # [MODIFY] 注册 GET /dashboard/trends
|
||
|
||
前端 /root/zt-closet-manage-frontend/
|
||
├── package.json # [MODIFY] 新增 echarts 依赖
|
||
├── src/components/BaseChart.vue # [NEW] ECharts 通用封装(init/resize/dispose/option 更新)
|
||
├── src/types/dashboard.ts # [MODIFY] 新增 Content/VIP/Goods/Trend 类型
|
||
├── src/api/dashboard.ts # [MODIFY] 新增 getDashboardTrends
|
||
└── src/views/dashboard/DashboardView.vue # [MODIFY] 趋势折线图 + 内容/VIP/商品三个环形图面板
|
||
```
|
||
|
||
## 实现要点
|
||
|
||
- DAO 趋势 SQL 使用 `DATE(FROM_UNIXTIME(created_at))` / `DATE(FROM_UNIXTIME(pay_time))` 分组,参数为秒级时间戳;返回 map[date]value 后由 service 按起始日期补零。
|
||
- StatsDao 各新方法保持 `func (d *StatsDao) Xxx(ctx context.Context, ...) (*XxxStats, error)` 风格,`WithContext` + `span.RecordError`,与现有 stats.go 一致。
|
||
- `TrendStatsGet` 用一次循环构造 `[]TrendPoint`,避免 N+1;`days` 参数在 handler 用 `ShouldBindQuery` 校验并限制 1~90。
|
||
- 前端 `BaseChart.vue` 使用 `echarts.init`,`watch` option 深度更新,`ResizeObserver` 监听容器尺寸,`onBeforeUnmount` 时 `dispose` 防泄漏。
|
||
- 趋势图折线:新增用户/订单量挂左轴,营收挂右轴(`formatMoney` 转元显示);分布图用 pie 环形,复用现有 `enumLabel` 常量映射文案。
|
||
- 不改动已有接口字段,保证 summary 旧展示路径不回归;仅在前端 `DashboardSummary` 类型上新增可选字段并渲染新面板。
|
||
|
||
## 设计风格
|
||
|
||
延续现有管理后台的现代清爽风格,在现有渐变 hero 横幅、白底圆角卡片基础上做可视化升级,强调信息密度与层次感。趋势图采用通栏大卡片,内容审核、VIP 会员、商品分类采用三列卡片布局,图表配色与页面既有渐变色系统一。
|
||
|
||
## 页面布局
|
||
|
||
- 顶部保留渐变欢迎横幅与待办数字
|
||
- 营收四卡片行保持不变
|
||
- 新增通栏「数据趋势」卡片:7 天 / 30 天分段切换 + 双轴折线图
|
||
- 新增三列分布卡片:内容审核概况、VIP 会员概况、商品分类统计,各配环形图与关键数字
|
||
- 保留原有用户概况、订单概况面板
|
||
|
||
## 交互
|
||
|
||
- 趋势图切换 7/30 天时局部刷新,不整页加载
|
||
- 环形图悬停显示数量与占比 tooltip
|
||
- 卡片沿用 hover 上浮阴影,保持与现有 stat-card 一致的微动效 |