first commit

This commit is contained in:
2026-09-11 01:46:36 +08:00
commit df4332a2a3
58 changed files with 9771 additions and 0 deletions
@@ -0,0 +1,212 @@
---
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 一致的微动效
@@ -0,0 +1,130 @@
---
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`。
- 不改动已有接口字段与展示路径,保证向后兼容。
@@ -0,0 +1,110 @@
---
name: 前后端逻辑对齐
overview: 以后端最新代码为准,修复前端与后端不一致的地方,重点解决用户额度调整语义错配、额度凭证(grants)功能缺失、商品与订单字段缺失等问题。
todos:
- id: align-user-types-api
content: 对齐用户额度/凭证类型并新增 revokeGrant 回收 API
status: completed
- id: update-user-view
content: 更新用户页额度发放表单与详情凭证列表回收
status: completed
dependencies:
- align-user-types-api
- id: align-goods-types-view
content: 补齐商品 valid_days 等字段并更新商品表单与展示
status: completed
- id: align-order-types-view
content: 补齐订单虚拟支付字段、枚举并更新订单详情展示
status: completed
---
## 用户需求
后端管理代码有更新,需全量核对后端(/root/zt-closet-manage-backend)与前端(/root/zt-closet-manage-frontend)的逻辑一致性。以后端最新代码为基准,前端做适配,确保接口字段、请求语义、枚举映射完全对齐。
## 核对结论与变更点
经全量对比,登录鉴权、仪表盘、内容审核、通知、退款、响应结构与错误码均已一致,无需改动。存在以下 5 处不一致需要修复:
1. **用户额度调整语义错配(功能不可用)**:后端已改为「发放额度凭证」语义,请求体为 `quota_type + amount + expire_days`;前端仍使用旧的 `quota_type + new_total + reason`,导致提交必失败。
2. **用户额度凭证(grants)功能缺失**:后端用户详情已返回 `grants` 列表,并提供 `DELETE /users/:uuid/grants/:id` 回收接口;前端类型、API、页面展示与回收操作均缺失。
3. **商品字段缺失**:后端商品新增 `valid_days`(有效期天数,可编辑)及只读的 `product_id`、`product_status`(虚拟支付道具);前端类型、表单与列表展示均未覆盖。
4. **订单字段缺失**:后端订单新增 `xpay_product_id`、`xpay_platform`、`xpay_env`(虚拟支付信息);前端类型与详情展示均未覆盖。
5. **支付渠道枚举缺失**:后端支付渠道为「1=微信支付、2=微信虚拟支付」;前端 `PAY_CHANNEL` 仅定义 value=1,虚拟支付订单会显示为 `-`。
## 技术栈
- 前端:Vue 3 + TypeScript + Element Plus + Pinia + axios(沿用现有架构,不引入新依赖)
- 后端:Go + Gin(只读参考,不修改)
## 实现方案
以后端 `internal/dto/*.go` 的 JSON tag 与路由为唯一基准,逐项对齐前端 `src/types`、`src/api`、`src/utils/constants` 与对应 `src/views` 页面。
### 关键决策
- **额度调整语义重构**:将前端 `UserQuotaAdjustRequest` 改为 `{ quota_type, amount, expire_days }`,移除 `new_total`、`reason`。页面表单同步改为「发放数量 + 有效期天数」,提交 `amount`(1~100000000)与 `expire_days`(1~3650)。这是当前最严重的不一致,修复后功能才可用。
- **补齐凭证管理闭环**:`UserDetailResponse` 增加 `grants: UserGrantItem[]`;`api/user.ts` 新增 `revokeGrant` 调用 `DELETE /users/:uuid/grants/:id`;详情抽屉展示凭证列表(类型/来源/数量/已用/到期/关联 ID)并增加「回收」操作,回收成功后重新拉取详情刷新。
- **只读字段与可编辑字段分离**:商品 `product_id`、`product_status` 为只读,仅展示、不参与创建/更新提交;`valid_days` 可编辑,加入表单回显与提交。商品更新接口为「传什么改什么」的指针语义,前端编辑时仅提交可编辑字段。
- **枚举与展示对齐**:`constants.ts` 新增 `GRANT_SOURCE`(1=会员包、2=加量包、3=广告激励),`PAY_CHANNEL` 补充 value=2(微信虚拟支付)。
- **单位约定不变**:价格仍为「分」,前端继续用 `yuanToCents`/`formatMoney` 换算,避免引入新的金额逻辑。
### 实现注意事项
- 所有字段命名严格遵循后端 JSON tag(snake_case),禁止自创字段名。
- 复用现有 `httpGet/httpPost/httpPut/httpDelete` 与 `enumLabel/enumTag/enumOptions/formatDate/formatText` 工具,不新增请求层逻辑。
- 回收凭证后需重新调用 `getUserDetail` 刷新详情,避免展示陈旧数据。
- 保持现有页面结构与组件风格,仅做字段级调整,不做无关重构。
## 目录结构
```
zt-closet-manage-frontend/
├── src/
│ ├── types/
│ │ ├── user.ts # [MODIFY] UserQuotaAdjustRequest 改为 amount+expire_days;新增 UserGrantItem;UserDetailResponse 增加 grants
│ │ ├── goods.ts # [MODIFY] GoodsItem 增加 valid_days/product_id/product_status;GoodsCreateRequest、GoodsUpdateRequest 增加 valid_days
│ │ └── order.ts # [MODIFY] OrderItem 增加 xpay_product_id/xpay_platform/xpay_env
│ ├── api/
│ │ └── user.ts # [MODIFY] 新增 revokeGrant(uuid, grantId) 调用 DELETE /users/:uuid/grants/:id
│ ├── utils/
│ │ └── constants.ts # [MODIFY] 新增 GRANT_SOURCE 枚举;PAY_CHANNEL 补充 value=2
│ └── views/
│ ├── user/
│ │ └── UserListView.vue # [MODIFY] 额度表单改为发放数量+有效期天数;详情抽屉展示 grants 并增加回收操作
│ ├── goods/
│ │ └── GoodsListView.vue # [MODIFY] 表单增加 valid_days;列表/详情展示 product_id、product_status
│ └── order/
│ └── OrderListView.vue # [MODIFY] 订单详情抽屉展示虚拟支付字段
```
## 关键代码结构
用户域核心类型(需与后端 dto/user.go 严格对齐):
```ts
// 额度发放请求(后端 UserQuotaAdjustRequest)
export interface UserQuotaAdjustRequest {
quota_type: number // 1=上传 2=AI 3=社区分享 4=衣柜分享
amount: number // 发放数量,min=1
expire_days: number // 有效期天数,min=1
}
// 用户额度凭证(后端 UserGrantItem)
export interface UserGrantItem {
id: number
quota_type: number
amount: number
used: number
source: number // 1=会员包 2=加量包 3=广告激励
expire_time: number // 秒,0=跟随 VIP
ref_id: string
created_at: number
}
// 用户详情(后端 UserDetailResponse)
export interface UserDetailResponse extends UserListItem {
quotas: QuotaItem[]
grants: UserGrantItem[]
}
```
@@ -0,0 +1,142 @@
---
name: 智能衣橱管理后台前端
overview: 基于 Vue3 + TypeScript + Vite 从零搭建「智能衣橱」管理后台前端,对接 Go 后端 /api/v1 全部接口,覆盖登录鉴权、仪表盘、用户/商品/订单退款/内容审核/通知/管理员管理 8 大模块。
design:
architecture:
framework: react
component: mui
---
## 产品概述
基于 zt-closet-manage-backend 后端 API 契约,从零构建「智能衣橱」管理后台前端系统(Vue 3 + TypeScript + Element Plus)。系统覆盖管理员登录鉴权(JWT 双 token 自动刷新)、仪表盘统计、用户管理、商品管理、订单与退款审核、内容审核(穿搭/衣物/衣柜分享)、通知推送,以及超级管理员专属的管理员账号管理,共 9 大功能模块。
## 核心功能
- **登录与鉴权**:账号密码登录,access/refresh 双 token 管理;access 过期自动用 refresh 换新并重放原请求;登出、修改密码;按 role 区分超管/普通管理员菜单与路由权限
- **仪表盘**:统计卡片展示用户总数/今日新增/状态分布、订单状态分布、累计与今日营收/累计退款、待办事项(待处理退款、待审核穿搭、上架商品数),金额以元展示
- **用户管理**:分页搜索(昵称/手机号/OpenID/状态)、详情查看(含四类额度)、封禁/解封(临时按天/永久)、额度人工调整、VIP 人工调整,均带原因填写与二次确认
- **商品管理**:分页筛选(类型/状态/关键字)、新增、编辑、上下架、软删除;商品类型含会员包/上传包/AI 包/衣柜分享包/搭配分享包,金额按分输入、按元展示
- **订单与退款**:订单列表筛选/详情抽屉;退款单列表(状态 0-3 可显式筛选待处理)、审核通过/驳回(必填备注原因)
- **内容审核**:穿搭列表筛选/详情(含衣物明细)、审核通过/驳回、封禁/解封;衣物列表/详情;衣柜分享列表/封禁/解封
- **通知推送**:单用户系统通知、全量广播(返回发送人数),表单带字数限制校验
- **管理员管理(超管专属)**:管理员列表、创建、编辑(昵称/密码/角色/状态)、删除;普通管理员无权限(后端 403,前端同时隐藏入口)
- **统一交互规范**:所有业务错误以 body.code 判断并提示;金额统一 `分→元` 格式化;时间戳统一格式化展示;列表统一分页(page/page_size 1~50)
## 视觉要求
深色侧边栏 + 浅色内容区的经典管理后台布局;侧边栏按业务域分组菜单并支持折叠;顶部栏含面包屑、管理员信息、修改密码、登出;状态使用彩色 Tag 标签、操作按钮使用文字链接风格;表格斑马纹、hover 高亮;统计卡片带渐变图标底;弹窗表单统一 Element Plus 风格,操作均带确认与结果反馈。
## 技术栈
- **框架**:Vue 3.5(`<script setup lang="ts">` 组合式 API)+ TypeScript 6.0
- **UI 组件库**:Element Plus(表格/表单/分页/对话框/抽屉/消息提示全覆盖)
- **路由**:vue-router 4(含全局前置守卫鉴权与角色权限)
- **状态管理**:Pinia(auth store 持久化 token/admin_info)
- **HTTP**:axios 实例封装(请求拦截注入 Bearer、响应拦截统一 code 处理、11002 自动刷新重放、防并发刷新)
- **开发代理**:Vite `server.proxy` 将 `/api` 转发 `http://localhost:8080`,规避 CORS
- **格式化**:手写 `formatMoney`(分→元)、`formatDate`(Unix 秒→字符串)工具函数,不引入额外依赖
## 实现方案
### 总体策略
按「基础骨架 → API 契约层 → 布局与鉴权 → 业务模块页」四阶段推进。所有 API 类型严格对齐后端 DTO 的 json tag;枚举以常量映射表集中管理(数值→文案→Tag 颜色);复用一套「筛选表单 + 表格 + 分页」的页面组织模式,保证 9 个列表页风格与交互一致。
### 关键技术决策
- **axios 拦截器设计**:响应 code 非 0 时统一 ElMessage 报错并 reject;HTTP 401 且 code=11002 时,以单例 Promise 防并发调用 refresh 接口(携带旧 access + refresh),成功后更新 token 并重放原请求队列;刷新失败清空会话跳转登录页。其余 401/403/500 直接提示并跳转/返回。
- **路由权限**:静态定义全部路由,meta 标记 `requiresAuth`/`superOnly`;守卫中校验 token 与 admin_info.role,超管专属路由对普通管理员重定向到仪表盘并提示无权限。
- **金额与时间**:所有金额字段后端为分(int64),输入框以「元」为单位编辑、提交时乘 100 取整,列表用 `formatMoney` 展示;时间戳为 Unix 秒,统一 `formatDate` 输出 `YYYY-MM-DD HH:mm:ss`,0/空值显示「—」。
- **枚举映射**:constants.ts 集中维护 status/vip/quota/goods/order/refund/outfit/share/image 等全部枚举的 `{value,label,tagType}` 映射表,组件通过辅助函数取文案与颜色,避免散落魔法数字。
- **页面组织模式**:列表页统一「筛选卡片区 + 表格卡片区 + 分页」三段式;写操作(封禁/调整额度/审核等)统一对话框表单 + 提交确认 + 成功后刷新当前页。
- **性能**:列表接口后端已分页(每页最多 50 条),前端不做全量拉取;表格列数多时用固定关键列 + 详情抽屉承载次要信息;组件按路由懒加载切分 chunk。
## 实施细节
- **依赖安装**:`npm i element-plus vue-router@4 pinia axios` 及 `@element-plus/icons-vue`;main.ts 全量引入 Element Plus(管理后台规模,按需引入收益有限)并注册图标。
- **主色定制**:通过 Element Plus CSS 变量(`--el-color-primary` 系列)覆盖为靛蓝色系,与深色侧边栏协调。
- **退款状态筛选注意**:`/refunds?status=0` 须显式传 0(待处理),前端下拉用「-1=全部」占位转换,防止丢失。
- **refresh-token 注意**:body 必须同时携带 `refresh_token` 与旧 `access_token`(后端强制校验)。
- **noUncheckedIndexedAccess 已开启**:数组/对象索引访问需判空处理。
- **业务错误提示**:后端多数业务错误 HTTP 仍为 200,必须读取 body.code 分支提示 msg;避免仅按 HTTP 状态判断。
- **安全**:token 仅存 localStorage(本场景无 SSR);密码字段不落日志;请求日志不打印 Authorization。
- **开发联调**:后端未启动时前端可正常渲染空态;启动后端(`go run .`,默认 8080)后经 Vite 代理联调。
## 架构设计
```mermaid
graph TB
subgraph 前端
A[Login 登录页] --> B[AdminLayout 主布局]
B --> C[Router 路由 + 守卫]
C --> D[业务页面 views]
D --> E[api 模块层]
E --> F[axios 实例 + 拦截器]
F --> G[Pinia auth store]
end
F -->|/api 经 Vite proxy| H[Go 后端 :8080/api/v1]
```
- **分层**:views(页面)→ api(接口封装,纯函数)→ request(axios 拦截器)→ store(token/管理员信息);类型集中在 types/,枚举与格式化工具在 utils/,与后端契约一一对应。
- **数据流**:用户操作 → 页面调用 api → axios 注入 token 发请求 → 响应拦截统一处理 code/401 → 页面更新表格数据/提示结果 → auth store 变更触发路由守卫响应。
## 目录结构
```
zt-closet-manage-frontend/
├── package.json # [MODIFY] 新增 element-plus/vue-router/pinia/axios/@element-plus/icons-vue 依赖
├── vite.config.ts # [MODIFY] 增加 server.proxy:/api → http://localhost:8080
├── index.html # [MODIFY] 标题改为「智能衣橱管理后台」
├── src/
│ ├── main.ts # [MODIFY] 挂载 router/pinia、全量引入 Element Plus 与图标、引入全局样式
│ ├── App.vue # [MODIFY] 替换为 <router-view/> 根组件
│ ├── assets/
│ │ ├── main.css # [MODIFY] 全局样式:布局背景、卡片圆角阴影、滚动条、通用工具类
│ │ └── element-theme.css # [NEW] Element Plus 主色变量覆盖(靛蓝系)+ 深色侧边栏配色变量
│ ├── router/index.ts # [NEW] 路由表 + 全局守卫(登录态校验、superOnly 角色校验、页面标题)
│ ├── stores/auth.ts # [NEW] Pinia auth store:token/refreshToken/adminInfo 持久化、login/logout/refresh 动作
│ ├── utils/
│ │ ├── request.ts # [NEW] axios 实例:注入 Bearer、code≠0 统一报错、11002 单例刷新+请求队列重放、401/403/500 处理
│ │ ├── format.ts # [NEW] formatMoney(分→元)、formatDate(秒→YYYY-MM-DD HH:mm:ss)、formatDateTimeRange 等
│ │ └── constants.ts # [NEW] 全量枚举映射:用户状态/VIP/额度/商品/订单/退款/穿搭/分享/图片处理/管理员角色等 → {label,tagType}
│ ├── types/
│ │ ├── common.ts # [NEW] ApiResponse{code,msg,data,details}、PageQuery、PageResult{total,page,page_size,list} 泛型
│ │ ├── auth.ts # [NEW] AdminInfo、AdminLoginResponse、RefreshTokenResponse、改密请求类型
│ │ ├── user.ts # [NEW] UserListItem/UserDetailResponse/QuotaItem/封禁/额度/VIP 调整请求类型
│ │ ├── goods.ts # [NEW] GoodsItem/GoodsCreateRequest/GoodsUpdateRequest/状态请求类型
│ │ ├── order.ts # [NEW] OrderItem/RefundItem/审核请求类型
│ │ ├── content.ts # [NEW] OutfitListItem/OutfitDetailResponse/OutfitClothesItem/ClothesItem/ClosetShareItem 及审核/封禁请求
│ │ ├── notification.ts # [NEW] 单发/广播请求与响应类型
│ │ └── dashboard.ts # [NEW] 仪表盘聚合响应嵌套结构类型
│ ├── api/
│ │ ├── auth.ts # [NEW] login/refreshToken/logout/changePassword
│ │ ├── dashboard.ts # [NEW] getSummary
│ │ ├── user.ts # [NEW] 列表/详情/封禁/解封/额度调整/VIP 调整
│ │ ├── goods.ts # [NEW] 列表/创建/更新/上下架/软删
│ │ ├── order.ts # [NEW] 订单列表/详情、退款列表/通过/驳回
│ │ ├── content.ts # [NEW] 穿搭列表/详情/审核/封禁解封、衣物列表/详情、分享列表/封禁解封
│ │ ├── notification.ts # [NEW] 单发/广播
│ │ └── admin.ts # [NEW] 管理员列表/创建/更新/删除
│ ├── components/
│ │ ├── PaginationBar.vue # [NEW] 通用分页条:v-model 页码/每页条数,联动 emit 刷新,封装 total 显示
│ │ └── SearchFormCard.vue # [NEW] 通用筛选卡片:插槽承载筛选控件,查询/重置按钮触发 emit
│ ├── layout/
│ │ ├── AdminLayout.vue # [NEW] 整体布局:深色可折叠侧边栏(分组菜单、按 role 过滤超管菜单)+ 顶栏 + 内容区
│ │ ├── SidebarMenu.vue # [NEW] 侧边栏菜单组件:递归渲染分组路由、折叠态图标提示、active 高亮
│ │ └── HeaderBar.vue # [NEW] 顶栏:面包屑、管理员昵称下拉(修改密码对话框/登出)
│ └── views/
│ ├── login/LoginView.vue # [NEW] 登录页:渐变背景居中卡片、账号密码表单校验、登录后按 role 跳转
│ ├── dashboard/DashboardView.vue # [NEW] 仪表盘:四组统计卡片(用户/订单/营收/待办)、金额元格式化、空态处理
│ ├── user/UserListView.vue # [NEW] 用户列表:筛选/表格(状态 Tag)/详情抽屉(额度表)/封禁、解封、额度调整、VIP 调整对话框
│ ├── goods/GoodsListView.vue # [NEW] 商品列表:筛选/表格/新增编辑对话框(分元输入转换)/上下架/软删确认
│ ├── order/OrderListView.vue # [NEW] 订单列表:筛选/表格/详情抽屉(金额与配额快照)
│ ├── order/RefundListView.vue # [NEW] 退款列表:状态筛选(含显式待处理)/通过、驳回对话框(必填原因)
│ ├── review/OutfitListView.vue # [NEW] 穿搭列表:多条件筛选/审核通过驳回(驳回必填原因)/封禁解封/详情抽屉(衣物明细)
│ ├── review/ClothesListView.vue # [NEW] 衣物列表:筛选/详情抽屉(属性字段分栏展示)
│ ├── review/ShareListView.vue # [NEW] 衣柜分享列表:筛选/封禁解封
│ ├── notification/NotifyView.vue # [NEW] 通知推送:单用户通知与全量广播两个表单卡片、字数限制、广播返回 sent_count 提示
│ └── admin/AdminListView.vue # [NEW] 管理员列表(超管):筛选/表格/创建编辑对话框/删除确认/状态禁用提示
```
删除模板遗留文件:`src/components/HelloWorld.vue`、`TheWelcome.vue`、`WelcomeItem.vue`、`src/assets/logo.svg`。