130 lines
6.0 KiB
Markdown
130 lines
6.0 KiB
Markdown
---
|
||
name: dashboard-usage-interaction
|
||
overview: 在运营仪表盘新增「今日消耗、COS 图数、点赞/收藏」指标:后端扩展 summary 聚合接口,前端新增展示卡片。
|
||
todos:
|
||
- id: add-social-models
|
||
content: 在 business.go 中新增 Like、Collect 表模型镜像
|
||
status: completed
|
||
- id: extend-dto-dao
|
||
content: 扩展 dashboard DTO 并新增 UsageStatsGet/SocialStatsGet 聚合方法
|
||
status: completed
|
||
dependencies:
|
||
- add-social-models
|
||
- id: aggregate-summary
|
||
content: 在 DashboardService.Summary 中聚合 usage 与 social 维度
|
||
status: completed
|
||
dependencies:
|
||
- extend-dto-dao
|
||
- id: extend-frontend-types
|
||
content: 扩展前端 dashboard 类型定义,新增 usage/social 字段
|
||
status: completed
|
||
dependencies:
|
||
- extend-dto-dao
|
||
- id: render-dashboard-metrics
|
||
content: 在仪表盘页新增「今日消耗」「内容互动」两列指标卡片
|
||
status: completed
|
||
dependencies:
|
||
- extend-frontend-types
|
||
---
|
||
|
||
## 产品概述
|
||
|
||
在现有运营仪表盘基础上,新增「今日消耗」与「内容互动」两组共 6 个运营指标,让运营人员直观掌握每日额度消耗与社区内容互动数据。
|
||
|
||
## 核心功能
|
||
|
||
- 今日 AI 推荐消耗次数
|
||
- 今日衣柜分享消耗次数
|
||
- 今日社区分享消耗次数
|
||
- COS 总图数
|
||
- 点赞数
|
||
- 收藏数
|
||
|
||
## 展示说明
|
||
|
||
- 在营收卡片下方、数据趋势面板上方,新增一行两列卡片:「今日消耗」展示 AI 推荐/衣柜分享/社区分享三项今日次数,「内容互动」展示 COS 图数/点赞数/收藏数三项累计值。
|
||
- 沿用现有 stat-card / mini-stat 卡片风格与图标配色,保持页面整体视觉一致。
|
||
|
||
## 技术栈
|
||
|
||
- 后端:Go + Gin + GORM,复用现有 `StatsDao` / `DashboardService`,不改表结构。
|
||
- 前端:Vue 3 + TypeScript + Element Plus,复用现有卡片样式,无需新增依赖。
|
||
|
||
## 实现方案
|
||
|
||
扩展现有 `GET /dashboard/summary` 响应的 `DashboardResponse`,新增 `usage`(今日消耗)与 `social`(互动+COS)两个子结构,一次请求返回全部新增指标;前端在 `DashboardView.vue` 中新增一行两列卡片渲染。
|
||
|
||
数据口径(已通过业务服务源码确认):
|
||
|
||
| 指标 | 数据来源 | 统计口径 |
|
||
| --- | --- | --- |
|
||
| 今日 AI 推荐消耗次数 | `user_daily_usages` | `stat_date = 今日(YYYYMMDD)`,`SUM(ai_recommend_count)` |
|
||
| 今日衣柜分享消耗次数 | `user_daily_usages` | `stat_date = 今日(YYYYMMDD)`,`SUM(closet_share_count)` |
|
||
| 今日社区分享消耗次数 | `user_daily_usages` | `stat_date = 今日(YYYYMMDD)`,`SUM(outfit_share_count)` |
|
||
| COS 总图数 | `clothes` | `processed_image != ''` 的记录数 |
|
||
| 点赞数 | `likes` | `status = 1`(已点赞)计数 |
|
||
| 收藏数 | `collects` | `status = 1`(已收藏)计数 |
|
||
|
||
|
||
关键决策:
|
||
|
||
- **今日消耗合并为一次查询**:`user_daily_usages` 一行同时含三项计数字段,直接 `SUM` 三列并 `WHERE stat_date = ?`,避免三次查询。
|
||
- **COS 总图数口径**:`clothes.processed_image` 是上传 COS 成功后回填的对象键路径,非空即代表已存图。
|
||
- **点赞/收藏按累计总数**:用户未加「今日」前缀,与「今日消耗」形成区分,取 `status=1` 全量计数。
|
||
- **Like/Collect 模型镜像补齐**:管理后台 `business.go` 当前缺少这两个表模型,按业务服务字段镜像新增,软删除由 `Model.DeletedAt` 自动过滤。
|
||
|
||
## 架构设计
|
||
|
||
沿用现有分层:`DashboardHandler.Summary → DashboardService.Summary → StatsDao → MySQL`。本次仅扩展 summary 聚合链路,不新增路由与 handler。
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
DV[DashboardView.vue] --> API[api/dashboard.ts]
|
||
API --> H[SummaryHandler]
|
||
H --> S[DashboardService.Summary]
|
||
S --> DAO[StatsDao]
|
||
DAO --> M[(MySQL 业务表)]
|
||
```
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
后端 /root/zt-closet-manage-backend/
|
||
├── internal/mysqlmodel/business.go # [MODIFY] 新增 Like、Collect 表模型镜像
|
||
├── internal/dto/dashboard.go # [MODIFY] 新增 DashboardUsage/DashboardSocial 及 DashboardResponse 字段
|
||
├── internal/mysqldao/stats.go # [MODIFY] 新增 UsageStatsGet/SocialStatsGet
|
||
└── internal/service/dashboard.go # [MODIFY] Summary 聚合 usage/social 维度
|
||
|
||
前端 /root/zt-closet-manage-frontend/
|
||
├── src/types/dashboard.ts # [MODIFY] 新增 DashboardUsage/DashboardSocial 类型及 DashboardSummary 字段
|
||
└── src/views/dashboard/DashboardView.vue # [MODIFY] 新增「今日消耗」「内容互动」两列卡片
|
||
```
|
||
|
||
## 关键代码结构
|
||
|
||
```
|
||
// dto/dashboard.go
|
||
type DashboardUsage struct {
|
||
AIRecommend int64 `json:"ai_recommend"` // 今日AI推荐消耗次数
|
||
ClosetShare int64 `json:"closet_share"` // 今日衣柜分享消耗次数
|
||
OutfitShare int64 `json:"outfit_share"` // 今日社区分享消耗次数
|
||
}
|
||
|
||
type DashboardSocial struct {
|
||
CosImageCount int64 `json:"cos_image_count"` // COS总图数
|
||
LikeCount int64 `json:"like_count"` // 点赞数
|
||
CollectCount int64 `json:"collect_count"` // 收藏数
|
||
}
|
||
|
||
// mysqldao/stats.go
|
||
func (d *StatsDao) UsageStatsGet(ctx context.Context, statDate int64) (*UsageStats, error)
|
||
func (d *StatsDao) SocialStatsGet(ctx context.Context) (*SocialStats, error)
|
||
```
|
||
|
||
## 实现要点
|
||
|
||
- `UsageStatsGet` 用单条 `Select("COALESCE(SUM(ai_recommend_count),0), COALESCE(SUM(closet_share_count),0), COALESCE(SUM(outfit_share_count),0)")` 配合 `Where("stat_date = ?", statDate)`,`Scan` 到三个字段。
|
||
- `SocialStatsGet` 三条独立计数:`clothes.processed_image <> ''`、`likes.status = 1`、`collects.status = 1`,各自带 `span.RecordError` 与现有 DAO 风格一致。
|
||
- `Summary` 内使用已存在的 `todayStatDate()`(service/service.go)计算今日 YYYYMMDD 整数,传给 `UsageStatsGet`。
|
||
- 前端新增字段为可选读取(`summary?.usage` / `summary?.social`),旧后端响应未升级时不会报错;采用 6 个 `mini-stat` 数字块,分组放入两个 `panel`。
|
||
- 不改动已有接口字段与展示路径,保证向后兼容。 |