文件
hl-api-changelog/changelogs-v2/2026-08/30_6717_车队关联供应商并展示供应商全名-修改接口-管理后台.md
T
Mimingguang 0e1ab992e8
changelog-filename-gate / validate (push) Successful in 2s
chore(changelog): 回写 #6717 前端消费状态
2026-08-30 18:10:46 +08:00

32 KiB
原始文件 Blame 文件历史

schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
schema ticket title consumer author change_type backend_status gateway_status frontend_status frontend_owner frontend_ref target_release verified_at status_note updated_at base
hl-changelog/v2 6717 车队关联供应商并展示供应商全名 admin wx(GIT) 修改接口 deployed verified verified mmg 4faf23bb v2.1 2026-08-30 PR #6753 已合并 dev-v3(merge commit 447b92f5);Deploy Panel 任务 2fe21f84(hl-fleet-service,2026-08-30 17:20)与 f29a293f(hl-resource-service,2026-08-30 17:22)均已部署测试服成功。真实 TEST 身份已验证 5 条负向链路全绿 + 列表字段结构正确,测试数据已清理。车队列表操作列的「供应商」按钮需下线,改为在车队新增/编辑弹窗选择供应商。前端已消费(frontend_status: verified):车队列表下线操作列「供应商」入口并新增供应商列透传 supplierName 快照;新增/编辑弹窗内嵌供应商 NSelect(远程搜索 FLEET+ACTIVE、可清空、编辑回填并补快照选项防显原始 ID),提交体携带 supplierId 字符串;601108/601109/601110/601111 按 bizCode 精确提示,新建不选供应商落 DISABLED 并提示。前端 commit 4faf23bb 已推 v2.1。 2026-08-30 dev-v3

车队管理:车队关联供应商并展示供应商全名

存放目录:

  • 二期(v3,order-v3 标签的工单)→ changelogs-v2/2026-08/

服务: hl-fleet-service(端口 8094)/ hl-resource-service(内部依赖) PR: #6753 Issue: #6717 日期: 2026-08-30 影响范围: 管理后台「车辆管理 - 车队管理」列表/新增/编辑/启用

车队管理新增供应商归属字段(可空),供应商只能随车队新增/编辑一起提交,不再提供单独配置入口。


⚠️ 关键变化

  • 车队列表操作列的「供应商」按钮(views/fleet/teams/index.vue 弹窗 SupplierResourceRelModal)需要下线;供应商关联改为在车队新增/编辑弹窗里选择。
  • 「不选供应商不能启动,只能停用」:未关联供应商的车队调用启用接口会被 601108 拦截;新建时不选供应商则车队落停用态。
  • 已有订单(名下车辆存在非取消派单)的车队,不允许更换或清除供应商;允许首次绑定。

一、背景

车队此前没有供应商归属字段;供应商域(supplier_main,类型字典 supplier_type)已支持车队类型供应商(FLEET),但车队主数据与供应商档案之间未建立关联。工单 #6717 要求车队管理列表展示供应商全名,并在车队新增/编辑时明确供应商归属。

最终口径(2026-08-30 用户确认,覆盖工单原文「必选」语义):

  1. 供应商字段不必填(可选);不选 → 不能启用,只能停用。
  2. 车队已有订单时,不允许更换或清除供应商(含已有订单的历史车队豁免存量,不动存量数据)。
  3. 去掉单独配置供应商接口入口:前端车队列表的「供应商」按钮下线;供应商关联只随车队新增/编辑一起提交。
  4. 供应商全名以写时快照存于 fleet_team.supplier_name;列表/详情零 Feign 读,供应商改名后陈旧、重新编辑可刷新。
  5. 供应商资格校验走跨服务 Feign(fleet → resource GET /internal/supplier/{supplierId}/fleet-eligibility):主体存在 + 状态 ACTIVE + 类型关联含 FLEET。

