# 【新增接口·管理后台】价格日历——§9.5 聚合总览 + §9.6 多车型批量设价(对齐原型,4→6 接口)

> 服务:hl-fleet-service(8087) | 分支:dev-v3 | PR:#3727 | 已部署测试服并 14 项 API 实测通过(2026-06-12)
> 契约出处:FLEET API v1.5.62 §9.5/§9.6(文档站已同步) | 前端触发位:车管控制台「价格日历」整页(page_pricing 原型)
> 背景:前端反馈现有价格日历接口拼不出原型页面(原型需要一次拿到全部车型×日期价格矩阵+节假日+统计,且批量改价是多车型多选)——本次补齐,**原有 4 接口零变更**。

## ⚠️ 关键说明

1. **整页数据一次拉取**:新增 `GET /admin/fleet/pricing-calendar/overview`,一次返回[大类→车型→区间价格矩阵+统计]+节假日列表+全局价格区间。「全部大类」月卡片、单大类月热力、季度/半年视图全部用它,**不再需要按车型逐个调 §9.1**。
2. **节假日数据源收口后端**:格子上的「假」标记请改用 overview 返回的 `holidays` 数组判断(原型里前端硬编码的 HOLIDAYS_2026 删掉),真相源=后端 Nacos 配置,每年由后端维护、前端零改动。
3. **`holidays` 只含请求区间内的节假日**:批量改价弹窗如果选择了超出当前已加载区间的日期(例如页面加载了 1-5 月、批改 10 月国庆),请按所选区间重拉一次 overview 取节假日。
4. **月卡片统计口径**:`stats` 按**请求区间**统计(均/低/高)。一次拉多个月时,单月统计请前端从 `prices[]` 按月自聚(原型本来就是前端算的,矩阵数据完备);`yearAvgPrice`(全年均)后端已算好直接用。
5. **多车型批量改价**:新增 `PUT /batch-set`,vehicleModelIds 1-50 个多选,**任一车型 ID 不存在整批拒绝**(600503,消息列出全部缺失 ID),三模式(ABS/DELTA/PERCENT)/仅周末/仅节假日等与单车型 §9.2 完全同源。整批一个事务,失败全回滚无半批。
6. 600503 消息升级为「车型型号不存在: {ID}」(带具体 ID,错误码不变,按 code 判断的前端无影响)。
7. 金额出参一律字符串(如 `"999.00"`),雪花 ID 字符串。

## 1. §9.5 价格日历聚合总览

`GET /admin/fleet/pricing-calendar/overview?startDate=2026-01-01&endDate=2026-05-31`

| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| startDate | query | string | 是 | 开始日期 yyyy-MM-dd |
| endDate | query | string | 是 | 结束日期,须 ≥ startDate 且区间 ≤ 366 天(600501/600502) |

### 响应示例(测试服实测裁剪)

```json
{
  "code": 200,
  "message": "成功",
  "data": {
    "startDate": "2026-01-01",
    "endDate": "2026-05-31",
    "globalMinPrice": "950.00",          // 区间内全部车型最低日价(色阶图例下界;无任何设价=null)
    "globalMaxPrice": "4500.00",         // 区间内全部车型最高日价(色阶图例上界)
    "holidays": ["2026-01-01", "2026-02-16", "2026-02-17"],  // 区间内节假日(格子「假」标记数据源,升序)
    "types": [                            // 车辆大类(sortOrder 升序,仅含有型号的大类)
      {
        "vehicleTypeId": "2057378611889180674",
        "typeKey": "suv2",
        "typeName": "SUV系列",
        "icon": "",
        "models": [
          {
            "vehicleModelId": "2057378612593823745",
            "modelName": "丰田普拉多",
            "basePrice": "1000.00",       // 车型基准价(可 null)
            "stats": {
              "avgPrice": "1673.00",      // 请求区间内已设价日均价(HALF_UP 两位;无设价=null)
              "minPrice": "1500.00",      // 区间最低
              "maxPrice": "2250.00",      // 区间最高
              "yearAvgPrice": "1293.00"   // startDate 所在自然年的全年均价(卡片「全年均」)
            },
            "prices": [                   // 区间内已设价日(升序;未设价日不出现)
              { "date": "2026-01-01", "dayPrice": "2250.00", "status": "AVAILABLE", "remark": "" }
            ]
          }
        ]
      }
    ]
  }
}
```

> 无设价的车型也会返回(prices=[]、stats 字段全 null),前端展示全部车型无需另调车型树。

### curl

```bash
curl -k "https://web.test.1814.love:9443/admin/fleet/pricing-calendar/overview?startDate=2026-01-01&endDate=2026-05-31" \
  -H "Authorization: Bearer {token}"
```

## 2. §9.6 多车型批量设价

`PUT /admin/fleet/pricing-calendar/batch-set`

### 入参(body) = §9.2 单车型全部字段 + vehicleModelIds

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| vehicleModelIds | string[] | 是 | 车型型号 ID 列表(1-50 个,雪花字符串);任一不存在整批拒绝 600503;重复自动去重;元素不能为 null |
| startDate / endDate | string | 是 | 同 §9.2(≤366 天) |
| adjustMode | string | 否 | ABS=固定价 / DELTA=现价加减 / PERCENT=百分比,默认 ABS |
| dayPrice | string | ABS 必填 | 同 §9.2 |
| adjustValue | string | DELTA/PERCENT 必填 | 同 §9.2(可负;PERCENT 如 10=+10%) |
| status / remark / weekdayOnly / weekendOnly / holidayOnly / selectedWeekdays / excludeDates | — | 否 | 全部与 §9.2 同源(三筛选互斥返 400) |

### 请求示例——原型「批量改价」弹窗:选 2 个车型春节区间上浮 15%

```bash
curl -k -X PUT "https://web.test.1814.love:9443/admin/fleet/pricing-calendar/batch-set" \
  -H "Authorization: Bearer {token}" -H "Content-Type: application/json" \
  -d '{"vehicleModelIds":["2057378612593823745","2064998010110029826"],
       "startDate":"2026-02-16","endDate":"2026-02-22",
       "adjustMode":"PERCENT","adjustValue":"15","holidayOnly":true}'
```

成功:`{ "code": 200, "message": "成功" }`

### 错误码

| code | 触发场景 |
|---|---|
| 400 | 参数校验(ID 列表空/>50/含 null、三筛选互斥、条件必填、白名单、两位小数) |
| 600501 / 600502 | 日期顺序 / 区间超 366 天 |
| 600503 | 任一车型不存在,消息列出全部缺失 ID,**整批不执行** |

### 防护(前端无感知,连点会收到提示)

- 同参数 3 秒幂等窗口(传参顺序/重复 ID 不影响判重)+ 批量请求间互斥锁
- 整批一个事务:任一失败全部回滚,不会出现"改了一半"

## 3. 测试服实测数据点

| 操作 | 结果 |
|---|---|
| overview 2099-02 区间(含 2 车型设价) | 200,types 树/stats/globalMin-Max/prices 全正确 |
| overview holidays(配置节假日区间) | `["2099-01-15"]` 与 Nacos 配置一致 |
| batch-set 2 车型 ABS 999 | 两车型全部写入,overview 立即可见 |
| batch-set 含不存在 ID | 600503 消息带缺失 ID,整批未执行 |
| 区间 >366 / start>end | 600502 / 600501 |
| 原 §9.1 单车型月视图 | 回归正常,零变更 |
