Files
WonderQ-Project/docs/concierge-api.md
duanshuwen e8eb8614f0 docs: 清理过时文档并更新管理端名称
删除home-api.md、team-building-api.md等废弃文档
统一替换所有文档中的`WonderQ-Admin-UI`为`WonderQ-Admin-UI-Vue`
更新README.md与联调文档的内容与路径
修正各API文档的过时描述,移除废弃的迁移说明与本地mock依赖
整理docs/README.md的文档索引,优化阅读路径
2026-08-26 19:41:15 +08:00

346 lines
12 KiB
Markdown
Raw Permalink 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.

# 管家管理 Admin API
> 适用端:`WonderQ-Admin`、`WonderQ-Admin-UI-Vue`。
>
> 状态:已实现。本文档约定 `WonderQ-Admin`、`WonderQ-Admin-UI-Vue` 的管家管理接口,并记录 MiniAPP 使用的对应 Public API。
所有 JSON 响应遵循 [三端统一 API 响应契约](./api-response-contract.md),成功业务对象位于 `data`,失败时 `data``null`
Admin 顾问记录的 `id` 为服务端生成的稳定 UUID 字符串MiniAPP Public 响应按现有契约不返回顾问 ID。不要使用姓名、角色或本地 mock ID 作为正式顾问标识。
## 领域边界
管家管理只维护管家顾问卡片资料:
- 头像、姓名和职位。
- 服务详情条目,包括图标和说明文案。
- 添加管家时展示的二维码。
- 顾问启用状态和展示顺序。
本接口不负责:
- 需求线索、客户、客服会话或登录。
- 订单、预订、商品和商品图片关联。
- 管家页面 Hero 文案和服务原则内容。
## 路线详情关联
路线详情可以关联一名管家顾问。`DetailRecord` 只保存可空的 `conciergeAdvisorId`,不建立数据库外键,也不复制头像、二维码或服务详情。玩法详情由详情接口维护,管家资料仍由本领域的 Admin CRUD 和 Public API 维护。
`GET /api/public/details/{key}` 会在关联顾问存在且启用时嵌入最新的 `conciergeAdvisor`;未配置、顾问已删除或已停用时返回 `conciergeAdvisor: null`不会阻塞路线详情读取。Admin UI 选择顾问时使用本接口返回的稳定 `id`,清空选择即解除关联。
当前 `WonderQ-MiniAPP/src/pages/concierge/index.vue` 中的 Hero 和服务原则仍是本地内容;顾问卡片由 Admin UI 维护MiniAPP 通过独立的 Public API 消费已启用顾问。
## 接口清单
API 前缀为 `/api/admin`,除登录接口外均需要后台 JWT。
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| `GET` | `/api/admin/concierge/advisors` | 获取全部管家顾问 |
| `POST` | `/api/admin/concierge/advisors` | 新增管家顾问 |
| `PATCH` | `/api/admin/concierge/advisors/{advisorId}` | 编辑管家顾问 |
| `DELETE` | `/api/admin/concierge/advisors/{advisorId}` | 删除管家顾问 |
| `PATCH` | `/api/admin/concierge/advisors/reorder` | 调整管家顾问展示顺序 |
MiniAPP Public API
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| `GET` | `/api/public/concierge/advisors` | 获取已启用的管家顾问展示数据 |
## 通用约定
- 请求和响应使用 JSON字段使用 camelCase。
- 所有管理接口需要 `Authorization: Bearer <admin-jwt>`
- `GET` 默认返回启用和停用的全部顾问,按 `sortOrder` 升序返回,供管理端完整维护。
- 创建、编辑、删除和排序成功后写入审计日志,再提交事务。
- 变更接口返回最新顾问对象;排序接口返回排序后的 `items`
- ID 由后端生成并作为非空字符串返回。
- 空列表返回 `[]`,不能返回 `null` 或省略字段。
- 成功结果放入 `data`;失败返回数字 `code``msg``data: null`,可选 `errorCode``details`
## 数据类型
`conciergeTypes.ts` 是 MiniAPP 渲染模型,当前没有 `id``isActive``sortOrder`。为了支持 Admin UI 编辑、删除和排序Admin API 在渲染字段之外增加管理元数据MiniAPP Public API 适配时可以移除这些管理字段。
```ts
type ConciergeDetail = {
icon: string;
label: string;
};
type ConciergeAdvisorContent = {
avatar: string;
name: string;
role: string;
details: ConciergeDetail[];
qrImage: string;
};
type ConciergeAdvisorRecord = ConciergeAdvisorContent & {
id: string;
isActive: boolean;
sortOrder: number;
createdAt: string;
updatedAt: string;
};
type ConciergeAdvisorCreate = {
avatar: string;
name: string;
role: string;
details: ConciergeDetail[];
qrImage: string;
isActive?: boolean;
sortOrder?: number;
};
type ConciergeAdvisorPatch = Partial<ConciergeAdvisorCreate>;
type ConciergeAdvisorListResponse = {
advisors: ConciergeAdvisorRecord[];
};
type ConciergeReorderRequest = {
itemIds: string[];
};
```
## 字段约束
| 字段 | 类型 | 必填 | 约束和用途 |
| --- | --- | --- | --- |
| `id` | `string` | 响应必填 | 顾问稳定标识,由后端生成。管理端不使用姓名作为编辑、删除或列表 `key`。 |
| `avatar` | `string` | 是 | 顾问头像 URL前台按圆形头像展示。 |
| `name` | `string` | 是 | 顾问姓名,去除首尾空白后不得为空。 |
| `role` | `string` | 是 | 顾问职位或英文职称,去除首尾空白后不得为空。 |
| `details` | `ConciergeDetail[]` | 是 | 服务详情列表,保留数组顺序;允许为空数组。 |
| `details[].icon` | `string` | 是 | `uni-icons` 使用的图标名称,例如 `calendar``navigate`。 |
| `details[].label` | `string` | 是 | 服务详情文案,去除首尾空白后不得为空。 |
| `qrImage` | `string` | 是 | 添加管家时展示的二维码图片 URL。接口只保存图片 URL不保存二维码原始 payload。 |
| `isActive` | `boolean` | 响应必填 | 是否在已发布前台内容中展示,创建默认 `true`。 |
| `sortOrder` | `number` | 响应必填 | 非负整数,数值越小越靠前;创建时未传则追加到末尾。 |
| `createdAt` | `string` | 响应必填 | ISO 8601 创建时间。 |
| `updatedAt` | `string` | 响应必填 | ISO 8601 最后更新时间。 |
头像和二维码应使用已上传素材的最终 URL。服务端应校验必填文本、URL 格式、`details` 数组结构和 `sortOrder` 非负整数;具体文本最大长度由后端 schema 统一定义,并同步到 Admin UI 表单校验。
## 接口详情
### 获取全部顾问
```http
GET /api/admin/concierge/advisors
Authorization: Bearer <admin-jwt>
```
成功响应:
```json
{
"code": 200,
"msg": "success",
"data": {
"advisors": [
{
"id": "advisor-001",
"avatar": "https://example.test/assets/advisor-avatar.jpg",
"name": "示例顾问",
"role": "SENIOR TRAVEL ADVISOR",
"details": [
{ "icon": "calendar", "label": "服务经验8年" },
{ "icon": "navigate", "label": "擅长领域:自然探索" }
],
"qrImage": "https://example.test/assets/advisor-qr.png",
"isActive": true,
"sortOrder": 0,
"createdAt": "2026-01-01T00:00:00Z",
"updatedAt": "2026-01-01T00:00:00Z"
}
]
}
}
```
### 新增顾问
```http
POST /api/admin/concierge/advisors
Authorization: Bearer <admin-jwt>
Content-Type: application/json
```
请求:
```json
{
"avatar": "https://example.test/assets/advisor-avatar.jpg",
"name": "示例顾问",
"role": "SENIOR TRAVEL ADVISOR",
"details": [
{ "icon": "calendar", "label": "服务经验8年" },
{ "icon": "navigate", "label": "擅长领域:自然探索" }
],
"qrImage": "https://example.test/assets/advisor-qr.png",
"isActive": true
}
```
成功返回 `201``data` 内新建的 `ConciergeAdvisorRecord`。未传 `sortOrder` 时追加到当前最大顺序之后。
### 编辑顾问
```http
PATCH /api/admin/concierge/advisors/{advisorId}
Authorization: Bearer <admin-jwt>
Content-Type: application/json
```
请求体为 `ConciergeAdvisorPatch`,只更新提交的字段。例如只更新服务详情:
```json
{
"details": [
{ "icon": "calendar", "label": "服务经验10年" },
{ "icon": "navigate", "label": "擅长领域:亲子与自然探索" }
]
}
```
成功返回 `data` 内更新后的 `ConciergeAdvisorRecord`。不存在的顾问返回 `404`,业务码为 `CONCIERGE_ADVISOR_NOT_FOUND`
### 删除顾问
```http
DELETE /api/admin/concierge/advisors/{advisorId}
Authorization: Bearer <admin-jwt>
```
删除成功返回:
```json
{
"code": 200,
"msg": "success",
"data": { "id": "advisor-001" }
}
```
删除后应重新规范化剩余顾问的 `sortOrder`,从 `0` 开始连续编号。若业务要求至少保留一名启用顾问,服务端在删除最后一名启用顾问时返回 `409 CONCIERGE_LAST_ACTIVE_ADVISOR`,否则允许删除并由前台处理空状态。
### 调整顾问顺序
```http
PATCH /api/admin/concierge/advisors/reorder
Authorization: Bearer <admin-jwt>
Content-Type: application/json
```
请求必须完整包含当前全部顾问 ID不能重复
```json
{ "itemIds": ["advisor-002", "advisor-001"] }
```
成功响应:
```json
{
"code": 200,
"msg": "success",
"data": { "items": [] }
}
```
其中 `items` 为更新 `sortOrder` 后的 `ConciergeAdvisorRecord[]`。缺少 ID、包含未知 ID 或出现重复 ID 时返回 `400 CONCIERGE_REORDER_INVALID`
### MiniAPP Public API
```http
GET /api/public/concierge/advisors
```
无需鉴权。接口只返回 `isActive === true` 的顾问,按 `sortOrder` 升序排列,并移除 `id``sortOrder`、时间和其他管理字段:
```ts
type PublicConciergeResponse = {
advisors: ConciergeAdvisorContent[];
};
```
顾问列表为空时返回 `data: { "advisors": [] }`。MiniAPP 应在请求期间展示 loading失败时展示错误和重试入口响应字段缺失时通过归一化函数过滤无效顾问。
## 图片与素材
Admin UI 使用现有素材上传接口获取图片 URL
```http
POST /api/admin/media-assets/upload
```
建议管家页面上传时使用 `group=concierge`,头像和二维码分别将返回的 `url` 写入 `avatar``qrImage`。API 不接受 base64 图片,也不在管家表中复制图片二进制内容。
二维码必须作为图片 URL 保存,不能把真实个人微信号、手机号或二维码 payload 写入文档、前端类型或接口日志。
## Admin UI 对接要求
Admin UI 应按以下方式调用:
1. 进入管家页面时调用 `GET /api/admin/concierge/advisors`,按 `sortOrder` 渲染全部顾问。
2. 列表展示头像、姓名、职位、详情数量、启用状态和编辑/删除操作。
3. 新增和编辑表单维护头像、姓名、职位、详情列表、二维码和启用状态。
4. `details` 使用可增删的重复字段编辑器,提交时保留用户排列顺序,不把多个详情拼成一个字符串。
5. 上移或下移顾问时提交完整顾问 ID 列表,不直接修改本地 `sortOrder` 后假设保存成功。
6. 删除前要求二次确认;处理最后一名启用顾问的 `409` 提示。
7. 处理 `401``404``409``422``5xx`,保存或排序请求进行中禁用重复提交。
8. 图片上传失败时不得提交旧草稿中的空 URL表单应保留其他已填写字段允许用户重试上传。
建议的 Admin UI API 封装函数:
```ts
getConciergeAdvisors();
createConciergeAdvisor(input: ConciergeAdvisorCreate);
updateConciergeAdvisor(advisorId: string, input: ConciergeAdvisorPatch);
deleteConciergeAdvisor(advisorId: string);
reorderConciergeAdvisors(itemIds: string[]);
```
## 与当前 MiniAPP 类型的映射
当前 `conciergeTypes.ts``ConciergeAdvisor` 仅包含前台渲染字段:
```ts
type ConciergeAdvisor = {
avatar: string;
name: string;
role: string;
details: Array<{ icon: string; label: string }>;
qrImage: string;
};
```
Admin API 返回的 `ConciergeAdvisorRecord` 可以通过以下方式映射为前台模型:
```ts
const advisor: ConciergeAdvisor = {
avatar: record.avatar,
name: record.name,
role: record.role,
details: record.details,
qrImage: record.qrImage,
};
```
只有 `isActive === true` 的记录进入已发布 Public 内容;`id``sortOrder``createdAt``updatedAt` 属于管理元数据,不应要求前台组件展示。
## 后端落地边界
当前实现由 `WonderQ-Admin` 提供 ORM 模型、schema、Admin/Public 路由、序列化和审计日志;由 `WonderQ-Admin-UI-Vue` 提供 API 类型、请求封装、管家列表、表单、图片上传、启停、排序和删除确认;由 `WonderQ-MiniAPP` 调用 Public API 并归一化顾问数据。Hero 和服务原则仍不在管家表中维护。
相关文档:
- [Admin API 主契约](./admin-api-requirements.md)
- [玩法管理 Admin API](./wanfa-api.md)
- [管家数据类型](../WonderQ-MiniAPP/src/pages/concierge/components/conciergeTypes.ts)