--- 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 一致的微动效