docs: 清理过时文档,新增首页API契约并更新相关内容

- 删除backend-plan.md、backend-api-service.md等多份过时项目文档
- 新增home-api.md规范首页三类内容的Admin API补充契约
- 更新docs/README.md的文档清单与展示格式
- 优化integration-workflow.md、admin-api-requirements.md等文档的表格与内容
- 为WonderQ-MiniAPP的homeExperienceData.ts新增API适配类型与归一化函数
This commit is contained in:
duanshuwen
2026-08-18 20:00:25 +08:00
parent ca6f9397e0
commit cda8069630
11 changed files with 475 additions and 512 deletions

View File

@@ -6,24 +6,22 @@
后端开发:
1. `backend-api-service.md`
2. `backend-plan.md`
3. `admin-api-requirements.md`
4. `wanfa-api.md`
5. `concierge-api.md`
6. `detail-api.md`
7. `module-config-api.md`
8. `public-api.md`
1. `admin-api-requirements.md`
2. `home-api.md`
3. `wanfa-api.md`
4. `concierge-api.md`
5. `detail-api.md`
6. `public-api.md`
管理前端开发:
1. `integration-workflow.md`
2. `admin-api-requirements.md`
3. `wanfa-api.md`
4. `concierge-api.md`
5. `detail-api.md`
6. `module-config-api.md`
7. `development-status.md`
3. `home-api.md`
4. `wanfa-api.md`
5. `concierge-api.md`
6. `detail-api.md`
7. `module-config-api.md`
MiniAPP 前台开发:
@@ -33,24 +31,26 @@ MiniAPP 前台开发:
## 文档清单
| 文档 | 作用 | 主要读者 |
| --- | --- | --- |
| `integration-workflow.md` | 三端本地启动、联调顺序、接口变更流程和验证命令 | 全部 |
| `development-status.md` | 三端能力对接状态矩阵和优先联调路径 | 全部 |
| `decisions.md` | 当前有效技术和文档决策 | 全部 |
| `backend-api-service.md` | 后端 API 服务运行与前端联调说明 | 后端 |
| `backend-plan.md` | 当前 FastAPI 后端定位、业务模块、近期优先级和安全部署原则 | 后端 |
| `admin-api-requirements.md` | Admin UI 必需的 Admin API 主契约 | 后端、管理前端 |
| `module-config-api.md` | 页面模块配置 CRUD 的唯一细节契约 | 后端、管理前端 |
| `wanfa-api.md` | 玩法分类和路线管理 API 的补充契约 | 后端、管理前端 |
| `concierge-api.md` | 管家顾问资料管理 API 的补充契约 | 后端、管理前端 |
| `detail-api.md` | 详情展示内容管理 API 的补充契约 | 后端、管理前端 |
| `public-api.md` | MiniAPP 对接后端的 Public API 契约 | 后端、MiniAPP |
| 文档 | 作用 | 主要读者 |
| --------------------------- | --------------------------------------------------------- | -------------- |
| `integration-workflow.md` | 三端本地启动、联调顺序、接口变更流程和验证命令 | 全部 |
| `development-status.md` | 三端能力对接状态矩阵和优先联调路径 | 全部 |
| `decisions.md` | 当前有效技术和文档决策 | 全部 |
| `backend-api-service.md` | 后端 API 服务运行与前端联调说明 | 后端 |
| `backend-plan.md` | 当前 FastAPI 后端定位、业务模块、近期优先级和安全部署原则 | 后端 |
| `admin-api-requirements.md` | Admin UI 必需的 Admin API 主契约 | 后端、管理前端 |
| `module-config-api.md` | 页面模块配置 CRUD 的唯一细节契约 | 后端、管理前端 |
| `home-api.md` | 首页体验、团队共创和极境视界内容的 Admin API 补充契约 | 后端、管理前端 |
| `wanfa-api.md` | 玩法分类和路线管理 API 的补充契约 | 后端、管理前端 |
| `concierge-api.md` | 管家顾问资料管理 API 的补充契约 | 后端、管理前端 |
| `detail-api.md` | 详情展示内容管理 API 的补充契约 | 后端、管理前端 |
| `public-api.md` | MiniAPP 对接后端的 Public API 契约 | 后端、MiniAPP |
## 文档边界
- `public-api.md` 是 MiniAPP 对接后端的唯一 Public API 契约。
- `admin-api-requirements.md` 是 Admin UI 对接后端的主契约。
- `home-api.md` 是首页内容管理的 Admin API 补充契约。
- `wanfa-api.md` 是玩法分类和路线管理的 Admin API 补充契约。
- `concierge-api.md` 是管家顾问资料管理的 Admin API 补充契约。
- `detail-api.md` 是详情展示内容管理的 Admin API 补充契约。