二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 分页查询车队 GET /admin/fleet/teams/page 响应新增字段 records[] 增加 supplierId(String/null) + supplierName(String/null)
2 查询车队详情 GET /admin/fleet/teams/{fleetTeamId} 响应新增字段 同 #1
3 新增车队 POST /admin/fleet/teams 请求体新增可选字段 + 响应新增字段 请求体加 supplierId(Long 字符串/可空);响应同 #2
4 编辑车队 PUT /admin/fleet/teams/{fleetTeamId} 请求体新增可选字段 + 响应新增字段 + 失败语义 请求体加 supplierId;更换/清除时已有订单被 601111 拦截;清除且当前 ACTIVE 会强制落 DISABLED
5 启用车队 POST /admin/fleet/teams/{fleetTeamId}/enable 失败语义新增 supplierId==null 时抛 601108「车队未关联供应商,不能启用」

三、接口详情

1. 分页查询车队 GET /admin/fleet/teams/page

VO: FleetTeamPageReqVO / Result<PageResult<FleetTeamRespVO>>

使用场景

管理后台「车辆管理 - 车队管理」列表页加载时调用。供应商列新增展示。

入参

字段 位置 类型 必填 约束 说明
page Query Integer 否 ≥1,默认 1 页码
pageSize Query Integer 否 1..100,默认 10 每页大小
keyword Query String 否 ≤64 车队名称/负责人姓名模糊搜索
teamType Query String 否 SELF_OPERATED/COOPERATIVE 车队类型筛选
status Query String 否 ACTIVE/DISABLED 状态筛选
settleType Query String 否 cash/sign/company 付款方式筛选

出参 Result<PageResult<FleetTeamRespVO>>

records[] 每一项 FleetTeamRespVO 字段(与改前相比只多两列,其余字段语义不变):

字段 类型 说明
fleetTeamId String 车队 ID(雪花序列化为字符串,禁止转 Number)
teamCode String 内部稳定编码(ft_xxx)
teamName String 车队名称
teamType String SELF_OPERATED/COOPERATIVE
leaderName String 负责人姓名
leaderPhone String 负责人电话(分页脱敏:138****8000)
settleType String cash/sign/company
status String ACTIVE/DISABLED
sortOrder Integer 排序值
remark String 备注
vehicleCount Integer 名下车辆总数(含停用)
activeVehicleCount Integer 名下在役车辆数
supplierId String/null 关联供应商 ID(雪花字符串;未关联为 null)
supplierName String/null 关联供应商全称快照(写时同步,未关联为 null)
createTime String 创建时间 yyyy-MM-dd HH:mm:ss
updateTime String 最后更新时间 yyyy-MM-dd HH:mm:ss

请求示例

GET /admin/fleet/teams/page?page=1&pageSize=10&status=ACTIVE
Authorization: Bearer <admin-token>

响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "total": 2,
    "page": 1,
    "pageSize": 10,
    "records": [
      {
        "fleetTeamId": "2102345678901234567",
        "teamCode": "ft_2x9k3m",
        "teamName": "合作车队A",
        "teamType": "COOPERATIVE",
        "leaderName": "测试负责人甲",
        "leaderPhone": "138****0001",
        "settleType": "cash",
        "status": "ACTIVE",
        "sortOrder": 10,
        "remark": "由 fleet_attribution/历史业务数据迁移",
        "vehicleCount": 12,
        "activeVehicleCount": 9,
        "supplierId": "2091381911266967553",
        "supplierName": "内蒙古呼籁旅游服务有限公司",
        "createTime": "2026-06-01 10:00:00",
        "updateTime": "2026-08-30 15:30:00"
      },
      {
        "fleetTeamId": "2102345678901234568",
        "teamCode": "ft_2x9k3n",
        "teamName": "自有车队",
        "teamType": "SELF_OPERATED",
        "leaderName": "自有负责人",
        "leaderPhone": "139****0002",
        "settleType": "company",
        "status": "DISABLED",
        "sortOrder": 20,
        "remark": "",
        "vehicleCount": 0,
        "activeVehicleCount": 0,
        "supplierId": null,
        "supplierName": null,
        "createTime": "2026-08-01 09:00:00",
        "updateTime": "2026-08-30 15:30:00"
      }
    ]
  }
}

