feat: ui update
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
---
|
||||
name: 穿搭页补全社区分段
|
||||
overview: 在穿搭 tab 新增「社区」分段,浏览所有用户公开的穿搭(作者信息、拼图封面、点赞/收藏数、场景与发布时间),并新增后端社区列表接口支撑。
|
||||
design:
|
||||
styleKeywords:
|
||||
- iOS HIG
|
||||
- 清爽克制
|
||||
- 发丝分隔线
|
||||
- 系统蓝
|
||||
- 线性图标
|
||||
fontSystem:
|
||||
fontFamily: PingFang SC
|
||||
heading:
|
||||
size: 32rpx
|
||||
weight: 600
|
||||
subheading:
|
||||
size: 28rpx
|
||||
weight: 500
|
||||
body:
|
||||
size: 26rpx
|
||||
weight: 400
|
||||
colorSystem:
|
||||
primary:
|
||||
- "#007AFF"
|
||||
- "#5856D6"
|
||||
background:
|
||||
- "#F2F2F7"
|
||||
- "#FFFFFF"
|
||||
text:
|
||||
- "#000000"
|
||||
- "#3C3C43"
|
||||
- "#8E8E93"
|
||||
- "#C7C7CC"
|
||||
functional:
|
||||
- "#FF2D55"
|
||||
- "#34C759"
|
||||
- "#FF9500"
|
||||
- "#FF3B30"
|
||||
todos:
|
||||
- id: backend-community-api
|
||||
content: 用 [subagent:code-explorer] 确认后端批量查询与计数模式;实现 GET /outfit/community 接口(DTO/DAO/Service/路由)并更新接口文档
|
||||
status: completed
|
||||
- id: frontend-community-data
|
||||
content: models.ts 新增社区穿搭类型;outfit.ts 实现三态分段、社区取数、相对时间与详情跳转
|
||||
status: completed
|
||||
dependencies:
|
||||
- backend-community-api
|
||||
- id: frontend-community-ui
|
||||
content: outfit.wxml/wxss 实现社区分段、作者行卡片、互动数据与空态样式
|
||||
status: completed
|
||||
dependencies:
|
||||
- frontend-community-data
|
||||
- id: verify-community
|
||||
content: 运行 go build 与 tsc 类型检查,核对前后端字段契约与路由注册
|
||||
status: completed
|
||||
dependencies:
|
||||
- backend-community-api
|
||||
- frontend-community-ui
|
||||
---
|
||||
|
||||
## 产品概述
|
||||
|
||||
为「纸条AI衣橱」小程序补全社区功能:在「穿搭」页现有「我的穿搭 / 已收藏」两个分段基础上,新增「社区」分段,让所有用户都能浏览其他用户公开的穿搭,并进入详情点赞、收藏,形成「公开到社区 → 他人浏览互动」的完整闭环。
|
||||
|
||||
## 核心功能
|
||||
|
||||
- 穿搭页分段控件扩展为三态:「我的穿搭 / 已收藏 / 社区」,切换即加载对应列表并重置分页
|
||||
- 社区分段以卡片流展示其他用户公开的穿搭(仅展示已公开且审核通过、状态正常的穿搭)
|
||||
- 社区卡片内容:作者头像与昵称(卡片顶部)、拼图式衣物封面与件数、穿搭名称、场景标签、点赞数与收藏数、相对发布时间
|
||||
- 点击社区卡片进入他人视角的穿搭详情页,可点赞、收藏(复用现有详情页,不新增页面)
|
||||
- 社区列表支持下拉刷新、上拉加载更多、骨架屏加载态与空态提示
|
||||
- 社区分段隐藏「+ 创建穿搭 / AI 推荐」入口行(浏览场景不展示管理入口)
|
||||
|
||||
## 视觉与交互效果
|
||||
|
||||
延续现有 iOS HIG 风格:分组灰底、纯白卡片、发丝分隔线、系统蓝强调色。社区卡片在现有穿搭卡片结构上顶部新增作者行(圆形头像 + 昵称 + 右侧相对时间),底部 meta 行新增点赞、收藏两组互动数据,整体与「我的穿搭」卡片流视觉统一、切换分段有平滑过渡。
|
||||
|
||||
## 技术栈
|
||||
|
||||
- 前端:微信小程序原生 + TypeScript(沿用现有 webview 渲染与纯 WXSS 手写方案,不引入组件库)
|
||||
- 后端:Go + Gin + GORM/MySQL(zt-closet-backend,新增接口沿用现有分层:router → handler → service → dao)
|
||||
- 复用:前端 `request` 封装、`paged` 分页工具、`format.formatRelativeTime`、`logger`、`empty-state` 组件与图标库;后端 `PageRequest/PageResponse`、`normalizePage`、批量查询与批量组装模式
|
||||
|
||||
## 实现方案
|
||||
|
||||
### 总体策略
|
||||
|
||||
后端新增鉴权接口 `GET /outfit/community`:分页返回「其他用户已公开(is_public=2 且 audit_status=2 且 status=1)」的穿搭列表,聚合作者信息与点赞/收藏计数后一次性下发;前端将 `pages/outfit` 页扩展为三态分段,第三段对接新接口渲染社区卡片流,点击进入现有他人视角详情页(owner=0)。全程复用既有模式,不引入新架构、不新增页面、不改动 tabBar。
|
||||
|
||||
### 关键决策与理由
|
||||
|
||||
1. **接口路径 `GET /outfit/community`**:与既有 `GET /outfit/:uuid` 在同一 Gin 路由树共存是安全的——项目内已有完全相同形态的先例(`/notification/unread` 与 `/notification/:uuid` 共存且线上运行正常),Gin 1.12 静态路由优先匹配。
|
||||
2. **排除本人的公开穿搭**(SQL 加 `user_id != 当前用户`):贴合用户「查看其他用户公开的穿搭」的表述,且避免与「我的穿搭」分段内容重复;后续如需包含自己,仅需去掉一个 WHERE 条件。
|
||||
3. **互动数据由后端批量聚合下发**(like_count / collect_count):现有穿搭列表在前端逐条请求 `/like/:uuid`(一页 20 条即 20 次请求),社区列表直接使用后端聚合值,杜绝该 N+1 问题。
|
||||
4. **后端批量组装杜绝 N+1**:复用 `buildOutfitListResponses` 的批量模式(一次性批量查明细 + 衣物),作者信息用已有 `UserGetByIDs`,点赞/收藏计数新增 `GROUP BY target_id` 批量方法;单页固定约 7 条 SQL,与页大小无关。
|
||||
5. **社区卡片复用现有拼图封面结构**(cover-item 循环)与卡片骨架,仅新增作者行与互动数据块,模板通过 `activeTab === 2` 条件渲染差异部分,避免大段重复。
|
||||
6. **仅社区分段隐藏入口按钮行**,「我的穿搭 / 已收藏」保持现状,控制改动面。
|
||||
|
||||
### 性能与可靠性
|
||||
|
||||
- 后端:分页 `page/page_size`(上限 50,`normalizePage` 规整),`ORDER BY id DESC` 走主键;批量计数对空列表短路,避免 `IN ()` 查询;错误统一返回现有错误码(19001 等),沿用 slog 日志风格。
|
||||
- 前端:`page_size=20`、切换分段重置并丢弃过期响应(沿用现有 reqSeq 序号防乱序机制);辅助字段(相对时间)本地计算零请求;失败不打断主流程,仅记录 code 不打印敏感信息。
|
||||
- 契约一致性:`created_at` 秒级时间戳(前端 `formatRelativeTime` 直接消费);`owner_avatar` 由后端 `upload.AvatarURL` 转为可访问 URL;`processed_image` 为完整 URL。
|
||||
|
||||
### 实施注意事项
|
||||
|
||||
- 后端仓库位于 `/root/zt-closet-backend`(不在前端工作区),当前存在未提交改动(收藏/通知修复),新代码只做追加、不动无关文件。
|
||||
- 后端改动需用户自行部署后,前端指向线上域名(BASE_URL)才能联调。
|
||||
- 前端不改 `app.json`、不改 `outfit-detail`、不改 tabBar;`outfit.json` 已引入所需组件,无需调整。
|
||||
- 复用 `isOutfitPublicVisible` 的可见性口径(公开 2 + 审核通过 2 + 状态正常 1),保证社区列表与详情页可见性判定一致。
|
||||
|
||||
## 目录结构
|
||||
|
||||
后端 `/root/zt-closet-backend/`:
|
||||
|
||||
```
|
||||
├── internal/dto/outfit.go # [MODIFY] 新增社区列表 DTO:OutfitCommunityListRequest(内嵌 PageRequest)/ OutfitCommunityListResponse(内嵌 PageResponse)/ OutfitCommunityItem(含 outfit_uuid、outfit_name、outfit_desc、scene、source、created_at、items、owner_name、owner_avatar、like_count、collect_count)
|
||||
├── internal/mysqldao/outfit.go # [MODIFY] 新增 OutfitListCommunity(ctx, excludeUserID, page, pageSize):查询 is_public=2 AND audit_status=2 AND status=1 AND user_id != 本人,Count + Order("id DESC") 分页,参照 OutfitListByUserID 写法
|
||||
├── internal/mysqldao/like.go # [MODIFY] 新增 LikeCountByTargets(ctx, likeType, targetIDs):SELECT target_id, COUNT(*) ... GROUP BY target_id(仅 status=1),空入参短路
|
||||
├── internal/mysqldao/collect.go # [MODIFY] 新增 CollectCountByTargets 批量计数(同上模式)
|
||||
├── internal/service/outfit.go # [MODIFY] 新增 CommunityList:normalizePage → 查列表 → 批量组装(复用 OutfitItemListByOutfitIDs + ClothesGetByIDs + UserGetByIDs + upload.AvatarURL + 批量计数),空列表直接返回空数组
|
||||
├── internal/routers/api/v1/outfit.go # [MODIFY] 新增 Community handler(GetUserID → ShouldBindQuery → svc → ToResponse,与现有 List 写法一致)
|
||||
├── internal/routers/router.go # [MODIFY] 鉴权组注册 auth.GET("/outfit/community", outfitHandler.Community)
|
||||
└── 接口文档.md # [MODIFY] 新增社区列表接口章节;修正 FAQ「没有社区广场接口」的过时说明
|
||||
```
|
||||
|
||||
前端 `/root/zt-closet-wxmini-frontend/`:
|
||||
|
||||
```
|
||||
└── miniprogram/
|
||||
├── types/models.ts # [MODIFY] 新增 CommunityOutfitItem 类型(与后端响应字段一一对应)
|
||||
└── pages/outfit/
|
||||
├── outfit.ts # [MODIFY] activeTab 扩展 0/1/2;fetchList 按分段选 /outfit、/collect、/outfit/community;社区项装饰(直接取 like_count/collect_count,计算相对时间 _time);onOutfitTap 社区项 owner=0;空态文案分支;日志沿用 logger
|
||||
├── outfit.wxml # [MODIFY] 分段控件增加「社区」;entry-row 在社区分段隐藏;卡片新增作者行(社区分段)与收藏数、相对时间;状态标签仅非社区分段展示;空态文案分支
|
||||
└── outfit.wxss # [MODIFY] 新增作者行、圆形头像(含 icon-user 占位)、昵称、时间、互动数据样式(延续现有 rpx 与色板)
|
||||
```
|
||||
|
||||
## 关键代码结构
|
||||
|
||||
后端响应契约(新增到 `internal/dto/outfit.go`):
|
||||
|
||||
```
|
||||
type OutfitCommunityListResponse struct {
|
||||
PageResponse
|
||||
List []OutfitCommunityItem `json:"list"`
|
||||
}
|
||||
|
||||
type OutfitCommunityItem struct {
|
||||
OutfitUUID string `json:"outfit_uuid"`
|
||||
OutfitName string `json:"outfit_name"`
|
||||
OutfitDesc string `json:"outfit_desc"`
|
||||
Scene string `json:"scene"`
|
||||
Source int8 `json:"source"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
Items []OutfitItemResponse `json:"items"`
|
||||
OwnerName string `json:"owner_name"`
|
||||
OwnerAvatar string `json:"owner_avatar"`
|
||||
LikeCount int64 `json:"like_count"`
|
||||
CollectCount int64 `json:"collect_count"`
|
||||
}
|
||||
```
|
||||
|
||||
前端类型(新增到 `types/models.ts`):
|
||||
|
||||
```ts
|
||||
export interface CommunityOutfitItem {
|
||||
outfit_uuid: string
|
||||
outfit_name: string
|
||||
outfit_desc: string
|
||||
scene: string
|
||||
source: number
|
||||
created_at: number
|
||||
items: { clothes_uuid: string; processed_image: string }[]
|
||||
owner_name: string
|
||||
owner_avatar: string
|
||||
like_count: number
|
||||
collect_count: number
|
||||
}
|
||||
```
|
||||
|
||||
## 设计风格
|
||||
|
||||
延续项目既有 iOS HIG 视觉语言:分组灰底 #F2F2F7、纯白卡片(圆角 32rpx)、0.5px 发丝分隔线、系统蓝 #007AFF 强调色、SF Symbols 风格线性图标,清爽克制、以内容为中心,社区分段与现有分段无缝衔接。
|
||||
|
||||
## 分段控件
|
||||
|
||||
胶囊分段由两项扩展为三项「我的穿搭 / 已收藏 / 社区」,三项等宽;选中项为白色滑块 + 系统蓝加粗文字,未选中为 #3C3C43;切换带轻量过渡,样式沿用现有 .segment 规格(高 64rpx、圆角 16rpx)。
|
||||
|
||||
## 社区卡片
|
||||
|
||||
- 作者行(新增):左侧 56rpx 圆形头像(无头像回退浅灰底 icon-user 占位),昵称 26rpx 深色单行省略,右侧相对时间 22rpx 灰字
|
||||
- 封面区:复用现有拼图 cover-item 错落摆放(最多 5 件)+ 右上角件数胶囊
|
||||
- 信息区:穿搭名 32rpx 加粗单行省略,描述 26rpx 灰字最多两行
|
||||
- 互动区(meta 行):左侧场景标签(tag-gray)与件数,右侧点赞(icon-heart)与收藏(icon-star)计数,图标 36rpx 灰字 22rpx,间距与现有卡片一致
|
||||
|
||||
## 状态设计
|
||||
|
||||
加载态复用骨架屏(sk-card 呼吸动画);社区空态复用 empty-state(title「还没有公开的穿搭」,desc「把喜欢的穿搭公开到社区,让大家看到你的搭配」,无按钮);列表底部「没有更多了」提示沿用现有样式;卡片按压态用现有 active 透明度反馈。
|
||||
|
||||
## Agent Extensions
|
||||
|
||||
### SubAgent
|
||||
|
||||
- **code-explorer**
|
||||
- Purpose: 后端仓库(117 个 Go 文件)实现社区接口前,跨文件梳理 like/collect 数据模型、批量计数与批量组装模式、DTO/Handler 既有写法,确保新代码完全复用现有模式
|
||||
- Expected outcome: 产出可复用的批量计数 SQL 模式与接口实现要点清单(表名、字段、既有工具函数位置),降低返工与不一致风险
|
||||
Reference in New Issue
Block a user