# 定制产品新增客户信息字段 - 前端对接指南

> **日期**: 2026-03-19
> **后端状态**: ✅ 已完成并部署测试环境
> **影响范围**: 产品创建/更新/保存/详情 接口（管理端）

---

## 变更说明

定制产品（productType=CUSTOM）新增3个客户信息字段，用于记录定制需求的客户基本信息。

**变更原因**：管理端「定制产品」编辑页的「客户信息」区域（客户姓名、联系电话、出发日期）无法保存，因为后端缺少对应字段。

---

## 新增字段

| 字段名 | 类型 | 最大长度 | 必填 | 说明 |
|--------|------|----------|------|------|
| customerName | String | 50字符 | 否 | 客户姓名（仅定制产品使用） |
| contactPhone | String | 20字符 | 否 | 联系电话（仅定制产品使用） |
| departureDate | String (yyyy-MM-dd) | - | 否 | 出发日期（仅定制产品使用） |

---

## 受影响的接口

| # | 接口 | 方法 | 路径 | 变更内容 |
|---|------|------|------|----------|
| 1 | 创建产品 | POST | `/admin/product` | 请求体新增3个字段 |
| 2 | 更新产品 | PUT | `/admin/product/{productId}` | 请求体新增3个字段 |
| 3 | 保存产品（创建或更新） | POST | `/admin/product/save` | 请求体新增3个字段 |
| 4 | 获取产品详情 | GET | `/admin/product/{productId}` | 响应体新增3个字段 |
| 5 | 获取产品详情（含价格） | GET | `/admin/product/{productId}/with-prices` | 响应体新增3个字段 |

---

## 接口 1：创建产品

```
POST /admin/product
```

### 请求体新增字段

```json
{
  "name": "丽江5日深度定制游",
  "productType": "CUSTOM",
  "tripDays": 5,
  "departureCity": "昆明",
  "destinationCity": "丽江",
  "customizerId": "1893012345678901234",
  "customerName": "张三",
  "contactPhone": "13800138000",
  "departureDate": "2026-07-01"
}
```

| 字段 | 类型 | 必填 | 校验规则 | 说明 |
|------|------|------|----------|------|
| customerName | String | 否 | 最长50字符 | 客户姓名（定制产品） |
| contactPhone | String | 否 | 最长20字符 | 联系电话（定制产品） |
| departureDate | String | 否 | 格式 yyyy-MM-dd | 出发日期（定制产品） |

---

## 接口 2：更新产品

```
PUT /admin/product/{productId}
```

### 请求体新增字段

与创建产品相同的3个字段。**选择性更新**：只有传入非null的字段才会更新，不传的字段保持原值不变。

```json
{
  "customerName": "李四",
  "contactPhone": "13900139000",
  "departureDate": "2026-08-15"
}
```

---

## 接口 3：保存产品（创建或更新）

```
POST /admin/product/save
```

### 请求体新增字段

与创建产品相同的3个字段。当 `productId` 有值时走更新逻辑（选择性更新），无值时走创建逻辑。

```json
{
  "productId": null,
  "name": "丽江定制游",
  "productType": "CUSTOM",
  "customerName": "王五",
  "contactPhone": "13700137000",
  "departureDate": "2026-09-01"
}
```

---

## 接口 4/5：获取产品详情

```
GET /admin/product/{productId}
GET /admin/product/{productId}/with-prices?departureDate=2026-07-01
```

### 响应体新增字段

```json
{
  "code": 200,
  "data": {
    "productId": "1893012345678901234",
    "productType": "CUSTOM",
    "name": "丽江5日深度定制游",
    "customerName": "张三",
    "contactPhone": "13800138000",
    "departureDate": "2026-07-01",
    "customizerId": "1893012345678901234",
    "status": "DRAFT"
  }
}
```

| 字段 | 类型 | 说明 |
|------|------|------|
| customerName | String | 客户姓名（定制产品，其他类型产品为null） |
| contactPhone | String | 联系电话（定制产品，其他类型产品为null） |
| departureDate | String (yyyy-MM-dd) | 出发日期（定制产品，其他类型产品为null） |

---

## 数据库变更

```sql
ALTER TABLE product
  ADD COLUMN customer_name VARCHAR(50) NULL COMMENT '客户姓名（定制产品）' AFTER customizer_id,
  ADD COLUMN contact_phone VARCHAR(20) NULL COMMENT '联系电话（定制产品）' AFTER customer_name,
  ADD COLUMN departure_date DATE NULL COMMENT '出发日期（定制产品）' AFTER contact_phone;
```

> 已在本地和测试环境执行完毕。

---

## 前端对接要点

1. **仅定制产品（CUSTOM）类型使用这3个字段**，其他产品类型（CORE/ROUTE/GROUP）这些字段返回null
2. **更新接口是选择性更新**：不传的字段不会被清空，只有显式传入的字段才会更新
3. **出发日期格式**：`yyyy-MM-dd`，如 `2026-07-01`
4. **字段位置**：在产品编辑页的「客户信息」区域展示，与定制师ID（customizerId）关联使用