View File

@@ -8,6 +8,8 @@
详情展示内容的字段、图片、排序与商品领域隔离约束见 [detail-api.md](./detail-api.md)。该文档是本主契约的详情领域补充,适用端为 `WonderQ-Admin` 和 `WonderQ-Admin-UI`。
首页体验、团队共创和极境视界内容的字段、图片、排序与商品领域隔离约束见 [home-api.md](./home-api.md)。该文档是本主契约的首页内容补充,适用端为 `WonderQ-Admin` 和 `WonderQ-Admin-UI`。
## 通用约定
- API 前缀:`/api/admin`。
@@ -18,22 +20,22 @@
## 接口清单
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| `POST` | `/api/admin/auth/login` | 后台登录 |
| `GET` | `/api/admin/me` | 当前后台用户 |
| `GET` | `/api/admin/dashboard` | 工作台统计和最近线索 |
| `GET` | `/api/admin/site-config` | 获取全部站点配置 |
| `POST` | `/api/admin/site-config/{module}` | 新增模块项 |
| `PATCH` | `/api/admin/site-config/{module}/{id}` | 更新模块项 |
| `DELETE` | `/api/admin/site-config/{module}/{id}` | 删除模块项 |
| `PATCH` | `/api/admin/site-config/{module}/reorder` | 调整排序 |
| `GET` | `/api/admin/leads` | 线索列表 |
| `PATCH` | `/api/admin/leads/{id}/status` | 更新线索状态 |
| `GET` | `/api/admin/media-assets` | 素材列表 |
| `POST` | `/api/admin/media-assets/upload` | 上传图片 |
| `POST` | `/api/admin/reset-guizhou-content` | 重置站点内容 |
| `POST` | `/api/admin/publish` | 发布站点快照 |
| 方法 | 路径 | 用途 |
| -------- | ----------------------------------------- | -------------------- |
| `POST` | `/api/admin/auth/login` | 后台登录 |
| `GET` | `/api/admin/me` | 当前后台用户 |
| `GET` | `/api/admin/dashboard` | 工作台统计和最近线索 |
| `GET` | `/api/admin/site-config` | 获取全部站点配置 |
| `POST` | `/api/admin/site-config/{module}` | 新增模块项 |
| `PATCH` | `/api/admin/site-config/{module}/{id}` | 更新模块项 |
| `DELETE` | `/api/admin/site-config/{module}/{id}` | 删除模块项 |
| `PATCH` | `/api/admin/site-config/{module}/reorder` | 调整排序 |
| `GET` | `/api/admin/leads` | 线索列表 |
| `PATCH` | `/api/admin/leads/{id}/status` | 更新线索状态 |
| `GET` | `/api/admin/media-assets` | 素材列表 |
| `POST` | `/api/admin/media-assets/upload` | 上传图片 |
| `POST` | `/api/admin/reset-guizhou-content` | 重置站点内容 |
| `POST` | `/api/admin/publish` | 发布站点快照 |
## 站点模块
@@ -46,19 +48,19 @@ type SiteModule =
| "demandHero"
| "demandFeatureCards"
| "demandForm"
| "vehicleOptions"
| "vehicleOptions";
```
模块职责:
| 模块 | 主要字段 | 约束 |
| --- | --- | --- |
| `heroSlides` | `title`、`kicker`、`image`、`isActive`、`sortOrder` | 可新增、编辑、删除、排序 |
| `destinationHero` | `title`、`kicker`、`image`、`isActive`、`sortOrder` | 可新增、编辑、删除、排序 |
| `demandHero` | `title`、`kicker`、`description`、`steps`、`isActive`、`sortOrder` | 可新增、编辑、删除、排序 |
| `demandFeatureCards` | `title`、`description`、`isActive`、`sortOrder` | 可新增、编辑、删除、排序 |
| `demandForm` | 表单标签、占位文案、`chips`、`isActive` | 单例,不支持排序 |
| `vehicleOptions` | `title`、`description`、`image`、`isActive`、`sortOrder` | 可新增、编辑、删除、排序 |
| 模块 | 主要字段 | 约束 |
| -------------------- | ------------------------------------------------------------------ | ------------------------ |
| `heroSlides` | `title`、`kicker`、`image`、`isActive`、`sortOrder` | 可新增、编辑、删除、排序 |
| `destinationHero` | `title`、`kicker`、`image`、`isActive`、`sortOrder` | 可新增、编辑、删除、排序 |
| `demandHero` | `title`、`kicker`、`description`、`steps`、`isActive`、`sortOrder` | 可新增、编辑、删除、排序 |
| `demandFeatureCards` | `title`、`description`、`isActive`、`sortOrder` | 可新增、编辑、删除、排序 |
| `demandForm` | 表单标签、占位文案、`chips`、`isActive` | 单例,不支持排序 |
| `vehicleOptions` | `title`、`description`、`image`、`isActive`、`sortOrder` | 可新增、编辑、删除、排序 |
`GET /api/admin/site-config` 返回以上全部模块,包含停用内容,空模块返回 `[]`。
@@ -74,43 +76,6 @@ type SiteModule =
成功响应包含 `token` 和 `{ id, email, name, role }`。
### 工作台统计
`GET /api/admin/dashboard` 返回:
```ts
{
stats: {
newLeadCount: number;
leadCount: number;
};
recentLeads: Lead[];
}
```
## 线索
### `GET /api/admin/leads`
Query 参数:`status`、`sourcePage`、`keyword`、`createdFrom`、`createdTo`、`take`。`take` 范围为 1-200,默认 100。关键词只搜索联系方式、目的地和备注。
### `PATCH /api/admin/leads/{id}/status`
请求:
```json
{ "status": "contacted" }
```
状态值:`new`、`assigned`、`contacted`、`planning`、`won`、`invalid`。
## 媒体与发布
- 图片上传字段为 multipart `file` 和 `group`。
- 允许 JPG、PNG、WebP、GIF,单文件最大 5MB。
- `POST /api/admin/publish` 保存当前启用内容快照并返回版本记录。
- `POST /api/admin/reset-guizhou-content` 只重置站点内容模块,不创建已移除领域的数据。
## 兼容边界
- 当前 Admin UI 不应调用未列出的领域接口。

View File

@@ -1,36 +0,0 @@
# 后台 API 服务
`WonderQ-Admin` 当前是独立的 Python + FastAPI API 服务,使用 PostgreSQL 保存业务数据,通过 Docker Compose 启动 `api`、`postgres` 和 `redis`。
## 本地 API 启动
从 `WonderQ-Project` 根目录启动时,先确认 Docker Desktop 已运行,再进入后端目录:
```powershell
Set-Location .\WonderQ-Admin
.\.venv\Scripts\Activate.ps1
docker-compose up -d postgres redis
python -m alembic upgrade head
python -m uvicorn app.main:app --host 0.0.0.0 --port 4000 --reload
```
首次缺少虚拟环境或依赖时再执行:
```powershell
Set-Location .\WonderQ-Admin
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -r requirements.txt
python -m alembic upgrade head
python -m app.seed --no-reset
```
健康检查:`http://localhost:4000/health`
## 前端联调
后台管理前端位于 `D:\www\znkj\WonderQ-Project\WonderQ-Admin-UI`。如需连接本服务,在前端 `.env` 或环境变量中配置:
```text
VITE_API_BASE_URL="http://localhost:4000"
```