空数据 / 降级响应

无车队时 records=[] total=0,code=200。供应商字段未关联时为 null(不是空串),前端按未关联渲染。

错误响应

分页查询无业务错误分支。网关/框架错误:

{ "code": 401, "message": "未登录", "success": false, "data": null }

业务边界

  • 只读查询;返回的 supplierId/supplierName 来自 fleet_team.supplier_id/supplier_name 列快照,不做实时跨服务取数。
  • 供应商改名后列表展示旧名(快照口径);如需最新名称,让用户重新编辑车队保存触发刷新。
  • 车队停用车队(status=DISABLED)也可被列表查到(不带状态筛选时默认返回全部状态)。

2. 查询车队详情 GET /admin/fleet/teams/{fleetTeamId}

VO: Result<FleetTeamRespVO>

使用场景

管理后台编辑车队弹窗初始化时调用,回填 supplierId/supplierName 到供应商选择器。

入参

字段 位置 类型 必填 约束 说明
fleetTeamId Path String(Long) 是 正整数 ID 字符串 目标车队 ID(雪花,不得转 Number)

出参 Result<FleetTeamRespVO>

字段与 #1 records[] 项结构一致(含新增 supplierId/supplierName):

字段 类型 说明
fleetTeamId String 车队 ID(雪花序列化为字符串,禁止转 Number)
teamCode String 内部稳定编码(ft_xxx)
teamName String 车队名称
teamType String SELF_OPERATED/COOPERATIVE
leaderName String 负责人姓名
leaderPhone String 负责人电话(详情返回原值,编辑场景回填用)
settleType String cash/sign/company
status String ACTIVE/DISABLED
sortOrder Integer 排序值
remark String 备注
vehicleCount Integer 名下车辆总数(含停用)
activeVehicleCount Integer 名下在役车辆数
supplierId String/null 关联供应商 ID(雪花字符串;未关联为 null)
supplierName String/null 关联供应商全称快照(写时同步)
createTime String 创建时间 yyyy-MM-dd HH:mm:ss
updateTime String 最后更新时间 yyyy-MM-dd HH:mm:ss

请求示例

GET /admin/fleet/teams/2102345678901234567
Authorization: Bearer <admin-token>

响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "fleetTeamId": "2102345678901234567",
    "teamCode": "ft_2x9k3m",
    "teamName": "合作车队A",
    "teamType": "COOPERATIVE",
    "leaderName": "测试负责人甲",
    "leaderPhone": "13800000001",
    "settleType": "cash",
    "status": "ACTIVE",
    "sortOrder": 10,
    "remark": "由 fleet_attribution/历史业务数据迁移",
    "vehicleCount": 12,
    "activeVehicleCount": 9,
    "supplierId": "2091381911266967553",
    "supplierName": "内蒙古呼籁旅游服务有限公司",
    "createTime": "2026-06-01 10:00:00",
    "updateTime": "2026-08-30 15:30:00"
  }
}

空数据 / 降级响应

车队不存在或已软删除(业务错误,见下方错误响应);无空数据分支。

错误响应

车队不存在或已软删除:

{ "code": 601100, "message": "车队不存在", "success": false, "data": null }

未登录(网关拦截):

{ "code": 401, "message": "未登录", "success": false, "data": null }

业务边界

  • 详情接口返回 leaderPhone 为原值(编辑场景需要回填),分页接口脱敏。
  • supplierId 必须按字符串处理,禁止转 JavaScript Number。

3. 新增车队 POST /admin/fleet/teams

VO: FleetTeamSaveReqVO / Result<FleetTeamRespVO>

使用场景

管理后台「车辆管理 - 车队管理」点击「新增车队」,在表单里可选填供应商。

入参

