docs: 私人定制完整流程对接指南(C端6接口 + 管理端5接口)

含状态机、按钮显示规则、字典、页面布局、完整调用示例

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
这个提交包含在:
API Changelog Bot 2026-03-19 12:49:39 +08:00
父节点 a64174435f
当前提交 fa41956b7a

查看文件

@ -0,0 +1,697 @@
# 私人定制完整流程C端提交 + 管理端处理) - 前端对接指南
> **日期**: 2026-03-19
> **后端状态**: ✅ 已完成,测试环境已部署
> **涉及模块**: hl-mp-serviceC端BFF、hl-order-service管理端+内部接口、hl-product-service定制产品
> **Knife4j 文档**: `192.168.100.236:8080/doc.html`
> - C端左侧选 "C端 - 定制需求接口"
> - 管理端:左侧选 "订单服务 - 私人定制管理"
---
## 业务流程总览
```
用户(小程序) 管理员(后台)
│ │
├─ 提交定制需求 ──────────────────→ │
│ POST /mp/custom/submit │
│ ├─ 查看定制请求列表
│ │ GET /admin/order/customize/page
│ │
│ ├─ 查看请求详情
│ │ GET /admin/order/customize/{id}
│ │
│ ├─ 接受请求(分配定制师)
│ │ PUT /admin/order/customize/{id}/accept
│ │
│ ├─ 回复/报价(关联产品)
│ ← 收到通知 ──────────────────────┤ PUT /admin/order/customize/{id}/reply
│ │
│ ├─ 标记完成
│ ← 收到通知 ──────────────────────┤ PUT /admin/order/customize/{id}/complete
│ │
├─ 查看定制需求列表 │
│ GET /mp/custom/list │
│ │
├─ 查看需求详情 │
│ GET /mp/custom/detail │
│ │
├─ 查看已完成的定制产品 │
│ GET /mp/custom/product/{id} │
│ │
├─ 取消定制需求 │
│ POST /mp/custom/{id}/cancel │
│ │
└─ 下单购买定制产品 │
POST /mp/order/create │
```
---
## 一、C端接口小程序,需登录
### 接口清单
| # | 接口 | 方法 | 路径 | 说明 |
|---|------|------|------|------|
| 1 | 提交定制需求 | POST | `/mp/custom/submit` | 用户发起定制请求 |
| 2 | 定制需求列表 | GET | `/mp/custom/list` | 分页查询我的定制需求 |
| 3 | 定制需求详情 | GET | `/mp/custom/detail` | 查看单条定制需求 |
| 4 | 取消定制需求 | POST | `/mp/custom/{requestId}/cancel` | 取消待处理/处理中的需求 |
| 5 | 已完成定制产品详情 | GET | `/mp/custom/product/{productId}` | 查看定制产品方案 |
| 6 | 我的已完成定制产品列表 | GET | `/mp/custom/products` | 所有已完成的定制产品 |
---
### 接口 C1提交定制需求
```
POST /mp/custom/submit
Content-Type: application/json
Authorization: Bearer {token}
```
#### 请求参数
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| designerId | Long | 否 | 指定定制师ID不传则系统分配 |
| destination | String | 否 | 目标地区,如"云南大理",最长200字 |
| travelPurpose | String | 否 | 旅游目的(字典:`travel_purpose` |
| requestType | String | 否 | 需求类型(字典:`customize_request_type` |
| startDate | String | 否 | 期望出发日期,格式 `yyyy-MM-dd` |
| endDate | String | 否 | 期望结束日期,格式 `yyyy-MM-dd` |
| days | Integer | 否 | 期望天数1~365 |
| adultCount | Integer | 否 | 成人数至少1,最多99 |
| childCount | Integer | 否 | 儿童数0~99 |
| budget | String | 否 | 预算范围(字典:`customize_budget` |
| requirements | String | 否 | 详细需求描述,最长2000字 |
| contactPhone | String | 否 | 联系电话,最长20字 |
| contactName | String | 否 | 联系人,最长50字 |
#### 响应示例
```json
{
"code": 200,
"message": "成功",
"data": {
"requestId": 2029926129876320258,
"userId": 2026279738275856300,
"designerId": null,
"destination": "呼伦贝尔",
"travelPurpose": "FAMILY",
"requestType": "FAMILY_TRIP",
"startDate": "2026-07-01",
"endDate": "2026-07-07",
"days": 7,
"adultCount": 2,
"childCount": 1,
"budget": "BUDGET_10000_20000",
"requirements": "希望安排亲子活动,孩子3岁",
"contactPhone": "13800138000",
"contactName": "张三",
"status": "PENDING",
"statusLabel": "待处理",
"designerName": null,
"designerAvatar": null,
"productId": null,
"reply": null,
"repliedAt": null,
"createTime": "2026-03-19T10:30:00",
"updateTime": "2026-03-19T10:30:00"
}
}
```
#### 响应字段
| 字段 | 类型 | 说明 |
|------|------|------|
| requestId | Long | 定制请求ID |
| userId | Long | 用户ID |
| designerId | Long | 指定定制师ID未指定则null |
| destination | String | 目标地区 |
| travelPurpose | String | 旅游目的(字典:`travel_purpose` |
| requestType | String | 需求类型(字典:`customize_request_type` |
| startDate | String | 期望出发日期 |
| endDate | String | 期望结束日期 |
| days | Integer | 期望天数 |
| adultCount | Integer | 成人数 |
| childCount | Integer | 儿童数 |
| budget | String | 预算范围(字典:`customize_budget` |
| requirements | String | 详细需求描述 |
| contactPhone | String | 联系电话 |
| contactName | String | 联系人 |
| status | String | 状态(字典:`customize_request_status` |
| statusLabel | String | 状态中文标签 |
| designerName | String | 定制师姓名未分配时null |
| designerAvatar | String | 定制师头像URL |
| productId | Long | 关联产品ID定制完成后才有值 |
| reply | String | 定制师回复内容 |
| repliedAt | String | 回复时间 |
| createTime | String | 创建时间 |
| updateTime | String | 更新时间 |
---
### 接口 C2定制需求列表
```
GET /mp/custom/list?page=1&pageSize=20
Authorization: Bearer {token}
```
#### 请求参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| page | int | 否 | 1 | 页码 |
| pageSize | int | 否 | 20 | 每页条数 |
#### 响应示例
```json
{
"code": 200,
"message": "成功",
"data": {
"records": [
{
"requestId": 2029926129876320258,
"userId": 2026279738275856300,
"destination": "呼伦贝尔",
"travelPurpose": "FAMILY",
"requestType": "FAMILY_TRIP",
"startDate": "2026-07-01",
"days": 7,
"adultCount": 2,
"childCount": 1,
"budget": "BUDGET_10000_20000",
"status": "DESIGNING",
"statusLabel": "设计中",
"designerName": "李设计师",
"designerAvatar": "https://oss.example.com/avatar.jpg",
"createTime": "2026-03-19T10:30:00"
}
],
"total": 3,
"page": 1,
"pageSize": 20
}
}
```
---
### 接口 C3定制需求详情
```
GET /mp/custom/detail?id={requestId}
Authorization: Bearer {token}
```
#### 请求参数
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | Long | ✅ | 定制请求ID |
#### 响应
同接口 C1 的响应字段(完整的 `MpCustomizeRequestVO`)。
**前端关键逻辑**
- 当 `status``QUOTED``COMPLETED``productId` 不为null → 展示"查看定制方案"按钮
- 当 `status``PENDING` / `ACCEPTED` / `DESIGNING` → 展示"取消定制"按钮
---
### 接口 C4取消定制需求
```
POST /mp/custom/{requestId}/cancel
Authorization: Bearer {token}
```
#### 请求参数
| 参数 | 类型 | 位置 | 必填 | 说明 |
|------|------|------|------|------|
| requestId | Long | 路径 | ✅ | 定制请求ID |
#### 业务规则
- ✅ 可取消状态:`PENDING`(待处理)、`ACCEPTED`(已接受)、`DESIGNING`(设计中)
- ❌ 不可取消状态:`QUOTED`(已报价)、`COMPLETED`(已完成)、`CANCELLED`(已取消)
#### 响应
同接口 C1 的响应字段,status 变为 `CANCELLED`
---
### 接口 C5/C6已完成定制产品
详见已有文档:`2026-03-19_custom_product_query.md`
---
## 二、管理端接口(后台,需管理员登录)
### 接口清单
| # | 接口 | 方法 | 路径 | 说明 |
|---|------|------|------|------|
| 1 | 定制请求列表 | GET | `/admin/order/customize/page` | 分页+搜索+筛选 |
| 2 | 定制请求详情 | GET | `/admin/order/customize/{requestId}` | 完整信息 |
| 3 | 接受请求 | PUT | `/admin/order/customize/{requestId}/accept` | 分配定制师 |
| 4 | 回复/报价 | PUT | `/admin/order/customize/{requestId}/reply` | 回复或关联产品 |
| 5 | 标记完成 | PUT | `/admin/order/customize/{requestId}/complete` | 定制完成 |
---
### 接口 A1定制请求列表分页
```
GET /admin/order/customize/page?page=1&pageSize=20
Authorization: Bearer {admin-token}
```
#### 请求参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| keyword | String | 否 | | 搜索关键词(联系人/目标地区/需求描述) |
| status | String | 否 | | 状态过滤(字典:`customize_request_status` |
| designerId | Long | 否 | | 定制师ID过滤 |
| sortBy | String | 否 | createTime | 排序字段:`createTime` / `startDate` |
| sortDir | String | 否 | desc | 排序方向:`desc` / `asc` |
| page | int | 否 | 1 | 页码 |
| pageSize | int | 否 | 20 | 每页条数最大100 |
#### 响应示例
```json
{
"code": 200,
"message": "成功",
"data": {
"records": [
{
"requestId": 2029926129876320258,
"userId": 2026279738275856300,
"destination": "呼伦贝尔",
"travelPurpose": "FAMILY",
"requestType": "FAMILY_TRIP",
"startDate": "2026-07-01",
"days": 7,
"adultCount": 2,
"childCount": 1,
"budget": "BUDGET_10000_20000",
"status": "PENDING",
"statusLabel": "待处理",
"designerName": null,
"designerAvatar": null,
"createTime": "2026-03-19T10:30:00"
}
],
"total": 15,
"page": 1,
"pageSize": 20
}
}
```
#### 响应字段CustomizeRequestListVO
| 字段 | 类型 | 说明 |
|------|------|------|
| requestId | Long | 请求ID |
| userId | Long | 用户ID |
| destination | String | 目标地区 |
| travelPurpose | String | 旅游目的(字典:`travel_purpose` |
| requestType | String | 需求类型(字典:`customize_request_type` |
| startDate | String | 期望出发日期 |
| days | Integer | 期望天数 |
| adultCount | Integer | 成人数 |
| childCount | Integer | 儿童数 |
| budget | String | 预算范围(字典:`customize_budget` |
| status | String | 状态(字典:`customize_request_status` |
| statusLabel | String | 状态中文标签 |
| designerName | String | 定制师姓名 |
| designerAvatar | String | 定制师头像URL |
| createTime | String | 创建时间 |
#### 使用场景
管理后台"私人定制"列表页:
1. 顶部筛选栏:状态下拉(全部/待处理/已接受/设计中/已报价/已完成/已取消)+ 关键词搜索 + 定制师筛选
2. 表格展示:目标地区、需求类型、出发日期、天数、人数、预算、定制师、状态、创建时间
3. 操作按钮根据状态显示(见下方状态机)
---
### 接口 A2定制请求详情
```
GET /admin/order/customize/{requestId}
Authorization: Bearer {admin-token}
```
#### 请求参数
| 参数 | 类型 | 位置 | 必填 | 说明 |
|------|------|------|------|------|
| requestId | Long | 路径 | ✅ | 定制请求ID |
#### 响应字段CustomizeRequestVO
同接口 C1 的完整响应字段24个字段。管理端可看到所有信息包括联系人电话等。
---
### 接口 A3接受定制请求
```
PUT /admin/order/customize/{requestId}/accept
Authorization: Bearer {admin-token}
```
#### 请求参数
| 参数 | 类型 | 位置 | 必填 | 说明 |
|------|------|------|------|------|
| requestId | Long | 路径 | ✅ | 定制请求ID |
无请求体。管理员ID从token中自动获取。
#### 业务规则
- 仅 `PENDING`(待处理)状态可接受
- 如果用户未指定定制师designerId为null,自动分配当前操作人为定制师
- 如果用户已指定定制师,保留原定制师
- 状态变更:`PENDING``ACCEPTED`
#### 响应
返回更新后的完整 `CustomizeRequestVO`status=ACCEPTED,designerName/designerAvatar 已填充)。
---
### 接口 A4回复/报价
```
PUT /admin/order/customize/{requestId}/reply
Content-Type: application/json
Authorization: Bearer {admin-token}
```
#### 请求参数
| 参数 | 类型 | 位置 | 必填 | 说明 |
|------|------|------|------|------|
| requestId | Long | 路径 | ✅ | 定制请求ID |
#### 请求体AdminReplyRequest
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| reply | String | ✅ | 回复内容,最长2000字 |
| productId | Long | 否 | 关联的定制产品ID已创建定制产品后传入 |
#### 业务规则
- 仅 `ACCEPTED`(已接受)或 `DESIGNING`(设计中)状态可回复
- **仅填写 reply**:状态变为 `DESIGNING`(设计中)
- **同时传 productId**:状态变为 `QUOTED`已报价,C端用户可通过 productId 查看产品方案
#### 响应示例
```json
{
"code": 200,
"message": "成功",
"data": {
"requestId": 2029926129876320258,
"status": "QUOTED",
"statusLabel": "已报价",
"reply": "您好我为您设计了一套7天6晚的呼伦贝尔亲子游方案,请查看。",
"productId": 2029926131830865921,
"repliedAt": "2026-03-19T14:00:00",
"designerName": "李设计师",
"..."
}
}
```
#### 前端操作流程
```
1. 定制师在后台创建定制产品product-service,productType=CUSTOM
2. 产品设计完成后,回到定制请求页面
3. 点击"回复/报价"按钮 → 弹窗填写回复内容 + 选择关联产品
4. 调用此接口提交
5. C端用户在"我的定制"中看到状态变为"已报价",可查看产品方案
```
---
### 接口 A5标记完成
```
PUT /admin/order/customize/{requestId}/complete
Authorization: Bearer {admin-token}
```
#### 请求参数
| 参数 | 类型 | 位置 | 必填 | 说明 |
|------|------|------|------|------|
| requestId | Long | 路径 | ✅ | 定制请求ID |
无请求体。
#### 业务规则
- 仅 `QUOTED`(已报价)状态可标记完成
- 状态变更:`QUOTED``COMPLETED`
- 通常在用户确认方案或已下单后,定制师手动标记
#### 响应
返回更新后的完整 `CustomizeRequestVO`status=COMPLETED
---
## 三、状态机与按钮显示
### 状态流转
```
PENDING(待处理) ──accept──→ ACCEPTED(已接受)
│ │
│cancel │cancel
↓ ↓
CANCELLED ──reply(仅文字)──→ DESIGNING(设计中)
│cancel
──reply(+productId)──→ QUOTED(已报价)
──complete──→ COMPLETED(已完成)
```
### 管理端按钮显示
| 状态 | 可用操作 |
|------|---------|
| PENDING待处理 | [接受请求] |
| ACCEPTED已接受 | [回复] [报价] |
| DESIGNING设计中 | [回复] [报价] |
| QUOTED已报价 | [标记完成] |
| COMPLETED已完成 | 无操作 |
| CANCELLED已取消 | 无操作 |
### C端按钮显示
| 状态 | 可用操作 |
|------|---------|
| PENDING待处理 | [取消定制] |
| ACCEPTED已接受 | [取消定制] |
| DESIGNING设计中 | [取消定制] |
| QUOTED已报价 | [查看定制方案] |
| COMPLETED已完成 | [查看定制方案] [去下单] |
| CANCELLED已取消 | 无操作 |
---
## 四、关联字典
### customize_request_status定制请求状态
| dict_value | dict_label | 说明 |
|------------|-----------|------|
| PENDING | 待处理 | 用户刚提交,等待定制师接受 |
| ACCEPTED | 已接受 | 定制师已接受请求 |
| DESIGNING | 设计中 | 定制师正在设计方案 |
| QUOTED | 已报价 | 已关联产品,等待用户确认 |
| COMPLETED | 已完成 | 定制流程完结 |
| CANCELLED | 已取消 | 用户取消请求 |
### customize_request_type需求类型
| dict_value | dict_label |
|------------|-----------|
| FAMILY_TRIP | 亲子游 |
| HONEYMOON | 蜜月游 |
| GROUP_TRIP | 团建游 |
| SENIOR_TRIP | 银发游 |
| ADVENTURE | 探险游 |
| PHOTOGRAPHY | 摄影游 |
| CULTURE | 文化游 |
| OTHER | 其他 |
### travel_purpose旅游目的
| dict_value | dict_label |
|------------|-----------|
| LEISURE | 休闲度假 |
| ADVENTURE | 探险体验 |
| CULTURE | 文化探访 |
| FAMILY | 亲子陪伴 |
| ROMANCE | 浪漫旅行 |
| TEAM | 团队建设 |
| OTHER | 其他 |
### customize_budget预算范围
| dict_value | dict_label |
|------------|-----------|
| UNDER_3000 | 3000元以下/人 |
| BUDGET_3000_5000 | 3000-5000元/人 |
| BUDGET_5000_10000 | 5000-10000元/人 |
| BUDGET_10000_20000 | 10000-20000元/人 |
| ABOVE_20000 | 20000元以上/人 |
| NO_LIMIT | 不限预算 |
---
## 五、管理端页面布局建议
### 定制请求列表页
```
┌─────────────────────────────────────────────────────────────────┐
│ 私人定制管理 │
├─────────────────────────────────────────────────────────────────┤
│ 状态: [全部 ▼] 定制师: [全部 ▼] 关键词: [____________] [搜索] │
├─────┬──────┬──────┬───┬───┬─────┬──────┬─────┬────────┬────────┤
│ 目的地│需求类型│出发日期│天数│人数│ 预算 │ 定制师 │ 状态 │ 创建时间 │ 操作 │
├─────┼──────┼──────┼───┼───┼─────┼──────┼─────┼────────┼────────┤
│呼伦贝尔│亲子游 │07-01 │ 7 │2大1小│1~2万/人│ 李设计师│待处理│03-19 10:30│[接受] │
│三亚 │蜜月游 │08-15 │ 5 │2大0小│5千~1万│ 未分配 │待处理│03-18 09:00│[接受] │
│大理 │文化游 │04-01 │ 3 │1大0小│不限 │ 王设计师│设计中│03-17 14:20│[回复] │
└─────┴──────┴──────┴───┴───┴─────┴──────┴─────┴────────┴────────┘
```
### 定制请求详情页(弹窗或新页面)
```
┌─────────────────────────────────────────────┐
│ 定制请求详情 状态: 待处理 │
├─────────────────────────────────────────────┤
│ 基本信息 │
│ 目标地区: 呼伦贝尔 │
│ 需求类型: 亲子游 │
│ 旅游目的: 亲子陪伴 │
│ 出发日期: 2026-07-01 ~ 2026-07-07 (7天) │
│ 人数: 2成人 1儿童 │
│ 预算: 10000-20000元/人 │
├─────────────────────────────────────────────┤
│ 联系人 │
│ 姓名: 张三 │
│ 电话: 13800138000 │
├─────────────────────────────────────────────┤
│ 需求描述 │
│ 希望安排亲子活动,孩子3岁 │
├─────────────────────────────────────────────┤
│ 定制师信息 │
│ 定制师: 未分配 │
│ 回复: 无 │
│ 关联产品: 无 │
├─────────────────────────────────────────────┤
│ [接受请求] │
└─────────────────────────────────────────────┘
```
---
## 六、完整调用示例
### 管理端:处理一个定制请求
```javascript
// 1. 加载列表(筛选待处理)
const list = await adminRequest.get('/admin/order/customize/page', {
params: { status: 'PENDING', page: 1, pageSize: 20 }
})
// 2. 查看详情
const detail = await adminRequest.get(`/admin/order/customize/${requestId}`)
// 3. 接受请求(自动分配当前管理员为定制师)
await adminRequest.put(`/admin/order/customize/${requestId}/accept`)
// 4. 定制师创建定制产品通过产品管理模块,productType=CUSTOM
// ... 创建产品后获得 productId
// 5. 回复并关联产品
await adminRequest.put(`/admin/order/customize/${requestId}/reply`, {
reply: '您好!我为您设计了一套呼伦贝尔亲子游方案,请查看。',
productId: createdProductId
})
// 6. 用户确认后标记完成
await adminRequest.put(`/admin/order/customize/${requestId}/complete`)
```
### C端提交并跟踪定制需求
```javascript
// 1. 提交定制需求
const res = await request.post('/mp/custom/submit', {
destination: '呼伦贝尔',
travelPurpose: 'FAMILY',
requestType: 'FAMILY_TRIP',
startDate: '2026-07-01',
endDate: '2026-07-07',
days: 7,
adultCount: 2,
childCount: 1,
budget: 'BUDGET_10000_20000',
requirements: '希望安排亲子活动',
contactName: '张三',
contactPhone: '13800138000'
})
// 2. 查看我的定制需求列表
const list = await request.get('/mp/custom/list', { params: { page: 1 } })
// 3. 查看详情
const detail = await request.get('/mp/custom/detail', { params: { id: requestId } })
// 4. 当状态变为 QUOTED/COMPLETED 且有 productId
if (detail.data.productId && ['QUOTED', 'COMPLETED'].includes(detail.data.status)) {
const product = await request.get(`/mp/custom/product/${detail.data.productId}`)
// 展示定制产品方案
}
// 5. 查看所有已完成的定制产品
const products = await request.get('/mp/custom/products')
```
---
🤖 Generated with [Claude Code](https://claude.com/claude-code)