View File

@@ -1,34 +0,0 @@
# WonderQ-Admin 后端规划摘要
## 当前定位
`WonderQ-Admin` 是 WonderQ 的独立后端 API 服务,当前技术栈已调整为 Python + FastAPI + SQLAlchemy 2 + Alembic + PostgreSQL,通过 Docker Compose 部署 API、PostgreSQL 和 Redis。
## 核心目标
- 为 H5 前台提供稳定的 Public API。
- 为后台管理端提供 JWT 鉴权的 Admin API。
- 保留现有 PostgreSQL 数据和主要接口路径,降低前端联调成本。
- 使用 Alembic 管理后续数据库迁移,已有数据库通过 `alembic stamp head` 接入 baseline。
## 当前业务模块
- 首页配置:轮播、目的地、发布版本。
- 线路产品:列表、详情、图片、详情区块、状态和排序。
- 线索:前台提交、后台列表、状态流转。
- 媒体:媒体资源登记。
- 审计:后台关键变更写入 `AuditLog`。
## 近期优先级
1. 保持 Public/Admin API 与现有前端调用兼容。
2. 补充更多 PostgreSQL 集成测试,覆盖迁移、seed 和核心接口。
3. 建立生产迁移流程:备份、`alembic stamp head`、后续增量迁移。
4. 按实际业务继续扩展权限、订单、客户和消息模块。
## 安全与部署原则
- 生产环境必须替换 `JWT_SECRET`,禁止使用示例值。
- 不提交 `.env`、日志、数据库备份和任何真实密钥。
- `python -m app.seed` 会重置内容数据,生产环境执行前必须明确确认。
- Docker Compose 适合本地和单机部署;生产可按相同环境变量拆分到托管数据库或容器平台。