字段 位置 类型 必填 约束 说明
teamName Body String 是 ≤64,唯一 车队名称
teamType Body String 是 SELF_OPERATED/COOPERATIVE 车队类型
leaderName Body String 是 ≤64 负责人姓名
leaderPhone Body String 是 电话格式正则 负责人电话
settleType Body String 是 cash/sign/company 付款方式
sortOrder Body Integer 是 ≥0 排序
remark Body String 否 ≤256 备注
supplierId Body String(Long)/null 否 @Positive 关联供应商 ID(雪花字符串;不填=不选供应商,新建车队落 DISABLED)

出参 Result<FleetTeamRespVO>

响应结构同 #2;supplierId/supplierName 按请求回填(选了供应商且校验通过则写入快照,否则为 null)。

字段 类型 说明
fleetTeamId String 新车队 ID(雪花序列化为字符串)
supplierId String/null 按请求回填(选了且校验通过)
supplierName String/null 写时同步的供应商全称快照;未选为 null
status String 选供应商=ACTIVE;不选=DISABLED
createTime String 创建时间 yyyy-MM-dd HH:mm:ss
updateTime String 创建时间(与 createTime 相同)
(其余字段) - 与详情 #2 同构

请求示例

POST /admin/fleet/teams
Authorization: Bearer <admin-token>
Content-Type: application/json

{
  "teamName": "新合作车队B",
  "teamType": "COOPERATIVE",
  "leaderName": "王队长",
  "leaderPhone": "13800138000",
  "settleType": "sign",
  "sortOrder": 20,
  "remark": "新签约车队",
  "supplierId": "2091381911266967553"
}

响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "fleetTeamId": "2103456789012345678",
    "teamCode": "ft_3a1b2c",
    "teamName": "新合作车队B",
    "teamType": "COOPERATIVE",
    "leaderName": "王队长",
    "leaderPhone": "13800138000",
    "settleType": "sign",
    "status": "ACTIVE",
    "sortOrder": 20,
    "remark": "新签约车队",
    "vehicleCount": 0,
    "activeVehicleCount": 0,
    "supplierId": "2091381911266967553",
    "supplierName": "内蒙古呼籁旅游服务有限公司",
    "createTime": "2026-08-30 16:00:00",
    "updateTime": "2026-08-30 16:00:00"
  }
}

空数据 / 降级响应

未选供应商创建(落 DISABLED,供应商字段为 null):

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "fleetTeamId": "2103456789012345679",
    "teamCode": "ft_3a1b2d",
    "teamName": "临时车队",
    "teamType": "COOPERATIVE",
    "leaderName": "临时负责人",
    "leaderPhone": "13900139000",
    "settleType": "cash",
    "status": "DISABLED",
    "sortOrder": 30,
    "remark": "",
    "vehicleCount": 0,
    "activeVehicleCount": 0,
    "supplierId": null,
    "supplierName": null,
    "createTime": "2026-08-30 16:00:00",
    "updateTime": "2026-08-30 16:00:00"
  }
}

错误响应

供应商不存在/未生效/不含车队类型(不写库):

{ "code": 601109, "message": "供应商不存在、未生效或不包含车队类型", "success": false, "data": null }

供应商校验依赖故障(Feign 不可用,不写库):

{ "code": 601110, "message": "暂时无法校验供应商,请稍后重试", "success": false, "data": null }

车队名称重复(uk_fleet_team_name 唯一索引兜底):

{ "code": 601101, "message": "车队名称已存在", "success": false, "data": null }

Bean Validation 校验失败:

{ "code": 400, "message": "供应商ID必须为正数", "success": false, "data": null }

业务边界

  • 幂等:同一 teamName + 请求摘要 10 秒窗口内重复提交只生效一次(@Idempotent key=fleet:team:create:{teamName})。
  • 分布式锁:同 teamName 创建串行化(@Lock4j)。
  • 选供应商时先 Feign 校验(事务外),通过后写库(事务内),Feign 失败/不合格一律不写库(失败关闭)。
  • 不写供应商时新建车队 status=DISABLED,需后续编辑绑定供应商后才能启用。

