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

156 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 团队共创详情接口契约
> 适用端:`WonderQ-Admin`、`WonderQ-Admin-UI`、`WonderQ-MiniAPP`。
> 目标:复用 `HomeTeamBuilding` 表,维护首页团队共创卡片和沉浸式详情页内容。
## 领域边界
- 团队共创卡片和详情共用一条 `HomeTeamBuilding` 记录。
- 详情封面复用 `image`,不新增独立详情表或第二张 hero 图片。
- `detailSubtitle` 是详情首屏副标题。
- `detailParagraphs` 是按阅读顺序保存的正文段落数组。
- Admin UI 使用正文 textarea 的“空行分隔段落”约定;后端保存前会清洗首尾空白和空段落。
- 首页卡片仍保留 `demandKeyword`,但点击行为改为详情页;该字段仅作为其他需求入口的普通文案,不建立商品或订单外键。
## 数据类型
```ts
type HomeTeamBuilding = {
id: string;
tag: string;
title: string;
description: string;
image: string;
demandKeyword: string;
detailSubtitle: string;
detailParagraphs: string[];
isActive: boolean;
sortOrder: number;
createdAt: string;
updatedAt: string;
};
type HomeTeamBuildingCreate = {
tag: string;
title: string;
description: string;
image: string;
demandKeyword: string;
detailSubtitle?: string;
detailParagraphs?: string[];
isActive?: boolean;
sortOrder?: number;
};
type HomeTeamBuildingPatch = Partial<HomeTeamBuildingCreate>;
```
兼容规则:旧客户端不提交详情字段时,后端使用模型默认值;迁移 `0020_home_team_building_details` 会把已有记录的副标题回填为 `description`,正文回填为 `[description]`。Public 序列化时仍会对空值做相同 fallback。
## Admin API
前缀为 `/api/admin`,需要 `Authorization: Bearer <admin-jwt>`。既有列表、创建、编辑、删除和排序路径保持不变:
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| `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` | 调整团队共创顺序 |
创建或编辑请求示例:
```json
{
"tag": "户外挑战",
"title": "山野挑战,共创极境",
"description": "洞穴、瀑降与协作,适合 10-30 人。",
"image": "https://example.test/assets/team-building.jpg",
"demandKeyword": "户外团建",
"detailSubtitle": "越过山丘,向来处去",
"detailParagraphs": [
"真正的贵州,从未被写进流水线的攻略里。",
"把会议室换成山野,让团队重新认识彼此。"
],
"isActive": true
}
```
约束:
- 文本字段去除首尾空白后不得为空;详情副标题最大 160 字,正文最多 30 段。
- `detailParagraphs` 保存时过滤空段落;编辑接口显式传空正文会返回 `422`
- 图片只接受 HTTP(S) URL排序值为非负整数。
- 列表接口返回启用和停用记录,按 `sortOrder` 升序;删除和排序继续写审计日志。
- 迁移只新增两列,不改变旧字段和现有接口路径;本次实现不自动执行迁移。
## Public API
### 首页摘要
```http
GET /api/public/home
```
首页响应中的 `teamBuildings` 只返回卡片摘要:
```ts
type PublicHomeTeamBuildingSummary = {
id: string;
tag: string;
title: string;
description: string;
image: string;
demandKeyword: string;
};
```
### 详情
```http
GET /api/public/home/team-buildings/{teamBuildingId}
```
无需鉴权。成功响应:
```ts
type PublicHomeTeamBuildingDetail = PublicHomeTeamBuildingSummary & {
detailSubtitle: string;
detailParagraphs: string[];
};
```
错误响应:
| 状态码 | 场景 |
| --- | --- |
| `404` | ID 不存在或团队共创已停用 |
| `5xx` | 服务端异常MiniAPP 进入本地 fallback |
响应中的 `detailSubtitle` 为空时返回 `description``detailParagraphs` 为空时返回 `[description]`。Public API 不返回管理端状态、排序和审计字段。
## MiniAPP 联调约定
1. 首页通过 `/api/public/home` 加载团队共创卡片。
2. `openTeamBuilding(item)` 调用 `goTeamBuildingDetail(item.id)`,跳转 `/pages/team-buildings/detail?id={teamBuildingId}`
3. 详情页调用 `fetchPublicTeamBuildingDetail(teamBuildingId)`,成功后通过 `normalizeHomeTeamBuildingDetail` 归一化。
4. 请求失败时按 ID 查找 `homeTeamBuildingFallback`;命中则展示模拟网络图片、标题、副标题和正文,并提示“接口暂不可用,当前展示模拟数据”。
5. 无 ID、ID 不存在且无 fallback 时展示未找到状态,并提供返回首页操作。
6. 页面必须覆盖 loading、接口失败、空正文和未找到状态详情布局使用 TailwindCSS不新增页面级自定义样式。
## 三端联调顺序
1.`WonderQ-Admin` 执行 `python -m alembic upgrade head`,仅在确认目标数据库后执行。
2. 启动后端并验证 `GET /health`
3. 在 Admin UI 创建或编辑团队共创,填写详情副标题和正文;正文 textarea 使用空行分段。
4. 验证 Admin API 返回详情字段Public 首页只返回摘要。
5. 在 MiniAPP 首页点击团队共创卡片,确认 URL 携带正确 ID。
6. 验证详情接口成功展示最新内容;停止后端后确认按 ID fallback 并显示提示。
## 变更文件
- 后端:`WonderQ-Admin/app/models.py``app/schemas.py``app/serializers.py``app/routers/public.py``alembic/versions/0020_home_team_building_details.py`
- 管理端:`WonderQ-Admin-UI/src/api.ts``src/pages/structure/HomeContentPage.tsx``src/components/admin/HomeContentEditor.tsx``src/components/admin/HomeContentCardRail.tsx`
- 前台:`WonderQ-MiniAPP/src/pages/home/components/homeTeamBuildingData.ts``src/lib/types.ts``src/lib/api.ts``src/lib/navigation.ts``src/pages/home/index.vue``src/pages/team-buildings/detail.vue``src/pages.json`