View File

@@ -1,108 +0,0 @@
# WonderQ 当前技术与文档决策
本文档只记录当前有效决策,避免非当前技术路径干扰后续开发。
## DEC-001:后端采用 Python + FastAPI 技术栈
状态:已接受
当前后端服务位于 `WonderQ-Admin`,技术栈为 Python、FastAPI、SQLAlchemy 2、Alembic、PostgreSQL、JWT 和 Pydantic。
原因:
- 当前代码和文档已经围绕该技术栈落地。
- Alembic 负责数据库迁移,适合继续演进 PostgreSQL 结构。
- FastAPI 与 Pydantic 能清晰表达 Public API 和 Admin API 的请求响应契约。
影响:
- 后端文档以 `backend-api-service.md` 和 `backend-plan.md` 为准。
- 不在当前文档中保留其它后端技术栈规划。
## DEC-002:Public API 与 Admin API 分离
状态:已接受
`WonderQ-MiniAPP` 只对接 `/api/public/...`,不依赖后台鉴权;`WonderQ-Admin-UI` 只对接 `/api/admin/...`,除登录外均需要后台登录态。
原因:
- 前台展示和后台运营权限边界不同。
- Public API 需要过滤未发布或未启用内容。
- Admin API 需要返回运营维护所需的完整配置和草稿数据。
影响:
- `public-api.md` 是 MiniAPP 对接后端的唯一 Public API 契约。
- `admin-api-requirements.md` 是 Admin UI 对接后端的主契约。
## DEC-003:页面模块 CRUD 细节以 `module-config-api.md` 为准
状态:已接受
首页轮播、目的地和万趣用车的新增、更新、删除、排序细节,统一维护在 `module-config-api.md`。
原因:
- 页面模块字段多、规则细,放在 Admin API 主文档里会造成重复。
- 管理前端和后端实现都需要同一份细粒度契约。
影响:
- `admin-api-requirements.md` 只保留站点配置主接口和模块入口说明。
- 任何页面模块字段、状态码、排序、媒体上传规则变化,都先更新 `module-config-api.md`。
## DEC-004:文档保持扁平结构
状态:已接受
`docs/` 目录不再按子项目分目录,所有当前文档直接放在 `docs/` 根目录。
原因:
- 当前项目只有少量关键文档,扁平结构查找更快。
- 三端联调需要跨项目阅读,按子项目分目录会增加跳转成本。
影响:
- `docs/README.md` 是唯一文档入口。
- 新文档必须在 `docs/README.md` 登记。
## DEC-005:当前文档只服务现行架构
状态:已接受
当前文档集中只保留服务现行架构和三端联调的内容。
原因:
- 非当前技术路径会干扰三端当前开发判断。
- 当前任务目标是提高后端、管理前端和 MiniAPP 的开发进度,文档需要服务现行架构。
影响:
- 新成员只需要阅读当前文档即可理解现行协作方式。
- 如未来需要记录重大调整,直接新增当前决策或更新本文件。
## DEC-006:MiniAPP 采用简约、内容优先的移动端视觉风格
状态:已接受
`WonderQ-MiniAPP` 的 H5 与微信小程序前台统一采用扁平、低装饰的简约风格。内容图片和信息层级优先于装饰效果,交互状态通过颜色、边框和轻量动效表达。
原因:
- 旅行内容页需要让用户快速扫描目的地、线路和服务入口,复杂背景和重装饰会削弱信息层级。
- H5 与小程序运行设备性能差异较大,减少渐变、模糊和重阴影可以降低渲染负担并提高跨端一致性。
- 固定导航采用稳定布局,避免浮动徽章和缩放动画造成视觉干扰或布局跳动。
约定:
- 基础色使用白色、浅灰和低饱和绿色;主操作使用绿色,价格等业务强调色保持低饱和暖色。
- 卡片、输入框和按钮优先使用 8-12px 圆角、细边框和轻阴影;不新增大面积渐变、装饰性光晕或重阴影。
- 复用 `WonderQ-MiniAPP/src/app.css` 的 `--wq-*` 设计变量及共享组件样式,页面局部样式不得重新建立一套颜色和阴影体系。
影响:
- 新增或调整 MiniAPP 页面时,应先复用共享样式,再补充页面特有布局。
- 如确需引入明显装饰效果,需要在页面需求中说明其内容价值,并同步更新本决策。

