---
schema: "hl-changelog/v2"
ticket: "5581"
title: "核算餐厅/导游/摄影资源下拉选项接口"
consumer: "admin"
author: "yst"
change_type: "新增接口"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "implemented"
frontend_owner: "mmg"
frontend_ref: "hl-admin@479c44ce399995782504887e0f3aa68274a24e19"
target_release: ""
verified_at: "2026-08-06"
status_note: "hl-resource-service；PR #5583 已合并 dev-v3 并部署测试服，Gateway 实调验证通过（3 接口 + 必填/关键词/鉴权边界全绿）；等待管理后台接入。"
updated_at: "2026-08-07"
base: "dev-v3"
---

# 核算餐厅 / 导游 / 摄影资源下拉选项接口（新增 3 个）

- **变更类型**：新增接口
- **端类型**：管理后台
- **日期**：2026-08-06
- **服务**：hl-resource-service（资源服务）
- **关联 Issue**：#5581 新增核算餐厅导游摄影资源下拉接口

---

## 1. 接口背景

管理后台核单（settlement）场景在录入餐厅 / 导游 / 摄影的实际费用时，需要下拉选择对应的资源（餐厅资源、导游人员、摄影人员），并直接看到该资源的默认单价用于预填费用。

本次在资源服务新增 3 个统一前缀的资源下拉选项查询接口，供管理后台核单页消费。接口只返回"识别资源 + 展示名 + 价格"所需的最小字段集合，与订单侧的人员分配（staffAssignment）无任何关联。

---

## 2. 变更清单

| # | 方法 | 路径 | 说明 |
|---|------|------|------|
| 1 | GET | `/admin/resource-options/restaurants` | 分页查询餐厅资源选项 |
| 2 | GET | `/admin/resource-options/guides` | 分页查询导游资源选项（固定 STAFF_TYPE=GUIDE） |
| 3 | GET | `/admin/resource-options/photographers` | 分页查询摄影资源选项（固定 STAFF_TYPE=PHOTOGRAPHER） |

三个接口均为**新增**，无既有接口被修改或删除。

---

## 3. 接口详情

| 项 | 说明 |
|---|------|
| 使用场景 | 管理后台核单录入费用时，下拉选择餐厅 / 导游 / 摄影资源 |
| 认证 | 需要登录态，请求头携带 `Authorization: Bearer <token>`，未携带返回 401 |
| 幂等性 | GET 查询接口，天然幂等，可安全重试 |
| 限流 | 无业务级限流，受网关通用限流约束 |
| 分页 | 三个接口均为分页查询，返回统一分页结构 `PageResult` |

---

## 4. 接口入参

### 4.1 GET /admin/resource-options/restaurants

全部为 Query 参数：

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| pageNo | Integer | 是 | 页码，从 1 开始 |
| pageSize | Integer | 是 | 每页条数 |
| keyword | String | 否 | 餐厅名称关键词，模糊匹配；服务端自动 trim，纯空白等价于不传 |
| city | String | 否 | 城市，精确匹配 |

### 4.2 GET /admin/resource-options/guides

全部为 Query 参数：

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| pageNo | Integer | 是 | 页码，从 1 开始 |
| pageSize | Integer | 是 | 每页条数 |
| serviceDate | LocalDate | **是** | 服务日期，格式 `yyyy-MM-dd`；用于匹配当日人员价格，缺失返回 400 |
| keyword | String | 否 | 人员姓名关键词，模糊匹配；服务端自动 trim，纯空白等价于不传 |

注：服务端固定按 `STAFF_TYPE=GUIDE` 过滤，**不含助理导游**，调用方无需也不支持传 staffType。

### 4.3 GET /admin/resource-options/photographers

入参与 guides 完全一致（serviceDate 必填），服务端固定按 `STAFF_TYPE=PHOTOGRAPHER` 过滤。

---

## 5. 出参字段

统一响应包装：`Result<PageResult<T>>`，`code=200` 表示成功。

实测响应顶层字段：`{ code, message, data, traceId, success }`（注意是 `message` 不是 `msg`）；其中分页数据在 `data` 内，字段为 `{ records, total, page, pageSize }`（注意列表字段是 `records` 不是 `list`）。

### 5.1 餐厅资源选项 RestaurantResourceOptionRespVO

