文件
hl-api-changelog/changelogs-v2/2026-09/19_7947_餐食删除编码关联餐厅增加桌人-修改接口-管理后台.md
2026-09-20 13:43:08 +08:00

17 KiB

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 7947 餐食删除编码,关联餐厅(含全部),增加桌/人 admin lc(GIT) 修改接口 deployed verified verified mmg e0d613c113fb5268e9cd2f790885046fce8ab1d0 2026-09-20 餐食接口去掉编码 dishCode;新增餐厅 restaurantId(不传为全部)与桌/人 priceUnit(person/table,不传按人);出参新增 restaurantId、restaurantName(全部返回「全部」)、priceUnit。编码、图片 URL、餐厅 ID 不需要展示。前端需按本文对接。前端已交付(hl-ui v2.1 @ e0d613c1):列表删编码列、加餐厅列(restaurantName,餐厅已删 null 显 -)、单价带 /人/桌后缀、keyword placeholder 去编码;编辑弹窗删 dishCode 表单项/rules/回填/提交,加餐厅远程候选(分页 options 首焦拉首页+防抖+请求序号防旧响应,编辑回显餐厅不在候选时注入当前项,清空=「全部」create 不带键/update 传 null)与桌/人 radio(默认 person、编辑带回显值);两 spec 重写 17/17,scoped checkpoint 全绿。 2026-09-19 dev-v3

resource: 餐食删除编码,关联餐厅(含全部),增加桌/人

服务: hl-resource-service(dish 表随服务部署由 Flyway 迁移) PR: #7958 Issue: #7947 日期: 2026-09-19 影响范围: 管理后台「餐食管理」5 个接口(分页、列表、详情、新建、修改)


⚠️ 关键变化

  • 🗑️ 编码 dishCode 删除:新建、修改不再有编码,分页不再按编码筛选,分页、列表、详情不再返回编码。340002「编码已存在」停用。
  • 🆕 餐食关联餐厅:入参新增 restaurantId(餐厅资源里的餐厅 ID),不传为「全部」;出参新增 restaurantId(全部为 null)与 restaurantName(全部返回「全部」)。
  • 🆕 桌/人 priceUnit:person 按人 / table 按桌,表示单价是每人还是每桌;不传按人。
  • 🔁 名称唯一范围变了:同一餐厅(「全部」算一组)内名称不能重复,报 340003;不同餐厅可以同名、单价各自维护。
  • 👁️ 不需要展示:编码、图片 URL、餐厅 ID。

一、背景

餐食不再需要编码;餐食按餐厅维护,同一道餐食在不同餐厅价格不同,另有一种餐厅是「全部」(没有餐厅 ID);新增「桌/人」。已有餐食上线后都归「全部」、桌/人为「人」。


二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 分页查询餐食 GET /admin/dish/items/page 修改 去掉查询参数 dishCode,keyword 只匹配名称;出参去掉 dishCode,加 restaurantId/restaurantName/priceUnit
2 查询餐食列表 GET /admin/dish/items/list 修改 keyword 只匹配名称;出参同接口 1
3 查询餐食详情 GET /admin/dish/items/{dishId}/view 修改 出参同接口 1
4 新建餐食 POST /admin/dish/items/add 修改 去掉入参 dishCode;加 restaurantId、priceUnit;重名按餐厅分组
5 修改餐食 PUT /admin/dish/items/{dishId}/update 修改 同接口 4;整份覆盖,restaurantId 不传即改为全部,priceUnit 不传即按人

三、接口详情

1. 分页查询餐食 GET /admin/dish/items/page

VO: DishPageReqVO → PageResult<DishListItemRespVO>

使用场景

餐食管理列表分页查询。

入参字段表

字段 位置 类型 必填 约束 说明
keyword Query String 否 去首尾空格后 ≤64 只模糊匹配名称(原来同时匹配编码)
dishCode Query — — — 已删除;继续传会被忽略
status / settleType / createdByName / page / pageSize Query — 否 不变 不变

出参字段表

字段 类型 说明
records[].dishCode — 已删除
records[].restaurantId String | null 新增。餐厅 ID;「全部」为 null
records[].restaurantName String | null 新增。餐厅名称;「全部」返回 "全部";餐厅已删除为 null
records[].priceUnit String 新增。person 按人 / table 按桌
records[] 其余字段、total / page / pageSize — 不变

请求示例

GET /admin/dish/items/page?page=1&pageSize=20&keyword=团队
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "records": [
      {
        "dishId": "2100767707048636418",
        "restaurantId": null,
        "restaurantName": "全部",
        "dishName": "团队标准餐(八菜一汤)",
        "unitPrice": 40.00,
        "priceUnit": "person",
        "imageUrl": null,
        "settleType": "cash",
        "status": 1,
        "remark": null,
        "createdBy": "1900000000000000001",
        "createdByName": "张三",
        "createdAt": "2026-09-18 10:02:11"
      },
      {
        "dishId": "2100767707048636501",
        "restaurantId": "2023382100664676353",
        "restaurantName": "菌香园火锅",
        "dishName": "团队升级餐(十菜一汤)",
        "unitPrice": 600.00,
        "priceUnit": "table",
        "imageUrl": null,
        "settleType": "cash",
        "status": 1,
        "remark": "含一道特色菜",
        "createdBy": "1900000000000000001",
        "createdByName": "张三",
        "createdAt": "2026-09-18 10:05:40"
      }
    ],
    "total": 2,
    "page": 1,
    "pageSize": 20
  }
}