View File

@@ -1,56 +0,0 @@
# WonderQ 开发状态矩阵
本文档记录三端当前对接范围,不替代实际构建、测试和联调结果。
| 能力 | 后端 | 管理前端 | MiniAPP | 入口 |
| --- | --- | --- | --- | --- |
| 健康检查 | 已覆盖 | 需实测 | 需实测 | `GET /health` |
| Public 站点配置 | 已覆盖 | 不直接使用 | 当前使用 | `GET /api/public/site-config` |
| Public 线索提交 | 已覆盖 | 不直接使用 | 当前使用 | `POST /api/public/leads` |
| Public 客户登录 | 已覆盖 | 不使用 | 当前使用 | `/api/public/auth/*` |
| Admin 登录 | 已覆盖 | 当前使用 | 不使用 | `POST /api/admin/auth/login` |
| Admin 站点配置 | 已覆盖 | 当前使用 | 不使用 | `GET /api/admin/site-config` |
| 页面模块 CRUD | 已覆盖 | 当前使用 | 不使用 | `module-config-api.md` |
| Admin 线索跟进 | 已覆盖 | 当前使用 | 不使用 | `/api/admin/leads` |
| 媒体上传 | 已覆盖 | 当前使用 | 不使用 | `/api/admin/media-assets/upload` |
| 发布站点配置 | 已覆盖 | 当前使用 | 不使用 | `POST /api/admin/publish` |
| 贵州内容重置 | 已覆盖 | 当前使用 | 不使用 | `POST /api/admin/reset-guizhou-content` |
## 当前页面联调路径
1. 后端启动后检查 `/health` 和 `/api/public/site-config`。
2. Admin UI 登录并读取站点配置。
3. 在首页、玩法页和需求页模块中新增、编辑、删除、排序或启停配置。
4. MiniAPP 启动并验证首页、玩法、需求和我的页面。
5. MiniAPP 提交线索,Admin UI 在“需求线索”中查询并更新状态。
6. Admin UI 发布站点配置,MiniAPP 刷新后验证启用内容。
## 验证命令
```powershell
Set-Location D:\www\znkj\WonderQ-Project\WonderQ-Admin
.\.venv\Scripts\python.exe -m pytest
```
```powershell
Set-Location D:\www\znkj\WonderQ-Project\WonderQ-Admin-UI
yarn build
```
```powershell
Set-Location D:\www\znkj\WonderQ-Project\WonderQ-MiniAPP
yarn test
yarn build:h5
yarn build:mp-weixin
```
## 本次领域清理
- MiniAPP 只保留站点内容、需求提交和客户登录相关逻辑。
- Public API 只保留 `site-config`、登录、客户和线索接口。
- Admin UI 只保留站点结构、素材、发布和线索管理入口。
- 后端通过 `0009_remove_product_domain` 迁移移除已退役表、关联表以及线索和订单中的旧外键列。
- 后端通过 `0010_remove_destination_module` 迁移移除省内目的地及别名表。
- 后端通过 `0012_remove_offer_modules` 迁移移除特价优惠、特色酒店及相关表。
- 后端通过 `0013_remove_map_theme_modules` 迁移移除贵州地图和主题甄选相关表。
- 未执行现有数据库的破坏性迁移;部署时应先备份,再按迁移流程执行。

