feat: 新增客片案例与团队共创模块,重构玩法与配置

- 新增客片案例全流程功能,包含前台页面、管理端配置、后端API、数据库迁移与文档
- 新增团队共创详情页面与对应接口
- 重构玩法模块:将静态playData替换为动态API获取,拆分类型定义到playTypes.ts
- 优化vite构建配置与环境变量处理,调整详情页操作栏文案
- 更新全量相关文档与配图,新增客片案例、团队共创API文档
- 新增测试用例,完善数据归一化逻辑
- 调整路由配置与环境变量示例文件
This commit is contained in:
duanshuwen
2026-08-19 20:23:04 +08:00
parent cda8069630
commit 7ba92f3c5d
76 changed files with 7970 additions and 137 deletions

View File

@@ -2,15 +2,16 @@
> 适用端:`WonderQ-Admin`、`WonderQ-Admin-UI`。
>
> 状态:待实现契约。本文件参考 `WonderQ-MiniAPP/src/pages/home/components/homeExperienceData.ts`、`homeTeamBuildingData.ts` 和 `homeWildArchivesData.ts` 定义首页卡片内容,以及管理端需要的查询、维护和排序接口。它是首页内容的 Admin API 补充契约,不是 MiniAPP Public API 文档。
> 状态:已实现。本文件约定首页内容的 Admin API,并记录 MiniAPP 使用的对应 Public API。首页玩法推荐不复制玩法文案,而是关联 `WanfaCategory`。
## 领域边界
首页内容管理只维护三类首页卡片:
首页内容管理维护四类首页内容:
- 体验推荐:徽标、分类、标题、英文标题、封面和需求关键词。
- 团队共创:标签、标题、描述、封面和需求关键词。
- 极境视界:案例标题、封面和需求关键词。
- 团队共创:标签、标题、描述、封面、需求关键词、详情副标题和详情正文段落。
- 极境视界:案例标题、封面、详情图片和需求关键词;首页卡片可进入客片案例详情。
- 玩法推荐:已关联的玩法分类、启用状态和首页展示顺序;分类名称及路线由玩法领域维护。
本领域不负责:
@@ -20,7 +21,7 @@
`demandKeyword` 只是点击卡片后预填需求页的普通字符串,不是商品 ID、路线 ID、订单 ID,也不建立数据库外键。
当前首页仍直接使用三个文件中的 mock 数组。Admin API 接入前,这些数组继续作为前台 fallback;本文件不代表接口已经在 `WonderQ-Admin` 或 `WonderQ-Admin-UI` 中实现。
当前首页通过 `GET /api/public/home` 消费四类内容;三个卡片 mock 数组仍作为接口失败、空响应或字段缺失时的前台 fallback,玩法推荐无本地模拟数据时保持空态。Admin UI 通过本文件列出的 Admin API 维护正式数据。
## 接口清单
@@ -43,6 +44,20 @@ API 前缀为 `/api/admin`,除登录接口外均需要后台 JWT。
| `PATCH` | `/api/admin/home/wild-archives/{archiveId}` | 编辑极境视界案例 |
| `DELETE` | `/api/admin/home/wild-archives/{archiveId}` | 删除极境视界案例 |
| `PATCH` | `/api/admin/home/wild-archives/reorder` | 调整极境视界案例顺序 |
| `GET` | `/api/admin/home/play-recommendations` | 获取首页已关联的玩法分类 |
| `POST` | `/api/admin/home/play-recommendations` | 关联一个玩法分类到首页 |
| `PATCH` | `/api/admin/home/play-recommendations/{recommendationId}` | 修改关联的启用状态或玩法分类 |
| `DELETE` | `/api/admin/home/play-recommendations/{recommendationId}` | 移除首页玩法分类关联,不删除玩法分类 |
| `PATCH` | `/api/admin/home/play-recommendations/reorder` | 调整首页玩法推荐顺序 |
MiniAPP Public API:
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| `GET` | `/api/public/home` | 获取已启用的首页内容和玩法推荐 |
| `GET` | `/api/public/home/team-buildings/{teamBuildingId}` | 获取单个团队共创详情 |
| `GET` | `/api/public/home/wild-archives` | 获取客片案例更多列表 |
| `GET` | `/api/public/home/wild-archives/{archiveId}` | 获取单个客片案例详情 |
## 通用约定
@@ -112,6 +127,8 @@ type HomeTeamBuilding = {
description: string;
image: string;
demandKeyword: string;
detailSubtitle: string;
detailParagraphs: string[];
};
type HomeTeamBuildingRecord = HomeTeamBuilding & {
@@ -138,6 +155,7 @@ type HomeWildArchive = {
id: string;
title: string;
image: string;
images: string[];
demandKeyword: string;
};
@@ -183,8 +201,11 @@ type HomeReorderRequest = {
| 团队共创 | `description` | `string` | 是 | 卡片描述,去除首尾空白后不得为空。 |
| 团队共创 | `image` | `string` | 是 | 可直接用于图片组件的封面 URL。 |
| 团队共创 | `demandKeyword` | `string` | 是 | 点击后预填需求页的关键词。 |
| 团队共创 | `detailSubtitle` | `string` | 是 | 详情页首屏副标题;旧数据回退为 `description`。 |
| 团队共创 | `detailParagraphs` | `string[]` | 是 | 详情页正文段落;至少一段,旧数据回退为 `[description]`。 |
| 极境视界 | `title` | `string` | 是 | 案例标题,去除首尾空白后不得为空。 |
| 极境视界 | `image` | `string` | 是 | 案例图片 URL。 |
| 极境视界 | `image` | `string` | 是 | 案例封面图片 URL。 |
| 极境视界 | `images` | `string[]` | 是 | 案例详情图片 URL 列表,至少一张;第一张建议与封面一致。 |
| 极境视界 | `demandKeyword` | `string` | 是 | 点击后预填需求页的关键词。 |
| 全部资源 | `isActive` | `boolean` | 响应必填 | 是否进入已发布前台内容,创建默认 `true`。 |
| 全部资源 | `sortOrder` | `number` | 响应必填 | 非负整数,数值越小越靠前。 |
@@ -254,6 +275,57 @@ Content-Type: application/json
成功响应为 `{ "items": [] }`,其中 `items` 是更新 `sortOrder` 后的完整记录列表。缺少 ID、包含未知 ID 或出现重复 ID 时返回 `400 HOME_REORDER_INVALID`。
### MiniAPP Public API
```http
GET /api/public/home
```
无需鉴权。接口只返回 `isActive === true` 的记录,首页卡片和玩法推荐分别按 `sortOrder` 升序返回,并移除管理端状态、排序和审计时间字段:
```ts
type PublicHomeResponse = {
experiences: HomeExperience[];
teamBuildings: HomeTeamBuilding[];
wildArchives: HomeWildArchive[];
playRecommendations: HomeWanfaRecommendation[];
};
type HomeWanfaRecommendation = {
id: string;
categoryId: string;
label: string;
routes: WanfaRoute[];
};
type WanfaRoute = {
id: string;
title: string;
subtitle: string;
image: string;
routeCount: number;
demandKeyword: string;
};
```
四组列表始终返回数组;没有可用内容时返回空数组。玩法推荐只返回启用的关联记录,并展开关联分类当前的路线。MiniAPP 应在数据层归一化字段并保留对应 mock fallback,不在页面组件内直接请求接口。
### 玩法推荐关联
`POST /api/admin/home/play-recommendations` 请求体:
```ts
type HomeWanfaRecommendationCreate = {
categoryId: string;
isActive?: boolean;
sortOrder?: number;
};
type HomeWanfaRecommendationPatch = Partial<HomeWanfaRecommendationCreate>;
```
Admin 响应记录包含 `id`、`categoryId`、`categoryLabel`、`routeCount`、`isActive`、`sortOrder`、`createdAt` 和 `updatedAt`。同一个玩法分类只能关联一次;分类不存在或已关联时分别返回 `404` 或 `409 HOME_WANFA_CATEGORY_DUPLICATE`。移除关联不会删除 `WanfaCategory` 或其路线。被首页推荐关联的玩法分类不能直接删除,需先移除首页关联。
## 当前 fallback 与迁移映射
迁移初始数据时应保留以下稳定 ID、字段值和当前数组顺序:
@@ -306,16 +378,17 @@ POST /api/admin/media-assets/upload
## Admin UI 对接要求
1. 进入首页内容管理时分别请求三个列表接口,按 `sortOrder` 渲染对应分组。
1. 进入首页内容管理时请求三类首页卡片列表,并同时请求玩法分类和首页玩法推荐关联,按 `sortOrder` 渲染对应分组。
2. 体验推荐表单维护 `badge`、`category`、`title`、`englishTitle`、`image` 和 `demandKeyword`。
3. 团队共创表单维护 `tag`、`title`、`description`、`image` 和 `demandKeyword`。
4. 极境视界表单维护 `title`、`image` 和 `demandKeyword`。
5. 三类资源都提供启用/停用、编辑、删除和上移/下移操作;排序时提交完整 ID 列表。
3. 团队共创表单维护 `tag`、`title`、`description`、`image`、`demandKeyword`、`detailSubtitle` 和 `detailParagraphs`;正文使用空行分隔多个段落。
4. 极境视界表单维护 `title`、`image`、`images` 和 `demandKeyword`;详情图片按一行一个 URL 编辑。
5. 三类首页卡片提供启用/停用、编辑、删除和上移/下移操作;玩法推荐提供启用/停用、移除和上移/下移操作;排序时提交完整 ID 列表。
6. 每次变更成功后以接口返回的记录或列表更新本地状态,不直接假设本地修改已经保存。
7. 删除前要求二次确认;删除成功后接受服务端返回的重新排序结果。
8. 处理 `401`、`404`、`409`、`422` 和 `5xx`,保存、上传和排序进行中禁用重复提交。
9. 不在首页表单中出现 Product ID、ProductImage ID、价格、库存、订单或预订字段。
10. 预览点击行为使用 `demandKeyword`;该字段为空时禁止提交,而不是由前端猜测或拼接商品标识。
11. 玩法推荐管理应先加载玩法分类,再加载首页关联;新增只能从未关联分类中选择,移除只取消关联,不能删除玩法分类。
建议的 Admin UI API 封装函数:
@@ -337,20 +410,51 @@ createHomeWildArchive(input: HomeWildArchiveCreate);
updateHomeWildArchive(archiveId: string, input: HomeWildArchivePatch);
deleteHomeWildArchive(archiveId: string);
reorderHomeWildArchives(itemIds: string[]);
getHomeWanfaRecommendations();
createHomeWanfaRecommendation(input: HomeWanfaRecommendationCreate);
updateHomeWanfaRecommendation(recommendationId: string, input: HomeWanfaRecommendationPatch);
deleteHomeWanfaRecommendation(recommendationId: string);
reorderHomeWanfaRecommendations(itemIds: string[]);
```
当前首页的“查看更多”按钮固定跳转需求关键词“极境视界”,不属于 `HomeWildArchive` 记录字段;如果未来需要后台配置该按钮,应另行增加首页 CTA 配置契约。
当前首页的“查看更多”按钮跳转客片案例列表;首页案例卡片跳转 `/pages/wild-archives/detail?id={archiveId}`,不再跳转需求页。
## 前后台数据边界
- Admin API 返回启用和停用的完整记录,供管理端维护。
- 未来 Public API 只返回已发布且启用的首页内容;Public API 的响应字段应与本契约的渲染字段兼容,但不应暴露 `createdAt`、`updatedAt` 等管理元数据。
- MiniAPP 接入时再同步更新 `src/lib/types.ts`、`src/lib/data.ts`、首页组件和 `docs/public-api.md`;本次文档不改变现有 mock 消费路径。
- MiniAPP 已在 `src/lib/api.ts`、`src/lib/types.ts` 和 `src/lib/store.ts` 接入 Public API;首页组件通过共享状态消费归一化后的四类内容,玩法推荐按关联分类展示。
- 后端不得把 `demandKeyword` 解析成 Product 或订单关联;如需线路、详情或预订能力,应另立领域契约。
## 团队共创详情
团队共创首页卡片点击后跳转 MiniAPP `/pages/team-buildings/detail?id={teamBuildingId}`,详情页再按 ID 请求 Public API。首页接口只返回卡片摘要,不携带正文段落。
```http
GET /api/public/home/team-buildings/{teamBuildingId}
```
成功响应在首页摘要基础上增加详情字段:
```ts
type PublicHomeTeamBuildingDetail = HomeTeamBuilding & {
detailSubtitle: string;
detailParagraphs: string[];
};
```
规则:
- 仅返回 `isActive === true` 的团队共创;不存在或已停用返回 `404`。
- `detailSubtitle` 为空时回退为 `description`。
- `detailParagraphs` 为空时回退为 `[description]`。
- MiniAPP 请求失败时按 `teamBuildingId` 使用本地模拟详情,并提示当前为模拟数据;找不到对应 fallback 时展示未找到状态。
- 详情封面复用 `image` 字段,不新增独立 hero 图片或详情表。
## 后端落地边界
本契约落地时需要由 `WonderQ-Admin` 补充对应 ORM 模型、迁移、schema、路由、序列化和审计日志;由 `WonderQ-Admin-UI` 补充 API 类型、请求封装、首页内容列表、表单、图片上传和排序交互。当前后端没有 `/api/admin/home/*` 路由,Admin UI 也未接入这三类首页数据。
当前实现由 `WonderQ-Admin` 提供三张首页内容表、`HomeWanfaRecommendation` 关联表、`0017_home_content`、`0018_home_wanfa_recommendations`、`0019_home_wild_archive_images` 与 `0020_home_team_building_details` 迁移、schema、Admin/Public 路由、序列化和审计日志;由 `WonderQ-Admin-UI` 提供首页玩法推荐入口、分类关联、启停、移除、排序、客片详情图片和团队共创详情维护;由 `WonderQ-MiniAPP` 调用 `/api/public/home`、团队共创详情和客片案例列表/详情接口。
相关文档:
@@ -359,4 +463,5 @@ reorderHomeWildArchives(itemIds: string[]);
- [Public API 契约](./public-api.md)
- [体验推荐数据](../WonderQ-MiniAPP/src/pages/home/components/homeExperienceData.ts)
- [团队共创数据](../WonderQ-MiniAPP/src/pages/home/components/homeTeamBuildingData.ts)
- [团队共创详情接口](./team-building-api.md)
- [极境视界数据](../WonderQ-MiniAPP/src/pages/home/components/homeWildArchivesData.ts)