空数据 / 降级响应

不变:无数据时 records 为 []、total 为 0。

错误响应

{ "code": 400, "message": "每页条数最大为100", "success": false, "data": null }

业务边界

  • 旧前端继续传 dishCode 查询参数不报错,但不再筛选。

2. 查询餐食列表 GET /admin/dish/items/list

VO: DishListReqVO → List<DishListItemRespVO>

使用场景

餐食下拉数据源(只返回上架餐食,不按餐厅过滤)。

入参字段表

字段 位置 类型 必填 约束 说明
keyword Query String 否 去首尾空格后 ≤64 只模糊匹配名称
settleType / limit Query — 否 不变 不变

出参字段表

字段 类型 说明
[] — 字段同接口 1 的 records[]:去掉 dishCode,新增 restaurantId、restaurantName、priceUnit

请求示例

GET /admin/dish/items/list?limit=50
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": [
    {
      "dishId": "2100767707048636418",
      "restaurantId": null,
      "restaurantName": "全部",
      "dishName": "团队标准餐(八菜一汤)",
      "unitPrice": 40.00,
      "priceUnit": "person",
      "imageUrl": null,
      "settleType": "cash",
      "status": 1,
      "remark": null,
      "createdBy": "1900000000000000001",
      "createdByName": "张三",
      "createdAt": "2026-09-18 10:02:11"
    }
  ]
}

空数据 / 降级响应

不变:没有上架餐食时 data 为 []。

错误响应

{ "code": 400, "message": "limit最大为200", "success": false, "data": null }

业务边界

  • 同名餐食在「全部」和各餐厅下各有一条时会同时出现,用 restaurantName 区分。

3. 查询餐食详情 GET /admin/dish/items/{dishId}/view

VO: DishRespVO

使用场景

编辑回显。

入参字段表

字段 位置 类型 必填 约束 说明
dishId Path String 是 正数 餐食 ID(不变)

出参字段表

字段 类型 说明
全部字段 — 同接口 1 的 records[]:去掉 dishCode,新增 restaurantId、restaurantName、priceUnit

请求示例

GET /admin/dish/items/2100767707048636501/view
Authorization: Bearer <admin token>

响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "dishId": "2100767707048636501",
    "restaurantId": "2023382100664676353",
    "restaurantName": "菌香园火锅",
    "dishName": "团队升级餐(十菜一汤)",
    "unitPrice": 600.00,
    "priceUnit": "table",
    "imageUrl": null,
    "settleType": "cash",
    "status": 1,
    "remark": "含一道特色菜",
    "createdBy": "1900000000000000001",
    "createdByName": "张三",
    "createdAt": "2026-09-18 10:05:40"
  }
}

空数据 / 降级响应

不变:餐食不存在或已删除返回 340001。

错误响应

{ "code": 340001, "message": "餐食不存在", "success": false, "data": null }

业务边界

  • 回显时 restaurantId 为 null 即「全部」。

4. 新建餐食 POST /admin/dish/items/add

VO: DishCreateReqVO → DishWriteRespVO

使用场景

新建餐食。

入参字段表

字段 位置 类型 必填 约束 说明
dishCode Body — — — 已删除;继续传会被忽略,不再校验
restaurantId Body String 否 餐厅资源里的餐厅 ID 新增。不传为「全部」
priceUnit Body String 否 person / table 新增。不传按 person 存
dishName Body String 是 去首尾空格后 1–500 同一餐厅(全部算一组)内不能重复
unitPrice / imageUrl / settleType / status / remark Body — — 不变 不变

出参字段表

字段 类型 说明
dishId String 新餐食 ID(不变)
dishName String 餐食名称(不变)

请求示例

{
  "restaurantId": "2023382100664676353",
  "dishName": "团队升级餐(十菜一汤)",
  "unitPrice": 600.00,
  "priceUnit": "table",
  "settleType": "cash",
  "remark": "含一道特色菜"
}

响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": { "dishId": "2100767707048636501", "dishName": "团队升级餐(十菜一汤)" }
}

空数据 / 降级响应

不变:要么 200 写入,要么返回错误码且零写入。

错误响应

{ "code": 340003, "message": "餐食名称已存在:团队升级餐(十菜一汤)", "success": false, "data": null }
{ "code": 400, "message": "桌/人必须是 person 或 table", "success": false, "data": null }

业务边界

  • 同名餐食可以在「全部」和不同餐厅下各建一条;同一餐厅(或都不传餐厅)下重名报 340003。