View File

@@ -0,0 +1,362 @@
# 首页内容管理 Admin API
> 适用端:`WonderQ-Admin`、`WonderQ-Admin-UI`。
>
> 状态:待实现契约。本文件参考 `WonderQ-MiniAPP/src/pages/home/components/homeExperienceData.ts`、`homeTeamBuildingData.ts` 和 `homeWildArchivesData.ts` 定义首页卡片内容,以及管理端需要的查询、维护和排序接口。它是首页内容的 Admin API 补充契约,不是 MiniAPP Public API 文档。
## 领域边界
首页内容管理只维护三类首页卡片:
- 体验推荐:徽标、分类、标题、英文标题、封面和需求关键词。
- 团队共创:标签、标题、描述、封面和需求关键词。
- 极境视界:案例标题、封面和需求关键词。
本领域不负责:
- 顶部轮播、车辆选项、需求表单或其他站点模块;这些内容遵循 [Admin API 主契约](./admin-api-requirements.md)。
- 商品、Product、ProductImage、详情、价格、库存、订单或预订。
- 线索创建和线索跟进。
`demandKeyword` 只是点击卡片后预填需求页的普通字符串,不是商品 ID、路线 ID、订单 ID,也不建立数据库外键。
当前首页仍直接使用三个文件中的 mock 数组。Admin API 接入前,这些数组继续作为前台 fallback;本文件不代表接口已经在 `WonderQ-Admin` 或 `WonderQ-Admin-UI` 中实现。
## 接口清单
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` | 调整极境视界案例顺序 |
## 通用约定
- 请求和响应使用 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;
};
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;
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` | 是 | 点击后预填需求页的关键词。 |
| 极境视界 | `title` | `string` | 是 | 案例标题,去除首尾空白后不得为空。 |
| 极境视界 | `image` | `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`。
## 当前 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`。
4. 极境视界表单维护 `title`、`image` 和 `demandKeyword`。
5. 三类资源都提供启用/停用、编辑、删除和上移/下移操作;排序时提交完整 ID 列表。
6. 每次变更成功后以接口返回的记录或列表更新本地状态,不直接假设本地修改已经保存。
7. 删除前要求二次确认;删除成功后接受服务端返回的重新排序结果。
8. 处理 `401`、`404`、`409`、`422` 和 `5xx`,保存、上传和排序进行中禁用重复提交。
9. 不在首页表单中出现 Product ID、ProductImage ID、价格、库存、订单或预订字段。
10. 预览点击行为使用 `demandKeyword`;该字段为空时禁止提交,而不是由前端猜测或拼接商品标识。
建议的 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[]);
```
当前首页的“查看更多”按钮固定跳转需求关键词“极境视界”,不属于 `HomeWildArchive` 记录字段;如果未来需要后台配置该按钮,应另行增加首页 CTA 配置契约。
## 前后台数据边界
- Admin API 返回启用和停用的完整记录,供管理端维护。
- 未来 Public API 只返回已发布且启用的首页内容;Public API 的响应字段应与本契约的渲染字段兼容,但不应暴露 `createdAt`、`updatedAt` 等管理元数据。
- MiniAPP 接入时再同步更新 `src/lib/types.ts`、`src/lib/data.ts`、首页组件和 `docs/public-api.md`;本次文档不改变现有 mock 消费路径。
- 后端不得把 `demandKeyword` 解析成 Product 或订单关联;如需线路、详情或预订能力,应另立领域契约。
## 后端落地边界
本契约落地时需要由 `WonderQ-Admin` 补充对应 ORM 模型、迁移、schema、路由、序列化和审计日志;由 `WonderQ-Admin-UI` 补充 API 类型、请求封装、首页内容列表、表单、图片上传和排序交互。当前后端没有 `/api/admin/home/*` 路由,Admin UI 也未接入这三类首页数据。
相关文档:
- [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)
- [极境视界数据](../WonderQ-MiniAPP/src/pages/home/components/homeWildArchivesData.ts)

View File

@@ -4,11 +4,11 @@
## 三端职责
| 端 | 目录 | 职责 | 主要契约 |
| --- | --- | --- | --- |
| 后端 API | `WonderQ-Admin` | 提供 Public API、Admin API、鉴权、数据库、迁移和 seed | `backend-api-service.md`、`backend-plan.md`、`public-api.md`、`admin-api-requirements.md` |
| 管理前端 | `WonderQ-Admin-UI` | 维护首页结构、目的地、线索和页面模块配置 | `admin-api-requirements.md`、`module-config-api.md` |
| 前台 MiniAPP | `WonderQ-MiniAPP` | H5 与微信小程序前台展示、咨询和线索提交 | `public-api.md` |
| 端 | 目录 | 职责 | 主要契约 |
| ------------ | ------------------ | ----------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| 后端 API | `WonderQ-Admin` | 提供 Public API、Admin API、鉴权、数据库、迁移和 seed | `backend-api-service.md`、`backend-plan.md`、`public-api.md`、`admin-api-requirements.md` |
| 管理前端 | `WonderQ-Admin-UI` | 维护首页结构、目的地、线索和页面模块配置 | `admin-api-requirements.md`、`module-config-api.md` |
| 前台 MiniAPP | `WonderQ-MiniAPP` | H5 与微信小程序前台展示、咨询和线索提交 | `public-api.md` |
## 本地启动顺序
@@ -90,11 +90,9 @@ MiniAPP 联调重点:
1. 先更新契约文档。
- Public API 变更:更新 `public-api.md`。
- Admin API 变更:更新 `admin-api-requirements.md`。
- 页面模块 CRUD 变更:更新 `module-config-api.md`。
2. 后端实现或调整接口,并补充对应验证。
3. 管理前端或 MiniAPP 按契约调整调用和类型。
4. 三端分别运行对应验证命令。
5. 若变更影响启动、部署或架构边界,同步更新 `backend-api-service.md`、`backend-plan.md` 或 `decisions.md`。
## 验证命令

View File

@@ -1,133 +0,0 @@
# 页面模块配置 Admin API 契约
本文档约束 `WonderQ-Admin-UI` 对站点结构模块的 CRUD、排序和字段白名单。
## 适用模块
| 模块 | 用途 |
| --- | --- |
| `heroSlides` | 首页顶部轮播 |
| `destinationHero` | 目的地页主视觉 |
| `demandHero` | 需求页主视觉 |
| `demandFeatureCards` | 需求页能力卡片 |
| `demandForm` | 需求提交表单 |
| `vehicleOptions` | 万趣用车卡片 |
## 通用规则
- 路径:`/api/admin/site-config/{module}`。
- 所有模块项都使用字符串 `id`;排序项使用整数 `sortOrder`。
- 创建、更新、删除和排序均需要后台 JWT。
- 后端只接受模块字段白名单,未知字段会被忽略。
- `demandForm` 是单例模块,重复创建返回 `409`。
- `demandForm` 不支持排序;其他模块支持排序。
- 所有变更写入审计日志,并在成功提交后返回最新模块项。
## 类型
```ts
type SiteModule =
| "heroSlides"
| "destinationHero"
| "demandHero"
| "demandFeatureCards"
| "demandForm"
| "vehicleOptions"
type SiteItemPatch = {
title?: string;
kicker?: string | null;
image?: string | null;
description?: string | null;
steps?: string[];
destinationLabel?: string;
destinationPlaceholder?: string | null;
phoneLabel?: string;
phonePlaceholder?: string | null;
noteLabel?: string;
notePlaceholder?: string | null;
submitLabel?: string;
chips?: string[];
targetType?: string | null;
targetValue?: string | null;
isActive?: boolean;
sortOrder?: number;
};
```
## 获取完整配置
### `GET /api/admin/site-config`
返回所有模块数组,包括停用项:
```ts
{
heroSlides: unknown[];
destinationHero: unknown[];
demandHero: unknown[];
demandFeatureCards: unknown[];
demandForm: unknown[];
vehicleOptions: unknown[];
}
```
空模块必须返回 `[]`,不能返回 `null` 或省略字段。
## CRUD
### 新增
```http
POST /api/admin/site-config/{module}
Authorization: Bearer <admin-jwt>
Content-Type: application/json
```
请求体使用 `SiteItemPatch`。成功返回 `201` 和新建模块项。各模块的主字段如下:
| 模块 | 主字段 |
| --- | --- |
| `heroSlides` | `title` |
| `destinationHero` | `title` |
| `demandHero` | `title` |
| `demandFeatureCards` | `title` |
| `demandForm` | `submitLabel` |
| `vehicleOptions` | `title` |
缺少主字段返回 `422 MODULE_CONFIG_VALIDATION_ERROR`。模块不存在返回 `400 MODULE_CONFIG_FORBIDDEN`。
### 更新
```http
PATCH /api/admin/site-config/{module}/{id}
```
只更新该模块允许的字段;不存在的 ID 返回 `404 MODULE_CONFIG_NOT_FOUND`。
### 删除
```http
DELETE /api/admin/site-config/{module}/{id}
```
成功返回 `{ "id": "..." }`。删除后,排序模块会重新从 0 开始编号。
### 排序
```http
PATCH /api/admin/site-config/{module}/reorder
Content-Type: application/json
{ "itemIds": ["id-2", "id-1"] }
```
`itemIds` 必须刚好包含当前模块的全部 ID,且不能重复。否则返回 `400 MODULE_CONFIG_REORDER_INVALID`。不支持排序的模块返回 `400 MODULE_CONFIG_REORDER_UNSUPPORTED`。
## 模块字段补充
- `demandForm` 的 `chips` 会过滤空白值;表单只保留一条配置。
## 删除范围边界
模块配置只维护站点内容,不负责客户、线索或订单数据。接口变更必须同步 `src/api.ts`、`src/types/admin.ts` 和本文档。

View File

@@ -11,13 +11,13 @@
## 接口清单
| 方法 | 路径 | 鉴权 | 用途 |
| --- | --- | --- | --- |
| `GET` | `/health` | 否 | 服务健康检查 |
| `GET` | `/api/public/site-config` | 否 | 获取启用的站点内容 |
| `POST` | `/api/public/auth/phone-login` | 否 | 微信手机号登录 |
| `GET` | `/api/public/auth/me` | Customer JWT | 获取当前客户 |
| `POST` | `/api/public/leads` | 否 | 提交出行需求 |
| 方法 | 路径 | 鉴权 | 用途 |
| ------ | ------------------------------ | ------------ | ------------------ |
| `GET` | `/health` | 否 | 服务健康检查 |
| `GET` | `/api/public/site-config` | 否 | 获取启用的站点内容 |
| `POST` | `/api/public/auth/phone-login` | 否 | 微信手机号登录 |
| `GET` | `/api/public/auth/me` | Customer JWT | 获取当前客户 |
| `POST` | `/api/public/leads` | 否 | 提交出行需求 |
## 站点配置
@@ -103,46 +103,3 @@ type DemandForm = {
```json
{ "id": "customer-id", "phoneMasked": "138****0000" }
```
## 出行需求
### `POST /api/public/leads`
请求字段:
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `destination` | `string` | 否 | 目的地或玩法 |
| `phone` | `string` | 是 | 联系方式,长度 2-64 |
| `travelDate` | `datetime` | 否 | 支持 `YYYY-MM-DD` |
| `peopleCount` | `number` | 否 | 大于 0 |
| `budgetMin` | `number` | 否 | 不小于 0 |
| `budgetMax` | `number` | 否 | 不小于 0 |
| `note` | `string` | 否 | 最长 1000 字符 |
| `sourcePage` | `string` | 否 | 来源页面标识 |
成功响应:
```json
{ "id": "lead-id", "status": "new" }
```
## 错误约定
- 未登录访问客户接口:`401`,消息为“请先登录”。
- 参数校验失败:`422`。
- 微信登录未配置:`503`。
- 微信登录凭证无效:`400`。
## MiniAPP 依赖
- 启动时只请求 `GET /api/public/site-config`。
- 首页使用 `heroSlides` 与 `vehicleOptions`。
- 需求提交只通过 `POST /api/public/leads`,失败时显示统一错误状态并保留本地表单内容。
## 验证建议
- 验证 `site-config` 的模块字段始终为数组。
- 验证 Public 内容只返回启用状态的数据。
- 验证需求请求不接受未知关联字段,并覆盖日期、联系方式和预算校验。
- 验证旧内容路径返回 `404`,避免客户端继续依赖已撤下的接口。