| 字段 | 类型 | 说明 |
|------|------|------|
| resourceId | String | 餐厅资源 ID，雪花 ID 序列化为字符串（防 JS 精度丢失）。**仅用于识别资源，不是订单侧人员分配 ID** |
| resourceName | String | 餐厅名称 |
| city | String \| null | 城市。取值规则：cityName 优先、city 回退，两者均空白时为 null |
| settleType | null | 固定 null（餐厅无结算方式概念） |
| settleTypeName | null | 固定 null |
| pricePerPerson | BigDecimal | 餐厅人均价。**餐厅唯一的价格来源**（不是日期价） |
| defaultUnitPrice | BigDecimal \| null | 默认单价，恒等于人均价；未配置人均价时为 null |
| priceConfigured | Boolean | 是否已配置人均价 |

### 5.2 人员资源选项 StaffResourceOptionRespVO（guides / photographers 共用）

| 字段 | 类型 | 说明 |
|------|------|------|
| resourceId | String | staff 表 staff_id，雪花 ID 序列化为字符串（防 JS 精度丢失）。**仅用于识别资源，明确不是 staffAssignmentId** |
| resourceName | String | 人员姓名 |
| staffType | String | 人员类型编码：`GUIDE` / `PHOTOGRAPHER` |
| staffTypeName | String | 人员类型名称：`导游` / `摄影师` |
| settleType | String \| null | 结算方式编码：`cash` / `sign` / `company`；空白时为 null；未知编码原样保留返回 |
| settleTypeName | String \| null | 结算方式名称：`现付` / `签单` / `公司付款`；编码为空或未知时为 null |
| serviceDate | LocalDate | 服务日期，即入参 serviceDate，是共享人员类型价格的匹配日期 |
| protocolPrice | BigDecimal \| null | 当日共享协议价 |
| settlementPrice | BigDecimal \| null | 当日共享结算价 |
| defaultUnitPrice | BigDecimal \| null | 默认单价：结算价优先、协议价回退，两者均空时为 null |
| priceConfigured | Boolean | 是否至少配置了一种当日价格 |

注：响应**不暴露** calendarStatus 字段。

---

## 6. 枚举 / 数据字典

### 6.1 staffType（人员类型，仅本接口出现的两个值）

| 编码 | 名称（staffTypeName） |
|------|----------------------|
| GUIDE | 导游 |
| PHOTOGRAPHER | 摄影师 |

### 6.2 settleType（结算方式）

| 编码 | 名称（settleTypeName） |
|------|----------------------|
| cash | 现付 |
| sign | 签单 |
| company | 公司付款 |

说明：编码为空时 settleType / settleTypeName 均为 null；出现上表之外的未知编码时，settleType 原样返回、settleTypeName 为 null。

---

## 7. 错误码

| HTTP / code | 触发条件 | 返回 message |
|---|---|---|
| 400 | guides / photographers 未传 serviceDate | 服务日期不能为空 |
| 401 | 未携带有效的 Authorization 头（未登录 / token 失效） | 缺少有效的 Authorization 头 |

---

## 8. 示例

### 8.1 典型成功

请求（餐厅）：

```
GET /admin/resource-options/restaurants?pageNo=1&pageSize=10&keyword=七间房&city=海拉尔
```

响应（实测）：

```json
{
  "code": 200,
  "message": "成功",
  "data": {
    "records": [
      {
        "resourceId": "2023382108491247617",
        "resourceName": "七间房全羊馆",
        "city": "海拉尔",
        "settleType": null,
        "settleTypeName": null,
        "pricePerPerson": 120.00,
        "defaultUnitPrice": 120.00,
        "priceConfigured": true
      }
    ],
    "total": 1,
    "page": 1,
    "pageSize": 10
  },
  "traceId": null,
  "success": true
}
```

请求（导游）：

```
GET /admin/resource-options/guides?pageNo=1&pageSize=10&serviceDate=2026-08-06&keyword=李雪梅
```

响应（实测）：

```json
{
  "code": 200,
  "message": "成功",
  "data": {
    "records": [
      {
        "resourceId": "1002",
        "resourceName": "李雪梅",
        "staffType": "GUIDE",
        "staffTypeName": "导游",
        "settleType": "cash",
        "settleTypeName": "现付",
        "serviceDate": "2026-08-06",
        "protocolPrice": 300.00,
        "settlementPrice": 299.00,
        "defaultUnitPrice": 299.00,
        "priceConfigured": true
      }
    ],
    "total": 1,
    "page": 1,
    "pageSize": 10
  },
  "traceId": null,
  "success": true
}
```

请求（摄影）：

```
GET /admin/resource-options/photographers?pageNo=1&pageSize=10&serviceDate=2026-08-06
```

