Files
SmartPlateCabinet/app/吐盘机接口文档.md
T
mazengfei 524837ec20 feat(face): 支持按userFaceId查询单条人脸记录
- FaceDao新增queryByUserFaceId接口,实现按userFaceId精确查询
- FaceApi新增queryByUserFaceId方法,封装Dao查询逻辑
- LoginByFaceActivity插入人脸时,先按userFaceId查询,存在则更新避免重复
- NetViewModelV2同步人脸数据时,优先用userFaceId判重,减少重复入库
- 修正FaceEntity中userId字段数据库列名错误(user_id替代user_idd)
- 增加注释说明及代码格式优化,提升代码可读性和健壮性
2026-08-18 09:12:40 +08:00

42 KiB
Raw Blame History

吐盘机(营养秤)接口文档

ControllerNutPickupScaleController 模块前缀:/neglect/pickup Nacos 白名单:/nutrition/neglect/**(无需 Sa-Token) 设备上下文:请求头 X-DEVICE-CODE 生成日期:2026-06-29 对照老版:Downloads/营养秤_API_DOC.mdv1.0.02026-05-26


一、服务器环境

环境 地址 端口
本地 http://localhost 24810
测试 https://dev.yixiong-tech.com 8083
生产 https://api.dm.yixiong-tech.com 8443

接口完整地址 = {baseUrl}/neglect/pickup/{sub-path}


二、请求头(全局)

Header 是否必填 说明
Content-Type application/json(上传接口 multipart/form-data
X-DEVICE-CODE 设备唯一编码,由 GlobalData.deviceId 注入;服务端据此解析食堂、餐次等上下文
X-Access-Token JWT Token,吐盘机白名单接口不强制校验
authorization 固定授权码 57ee87183f2a4fa59683ec9ef41c8f5d

三、通用响应格式

所有接口统一返回 Result<T>

{
  "code": "00000",
  "msg": "success",
  "data": { },
  "total": 0
}
字段 类型 说明
code String "00000" 表示成功,其它为业务/系统错误码
msg String 响应描述
data T 业务数据,类型随接口变化
total int 分页总条数,不分页接口为 0

Long 类型 ID 在 JSON 中序列化为 String,避免 JS 精度丢失。


四、接口详情

4.1 人脸数据同步


接口 P-01 — 获取全量人脸数据

POST /neglect/pickup/face/page

设备开机或重置本地特征库时调用,分页拉取全量人脸特征。

入参(Body JSONBasePageQuery

字段 类型 必填 说明
pageNum Long 页码,从 1 开始
pageSize Long 每页条数,建议 100
column String 排序字段
order String 排序方向(asc/desc

入参示例

{
  "pageNum": 1,
  "pageSize": 100
}

响应 dataList<NutTerminalAppFaceVO>

字段 类型 说明
userFaceId String 人脸记录 id
userId String 用户 id
faceFeature String 人脸特征码(Base64 字符串)
faceUpdateTimestamp Long 人脸更新时间戳(毫秒)
cardNo String 会员卡号;非会员或未发卡为空
member Boolean 是否会员
faceDeleted Boolean 是否已删除(true 表示用户/人脸已注销,APP 端需清理本地缓存)
personType String 人员类型:1-员工,2-工作人员,3-普通用户,4-外部人员,5-会员

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": [
    {
      "userFaceId": "1024",
      "userId": "88001",
      "faceFeature": "ArcFaceBase64...",
      "faceUpdateTimestamp": 1748000000000,
      "cardNo": "M2024001",
      "member": true,
      "faceDeleted": false,
      "personType": "5"
    }
  ],
  "total": 128
}

接口 P-02 — 获取增量人脸数据

POST /neglect/pickup/face/increment

按时间戳增量同步,仅返回 update_time 严格大于 timestamp 的记录(含已删除记录,APP 端据此清理本地缓存)。

入参(Body JSONNutTerminalAppFaceIncrementQuery(继承 BasePageQuery

字段 类型 必填 说明
pageNum Long 页码
pageSize Long 每页条数
column String 排序字段(继承)
order String 排序方向(继承)
timestamp Long 上次同步时间戳(毫秒),首次同步传 0

入参示例

{
  "pageNum": 1,
  "pageSize": 100,
  "timestamp": 1748000000000
}

响应 data — 同 P-01List<NutTerminalAppFaceVO>


4.2 菜品查询


接口 P-03 — 按名称模糊搜索菜品

POST /neglect/pickup/food/search

按菜品名称关键词分页模糊搜索。结果按当前食堂 + 当餐次过滤。

入参(Body JSONNutTerminalAppFoodSearchQuery(继承 BasePageQuery

字段 类型 必填 说明
pageNum Long 页码
pageSize Long 每页条数
name String 菜品名称关键词,不传则返回当餐全部菜品

入参示例

{
  "pageNum": 1,
  "pageSize": 20,
  "name": "宫保鸡丁"
}

响应 dataList<NutTerminalAppFoodVO>

字段 类型 说明
cookOrderId String 按单烹制 id(就餐时需回传给下单接口)
foodId String 菜品 id
foodName String 菜品名称
calorie BigDecimal 能量(kcal/100g
protein BigDecimal 蛋白质(g/100g
fat BigDecimal 脂肪(g/100g
carbohydrate BigDecimal 碳水化合物(g/100g
price BigDecimal 称重基础价(元/100g),对应 nut_food.weight_base_price
specPrice BigDecimal 默认规格售价(元)
vipPrice BigDecimal VIP 售卖价;新系统暂无该概念,固定返回 null
specWeight BigDecimal 默认规格重量(g
stapleFood BigDecimal 主食占比(g/100g):grain + potato
fruitsVegetables BigDecimal 果蔬占比(g/100g):vegetable + fruits
meatEggs BigDecimal 肉蛋占比(g/100g):livestock + birds + aquatic + egg
recommendCalorie BigDecimal 推荐能量;菜品层面无意义,固定 0
foodMaterialId String 餐品营养表 id(默认主料 mater_id
specId String 默认规格 id
foodImg String 菜品图片 URL(首张图片型 media)
tablewareStatus Boolean 是否含餐具;当前未建模,固定 false
tablewareWeight Integer 餐具重量(g);当前未建模,固定 0
foodLabel String 菜品标签(tags 字段)

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": [
    {
      "cookOrderId": "CO20260629-001",
      "foodId": "2001",
      "foodName": "宫保鸡丁",
      "calorie": 195.5,
      "protein": 8.2,
      "fat": 12.1,
      "carbohydrate": 9.3,
      "price": 0.28,
      "specPrice": 6.00,
      "vipPrice": null,
      "specWeight": 200,
      "stapleFood": 9.3,
      "fruitsVegetables": 2.0,
      "meatEggs": 8.2,
      "recommendCalorie": 0,
      "foodMaterialId": "3001",
      "specId": "2001-1",
      "foodImg": "https://cdn.yixiong.com/food/2001.jpg",
      "tablewareStatus": false,
      "tablewareWeight": 0,
      "foodLabel": "招牌,微辣"
    }
  ],
  "total": 1
}

接口 P-04 — 当餐菜品列表

POST /neglect/pickup/food/current-meal

返回当前食堂 + 当前餐次下所有可供应菜品。无入参。

入参示例

{ }

响应 dataList<NutTerminalAppFoodVO>,字段同 P-03


接口 P-05 — 菜品详情

POST /neglect/pickup/food/detail

入参(Body JSONIdDTO

字段 类型 必填 说明
id Long 菜品 idfoodId

入参示例

{ "id": 2001 }

响应 dataNutTerminalAppFoodVO,字段同 P-03


接口 P-06 — 按多个菜品名称查询(顺序一致)

POST /neglect/pickup/food/by-names

开餐页面批量按名称查询菜品,返回顺序与传入 nameList 一致。

入参(Body JSONNutPickupFoodNamesQuery

字段 类型 必填 说明
nameList List<String> 菜品名称列表,至少 1 条

入参示例

{
  "nameList": ["宫保鸡丁", "西红柿炒鸡蛋", "米饭"]
}

响应 dataList<NutTerminalAppFoodVO>,字段同 P-03


4.3 开餐 / 加菜


接口 P-07 — 开餐(记录初始制作量)

POST /neglect/pickup/meal/start

档口开餐时记录菜品初始制作量,作为余量监控的起始锚点。

入参(Body JSONNutTerminalAppStartMealDTO

字段 类型 必填 说明
foodId Long 菜品 id
foodName String 菜品名称(冗余)
foodWeight BigDecimal 食物重量(克)
powerOnTime LocalDateTime 开机时间(设备上报),格式 yyyy-MM-dd HH:mm:ss

设备编码、食堂 id 等终端上下文由 X-DEVICE-CODE 头解析,无需 DTO 携带。

入参示例

{
  "foodId": 2001,
  "foodName": "宫保鸡丁",
  "foodWeight": 5000,
  "powerOnTime": "2026-06-29 10:30:00"
}

响应 data — 无(Result<Void>),仅以 code 判断成功

响应示例

{ "code": "00000", "msg": "success", "data": null, "total": 0 }

接口 P-08 — 加菜(追加制作量)

POST /neglect/pickup/meal/add

开餐过程中追加制作量,累加到该菜品当前制作总量。

入参 / 响应 — 同 P-07NutTerminalAppStartMealDTO / Result<Void>


4.4 就餐记录


接口 P-09a — 取餐盘(记录开始就餐时刻)

POST /neglect/pickup/plate-pickup

记录用户"开始就餐"的时刻(取餐盘时间)。调用一次 = upsert 到 nut_pickup_orderplate_pickup_time 字段。

使用约束

  • 本接口是 P-09 提交单道菜就餐记录强前置:未取盘直接打菜会返回错误 msg: "请先取餐盘再提交就餐记录"
  • upsert 语义:当日 + 当前餐次 + 当前食堂已有 pickup_method='plate_only'plate_pickup_time 非空的主单 → 刷新时间戳,共用一条主单;否则新建 pickup_method='plate_only' 的独立主单(无子表、无占位流水,不进入支付链路)。
  • 不限制设备(取盘机 vs 营养秤可以是不同设备),按 userId 关联。

入参(Body JSONIdDTO

字段 类型 必填 说明
id Long 用户 id(餐盘号)

入参示例

{ "id": 88001 }

响应 dataString,主单 recordNoResult.saveSuccess 包装,新建或刷新)

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": "M-20260709-0001",
  "total": 0
}

设备编码、食堂 id、餐线 id、餐次等终端上下文由请求头 X-DEVICE-CODE 解析,无需 DTO 携带。


接口 P-09 — 提交单道菜就餐记录

POST /neglect/pickup/eat

调用一次 = 一道菜的就餐数据;同一用户同一餐次多次调用按主单聚合:

  • 主单查找规则:(userId, eatDay=今日, mealType=当前餐次, pickup_end_time IS NULL)
  • 命中则只追加子表 + 更新主单合计;未命中则新建主单 + 1 条子表

强前置校验(取盘校验)

本接口被调用前,业务端必须保证当前用户当日在当前食堂、当前餐次存在一条 pickup_method='plate_only'plate_pickup_time 非空的主单(即已先调用 P-09a 取餐盘)。否则直接抛业务异常:

msg: "请先取餐盘再提交就餐记录"

该校验由 NutPickupScaleAppServiceImpl#submitEat 在主单查找之前完成,过滤条件严格按 (userId, canteenId, eatDay, mealType, pickup_method='plate_only', plate_pickup_time IS NOT NULL) 命中,避免跨餐次/跨食堂误判。

入参(Body JSONNutTerminalAppEatDTO

字段 类型 必填 说明
userId Long 用户 id(餐盘号 = userId
foodId Long 菜品 id
foodName String 菜品名称(冗余存储,便于历史回溯)
specId Long 菜品规格 id;无规格传 0
foodWeight BigDecimal 菜品总重量(克)
eatWeight BigDecimal 实际食用重量(克),可为 0
member Boolean 是否会员(仅作冗余记录用;新表 person_typenut_user 实际身份决定)
cookOrderId Long 按单烹制 id(终端菜品列表返回的 cookOrderId,就餐时原样回传)

入参示例

{
  "userId": 88001,
  "foodId": 2001,
  "foodName": "宫保鸡丁",
  "specId": 0,
  "foodWeight": 200,
  "eatWeight": 150,
  "member": true,
  "cookOrderId": 1000123
}

响应 dataString,主单 idResult.saveSuccess 包装)

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": "1000456",
  "total": 0
}

接口 P-10 — 按用户 id(餐盘号)查本餐就餐数据

POST /neglect/pickup/plate-food

按餐盘号(= userId)查询本餐次已就餐明细,实时聚合主单 + 子表 + 营养现算。

入参(Body JSONIdDTO

字段 类型 必填 说明
id Long 用户 id(餐盘号)

入参示例

{ "id": 88001 }

响应 dataNutTerminalAppPlateFoodVO

字段 类型 说明
name String 用户姓名
calorie BigDecimal 本餐热量(kcal
grain BigDecimal 谷类摄入量(g
fruitsVegetables BigDecimal 果蔬摄入量(g
other BigDecimal 肉蛋豆摄入量(g
eatWeightSum Integer 食用总重量(g
incomeSum BigDecimal 菜品总收入价格(元)
discountSum BigDecimal 优惠总价格(元);当前固定 0
recommendCalorie BigDecimal 推荐能量(kcal);当前固定 0
maxCalorie BigDecimal 能量上限(kcal);当前固定 0
minCalorie BigDecimal 能量下限(kcal);当前固定 0
grainRecommend / grainNearExcess / grainExcess String 谷类推荐/即将超量/超量描述(当前固定空)
fruitsVegetablesRecommend / fruitsVegetablesNearExcess / fruitsVegetablesExcess String 果蔬推荐/即将超量/超量描述(当前固定空)
otherRecommend / otherNearExcess / otherExcess String 肉蛋豆推荐/即将超量/超量描述(当前固定空)
message String 提示信息(暂未启用)
list List<Food> 本餐菜品明细列表,见下表

NutTerminalAppPlateFoodVO.Food 子对象:

字段 类型 说明
foodId String 菜品 id
foodName String 菜品名称
foodMaterialId String 菜品营养表 id(默认主料 mater_id
specId String 餐品规格 id;无规格为 0
eatWeight Integer 食用重量(g
deviceWeight Integer 记录 eatWeight 时秤的当前重量(g
initWeight Integer 记录前秤重量(g= realWeight + eatWeight
eatNum Integer 份数
price BigDecimal 菜品单价(元)
discount BigDecimal 优惠价格(元);当前固定 0
income BigDecimal 菜品收入(元)
isSyncData Boolean 是否已同步标识;新接口固定 true
orderFrom Integer 来源:1-营养秤,2-档口机;当前固定 1

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": {
    "name": "张三",
    "calorie": 293.25,
    "grain": 75.0,
    "fruitsVegetables": 30.0,
    "other": 124.5,
    "eatWeightSum": 229,
    "incomeSum": 6.50,
    "discountSum": 0,
    "recommendCalorie": 0,
    "maxCalorie": 0,
    "minCalorie": 0,
    "grainRecommend": "",
    "grainNearExcess": "",
    "grainExcess": "",
    "fruitsVegetablesRecommend": "",
    "fruitsVegetablesNearExcess": "",
    "fruitsVegetablesExcess": "",
    "otherRecommend": "",
    "otherNearExcess": "",
    "otherExcess": "",
    "message": "",
    "list": [
      {
        "foodId": "2001",
        "foodName": "宫保鸡丁",
        "foodMaterialId": "3001",
        "specId": "0",
        "eatWeight": 150,
        "deviceWeight": 350,
        "initWeight": 500,
        "eatNum": 1,
        "price": 6.50,
        "discount": 0,
        "income": 6.50,
        "isSyncData": true,
        "orderFrom": 1
      }
    ]
  },
  "total": 0
}

接口 P-11 — 推送菜品实时重量

POST /neglect/pickup/weight

设备在称重过程中持续推送当前菜品重量。服务端按 (deviceCode, foodId) 写入 RedisTTL 60s,BI/监控屏读取后自动刷新展示,无心跳即过期降级。

入参(Body JSONNutTerminalAppScaleWeightDTO

字段 类型 必填 说明
foodId Long 菜品 id
foodWeight Integer 当前菜品重量(克),不能为负

设备编码由 X-DEVICE-CODE 头携带。

入参示例

{
  "foodId": 2001,
  "foodWeight": 425
}

响应 data — 无(Result<Void>


4.5 公共能力


接口 P-12 — 用户当日就餐营养

POST /neglect/pickup/user/current-food

按用户 id 累加当日全部已就餐主单(不仅本餐次),按子表 food_weight × 营养项/100g 现算。

入参(Body JSONIdDTO

字段 类型 必填 说明
id Long 用户 id

入参示例

{ "id": 88001 }

响应 dataNutTerminalAppUserNutritionVO

字段 类型 说明
name String 用户姓名
calorie BigDecimal 已摄入热量(kcal
fruitsVegetables BigDecimal 果蔬摄入量(g
meatEggs BigDecimal 肉蛋摄入量(g
stapleFood BigDecimal 主食摄入量(g
maxCalorie BigDecimal 能量上限(kcal);当前固定 0
minCalorie BigDecimal 能量下限(kcal);当前固定 0
recommendCalorie BigDecimal 推荐能量(kcal);当前固定 0
stapleFoodRecommend / stapleFoodNearExcess / stapleFoodExcess String 主食推荐/即将超量/超量描述(当前固定空)
fruitsVegetablesRecommend / fruitsVegetablesNearExcess / fruitsVegetablesExcess String 果蔬推荐/即将超量/超量描述(当前固定空)
meatEggsRecommend / meatEggsNearExcess / meatEggsExcess String 肉蛋推荐/即将超量/超量描述(当前固定空)
message String 提示信息(暂未启用)

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": {
    "name": "张三",
    "calorie": 588.5,
    "fruitsVegetables": 60.0,
    "meatEggs": 124.5,
    "stapleFood": 150.0,
    "maxCalorie": 0,
    "minCalorie": 0,
    "recommendCalorie": 0,
    "stapleFoodRecommend": "",
    "stapleFoodNearExcess": "",
    "stapleFoodExcess": "",
    "fruitsVegetablesRecommend": "",
    "fruitsVegetablesNearExcess": "",
    "fruitsVegetablesExcess": "",
    "meatEggsRecommend": "",
    "meatEggsNearExcess": "",
    "meatEggsExcess": "",
    "message": ""
  },
  "total": 0
}

接口 P-13 — 虹软 SDK 设备配置

GET /neglect/pickup/device/config

无入参(设备编码由 X-DEVICE-CODE 头传递)。终端 APP 启动时调一次缓存到本地,不需要持续轮询。

响应 dataNutTerminalAppDeviceConfigVO

字段 类型 说明
arcsoftAppId String 虹软 ArcFace SDK App Id
arcsoftSdkKey String 虹软 ArcFace SDK Key
arcsoftActiveKey String 虹软 ArcFace 激活码
payType Integer 档口秤结算方式:1-独立结算,2-联合结算;吐盘机无意义

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": {
    "arcsoftAppId": "8cXr...",
    "arcsoftSdkKey": "FpHn...",
    "arcsoftActiveKey": "3aEb...",
    "payType": null
  },
  "total": 0
}

接口 P-14 — 当前餐次信息

GET /neglect/pickup/meal/current

无入参。餐次时段当前由 MealPeriodHelper 硬编码(公司全局统一),不在任何区间时返回最近的下一餐。

响应 dataNutTerminalAppMealInfoVO

字段 类型 说明
mealName String 餐次名称(早餐/午餐/晚餐/加餐)
mealTimeStart LocalDateTime 餐次开始时间,格式 yyyy-MM-dd HH:mm:ss
mealTimeEnd LocalDateTime 餐次结束时间,格式 yyyy-MM-dd HH:mm:ss

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": {
    "mealName": "午餐",
    "mealTimeStart": "2026-06-29 11:30:00",
    "mealTimeEnd": "2026-06-29 13:00:00"
  },
  "total": 0
}

接口 P-15 — 会员折扣率

POST /neglect/pickup/member/discount

按用户 id 返回折扣系数(如 0.9 表示九折)。

入参(Body JSONIdDTO

字段 类型 必填 说明
id Long 用户 id

入参示例

{ "id": 88001 }

响应 dataBigDecimal

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": 0.90,
  "total": 0
}

4.6 食材库存 / 净菜加工


接口 P-16 — 食材库存搜索

POST /neglect/pickup/ingredient/search

按食材名称模糊搜索,按溯源码分组返回。

入参(Body JSONNutIngredientSearchQuery(继承 BasePageQuery

字段 类型 必填 说明
pageNum Long 页码
pageSize Long 每页条数
keyword String 食材名称(模糊)

入参示例

{
  "pageNum": 1,
  "pageSize": 20,
  "keyword": "白菜"
}

响应 dataList<NutIngredientInventoryVO>

字段 类型 说明
materId Long 食材 id
materName String 食材名称
traceCode String 溯源码
totalWeight BigDecimal 总库存量(kg
vegTypeList List<NutMaterVegTypeOptionVO> 净菜类型列表

NutMaterVegTypeOptionVO 子对象:

字段 类型 说明
vegTypeId Long 净菜类型 id
vegTypeName String 净菜类型名称(如 洗净米、肉片、豆腐块)

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": [
    {
      "materId": 1001,
      "materName": "大白菜",
      "traceCode": "HV2026060001",
      "totalWeight": 125.50,
      "vegTypeList": [
        { "vegTypeId": 11, "vegTypeName": "洗净叶菜" },
        { "vegTypeId": 12, "vegTypeName": "菜段" }
      ]
    }
  ],
  "total": 1
}

接口 P-17 — 加工步骤字典

GET /neglect/pickup/dict/process-step

无入参。返回净菜加工步骤字典(清洗/去皮/切割/分拣/综合加工)。

响应 dataList<NutDictItemVO>

字段 类型 说明
id Long 主键 id
dictType String 所属字典类型编码
dictCode String 字典值(存入业务表的实际值)
dictLabel String 显示名称
sortOrder Integer 排序
isBuiltin Short 是否系统内置(1-是,0-否)
status Short 状态(1-启用,0-禁用)
remark String 备注说明
updateBy Long 修改人 id
updateByName String 修改人姓名
createTime LocalDateTime 创建时间
updateTime LocalDateTime 修改时间

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": [
    { "id": 501, "dictType": "PROCESS_STEP", "dictCode": "WASH",  "dictLabel": "清洗",     "sortOrder": 1, "isBuiltin": 1, "status": 1, "remark": "", "updateBy": 1, "updateByName": "system", "createTime": "2026-05-20 09:00:00", "updateTime": "2026-05-20 09:00:00" },
    { "id": 502, "dictType": "PROCESS_STEP", "dictCode": "PEEL",  "dictLabel": "去皮",     "sortOrder": 2, "isBuiltin": 1, "status": 1, "remark": "", "updateBy": 1, "updateByName": "system", "createTime": "2026-05-20 09:00:00", "updateTime": "2026-05-20 09:00:00" },
    { "id": 503, "dictType": "PROCESS_STEP", "dictCode": "CUT",   "dictLabel": "切割",     "sortOrder": 3, "isBuiltin": 1, "status": 1, "remark": "", "updateBy": 1, "updateByName": "system", "createTime": "2026-05-20 09:00:00", "updateTime": "2026-05-20 09:00:00" },
    { "id": 504, "dictType": "PROCESS_STEP", "dictCode": "SORT",  "dictLabel": "分拣",     "sortOrder": 4, "isBuiltin": 1, "status": 1, "remark": "", "updateBy": 1, "updateByName": "system", "createTime": "2026-05-20 09:00:00", "updateTime": "2026-05-20 09:00:00" },
    { "id": 505, "dictType": "PROCESS_STEP", "dictCode": "MIXED", "dictLabel": "综合加工", "sortOrder": 5, "isBuiltin": 1, "status": 1, "remark": "", "updateBy": 1, "updateByName": "system", "createTime": "2026-05-20 09:00:00", "updateTime": "2026-05-20 09:00:00" }
  ],
  "total": 0
}

接口 P-18 — 净菜加工新增

POST /neglect/pickup/clean-process/add

提交一条净菜加工记录,关联毛菜批次与食材溯源。

入参(Body JSONNutSupCleanProcessDTO

字段 类型 必填 说明
id Long 主键 id(修改时必填)
batchNo String 加工批次号,如 PROC-001,全局唯一
traceCode String 溯源码(来源 nut_farm_harvest.trace_code
materialId Long 食材 idFK→nut_mater_base.id
ingredientName String 食材名称
vegTypeId Long 净菜类型 idFK→nut_mater_veg_type.id
requiredCleanWeight BigDecimal 净菜需求重量(kg),来源毛菜清洗任务的 required_weight
rawBatchNo String 关联毛菜秤批次号 LC-xxx(毛菜秤提交时自动写入)
processStep String 加工步骤:清洗/去皮/切割/分拣/综合加工
rawWeight BigDecimal 毛菜重量(kg
cleanWeight BigDecimal 净菜重量(kg),加工完成后填写
yieldRate BigDecimal 出净率(%),= clean_weight / raw_weight * 100,应用层计算回填
operator String 加工人员姓名,不传时从登录态自动取
startTime LocalDateTime 加工开始时间
endTime LocalDateTime 加工结束时间
qcResult Short 质检结果(0-待检,1-合格,2-不合格),不传默认 0
inboundStatus Short 入库状态(0-未入库,1-已入库)
cameraCode String 关联摄像头编号
videoUrl String 加工监控视频地址
opType Short 操作类型(1-设备自动,2-人工录入)
deviceType String 设备类型(字典值),如 CLEAN_PROCESS_SCALE
deviceCode String 设备编码
remark String 备注

入参示例

{
  "traceCode": "HV2026060001",
  "materialId": 1001,
  "ingredientName": "大白菜",
  "vegTypeId": 11,
  "processStep": "清洗",
  "rawWeight": 50.0,
  "cleanWeight": 45.0,
  "startTime": "2026-06-29 14:00:00",
  "endTime": "2026-06-29 14:20:00",
  "deviceType": "CLEAN_PROCESS_SCALE",
  "deviceCode": "CPS-001",
  "opType": 1
}

响应 data — 无(Result<Void>


4.7 采样-分类 / 菜品搜索


接口 P-19 — 采样菜品分类列表

GET /neglect/pickup/sampling/categories

无入参。返回采样页面用的餐品分类列表。

响应 dataList<NutFoodClassSimpleVO>

字段 类型 说明
classId String 分类 id
className String 分类名称(主食/荤菜/素菜/汤品/饮品)

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": [
    { "classId": "1", "className": "主食" },
    { "classId": "2", "className": "荤菜" },
    { "classId": "3", "className": "素菜" },
    { "classId": "4", "className": "汤品" },
    { "classId": "5", "className": "饮品" }
  ],
  "total": 0
}

接口 P-20 — 采样菜品搜索

POST /neglect/pickup/sampling/food/search

按分类 + 名称模糊搜索,从按单烹制按食堂 + 日期 + 餐次过滤。

入参(Body JSONNutSamplingFoodSearchQuery(继承 BasePageQuery

字段 类型 必填 说明
pageNum Long 页码
pageSize Long 每页条数
categoryId Long 分类 idnull 或 0 表示全部
foodName String 菜品名称,支持模糊搜索

入参示例

{
  "pageNum": 1,
  "pageSize": 20,
  "categoryId": 2,
  "foodName": "鸡"
}

响应 dataList<NutSamplingFoodVO>

字段 类型 说明
cookOrderId String 按单烹制 id
foodId String 菜品 id
foodName String 菜品名称
foodImg String 菜品图片 URL
classId String 分类 id
className String 分类名称
mainIngredientName String 主要食材名称
calorie BigDecimal 能量(kcal/100g

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": [
    {
      "cookOrderId": "CO20260629-001",
      "foodId": "2001",
      "foodName": "宫保鸡丁",
      "foodImg": "https://cdn.yixiong.com/food/2001.jpg",
      "classId": "2",
      "className": "荤菜",
      "mainIngredientName": "鸡胸肉",
      "calorie": 195.5
    }
  ],
  "total": 1
}

4.8 采样-保存采集数据


接口 P-21 — 保存采集图片及向量

POST /neglect/pickup/sampling/savemultipart/form-data

提交一道菜的采样图片及特征向量,返回上传成功的图片 URL 列表。

入参(multipart 表单字段)

字段 类型 必填 说明
foodId Long 菜品 idform 字段)
foodName String 菜品名称(form 字段)
version String 模型版本号(form 字段)
foodVector String 菜品特征向量(JSON 数组字符串,form 字段)
foodPics MultipartFile[] 菜品图片文件列表(file part

响应 dataList<String>,上传成功的图片 URL 列表

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": [
    "https://cdn.yixiong.com/sample/2001_v1_1.jpg",
    "https://cdn.yixiong.com/sample/2001_v1_2.jpg",
    "https://cdn.yixiong.com/sample/2001_v1_3.jpg"
  ],
  "total": 0
}

4.9 采样历史


接口 P-22 — 采样历史分页(按菜品聚合)

POST /neglect/pickup/sampling/history/page

按菜品聚合返回采样历史,每条含 3 张缩略图。

入参(Body JSONNutSamplingHistoryQuery(继承 BasePageQuery

字段 类型 必填 说明
pageNum Long 页码
pageSize Long 每页条数
categoryId Long 分类 idnull 或 0 表示全部
foodName String 菜品名称,支持模糊搜索

入参示例

{
  "pageNum": 1,
  "pageSize": 10,
  "foodName": "鸡"
}

响应 dataList<NutSamplingHistoryVO>

字段 类型 说明
foodId String 菜品 id
foodName String 菜品名称
foodImg String 菜品图片 URL
className String 分类名称
mainIngredientName String 主要食材名称
calorie BigDecimal 能量(kcal/100g
totalCount Long 采样总条数
previewUrls List<String> 已采集图片缩略图(最多 3 张)
lastSampleTime String 最近采样时间

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": [
    {
      "foodId": "2001",
      "foodName": "宫保鸡丁",
      "foodImg": "https://cdn.yixiong.com/food/2001.jpg",
      "className": "荤菜",
      "mainIngredientName": "鸡胸肉",
      "calorie": 195.5,
      "totalCount": 12,
      "previewUrls": [
        "https://cdn.yixiong.com/sample/2001_v1_1.jpg",
        "https://cdn.yixiong.com/sample/2001_v1_2.jpg",
        "https://cdn.yixiong.com/sample/2001_v1_3.jpg"
      ],
      "lastSampleTime": "2026-06-28 17:45:00"
    }
  ],
  "total": 1
}

接口 P-23 — 菜品采样全部图片

POST /neglect/pickup/sampling/history/detail

按菜品 id 查询采样全部图片(最多 50 条)。

入参(Body JSONIdDTO

字段 类型 必填 说明
id Long 菜品 id

入参示例

{ "id": 2001 }

响应 dataList<NutSamplingDetailVO>

字段 类型 说明
id String 采集图片 id
foodPic String 采集图片 URL
createTime String 采样时间

响应示例

{
  "code": "00000",
  "msg": "success",
  "data": [
    { "id": "9001", "foodPic": "https://cdn.yixiong.com/sample/2001_v1_1.jpg", "createTime": "2026-06-28 17:45:00" },
    { "id": "9002", "foodPic": "https://cdn.yixiong.com/sample/2001_v1_2.jpg", "createTime": "2026-06-28 17:45:01" }
  ],
  "total": 0
}

五、接口速查表

接口号 接口名称 方法 路径
P-01 全量人脸数据 POST /neglect/pickup/face/page
P-02 增量人脸数据 POST /neglect/pickup/face/increment
P-03 模糊搜索菜品 POST /neglect/pickup/food/search
P-04 当餐菜品列表 POST /neglect/pickup/food/current-meal
P-05 菜品详情 POST /neglect/pickup/food/detail
P-06 按多名菜品查询 POST /neglect/pickup/food/by-names
P-07 开餐(初始制作量) POST /neglect/pickup/meal/start
P-08 加菜(追加制作量) POST /neglect/pickup/meal/add
P-09a 取餐盘(记录开始就餐时刻) POST /neglect/pickup/plate-pickup
P-09 提交单道菜就餐记录 POST /neglect/pickup/eat
P-10 餐盘号查本餐就餐数据 POST /neglect/pickup/plate-food
P-11 推送菜品实时重量 POST /neglect/pickup/weight
P-12 用户当日就餐营养 POST /neglect/pickup/user/current-food
P-13 虹软 SDK 设备配置 GET /neglect/pickup/device/config
P-14 当前餐次信息 GET /neglect/pickup/meal/current
P-15 会员折扣率 POST /neglect/pickup/member/discount
P-16 食材库存搜索 POST /neglect/pickup/ingredient/search
P-17 加工步骤字典 GET /neglect/pickup/dict/process-step
P-18 净菜加工新增 POST /neglect/pickup/clean-process/add
P-19 采样菜品分类列表 GET /neglect/pickup/sampling/categories
P-20 采样菜品搜索 POST /neglect/pickup/sampling/food/search
P-21 保存采集图片及向量 POST /neglect/pickup/sampling/save
P-22 采样历史分页 POST /neglect/pickup/sampling/history/page
P-23 菜品采样全部图片 POST /neglect/pickup/sampling/history/detail

六、版本差异(对照老版 营养秤_API_DOC.md v1.0.0 / 2026-05-26

6.1 全局差异

维度 老版 新版 影响
路径前缀 /terminal/neglect/...(混杂 common/appnutrition/scale/appboothMachine/app 统一 /neglect/pickup/... 全部接口路径变更,APP 端需更新 Retrofit baseUrl 映射
响应包装 { "code": "00000", "msg": "...", "data": {} } { "code": "00000", "msg": "...", "data": {}, "total": 0 } 新增 total 字段(分页接口返回总条数,非分页为 0)
鉴权 全局硬编码 X-Access-Token + authorization Nacos 白名单 /nutrition/neglect/**,不强制校验 Sa-Token APP 端可继续保留请求头,但服务端不再据此鉴权
设备上下文 DTO 内冗余携带 deviceId 统一由 X-DEVICE-CODE 请求头解析 DTO 字段精简(详见各接口差异)
HTTP 方法 大量使用 GET + Query String 项目规范强制 POST + @RequestBody,仅查询类无入参接口保留 GET 多个老 GET 接口改为 POST + body(详见下表)

6.2 逐接口差异

老接口号 老路径 / 方法 新路径 / 方法 入参变化 响应变化
2.1 POST /terminal/neglect/common/app/faceFeature/list POST /neglect/pickup/face/page 入参从 {pageNum, pageSize} 升级为 BasePageQuery(含 column/order 排序字段),pageNum/pageSize 类型由 Integer 改为 Long 字段精简:移除 faceFeatureStringfaceFeatureStr 备用字段,新增 personType 字段
2.2 POST /terminal/neglect/common/app/faceFeature/increment/list POST /neglect/pickup/face/increment 入参 pageNum/pageSize 由 Long 保留为 Longtimestamp 含义不变 同 2.1
2.3 POST /terminal/neglect/nutrition/scale/app/startMealService 拆为两个接口:POST /neglect/pickup/meal/starttype=1+ POST /neglect/pickup/meal/addtype=2 拆分:老接口靠 type 字段区分 0-就餐/1-初始制作量/2-后期加菜,新版按业务拆为独立 endpoint;就餐数据走 P-09 /eatDTO 字段精简,移除 deviceIdspecIdfoodMaterialIdtypecurrentScaleWeight,新增 powerOnTime 响应仍为空对象
2.4 POST /terminal/neglect/nutrition/scale/app/userEatFood POST /neglect/pickup/eat 字段类型:userId/foodId/specId 由 String 改为 LongfoodWeight/eatWeight 由 String 改为 BigDecimal;移除 deviceIdfoodMaterialId;新增 cookOrderId(按单烹制回传) 响应 data 由空 Object 改为 String(主单 id
2.5 GET /terminal/neglect/boothMachine/app/getUserCurrentFoodDetails?id=xxx POST /neglect/pickup/user/current-food 方法由 GET 改为 POST;入参从 Query id 改为 IdDTO body 字段语义不变;maxCalorie/minCalorie/recommendCalorie 当前固定 0;各 *Recommend/*NearExcess/*Excess 描述字段当前固定空字符串
2.6 GET /terminal/neglect/nutrition/scale/app/getFoodInfoByPlateNumber?userId=xxx POST /neglect/pickup/plate-food 方法由 GET 改为 POST;入参从 Query userId 改为 IdDTO bodyid 即 userId/餐盘号) 子对象 Food 字段类型对齐:eatWeight/deviceWeight/initWeight/eatNum 改为 Integerprice/discount/income 改为 BigDecimalisSyncData 固定 true、orderFrom 固定 1
2.7 POST /terminal/neglect/boothMachine/app/getFoodsByFoodNameList POST /neglect/pickup/food/search 入参从 {name, pageNum, pageSize}String)改为 NutTerminalAppFoodSearchQueryLong + name),name 改为非必填 FoodInfo 字段语义变化:price 单位由「元/千克」改为「元/100g」;vipPrice 固定 nullrecommendCalorie 固定 0;新增 cookOrderIdtablewareStatus 固定 false、tablewareWeight 固定 0
2.8 GET /terminal/neglect/boothMachine/app/getFoodsByCurrentMeal POST /neglect/pickup/food/current-meal 方法由 GET 改为 POST;无入参 同 2.7
2.9 GET /terminal/neglect/common/app/getfoodInfoByFoodId?foodId=xxx POST /neglect/pickup/food/detail 方法由 GET 改为 POST;入参从 Query foodId 改为 IdDTO body 同 2.7
2.10 GET /terminal/neglect/common/app/getYxEquipmentByEquipmentCode GET /neglect/pickup/device/config 路径变更,方法保留 GET,无入参 新增 payType 字段(吐盘机无意义,仅档口秤用)
2.11 POST /terminal/neglect/nutrition/scale/app/updateScaleRealTimeWeight POST /neglect/pickup/weight DTO 字段精简:移除 deviceId(由请求头携带),保留 foodId/foodWeight;类型 foodId 由 String 改为 Long 响应仍为空
2.12 GET /terminal/neglect/common/app/getCurrentPlaceMeal GET /neglect/pickup/meal/current 路径变更,方法保留 GET 字段类型由 String 改为 LocalDateTime(仍按 yyyy-MM-dd HH:mm:ss 序列化)
2.13 GET /terminal/neglect/common/app/getMemberDiscount?userId=xxx POST /neglect/pickup/member/discount 方法由 GET 改为 POST;入参从 Query userId 改为 IdDTO body 返回类型由 Double 改为 BigDecimal

6.3 新版新增接口(老版无对应)

接口号 路径 用途
P-06 /neglect/pickup/food/by-names 按多个菜品名称查询(顺序一致),开餐页面批量查询
P-08 /neglect/pickup/meal/add 加菜(从老 2.3 拆分独立)
P-16 /neglect/pickup/ingredient/search 食材库存搜索(按溯源码分组)
P-17 /neglect/pickup/dict/process-step 加工步骤字典
P-18 /neglect/pickup/clean-process/add 净菜加工记录新增
P-19 /neglect/pickup/sampling/categories 采样菜品分类列表
P-20 /neglect/pickup/sampling/food/search 采样菜品搜索
P-21 /neglect/pickup/sampling/save 保存采集图片及向量
P-22 /neglect/pickup/sampling/history/page 采样历史分页
P-23 /neglect/pickup/sampling/history/detail 菜品采样全部图片

6.4 字段类型迁移注意事项

  1. ID 字段统一 Long:老版 foodId/userId/specId/foodMaterialId 全为 String,新版统一为 LongJSON 序列化时仍以 String 形式输出,避免 JS 精度丢失,但 APP 端反序列化目标类型需调整为 Long。
  2. 重量字段统一 BigDecimal:老版 foodWeight/eatWeight 为 String,新版改为 BigDecimal,杜绝字符串数字解析异常。
  3. 价格单位变化FoodInfo.price 由「元/千克」改为「元/100g」,APP 端计价公式需同步调整:总价 = 重量(g) × price / 100
  4. VIP 价格概念移除vipPrice 固定返回 null,会员优惠改走 member/discount 接口拿折扣系数。
  5. personType 字段新增:人脸 VO 新增 personType(1-员工,2-工作人员,3-普通用户,4-外部人员,5-会员),用于设备端差异化提示。