4. 编辑车队 PUT /admin/fleet/teams/{fleetTeamId}

VO: FleetTeamSaveReqVO / Result<FleetTeamRespVO>

使用场景

管理后台编辑车队弹窗提交。可修改基础字段 + 供应商;不允许修改 status(启停用走独立接口)。

入参

字段 位置 类型 必填 约束 说明
fleetTeamId Path String(Long) 是 正整数 ID 字符串 目标车队 ID(不得转 Number)
(其余字段) Body String 同新增 同新增 全字段提交(SaveReqVO 整体语义)
supplierId Body String(Long)/null 否 @Positive 供应商 ID;更换/清除受订单围栏

出参 Result<FleetTeamRespVO>

同 #2;supplierId/supplierName 反映最新写入值。

字段 类型 说明
fleetTeamId String 车队 ID(路径回显)
supplierId String/null 最新写入值(更换/清除后刷新)
supplierName String/null 最新写入快照(更换时取新供应商 full_name;清除时为 null)
status String 清除供应商且当前 ACTIVE 时强制落 DISABLED;其余场景不变
updateTime String 本次写入时间(秒级严格递增)
(其余字段) - 与详情 #2 同构

请求示例

PUT /admin/fleet/teams/2102345678901234567
Authorization: Bearer <admin-token>
Content-Type: application/json

{
  "teamName": "合作车队A",
  "teamType": "COOPERATIVE",
  "leaderName": "测试负责人甲",
  "leaderPhone": "13800000001",
  "settleType": "cash",
  "sortOrder": 10,
  "remark": "",
  "supplierId": "2091381911266967553"
}

响应示例

成功(更换供应商且无订单):

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "fleetTeamId": "2102345678901234567",
    "teamCode": "ft_2x9k3m",
    "teamName": "合作车队A",
    "teamType": "COOPERATIVE",
    "leaderName": "测试负责人甲",
    "leaderPhone": "13800000001",
    "settleType": "cash",
    "status": "ACTIVE",
    "sortOrder": 10,
    "remark": "",
    "vehicleCount": 12,
    "activeVehicleCount": 9,
    "supplierId": "2091381911266967553",
    "supplierName": "内蒙古呼籁旅游服务有限公司",
    "createTime": "2026-06-01 10:00:00",
    "updateTime": "2026-08-30 16:30:00"
  }
}

空数据 / 降级响应

清除供应商(原值 → null)且车队无订单:快照清空,若当前 ACTIVE 强制落 DISABLED(保持不变量:ACTIVE ⇒ 已绑供应商)。

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "fleetTeamId": "2102345678901234567",
    "teamCode": "ft_2x9k3m",
    "teamName": "合作车队A",
    "teamType": "COOPERATIVE",
    "status": "DISABLED",
    "supplierId": null,
    "supplierName": null,
    "updateTime": "2026-08-30 16:30:00"
  }
}

错误响应

车队已有订单时更换/清除供应商(含从原供应商换到新供应商、从原供应商清为空):

{ "code": 601111, "message": "车队已关联订单,不能更换供应商", "success": false, "data": null }