响应结构与导游一致，staffType 为 `PHOTOGRAPHER`、staffTypeName 为 `摄影师`。

### 8.2 边界情况

keyword 为纯空白（自动 trim 后等价于不传，按全量分页返回）：

```
GET /admin/resource-options/restaurants?pageNo=1&pageSize=10&keyword=%20%20
```

响应：正常 200，keyword 不生效，返回全量分页数据。

无任何匹配结果（空数组，注意 total=0、records 为空数组而非 null）：

```json
{
  "code": 200,
  "message": "成功",
  "data": {
    "records": [],
    "total": 0,
    "page": 1,
    "pageSize": 10
  },
  "traceId": null,
  "success": true
}
```

人员当日未配置任何价格（defaultUnitPrice 为 null、priceConfigured 为 false）：

```json
{
  "code": 200,
  "message": "成功",
  "data": {
    "records": [
      {
        "resourceId": "1003",
        "resourceName": "张三",
        "staffType": "GUIDE",
        "staffTypeName": "导游",
        "settleType": null,
        "settleTypeName": null,
        "serviceDate": "2026-08-06",
        "protocolPrice": null,
        "settlementPrice": null,
        "defaultUnitPrice": null,
        "priceConfigured": false
      }
    ],
    "total": 1,
    "page": 1,
    "pageSize": 10
  },
  "traceId": null,
  "success": true
}
```

### 8.3 业务失败

guides / photographers 缺失必填的 serviceDate：

```
GET /admin/resource-options/guides?pageNo=1&pageSize=10
```

响应：

```json
{
  "code": 400,
  "message": "服务日期不能为空",
  "data": null,
  "traceId": null,
  "success": false
}
```

未登录调用：

```
GET /admin/resource-options/restaurants?pageNo=1&pageSize=10
（不携带 Authorization 头）
```

响应：

```json
{
  "code": 401,
  "message": "缺少有效的 Authorization 头",
  "data": null,
  "traceId": "00fef1580108417f",
  "success": false
}
```

---

## 9. 业务边界

适用：
- 管理后台核单录入费用时，下拉选择餐厅 / 导游 / 摄影资源。

不适用 / 特殊边界：
- resourceId **仅用于识别资源**：餐厅接口的 resourceId 是餐厅资源 ID；人员接口的 resourceId 是 staff 表 staff_id，**明确不是订单侧的 staffAssignmentId**，不能拿它去调订单人员分配相关接口。
- 餐厅价格只有"人均价"一个来源，不存在按日期变化的价格；defaultUnitPrice 恒等于 pricePerPerson。
- 人员价格是"共享人员类型价格"，按 serviceDate 匹配当日协议价 / 结算价；当日两种价格均未配置时 defaultUnitPrice 为 null、priceConfigured 为 false。
- defaultUnitPrice 取值规则固定为"结算价优先、协议价回退"，调用方不需要自行二选一。
- guides 接口固定只返回 GUIDE 类型人员，**不含助理导游**；photographers 固定只返回 PHOTOGRAPHER 类型。
- 餐厅的 settleType / settleTypeName 固定为 null，不是数据缺失。

---

## 10. 修改前后对比

新增接口，无修改前后对比。

---

## 11. 影响评估 / 回滚

新增接口，无回滚影响：
- 不破坏任何既有接口与字段，无兼容性问题。
- 不要求前端同步上线；前端未接入时接口存在但不影响任何现有功能。
- 如需回滚，下线 3 个新端点即可，无数据 / 状态残留。

---

## 12. 注意事项

- 三个接口的资源 ID 均为雪花 ID 序列化后的 **String 类型**，前端请勿按 Number 处理，避免精度丢失。
- guides / photographers 的 serviceDate 是**必填**项（格式 `yyyy-MM-dd`），缺失直接 400；restaurants 无此参数。
- keyword 服务端自动 trim，前端无需预处理空白。
- 人员 settleType 可能出现上表之外的未知编码，此时 settleType 原样返回、settleTypeName 为 null，需按未知编码兜底处理。
- 响应不暴露 calendarStatus 字段。

---

## 13. 关联 / 联系人

- Issue：https://git.1814.love:8443/wx/HL/issues/5581
- PR：https://git.1814.love:8443/wx/HL/pulls/5583
- Commit：https://git.1814.love:8443/wx/HL/commit/258a7d9485cd2c0a8cbeca32b3b1e272d44b5376
- 后端负责人：腰苏图
- 接口已在测试服（web.test.1814.love:9443）实调验证通过。
