Files
WonderQ-Project/docs/public-api.md
duanshuwen d42f69bd47 feat: 新增用车需求服务及线索管理全功能
- 新增后台用车服务配置模块,支持维护服务简介、优势与使用流程
- 新增需求线索管理页面,支持筛选、查看与更新用车线索状态
- 新增小程序用车需求页面,优化登录路径与回跳逻辑
- 优化车型卡片跳转与用车需求提交功能
- 新增服务端API与数据处理逻辑,完善权限校验
- 更新全站配置与API文档,新增相关测试用例
2026-08-22 21:48:08 +08:00

328 lines
10 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 MiniAPP Public API
本文档是 `WonderQ-MiniAPP` 当前使用的 Public API 契约。接口提供站点内容、首页卡片、玩法展示、管家展示、登录和出行需求提交能力。
## 基础约定
- API 前缀:`/api/public`
- 响应使用 JSON时间使用 ISO 8601 字符串。
- 所有 `/health``/api/public/**` JSON 响应遵循 [三端统一 API 响应契约](./api-response-contract.md),成功业务对象位于 `data`,失败时 `data``null`
- 所有返回的持久化资源 `id` 都是稳定 UUID 字符串,不是标题、分类名或本地 mock 使用的语义 ID详情、列表和跳转必须复用同一个 ID。
- H5 本地开发通过 `/api` 代理访问后端。
- 内容接口失败时MiniAPP 使用 `src/content.ts` 的本地兜底内容。
## 接口清单
| 方法 | 路径 | 鉴权 | 用途 |
| ------ | ------------------------------ | ------------ | ------------------ |
| `GET` | `/health` | 否 | 服务健康检查 |
| `GET` | `/api/public/site-config` | 否 | 获取启用的站点内容 |
| `GET` | `/api/public/home` | 否 | 获取已启用的首页内容和玩法推荐 |
| `GET` | `/api/public/home/team-buildings/{teamBuildingId}` | 否 | 获取团队共创详情 |
| `GET` | `/api/public/home/wild-archives` | 否 | 获取客片案例更多列表 |
| `GET` | `/api/public/home/wild-archives/{archiveId}` | 否 | 获取客片案例详情和图片 |
| `GET` | `/api/public/wanfa/categories` | 否 | 获取玩法分类和路线 |
| `GET` | `/api/public/details/{key}` | 否 | 获取玩法路线详情 |
| `GET` | `/api/public/concierge/advisors` | 否 | 获取已启用的管家顾问 |
| `POST` | `/api/public/auth/phone-login` | 否 | 微信手机号登录 |
| `GET` | `/api/public/auth/me` | Customer JWT | 获取当前客户 |
| `POST` | `/api/public/leads` | 否 | 提交出行需求 |
## 站点配置
`GET /api/public/site-config` 返回以下稳定字段:
```ts
type SiteConfig = {
heroSlides: HeroSlide[];
destinationHero: DestinationHero[];
vehicleOptions: VehicleOption[];
demandHero: DemandHero[];
demandFeatureCards: DemandFeatureCard[];
demandForm: DemandForm[];
vehicleService: VehicleService | null;
};
type VehicleService = {
id: string;
introTitle: string;
intro: string;
serviceSections: Array<{ title: string; description: string }>;
advantages: string[];
processSteps: Array<{ title: string; description: string }>;
};
```
Public 响应只返回启用内容,其余模块按 `isActive` 过滤。
`vehicleService` 是用车需求页的启用单例配置;未配置或停用时返回 `null`MiniAPP 使用本地安全文案兜底,不代表实时库存、价格或订单承诺。
### 用车需求提交
`POST /api/public/leads` 的通用线索仍允许游客提交;`leadType=vehicle` 必须携带客户 JWT。服务端从 JWT 写入 `customerId`,客户端不得传入该字段。
```json
{
"leadType": "vehicle",
"contactName": "联系人",
"phone": "13800000000",
"sourcePage": "home-vehicle",
"vehicleDemand": {
"serviceType": "charter",
"charterDuration": "fullDay",
"travelDate": "2026-08-25",
"pickupTime": "09:00",
"pickupLocation": "贵阳北站",
"dropoffLocation": "黄果树景区",
"peopleCount": 5,
"luggageCount": 3,
"vehicleOptionId": "vehicle-option-uuid",
"vehicleOptionTitle": "多人商务车",
"specialRequirements": "需要儿童座椅"
}
}
```
服务端从 `vehicleDemand` 归一化 `destination``travelDate``peopleCount` 摘要字段。未登录、参数不完整或服务异常分别返回 `401``422``500`,失败时 `data``null`
## 玩法展示
### `GET /api/public/wanfa/categories`
无需鉴权。接口按后台维护的分类和路线顺序返回 MiniAPP 玩法页所需的最小展示字段,不返回后台排序、审计和时间字段。
成功响应:
```ts
type PublicWanfaResponse = {
categories: PublicWanfaCategory[];
};
type PublicWanfaCategory = {
id: string;
label: string;
routes: PublicWanfaRoute[];
};
type PublicWanfaRoute = {
id: string;
title: string;
subtitle: string;
image: string;
routeCount: number;
demandKeyword: string;
};
```
MiniAPP 使用 `demandKeyword` 作为需求页预填关键词;接口失败或响应为空时,玩法页展示对应的错误、重试或空态,不再读取 `playData.ts` 模拟数据。
### 路线详情
`GET /api/public/details/{key}` 无需鉴权,`key` 使用玩法路线 ID例如 `family-water`。成功响应只返回详情展示字段:
```ts
type PublicDetail = {
key: string;
eyebrow: string;
duration: string;
title: string;
subtitle: string;
intro: string;
highlights: string[];
included: string[];
excluded: string[];
notes: string[];
gallery: string[];
conciergeAdvisor: {
avatar: string;
name: string;
role: string;
details: Array<{ icon: string; label: string }>;
qrImage: string;
} | null;
};
```
不存在、停用或未配置详情返回 `404`。关联管家未配置、已删除或已停用时 `conciergeAdvisor``null`。MiniAPP 路线详情页通过 `/pages/detail/index?routeId={key}` 进入;接口失败或字段不完整时按路线 ID 使用本地网络图片和模拟文案fallback 不伪造管家数据。仅当 `conciergeAdvisor` 有效时展示联系管家入口。
## 管家展示
### `GET /api/public/concierge/advisors`
无需鉴权。接口只返回后台启用的管家顾问,按后台维护顺序返回;不返回管理端 ID、启停状态、排序元数据和时间字段。
```ts
type PublicConciergeDetail = {
icon: string;
label: string;
};
type PublicConciergeAdvisor = {
avatar: string;
name: string;
role: string;
details: PublicConciergeDetail[];
qrImage: string;
};
type PublicConciergeResponse = {
advisors: PublicConciergeAdvisor[];
};
```
成功响应示例:
```json
{
"advisors": [
{
"avatar": "https://example.test/assets/advisor-avatar.jpg",
"name": "示例顾问",
"role": "SENIOR TRAVEL ADVISOR",
"details": [{ "icon": "calendar", "label": "服务经验8年" }],
"qrImage": "https://example.test/assets/advisor-qr.png"
}
]
}
```
无可用顾问时返回 `data: { "advisors": [] }`。MiniAPP 应处理 loading、错误、重试和空态不能依赖固定顾问姓名或本地模拟数组。
## 首页内容
### `GET /api/public/home`
无需鉴权。接口只返回后台启用的首页玩法推荐、团队共创和极境视界内容,按后台排序返回,不暴露管理元数据。为统一前台消费模型,玩法推荐列表放在 `experiences` 字段,响应中不再返回 `playRecommendations`
```ts
type PublicHomeResponse = {
experiences: HomeWanfaRecommendation[];
teamBuildings: HomeTeamBuilding[];
wildArchives: HomeWildArchive[];
};
type HomeWanfaRecommendation = {
id: string;
categoryId: string;
label: string;
routes: WanfaRoute[];
};
type WanfaRoute = {
id: string;
title: string;
subtitle: string;
image: string;
routeCount: number;
demandKeyword: string;
};
type HomeTeamBuilding = {
id: string;
tag: string;
title: string;
description: string;
image: string;
demandKeyword: string;
};
type PublicHomeTeamBuildingDetail = HomeTeamBuilding & {
detailSubtitle: string;
detailParagraphs: string[];
};
type HomeWildArchive = {
id: string;
title: string;
image: string;
demandKeyword: string;
photoCount: number;
};
```
无可用内容时,`experiences``teamBuildings``wildArchives` 均返回空数组。`experiences` 实际承载首页玩法推荐由首页内容域关联玩法分类后生成接口只返回启用的关联及分类当前路线MiniAPP 接口失败或字段不完整时使用对应空态,不再读取 `playRecommendations`
客片案例更多列表使用 `GET /api/public/home/wild-archives`,返回同样的摘要字段;详情使用 `GET /api/public/home/wild-archives/{archiveId}`,在摘要字段基础上增加 `images: string[]`。首页卡片点击详情,`查看更多` 点击案例列表,不再跳转需求页。
### 团队共创详情
`GET /api/public/home/team-buildings/{teamBuildingId}` 无需鉴权,只返回启用的团队共创详情。响应包含首页摘要字段,以及 `detailSubtitle``detailParagraphs`。不存在或已停用返回 `404`
详情页接口失败时MiniAPP 按 ID 使用 `homeTeamBuildingData.ts` 中的网络图片和模拟正文 fallback并显示接口不可用提示首页 `/api/public/home` 不返回 `detailParagraphs`,避免首页请求携带长正文。
### 通用字段
站点模块通常包含 `id``createdAt``updatedAt``isActive``sortOrder`。客户端按 `sortOrder` 消费排序模块,不依赖固定 ID。
### 需求配置
```ts
type DemandHero = {
id: string;
title: string;
kicker: string | null;
description: string | null;
steps: string[];
isActive: boolean;
sortOrder: number;
};
type DemandFeatureCard = {
id: string;
title: string;
description: string | null;
isActive: boolean;
sortOrder: number;
};
type DemandForm = {
id: string;
destinationLabel: string;
destinationPlaceholder: string | null;
phoneLabel: string;
phonePlaceholder: string | null;
noteLabel: string;
notePlaceholder: string | null;
submitLabel: string;
chips: string[];
isActive: boolean;
};
```
## 登录接口
### `POST /api/public/auth/phone-login`
请求:
```json
{ "code": "wechat-phone-code" }
```
成功响应:
```json
{
"code": 200,
"msg": "success",
"data": {
"token": "<customer-jwt>",
"customer": { "id": "customer-id", "phoneMasked": "138****0000" }
}
}
```
### `GET /api/public/auth/me`
请求头:`Authorization: Bearer <customer-jwt>`
成功响应:
```json
{
"code": 200,
"msg": "success",
"data": { "id": "customer-id", "phoneMasked": "138****0000" }
}
```