5. 修改餐食 PUT /admin/dish/items/{dishId}/update

VO: DishUpdateReqVO → DishWriteRespVO

使用场景

修改餐食(整份覆盖)。

入参字段表

字段 位置 类型 必填 约束 说明
dishId Path String 是 正数 餐食 ID(不变)
dishCode Body — — — 已删除;继续传会被忽略
restaurantId Body String 否 餐厅资源里的餐厅 ID 新增。整份覆盖:不传即改为「全部」,编辑时须带回原值
priceUnit Body String 否 person / table 新增。整份覆盖:不传即按 person 存,编辑时须带回原值
其余入参 Body — — 不变 dishName、unitPrice、imageUrl、settleType、status、remark 不变

出参字段表

字段 类型 说明
dishId String 餐食 ID(不变)
dishName String 修改后的名称(不变)

请求示例

{
  "restaurantId": "2023382100664676353",
  "dishName": "团队升级餐(十菜一汤)",
  "unitPrice": 620.00,
  "priceUnit": "table",
  "imageUrl": null,
  "settleType": "cash",
  "status": 1,
  "remark": "含一道特色菜"
}

响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": { "dishId": "2100767707048636501", "dishName": "团队升级餐(十菜一汤)" }
}

空数据 / 降级响应

不变:要么 200 覆盖写入,要么返回错误码且不改动数据。

错误响应

{ "code": 340003, "message": "餐食名称已存在:团队升级餐(十菜一汤)", "success": false, "data": null }

业务边界

  • 查重在修改后的餐厅内进行,排除自己。

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

场景 payload
✅ 「全部」下按人的餐食 { "dishName": "素斋套餐", "unitPrice": 50.00 }
✅ 某餐厅下按桌的餐食 { "restaurantId": "2023382100664676353", "dishName": "团队升级餐(十菜一汤)", "unitPrice": 600.00, "priceUnit": "table" }
✅ 同名餐食在另一家餐厅 换一个 restaurantId 再建同名,单价可不同
❌ 同一餐厅(或「全部」)下重名 340003「餐食名称已存在」
❌ priceUnit 传 seat 400「桌/人必须是 person 或 table」
⚠️ 修改时漏传 restaurantId / priceUnit 整份覆盖:会改成「全部」/按人

五、数据库行为

dish 表删除 dish_code,新增 restaurant_id(空即全部)、price_unit(默认 person);名称唯一改为同一餐厅(全部算一组)内唯一。已有餐食迁移后都是「全部」、按人,其余字段不变。


六、边界行为

  • 未登录 → 401(网关拦截),不变。
  • 餐厅被删除后,其下餐食的 restaurantName 为 null,restaurantId 仍返回。

六.6、修改前后对比

字段级对比

字段 改前 改后
dishCode(入参、出参、分页查询参数) 必填,≤20,唯一 删除
restaurantId(入参、出参) 无 新增,空即全部
restaurantName(出参) 无 新增,全部返回「全部」
priceUnit(入参、出参) 无 新增,person / table,不传按人
keyword 匹配编码或名称 只匹配名称

行为级对比

行为 改前 改后
名称唯一 全部未删除餐食内唯一 同一餐厅(全部算一组)内唯一
340002 编码已存在 会返回 停用

六.7、影响评估

  • 是否破坏向后兼容: 是(出参去掉 dishCode;旧前端多传的 dishCode 会被忽略,不报错)
  • 前端是否必须同步上线: 是,按本文对接餐厅与桌/人;编码、图片 URL、餐厅 ID 不需要展示
  • 前端 workaround 清理点: 去掉编码相关的传参与展示

七、不影响范围

  • 仅影响: 餐食接口 1–5
  • 零影响:
    • 餐食上下架 PUT /admin/dish/items/{dishId}/status/update、删除 DELETE /admin/dish/items/{dishId}/del
    • 订单用餐信息、用餐模版接口(其中的「餐食编码快照」以后不会再有值)

八、测试环境已验证

部署提交 4cbccc26b,经 Gateway 用真实身份实测 34 项全部通过:

已有 9 行餐食(含已删除)                          → 编码列已删,其余列与部署前一致;全部归「全部」、按人 ✓
分页、列表、7 个详情                               → 不再有 dishCode,其余字段与部署前逐字段一致 ✓
不传编码新建、修改;传空串 / 25 字符 / 重复编码     → 均成功,编码被忽略 ✓
按 22 行数据表新建(全部 10 道 + 3 家餐厅各 4 道)  → 全部成功,详情逐字段一致;同名在全部与 3 家餐厅各一条、单价不同 ✓
不传 priceUnit 新建、修改                           → 存为 person ✓
全部下 / 同一餐厅下重名,修改成已有名称            → 340003,零写入 ✓
Swagger 部署前后                                   → 餐食模型只去 dishCode、加 restaurantId/restaurantName/priceUnit,其余一致 ✓

十、相关文档

关联 / 联系人

链接

联系人

  • 后端负责人: @lc