- 新增客片案例全流程功能,包含前台页面、管理端配置、后端API、数据库迁移与文档 - 新增团队共创详情页面与对应接口 - 重构玩法模块:将静态playData替换为动态API获取,拆分类型定义到playTypes.ts - 优化vite构建配置与环境变量处理,调整详情页操作栏文案 - 更新全量相关文档与配图,新增客片案例、团队共创API文档 - 新增测试用例,完善数据归一化逻辑 - 调整路由配置与环境变量示例文件
468 lines
20 KiB
Markdown
468 lines
20 KiB
Markdown
# 首页内容管理 Admin API
|
||
|
||
> 适用端:`WonderQ-Admin`、`WonderQ-Admin-UI`。
|
||
>
|
||
> 状态:已实现。本文件约定首页内容的 Admin API,并记录 MiniAPP 使用的对应 Public API。首页玩法推荐不复制玩法文案,而是关联 `WanfaCategory`。
|
||
|
||
## 领域边界
|
||
|
||
首页内容管理维护四类首页内容:
|
||
|
||
- 体验推荐:徽标、分类、标题、英文标题、封面和需求关键词。
|
||
- 团队共创:标签、标题、描述、封面、需求关键词、详情副标题和详情正文段落。
|
||
- 极境视界:案例标题、封面、详情图片和需求关键词;首页卡片可进入客片案例详情。
|
||
- 玩法推荐:已关联的玩法分类、启用状态和首页展示顺序;分类名称及路线由玩法领域维护。
|
||
|
||
本领域不负责:
|
||
|
||
- 顶部轮播、车辆选项、需求表单或其他站点模块;这些内容遵循 [Admin API 主契约](./admin-api-requirements.md)。
|
||
- 商品、Product、ProductImage、详情、价格、库存、订单或预订。
|
||
- 线索创建和线索跟进。
|
||
|
||
`demandKeyword` 只是点击卡片后预填需求页的普通字符串,不是商品 ID、路线 ID、订单 ID,也不建立数据库外键。
|
||
|
||
当前首页通过 `GET /api/public/home` 消费四类内容;三个卡片 mock 数组仍作为接口失败、空响应或字段缺失时的前台 fallback,玩法推荐无本地模拟数据时保持空态。Admin UI 通过本文件列出的 Admin API 维护正式数据。
|
||
|
||
## 接口清单
|
||
|
||
API 前缀为 `/api/admin`,除登录接口外均需要后台 JWT。
|
||
|
||
| 方法 | 路径 | 用途 |
|
||
| --- | --- | --- |
|
||
| `GET` | `/api/admin/home/experiences` | 获取全部体验推荐卡片 |
|
||
| `POST` | `/api/admin/home/experiences` | 新增体验推荐卡片 |
|
||
| `PATCH` | `/api/admin/home/experiences/{experienceId}` | 编辑体验推荐卡片 |
|
||
| `DELETE` | `/api/admin/home/experiences/{experienceId}` | 删除体验推荐卡片 |
|
||
| `PATCH` | `/api/admin/home/experiences/reorder` | 调整体验推荐卡片顺序 |
|
||
| `GET` | `/api/admin/home/team-buildings` | 获取全部团队共创卡片 |
|
||
| `POST` | `/api/admin/home/team-buildings` | 新增团队共创卡片 |
|
||
| `PATCH` | `/api/admin/home/team-buildings/{teamBuildingId}` | 编辑团队共创卡片 |
|
||
| `DELETE` | `/api/admin/home/team-buildings/{teamBuildingId}` | 删除团队共创卡片 |
|
||
| `PATCH` | `/api/admin/home/team-buildings/reorder` | 调整团队共创卡片顺序 |
|
||
| `GET` | `/api/admin/home/wild-archives` | 获取全部极境视界案例 |
|
||
| `POST` | `/api/admin/home/wild-archives` | 新增极境视界案例 |
|
||
| `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}` | 获取单个客片案例详情 |
|
||
|
||
## 通用约定
|
||
|
||
- 请求和响应使用 JSON,字段使用 camelCase。
|
||
- 所有管理接口需要 `Authorization: Bearer <admin-jwt>`。
|
||
- `GET` 返回启用和停用的全部记录,按 `sortOrder` 升序返回,供 Admin UI 完整维护。
|
||
- 创建、编辑、删除和排序成功后写入审计日志,再提交事务。
|
||
- 创建和编辑返回最新记录;排序接口返回排序后的 `items`。
|
||
- ID 由后端生成并作为非空字符串返回。初始化迁移时应优先保留三个 mock 文件中的稳定 ID。
|
||
- 空集合返回 `[]`,不能返回 `null` 或省略字段。
|
||
- 所有资源的 `sortOrder` 从 `0` 开始,数值越小越靠前;新增未传排序时追加到末尾。
|
||
- 失败响应沿用 Admin API 主契约,包含 `message`、`code` 和可选的 `details`。
|
||
|
||
## 数据类型
|
||
|
||
### 体验推荐
|
||
|
||
`homeExperienceData.ts` 已包含前台渲染类型和 API 过渡类型。Admin API 的完整记录应补充管理元数据:
|
||
|
||
```ts
|
||
type HomeExperience = {
|
||
id: string;
|
||
badge: string;
|
||
category: string;
|
||
title: string;
|
||
englishTitle: string;
|
||
image: string;
|
||
demandKeyword: string;
|
||
};
|
||
|
||
type HomeExperienceApiItem = {
|
||
id?: string | null;
|
||
badge?: string | null;
|
||
category?: string | null;
|
||
title?: string | null;
|
||
englishTitle?: string | null;
|
||
image?: string | null;
|
||
demandKeyword?: string | null;
|
||
isActive?: boolean | null;
|
||
sortOrder?: number | null;
|
||
};
|
||
|
||
type HomeExperienceRecord = HomeExperience & {
|
||
isActive: boolean;
|
||
sortOrder: number;
|
||
createdAt: string;
|
||
updatedAt: string;
|
||
};
|
||
|
||
type HomeExperienceCreate = Omit<HomeExperience, "id"> & {
|
||
isActive?: boolean;
|
||
sortOrder?: number;
|
||
};
|
||
|
||
type HomeExperiencePatch = Partial<HomeExperienceCreate>;
|
||
```
|
||
|
||
### 团队共创
|
||
|
||
`homeTeamBuildingData.ts` 当前只包含前台渲染字段,管理端记录增加状态、排序和审计时间:
|
||
|
||
```ts
|
||
type HomeTeamBuilding = {
|
||
id: string;
|
||
tag: string;
|
||
title: string;
|
||
description: string;
|
||
image: string;
|
||
demandKeyword: string;
|
||
detailSubtitle: string;
|
||
detailParagraphs: string[];
|
||
};
|
||
|
||
type HomeTeamBuildingRecord = HomeTeamBuilding & {
|
||
isActive: boolean;
|
||
sortOrder: number;
|
||
createdAt: string;
|
||
updatedAt: string;
|
||
};
|
||
|
||
type HomeTeamBuildingCreate = Omit<HomeTeamBuilding, "id"> & {
|
||
isActive?: boolean;
|
||
sortOrder?: number;
|
||
};
|
||
|
||
type HomeTeamBuildingPatch = Partial<HomeTeamBuildingCreate>;
|
||
```
|
||
|
||
### 极境视界
|
||
|
||
`homeWildArchivesData.ts` 当前只包含前台渲染字段,管理端记录增加状态、排序和审计时间:
|
||
|
||
```ts
|
||
type HomeWildArchive = {
|
||
id: string;
|
||
title: string;
|
||
image: string;
|
||
images: string[];
|
||
demandKeyword: string;
|
||
};
|
||
|
||
type HomeWildArchiveRecord = HomeWildArchive & {
|
||
isActive: boolean;
|
||
sortOrder: number;
|
||
createdAt: string;
|
||
updatedAt: string;
|
||
};
|
||
|
||
type HomeWildArchiveCreate = Omit<HomeWildArchive, "id"> & {
|
||
isActive?: boolean;
|
||
sortOrder?: number;
|
||
};
|
||
|
||
type HomeWildArchivePatch = Partial<HomeWildArchiveCreate>;
|
||
```
|
||
|
||
列表响应和排序请求统一使用以下结构:
|
||
|
||
```ts
|
||
type HomeListResponse<T> = {
|
||
items: T[];
|
||
};
|
||
|
||
type HomeReorderRequest = {
|
||
itemIds: string[];
|
||
};
|
||
```
|
||
|
||
## 字段约束
|
||
|
||
| 资源 | 字段 | 类型 | 必填 | 约束和用途 |
|
||
| --- | --- | --- | --- | --- |
|
||
| 体验推荐 | `badge` | `string` | 是 | 卡片徽标,去除首尾空白后不得为空。 |
|
||
| 体验推荐 | `category` | `string` | 是 | 体验分类文案,去除首尾空白后不得为空。 |
|
||
| 体验推荐 | `title` | `string` | 是 | 卡片主标题,去除首尾空白后不得为空。 |
|
||
| 体验推荐 | `englishTitle` | `string` | 是 | 卡片英文标题,去除首尾空白后不得为空。 |
|
||
| 体验推荐 | `image` | `string` | 是 | 可直接用于图片组件的封面 URL。 |
|
||
| 体验推荐 | `demandKeyword` | `string` | 是 | 点击后预填需求页的关键词。 |
|
||
| 团队共创 | `tag` | `string` | 是 | 卡片标签,去除首尾空白后不得为空。 |
|
||
| 团队共创 | `title` | `string` | 是 | 卡片标题,去除首尾空白后不得为空。 |
|
||
| 团队共创 | `description` | `string` | 是 | 卡片描述,去除首尾空白后不得为空。 |
|
||
| 团队共创 | `image` | `string` | 是 | 可直接用于图片组件的封面 URL。 |
|
||
| 团队共创 | `demandKeyword` | `string` | 是 | 点击后预填需求页的关键词。 |
|
||
| 团队共创 | `detailSubtitle` | `string` | 是 | 详情页首屏副标题;旧数据回退为 `description`。 |
|
||
| 团队共创 | `detailParagraphs` | `string[]` | 是 | 详情页正文段落;至少一段,旧数据回退为 `[description]`。 |
|
||
| 极境视界 | `title` | `string` | 是 | 案例标题,去除首尾空白后不得为空。 |
|
||
| 极境视界 | `image` | `string` | 是 | 案例封面图片 URL。 |
|
||
| 极境视界 | `images` | `string[]` | 是 | 案例详情图片 URL 列表,至少一张;第一张建议与封面一致。 |
|
||
| 极境视界 | `demandKeyword` | `string` | 是 | 点击后预填需求页的关键词。 |
|
||
| 全部资源 | `isActive` | `boolean` | 响应必填 | 是否进入已发布前台内容,创建默认 `true`。 |
|
||
| 全部资源 | `sortOrder` | `number` | 响应必填 | 非负整数,数值越小越靠前。 |
|
||
| 全部资源 | `createdAt` | `string` | 响应必填 | ISO 8601 创建时间。 |
|
||
| 全部资源 | `updatedAt` | `string` | 响应必填 | ISO 8601 最后更新时间。 |
|
||
|
||
服务端应校验所有必填文本、URL 格式和非负整数排序值;具体文本最大长度由后端 schema 统一定义,并同步到 Admin UI 表单校验。图片字段只保存最终 URL,不接受 base64,不在首页内容记录中保存图片二进制。
|
||
|
||
## 接口详情
|
||
|
||
以下规则适用于三类资源;路径中的资源名和 ID 参数以接口清单为准。
|
||
|
||
### 获取列表
|
||
|
||
```http
|
||
GET /api/admin/home/experiences
|
||
Authorization: Bearer <admin-jwt>
|
||
```
|
||
|
||
团队共创和极境视界分别使用 `/api/admin/home/team-buildings`、`/api/admin/home/wild-archives`。
|
||
|
||
成功响应示例:
|
||
|
||
```json
|
||
{
|
||
"items": [
|
||
{
|
||
"id": "waterfall-descent",
|
||
"badge": "玩过推荐",
|
||
"category": "瀑降体验",
|
||
"title": "悬崖瀑降",
|
||
"englishTitle": "WATERFALL DESCENT",
|
||
"image": "https://example.test/assets/waterfall-descent.jpg",
|
||
"demandKeyword": "悬崖瀑降",
|
||
"isActive": true,
|
||
"sortOrder": 0,
|
||
"createdAt": "2026-01-01T00:00:00Z",
|
||
"updatedAt": "2026-01-01T00:00:00Z"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
接口返回启用和停用的全部记录;Admin UI 负责显示状态,不能让后端默认隐藏停用记录。
|
||
|
||
### 新增、编辑与删除
|
||
|
||
- `POST /api/admin/home/{resource}`:请求体为对应资源的 `Create` 类型,成功返回 `201` 和新建记录;未传 `sortOrder` 时追加到末尾。
|
||
- `PATCH /api/admin/home/{resource}/{id}`:请求体为对应资源的 `Patch` 类型,只更新提交字段;成功返回更新后的记录,不存在返回 `404`。
|
||
- `DELETE /api/admin/home/{resource}/{id}`:成功返回 `{ "id": "..." }`,删除后重新规范化同一资源剩余记录的 `sortOrder`。
|
||
|
||
其中 `{resource}` 只能是 `experiences`、`team-buildings` 或 `wild-archives`;对应路径参数分别为 `experienceId`、`teamBuildingId`、`archiveId`。删除不触发商品、订单、预订或线索级联操作。
|
||
|
||
### 调整顺序
|
||
|
||
```http
|
||
PATCH /api/admin/home/experiences/reorder
|
||
Authorization: Bearer <admin-jwt>
|
||
Content-Type: application/json
|
||
```
|
||
|
||
团队共创和极境视界分别使用 `/api/admin/home/team-buildings/reorder`、`/api/admin/home/wild-archives/reorder`。请求必须完整包含当前资源的全部 ID,不能重复:
|
||
|
||
```json
|
||
{ "itemIds": ["cave-exploration", "waterfall-descent"] }
|
||
```
|
||
|
||
成功响应为 `{ "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、字段值和当前数组顺序:
|
||
|
||
### 体验推荐
|
||
|
||
| 顺序 | ID | 标题 | 需求关键词 |
|
||
| --- | --- | --- | --- |
|
||
| 0 | `waterfall-descent` | 悬崖瀑降 | 悬崖瀑降 |
|
||
| 1 | `cave-exploration` | 森林&探洞 | 地心探险 |
|
||
|
||
`homeExperienceData.ts` 当前的 `normalizeHomeExperiences` 具有以下过渡行为:
|
||
|
||
- `isActive === false` 的 API 项被过滤。
|
||
- 缺少有效 `title` 的 API 项被过滤。
|
||
- 其余项目按 `sortOrder` 升序排列,未传排序时保持 API 原顺序。
|
||
- 文案和图片字段为空时使用当前 fallback 对应位置的值。
|
||
- API 没有有效项目时返回当前 `homeExperienceMocks` 的副本。
|
||
|
||
这些规则用于前台接入过渡,不应替代服务端校验。后端返回正式记录后,Admin UI 应提交完整字段,避免依赖位置 fallback。
|
||
|
||
### 团队共创
|
||
|
||
| 顺序 | ID | 标题 | 需求关键词 |
|
||
| --- | --- | --- | --- |
|
||
| 0 | `wild-challenge` | 山野挑战,共创极境 | 户外团建 |
|
||
| 1 | `canyon-teamwork` | 峡谷溯溪,默契同行 | 峡谷团建 |
|
||
| 2 | `village-gathering` | 苗寨共聚,认识彼此 | 贵州团建 |
|
||
|
||
### 极境视界
|
||
|
||
| 顺序 | ID | 标题 | 需求关键词 |
|
||
| --- | --- | --- | --- |
|
||
| 0 | `hundred-meter-descent` | 百米自降 | 悬崖瀑降 |
|
||
| 1 | `shilong-cave` | 石龙洞 | 地心探险 |
|
||
| 2 | `cliff-current` | 绝壁迎流 | 峡谷探险 |
|
||
| 3 | `canyon-streaming` | 峡谷溯溪 | 峡谷溯溪 |
|
||
|
||
三个 mock 文件中的图片 URL 只作为初始化内容来源。正式数据应通过媒体上传接口获得最终 URL;不要把 mock 文件中的远程图片地址当成图片存储协议。
|
||
|
||
## 图片与素材
|
||
|
||
Admin UI 使用现有素材上传接口获取图片 URL:
|
||
|
||
```http
|
||
POST /api/admin/media-assets/upload
|
||
```
|
||
|
||
建议首页内容使用 `group=home`,上传成功后将返回的 `url` 写入对应的 `image` 字段。接口只保存 URL,不接受 base64,也不创建 ProductImage 或商品图片关联。
|
||
|
||
## Admin UI 对接要求
|
||
|
||
1. 进入首页内容管理时请求三类首页卡片列表,并同时请求玩法分类和首页玩法推荐关联,按 `sortOrder` 渲染对应分组。
|
||
2. 体验推荐表单维护 `badge`、`category`、`title`、`englishTitle`、`image` 和 `demandKeyword`。
|
||
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 封装函数:
|
||
|
||
```ts
|
||
getHomeExperiences();
|
||
createHomeExperience(input: HomeExperienceCreate);
|
||
updateHomeExperience(experienceId: string, input: HomeExperiencePatch);
|
||
deleteHomeExperience(experienceId: string);
|
||
reorderHomeExperiences(itemIds: string[]);
|
||
|
||
getHomeTeamBuildings();
|
||
createHomeTeamBuilding(input: HomeTeamBuildingCreate);
|
||
updateHomeTeamBuilding(teamBuildingId: string, input: HomeTeamBuildingPatch);
|
||
deleteHomeTeamBuilding(teamBuildingId: string);
|
||
reorderHomeTeamBuildings(itemIds: string[]);
|
||
|
||
getHomeWildArchives();
|
||
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[]);
|
||
```
|
||
|
||
当前首页的“查看更多”按钮跳转客片案例列表;首页案例卡片跳转 `/pages/wild-archives/detail?id={archiveId}`,不再跳转需求页。
|
||
|
||
## 前后台数据边界
|
||
|
||
- Admin API 返回启用和停用的完整记录,供管理端维护。
|
||
- 未来 Public API 只返回已发布且启用的首页内容;Public API 的响应字段应与本契约的渲染字段兼容,但不应暴露 `createdAt`、`updatedAt` 等管理元数据。
|
||
- 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` 提供三张首页内容表、`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`、团队共创详情和客片案例列表/详情接口。
|
||
|
||
相关文档:
|
||
|
||
- [Admin API 主契约](./admin-api-requirements.md)
|
||
- [页面模块配置契约](./module-config-api.md)
|
||
- [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)
|