供应商校验失败(同新增 #3 的 601109/601110);车队不存在:

{ "code": 601100, "message": "车队不存在", "success": false, "data": null }

业务边界

  • 幂等:同 fleetTeamId + 请求摘要(含 supplierId 参与摘要)10 秒窗口内重复提交只生效一次(@Idempotent key=fleet:team:update:{fleetTeamId}:{sha256})。
  • 分布式锁:同 fleetTeamId 编辑串行化(@Lock4j)。
  • 更换供应商校验顺序:订单围栏(601111)→ Feign 资格校验(601109/601110)→ 写库。
  • 供应商不变时(含 null→null)不触发订单围栏,也不调 Feign。
  • 首次绑定(null → 新值)即使已有订单也允许。
  • status 不在 SaveReqVO,本接口不修改启停状态;清除供应商且当前 ACTIVE 时强制落 DISABLED 是唯一例外。

5. 启用车队 POST /admin/fleet/teams/{fleetTeamId}/enable

VO: Result<Void>

使用场景

管理后台对已停用车队点击「启用」。

入参

字段 位置 类型 必填 约束 说明
fleetTeamId Path String(Long) 是 正整数 ID 字符串 目标车队 ID

出参 Result<Void>

成功时 data=null:

字段 类型 说明
code Integer 恒为 200 表示成功
data null 启用接口无返回体

空数据 / 降级响应

启用成功恒返回 {"code":200,"success":true,"data":null};无空数据分支。已是启用态时幂等放行不重复写(返回同样结构)。

请求示例

POST /admin/fleet/teams/2102345678901234567/enable
Authorization: Bearer <admin-token>

响应示例

{ "code": 200, "message": "成功", "success": true, "data": null }

错误响应

未关联供应商(新增语义):

{ "code": 601108, "message": "车队未关联供应商,不能启用", "success": false, "data": null }

已是启用态(幂等放行,不重复写):

{ "code": 200, "message": "成功", "success": true, "data": null }

车队不存在:601100。

业务边界

  • 幂等:同 fleetTeamId 重复调用只生效一次(@Idempotent key=fleet:team:enable:{fleetTeamId})。
  • 分布式锁:同 fleetTeamId 启停用串行化(@Lock4j key=fleet:team:status:{fleetTeamId})。
  • 存量迁移车队(own/coopA/coopB)当前 ACTIVE 且无供应商:enable 若已被置 DISABLED 后会被 601108 拦截,需先编辑绑定供应商再启用。

四、契约约束与正确调用方式

✅ 正确 / ❌ 错误 payload 对照

场景 调用 / 结果
✅ 新增时不选供应商 { "supplierId": null }(或不传)→ 车队落 DISABLED,待绑定后启用
✅ 新增时选供应商 { "supplierId": "2091381911266967553" } → Feign 校验通过后落 ACTIVE
✅ 编辑时供应商不变 原 supplierId 原样传回(或省略由后端按原值处理?——必须原样传,SaveReqVO 整份语义)
✅ 首次绑定 原 supplierId=null,新 supplierId=有效 FLEET 供应商 → 允许(不受订单围栏)
✅ 供应商改名后刷新快照 重新编辑车队并保存(supplierId 原样),快照重新取最新 full_name
❌ 供应商 ID 转 Number 雪花精度丢失;必须按字符串传输
❌ 已有订单车队换供应商 601111,不写库
❌ 已有订单车队清供应商 601111,不写库
❌ 清除供应商后期望仍 ACTIVE 无订单时快照清空+强制 DISABLED;前端收到 200 但 status=DISABLED 属于预期行为

关键提示(当前 TEST 构建)

  • supplierId/supplierName 在所有响应中均按字符串序列化(@JsonSerialize(ToStringSerializer));禁止前端用 Number()/parseInt()/一元 + 转换。
  • 供应商全名快照为写时取数:supplier_main.full_name 改名后列表展示旧值,重新编辑车队保存触发刷新。
  • 供应商选择器数据源:可复用 GET /admin/supplier/items/list?typeCode=FLEET&status=ACTIVE(mmg 自查前端是否已有该接口封装;无则后端再补)。

五、数据库行为

  • 写操作只影响 fleet_team 一行(新增 insert / 编辑 update / 启停用 update),不跨服务写 supplier_resource_rel 或 supplier_main。
  • 快照列:supplier_id(关联 ID)+ supplier_name(全称快照)同列写入;清除时同列置 NULL。
  • 幂等窗口内重复请求只写一次;锁键串行化同车队写。
  • 迁移:V20260830_001__add_supplier_to_fleet_team.sql 对 fleet_team 加 supplier_id BIGINT NULL + supplier_name VARCHAR(500) NULL + 索引 idx_fleet_team_supplier(supplier_id);存量车队两列均为 NULL。
  • 不动 supplier_resource_rel(车队供应商不走资源关系表;关系表仅用于九大资源模块)。

六、边界行为

  • 未登录/登录失效:业务码 401(网关拦截)。
  • 车队不存在:601100。
  • 车队名称重复:601101(含 DuplicateKeyException 翻译)。
  • 车队已停用仍选该车:601102(既有口径,本工单不改)。
  • 车队下有在役车辆时禁止停用:601103(既有口径)。
  • 车队已关联车辆时禁止改自有/合作类型:601104(既有口径)。
  • 车队名下仍有车辆/司机时禁止删除:601107(既有口径)。
  • 车队未关联供应商禁止启用:601108(新增)。
  • 供应商不存在/未生效/不含车队类型:601109(新增)。
  • 供应商校验依赖故障:601110(新增,失败关闭不写库)。
  • 车队已有订单禁止更换/清除供应商:601111(新增)。
  • Bean Validation 校验失败:400。
  • 跨服务 Feign 不可用:写接口一律失败关闭(601110);读接口(列表/详情)读快照列,不受影响。

六.5、枚举 / 数据字典

status(车队启停状态)

所属字段: FleetTeamRespVO.status | 类型: String

值 中文 说明
ACTIVE 启用 可被车辆选择;前提:已关联供应商
DISABLED 停用 不可被车辆选择;新建未选供应商时默认落此态

teamType(车队类型)

所属字段: FleetTeamSaveReqVO.teamType / FleetTeamRespVO.teamType | 类型: String

值 中文 说明
SELF_OPERATED 自有 自有车队
COOPERATIVE 合作 合作车队

settleType(付款方式,字典 resource_settle_type)

所属字段: FleetTeamSaveReqVO.settleType / FleetTeamRespVO.settleType | 类型: String

值 中文 说明
cash 现付 -
sign 挂账签单 -
company 公司月结 -

六.6、修改前后对比

字段级对比

字段 改前 改后
FleetTeamSaveReqVO.supplierId 无 新增可选字段,@Positive,参与幂等摘要
FleetTeamRespVO.supplierId 无 新增,String/null(ToStringSerializer)
FleetTeamRespVO.supplierName 无 新增,String/null(快照)

行为级对比

行为 改前 改后
新建车队默认状态 ACTIVE 选供应商=ACTIVE;不选=DISABLED
启用校验 只查当前状态 增加 supplierId==null → 601108
编辑车队供应商 无此字段 有订单禁换/禁清(601111);清除+ACTIVE→强制 DISABLED
供应商配置入口 前端有独立「供应商」按钮(调通用资源关系接口) 下线;改为车队新增/编辑内嵌选择

六.7、影响评估

  • 是否破坏向后兼容: 否(新增可选字段;响应只多两列,前端旧版忽略即兼容)
  • 前端是否必须同步上线: 是(车队列表「供应商」按钮需下线,否则用户仍能从旧入口调通用接口——但通用接口对车队模块本工单起后端侧保留不拦,是前端入口下线)
  • 前端 workaround 清理点: 车队列表的「供应商」操作入口(views/fleet/teams/index.vue 中 supplierRelaShow/supplierRelaRow/openSupplierRelation 相关代码)整体删除

七、不影响范围

  • 仅影响: 管理后台「车辆管理 - 车队管理」列表/新增/编辑/启用 4 个端点 + 详情 1 个端点。
  • 零影响:
    • 车辆档案(fleet_vehicle)/ 司机档案(fleet_driver)/ 派单(fleet_assignment)等车队下游域——它们继续经 FleetTeamService.resolveForVehicle 解析车队,供应商字段不影响车辆选车队。
    • 供应商域九大资源模块(景区/餐厅/备品/组合/游玩项目/酒店/服务/额外成本/服务人员/车辆)的独立供应商关系维护(/admin/supplier/resource-relations/{module}/{id}/update 等通用接口保留不动)。
    • 订单/对账/看板读路径(只读 fleet_team 既有字段,新增两列不影响)。
    • Gateway 路由(/admin/fleet/** 通配已覆盖;/internal/** 不走网关)。
    • Redis/MQ(无新增 key/消息)。

八、测试环境已验证

真实 TEST 环境实测(2026-08-30,网关 https://api.test.1814.love:9443,admin token 走 /admin/auth/login):

POST /admin/fleet/teams                    无供应商新建 → 200, status=DISABLED, supplierId=null, supplierName=null ✓
POST /admin/fleet/teams/{id}/enable        无供应商启用 → 601108「车队未关联供应商,不能启用」 ✓
PUT  /admin/fleet/teams/{id}               绑定 DRAFT 供应商 → 601109 ✓
PUT  /admin/fleet/teams/{id}               绑定不存在供应商 → 601109 ✓
PUT  /admin/fleet/teams/{id}               绑定非 FLEET 类型 ACTIVE 供应商(RESTAURANT) → 601109 ✓
GET  /admin/fleet/teams/page               → records[] 含 supplierId/supplierName 键(未关联为 null) ✓
  • 部署:Deploy Panel 任务 2fe21f84(hl-fleet-service,2026-08-30 17:20 success)+ f29a293f(hl-resource-service,2026-08-30 17:22 success),预期/实际提交均为 447b92f5143e9ca4381d590d4f868d518cf66e0a(dev-v3 HEAD)。
  • 正向链路(绑定合格 FLEET ACTIVE 供应商 → ACTIVE + 快照写 supplierName):测试服当前无 ACTIVE 状态的 FLEET 类型供应商(供应商审批链要求必备资质,supplier_type_qualification_rule 规则表为空,无法造出合格供应商);该路径本地单测已覆盖(FleetTeamServiceTest#create_withEligibleSupplier_activeAndSnapshot 等 24 用例全绿),建议 mmg 联调时在真实数据上补验。
  • 有订单换供应商(601111)链路:测试服车队均无订单派单可安全构造验证数据,本地单测覆盖(FleetTeamServiceTest#update_changeSupplierWithOrders_rejected / update_clearSupplierWithOrders_rejected)。
  • 本地自动化:fleet 全量 3883 项 0 失败 0 错误(含 FleetRedLineArchTest 13 项门禁);resource 全量 0 失败 0 错误;spotless:check 绿。
  • 数据清理:测试车队(352385968453586944)与测试供应商(2093993745543299074)均已删除;未触碰同事真实订单;admin token 已登出。

九、相关历史 PR

PR Issue 说明 是否仍有效
#6753 #6717 车队关联供应商并展示供应商全名(本次) ✅ 最新

十、相关文档

  • 关联 Issue: wx/HL#6717
  • 关联 PR: wx/HL#6753
  • 任务设计文档: docs/tasks/6717-fleet-team-supplier.md(worktree D:\work2\HL-v3-0830-fleetsup)

撤回

  1. 管理端先恢复车队列表「供应商」操作入口(参照改前版本),保持线上可用。
  2. 从最新 dev-v3 建独立回退分支,回退 PR #6753 的合并 commit(72c9018ab 及其后续如有),验证后经独立 PR 合入。
  3. 仅需下线新供应商字段时可先保留两列(快照保留无副作用),只回退 Controller/Service 逻辑与 Feign 校验。
  4. 使用 Deploy Panel 滚动部署 hl-fleet-service 与 hl-resource-service;数据库列保留不删(supplier_id/supplier_name 允许 NULL,回退后不影响)。
  5. 撤回后经 Gateway 验证新增/编辑/启用接口按改前口径通过;车队列表的供应商列展示空白或下线列头。

关联 / 联系人

链接

  • Issue: #6717
  • PR: #6753
  • Merge commit: 待合并后回填

联系人

  • 后端负责人: @wx
  • 前端联动: @mmg(下线车队列表「供应商」按钮 + 车队新增/编辑弹窗加供应商选择器)