793 lines
24 KiB
Markdown
793 lines
24 KiB
Markdown
# 菜品识别管理系统第三方接口文档
|
||
|
||
版本:v1.3
|
||
更新时间:2026-10-13
|
||
|
||
## 1. 接口地址
|
||
|
||
生产环境基础地址:
|
||
|
||
```text
|
||
https://cpsb.ruimeida.cc/
|
||
```
|
||
|
||
基地和菜品查询接口使用 `GET` 请求;识别结果、无法识别样本和菜品图库样本写入接口使用 `POST` 请求;菜品学习状态和设备状态更新使用 `PATCH` 请求。
|
||
|
||
## 2. 接口认证
|
||
|
||
接口使用独立的 API Key 认证,不使用后台用户登录账号密码。
|
||
|
||
每次请求都必须携带请求头:
|
||
|
||
```http
|
||
X-API-Key: <THIRD_PARTY_API_KEY>
|
||
```
|
||
|
||
请向系统管理员获取正式 API Key,不要将 API Key 写入前端页面、公开代码仓库或日志中。
|
||
|
||
## 3. 写入菜品识别结果
|
||
|
||
该接口接收一次识别任务的主信息和菜品明细,供第三方识别程序回传结果。接口使用
|
||
`request_id` 做幂等键:同一个 `request_id` 再次提交时会更新主记录,并完整替换该任务的菜品明细,不会产生重复订单。
|
||
|
||
### 请求
|
||
|
||
```http
|
||
POST /api/public/recognition-orders
|
||
Content-Type: application/json
|
||
X-API-Key: <THIRD_PARTY_API_KEY>
|
||
```
|
||
|
||
完整地址:
|
||
|
||
```text
|
||
https://cpsb.ruimeida.cc/api/public/recognition-orders
|
||
```
|
||
|
||
### 请求体示例
|
||
|
||
```json
|
||
{
|
||
"request_id": "REQ_20260916_000001",
|
||
"base_name": "上海路基地",
|
||
"device_code": "DEV-0018",
|
||
"capture_time": "2026-09-16 12:34:56",
|
||
"source_image": "https://example.com/images/source.jpg",
|
||
"labeled_image": "https://example.com/images/labeled.jpg",
|
||
"dish_count": 2,
|
||
"dishes": [
|
||
{
|
||
"index": 1,
|
||
"name": "红烧鸡块",
|
||
"score": 0.96,
|
||
"is_unknown": false,
|
||
"suggested_name": null,
|
||
"box": [120, 80, 460, 390],
|
||
"crop_image": "https://example.com/images/crop-1.jpg",
|
||
"text": "识别为红烧鸡块,相似度 0.96"
|
||
},
|
||
{
|
||
"index": 2,
|
||
"name": null,
|
||
"score": 0.42,
|
||
"is_unknown": true,
|
||
"suggested_name": "辣椒炒肉",
|
||
"box": [500, 90, 820, 400],
|
||
"crop_image": "https://example.com/images/crop-2.jpg",
|
||
"text": "低于阈值,建议人工确认"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### Body 字段
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `request_id` | string | 是 | 唯一请求号,建议使用 `REQ_` 加毫秒时间戳或业务流水号 |
|
||
| `base_name` | string | 是 | 基地名称,必须与基地信息中的 `name` 完全一致,例如 `上海路基地` |
|
||
| `device_code` | string | 是 | 设备编号,对应设备列表中的设备编号 |
|
||
| `capture_time` | string | 是 | 采集时间,格式为 `YYYY-MM-DD HH:mm:ss`,也支持 ISO 8601 字符串 |
|
||
| `source_image` | string \| null | 否 | 原图路径或 URL;没有时传 `null` 或空字符串 |
|
||
| `labeled_image` | string \| null | 否 | 标注预览图路径或 URL;没有时传 `null` 或空字符串 |
|
||
| `dish_count` | int | 是 | 菜品区域数,必须等于 `dishes.length`,不能小于 0 |
|
||
| `dishes` | array | 是 | 菜品识别明细数组 |
|
||
|
||
### `dishes[]` 字段
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `index` | int | 是 | 从 1 开始的顺序号,与标注预览图中的编号/框对应,任务内不可重复 |
|
||
| `name` | string \| null | 是 | 识别菜名;未知菜品时传 `null` |
|
||
| `score` | number \| null | 否 | 相似度,建议范围为 0~1;未知或没有分数时传 `null` |
|
||
| `is_unknown` | boolean | 是 | 是否未达阈值或未知,未知时为 `true` |
|
||
| `suggested_name` | string \| null | 否 | 未知菜品的近似菜名建议 |
|
||
| `box` | number[4] \| null | 否 | 像素坐标 `[x1, y1, x2, y2]` |
|
||
| `crop_image` | string \| null | 否 | 当前菜品裁剪图路径或 URL |
|
||
| `text` | string \| null | 否 | 可读摘要文本,仅用于调试或展示 |
|
||
|
||
### cURL 示例
|
||
|
||
```bash
|
||
curl -X POST "https://cpsb.ruimeida.cc/api/public/recognition-orders" \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-API-Key: <THIRD_PARTY_API_KEY>" \
|
||
-d @recognition-order.json
|
||
```
|
||
|
||
### 成功返回
|
||
|
||
```json
|
||
{
|
||
"message": "识别结果已保存",
|
||
"item": {
|
||
"request_id": "REQ_20260916_000001",
|
||
"base_name": "上海路基地",
|
||
"device_code": "DEV-0018",
|
||
"capture_time": "2026-09-16 12:34:56",
|
||
"dish_count": 2
|
||
}
|
||
}
|
||
```
|
||
|
||
### 校验与存储说明
|
||
|
||
1. `base_name` 必须传启用基地的名称,并且需要与基地信息中的 `name` 完全一致;接口会在服务端匹配基地编码保存关联关系。
|
||
2. `device_code` 必须传设备列表中的设备编号。
|
||
3. `dish_count` 必须与明细条数一致;`index` 在同一请求内必须唯一且从 1 开始。
|
||
4. `box` 只能是 4 个数字,顺序为 `[x1, y1, x2, y2]`,单位为原图像素。
|
||
5. 识别原图、标注图和裁剪图由第三方自行保存,接口只保存传入的路径或 URL。
|
||
6. 数据分别保存于 `recognition_orders` 和 `recognition_order_dishes` 两张表,删除或更新主记录时会同步处理明细。
|
||
7. 新版接口使用 `base_name`,不再要求第三方传基地编码;服务端会根据基地名称匹配并保存内部关联关系。历史版本的 `base_id` 仅作兼容处理,不建议新接入继续使用。
|
||
|
||
## 4. 上报无法识别样本
|
||
|
||
第三方识别程序在识别到未知菜品后调用该接口,上报的数据进入后台「数据管理 → 识别数据管理 → 无法识别统计」列表。管理员可在该页面勾选裁剪图、填写菜名后提交手动学习,学习提交会转发到识别端学习接口(`POST /api/client/manual-learn`)。
|
||
|
||
### 请求
|
||
|
||
```http
|
||
POST /api/public/unrecognized-samples
|
||
Content-Type: application/json
|
||
X-API-Key: <THIRD_PARTY_API_KEY>
|
||
```
|
||
|
||
完整地址:
|
||
|
||
```text
|
||
https://cpsb.ruimeida.cc/api/public/unrecognized-samples
|
||
```
|
||
|
||
### 请求体示例
|
||
|
||
```json
|
||
{
|
||
"request_id": "REQ_20260916_000002",
|
||
"order_no": "HW26091612341817",
|
||
"base_name": "上海路基地",
|
||
"device_code": "DEV-0018",
|
||
"capture_time": "2026-09-16 12:34:46",
|
||
"image_url": "https://example.com/images/source.jpg",
|
||
"unknown_count": 2,
|
||
"suggested_names": ["梅菜扣肉", "黑米饭"],
|
||
"crops": [
|
||
{
|
||
"index": 1,
|
||
"image_url": "https://example.com/images/crop-1.jpg",
|
||
"suggested_name": "梅菜扣肉",
|
||
"score": 0.62
|
||
},
|
||
{
|
||
"index": 2,
|
||
"image_url": "https://example.com/images/crop-2.jpg",
|
||
"suggested_name": null,
|
||
"score": 0.41
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### Body 字段
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `request_id` | string | 否 | 唯一请求号,作为幂等键;传入后同一 `request_id` 重复上报会覆盖主记录并重建明细 |
|
||
| `order_no` | string | 是 | 业务单号,后台无法识别统计与手动学习接口使用 |
|
||
| `base_code` | string | 否 | 基地编码,与 `base_name` 至少传一个;服务端匹配启用基地后保存关联 |
|
||
| `base_name` | string | 否 | 基地名称,需与基地信息中的 `name` 一致;与 `base_code` 同时传入时优先按编码匹配 |
|
||
| `device_code` | string | 是 | 设备编号 |
|
||
| `capture_time` | string | 是 | 采集时间,格式为 `YYYY-MM-DD HH:mm:ss`,也支持 ISO 8601 字符串 |
|
||
| `image_url` | string | 是 | 整盘原图路径或 URL |
|
||
| `unknown_count` | number | 否 | 未知菜品数量;不传或非法时按 `crops.length` 保存 |
|
||
| `suggested_names` | string[] | 否 | 建议菜名列表,在列表页「建议菜名」列展示 |
|
||
| `crops` | array | 否 | 未知菜品裁剪图明细,供后台学习弹框逐盘学习 |
|
||
|
||
### `crops[]` 字段
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `index` | int | 否 | 从 1 开始的顺序号,缺省按数组位置生成;同一样本内不可重复 |
|
||
| `image_url` | string \| null | 否 | 当前未知菜品的裁剪图路径或 URL |
|
||
| `suggested_name` | string \| null | 否 | 近似菜名建议;后台学习弹框会预填到菜名输入框 |
|
||
| `score` | number \| null | 否 | 相似度,范围 0~1;后台学习弹框展示为置信度 |
|
||
|
||
### cURL 示例
|
||
|
||
```bash
|
||
curl -X POST "https://cpsb.ruimeida.cc/api/public/unrecognized-samples" \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-API-Key: <THIRD_PARTY_API_KEY>" \
|
||
-d @unrecognized-sample.json
|
||
```
|
||
|
||
### 成功返回
|
||
|
||
```json
|
||
{
|
||
"message": "无法识别样本已保存",
|
||
"item": {
|
||
"id": 1,
|
||
"order_no": "HW26091612341817",
|
||
"unknown_count": 2
|
||
}
|
||
}
|
||
```
|
||
|
||
### 校验与存储说明
|
||
|
||
1. `order_no`、`device_code`、`capture_time`、`image_url` 为必填,缺失或格式无效返回 `400`。
|
||
2. `base_code` / `base_name` 传入时服务端会匹配启用状态的基地并保存编码和名称;匹配不到时按传入原值保存,不影响入库。
|
||
3. `score` 超出 0~1、`index` 重复或非法时返回 `400`。
|
||
4. 传 `request_id` 时按幂等处理:重复上报覆盖主记录并完整替换 `crops` 明细;不传 `request_id` 时每次上报都会新增一条样本。
|
||
5. 数据保存于 `unrecognized_samples` 和 `unrecognized_sample_crops` 两张表。
|
||
6. 后台无法识别统计列表支持按时段、日期范围、基地、餐段、学习状态(默认未学习)和关键字筛选;餐段按 `capture_time` 落入系统餐段配置的时间范围判定。
|
||
|
||
## 5. 上报菜品图库样本(近期学习菜品)
|
||
|
||
识别端在学菜完成后调用该接口,把「菜名 ↔ 样本图片」映射上报给管理系统,数据展示在后台「AI 自主学习管理 → 近期学习菜品」页面,详情弹框中展示每个菜品的名称和多张样本图片。
|
||
|
||
### 请求
|
||
|
||
```http
|
||
POST /api/public/dish-gallery/samples
|
||
Content-Type: application/json
|
||
X-API-Key: <THIRD_PARTY_API_KEY>
|
||
```
|
||
|
||
完整地址:
|
||
|
||
```text
|
||
https://cpsb.ruimeida.cc/api/public/dish-gallery/samples
|
||
```
|
||
|
||
### 请求体示例(单菜)
|
||
|
||
```json
|
||
{
|
||
"request_id": "REQ_20260916_120001",
|
||
"base_name": "上海路基地",
|
||
"device_code": "DEV-0018",
|
||
"learned_at": "2026-09-16 12:00:01",
|
||
"name": "梅菜扣肉",
|
||
"code": "DISH-001",
|
||
"category": "成品",
|
||
"images": [
|
||
"https://example.com/template/mc/20260916_120001_01.jpg",
|
||
"https://example.com/template/mc/20260916_120001_02.jpg"
|
||
]
|
||
}
|
||
```
|
||
|
||
### 请求体示例(一次报多个菜)
|
||
|
||
```json
|
||
{
|
||
"request_id": "REQ_20260916_120001",
|
||
"base_name": "上海路基地",
|
||
"learned_at": "2026-09-16 12:00:01",
|
||
"dishes": [
|
||
{
|
||
"name": "梅菜扣肉",
|
||
"code": "DISH-001",
|
||
"category": "成品",
|
||
"images": ["https://example.com/template/mc/20260916_120001_01.jpg"]
|
||
},
|
||
{
|
||
"name": "黑米饭",
|
||
"category": "成品",
|
||
"images": ["https://example.com/template/hmf/20260916_120001_02.jpg"]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### Body 字段
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `request_id` | string | 否 | 请求号,与菜品名称一起作为幂等键;不传时服务端自动生成 |
|
||
| `base_code` | string | 否 | 基地编码,与 `base_name` 至少传一个;服务端匹配启用基地后保存关联 |
|
||
| `base_name` | string | 否 | 基地名称,需与基地信息中的 `name` 一致 |
|
||
| `device_code` | string | 否 | 设备编号 |
|
||
| `learned_at` | string | 是 | 学习完成时间,格式为 `YYYY-MM-DD HH:mm:ss`,也支持 ISO 8601 字符串;兼容 `capture_time` 字段名 |
|
||
| `name` | string | 单菜必填 | 菜品名称(单菜格式) |
|
||
| `code` | string | 否 | 菜品编码(单菜格式) |
|
||
| `category` | string | 否 | 分类,默认 `成品`,建议传 `成品` 或 `配菜` |
|
||
| `images` | string[] | 单菜必填 | 样本图片路径或 URL 数组,至少一张(单菜格式) |
|
||
| `dishes` | array | 多菜必填 | 多菜品格式;与 `name` 同时传入时优先使用 `dishes` |
|
||
|
||
### `dishes[]` 字段
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `name` | string | 是 | 菜品名称 |
|
||
| `code` | string | 否 | 菜品编码 |
|
||
| `category` | string | 否 | 分类,默认 `成品` |
|
||
| `images` | string[] | 是 | 样本图片路径或 URL 数组,至少一张 |
|
||
|
||
### cURL 示例
|
||
|
||
```bash
|
||
curl -X POST "https://cpsb.ruimeida.cc/api/public/dish-gallery/samples" \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-API-Key: <THIRD_PARTY_API_KEY>" \
|
||
-d @dish-gallery-sample.json
|
||
```
|
||
|
||
### 成功返回
|
||
|
||
```json
|
||
{
|
||
"message": "图库样本已保存",
|
||
"item": {
|
||
"request_id": "REQ_20260916_120001",
|
||
"count": 2
|
||
}
|
||
}
|
||
```
|
||
|
||
### 校验与存储说明
|
||
|
||
1. `learned_at`(或 `capture_time`)缺失或格式无效返回 `400`。
|
||
2. 单菜格式必须同时传 `name` 和非空 `images`;多菜格式每个菜品的 `name` 和 `images` 同样必填,否则返回 `400`。
|
||
3. 幂等键为 `request_id + 菜品名称`:同一组合重复上报时更新样本(图片、分类、学习时间等以最新为准);上报未携带 `code` 时保留原编码。
|
||
4. 数据保存于 `dish_gallery_samples` 表。
|
||
5. 后台「近期学习菜品」列表按学习时间倒序展示,支持时段、日期范围、基地和关键字筛选;点「详情」按 `request_id` 展示该次学习的全部菜品及多张样本图片。
|
||
|
||
## 6. 后台查询识别结果
|
||
|
||
以下接口用于系统后台的统计列表和详情查询,使用登录用户的 JWT,不使用第三方 API Key。第三方系统如需查询自身回传的数据,建议由业务服务端代理调用,不要把管理员 JWT 暴露给浏览器。
|
||
|
||
### 识别统计列表
|
||
|
||
```http
|
||
GET /api/recognition-stats
|
||
Authorization: Bearer <ACCESS_TOKEN>
|
||
```
|
||
|
||
可选参数:`period`(`today`、`yesterday`、`week`、`month`)、`baseCode`、`keyword`、`startDate`、`endDate`、`page`、`pageSize`。`pageSize` 支持 10、20、50。
|
||
|
||
### 识别结果详情
|
||
|
||
```http
|
||
GET /api/recognition-orders/{request_id}
|
||
Authorization: Bearer <ACCESS_TOKEN>
|
||
```
|
||
|
||
详情返回主记录和 `dishes` 明细,主记录返回 `base_name`、`device_code`,不返回或展示基地编码 `base_id`;明细包含 `index`、`name`、`score`、`is_unknown`、`suggested_name`、`box`、`crop_image`、`text`。
|
||
|
||
## 7. 更新设备状态信息
|
||
|
||
第三方设备程序使用该接口按设备编号更新设备状态、心跳更新时间和菜谱当前日期。接口使用 API Key 认证。
|
||
|
||
### 请求
|
||
|
||
```http
|
||
PATCH /api/public/devices/{device_code}/status
|
||
Content-Type: application/json
|
||
X-API-Key: <THIRD_PARTY_API_KEY>
|
||
```
|
||
|
||
完整地址示例:
|
||
|
||
```text
|
||
https://cpsb.ruimeida.cc/api/public/devices/DEV-0018/status
|
||
```
|
||
|
||
### 请求体
|
||
|
||
```json
|
||
{
|
||
"status": "在线",
|
||
"updated_at": "2026-09-16 14:30:00",
|
||
"recipe_date": "2026-09-16"
|
||
}
|
||
```
|
||
|
||
### 参数说明
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| 路径 `device_code` | string | 是 | 设备编号,对应设备列表中的设备编号 |
|
||
| `status` | string | 是 | 设备状态,支持 `在线`、`离线`,也支持 `online`、`offline` |
|
||
| `updated_at` | string \| null | 否 | 设备最后更新时间,格式为 `YYYY-MM-DD HH:mm:ss`;不传时使用服务器当前时间 |
|
||
| `recipe_date` | string \| null | 否 | 菜谱当前日期,格式为 `YYYY-MM-DD`;不传时保留原值,传 `null` 或空字符串可清空 |
|
||
|
||
### cURL 示例
|
||
|
||
```bash
|
||
curl -X PATCH "https://cpsb.ruimeida.cc/api/public/devices/DEV-0018/status" \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-API-Key: <THIRD_PARTY_API_KEY>" \
|
||
-d '{"status":"在线","updated_at":"2026-09-16 14:30:00","recipe_date":"2026-09-16"}'
|
||
```
|
||
|
||
### 成功返回
|
||
|
||
```json
|
||
{
|
||
"message": "设备状态信息已更新",
|
||
"item": {
|
||
"id": 1,
|
||
"code": "DEV-0018",
|
||
"status": 1,
|
||
"status_label": "在线",
|
||
"updated_at": "2026-09-16 14:30:00",
|
||
"recipe_date": "2026-09-16"
|
||
}
|
||
}
|
||
```
|
||
|
||
设备列表查询接口 `GET /api/devices` 返回的字段包括 `status`、`status_label`、`updated_at`、`recipe_date`,其中 `status=1` 表示在线,`status=0` 表示离线。设备状态和时间信息保存于 `devices` 表。
|
||
|
||
## 8. 菜品信息接口
|
||
|
||
菜品接口使用 API Key 认证,返回菜品名称、菜品分类、学习状态、价格等信息。
|
||
|
||
### 8.1 获取菜品信息
|
||
|
||
```http
|
||
GET /api/public/dishes
|
||
X-API-Key: <THIRD_PARTY_API_KEY>
|
||
```
|
||
|
||
完整地址:
|
||
|
||
```text
|
||
https://cpsb.ruimeida.cc/api/public/dishes
|
||
```
|
||
|
||
查询参数均为可选,不传参数时返回全部菜品:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `name` | string | 否 | 按菜品名称模糊查询,例如 `鸡` |
|
||
| `category` | string | 否 | 按菜品分类精确查询,例如 `素菜`;传 `全部` 等同于不筛选 |
|
||
|
||
查询全部菜品:
|
||
|
||
```bash
|
||
curl -X GET "https://cpsb.ruimeida.cc/api/public/dishes" \
|
||
-H "X-API-Key: <THIRD_PARTY_API_KEY>"
|
||
```
|
||
|
||
按菜品名称和分类查询:
|
||
|
||
```bash
|
||
curl -G "https://cpsb.ruimeida.cc/api/public/dishes" \
|
||
-H "X-API-Key: <THIRD_PARTY_API_KEY>" \
|
||
--data-urlencode "name=鸡" \
|
||
--data-urlencode "category=大荤"
|
||
```
|
||
|
||
返回示例:
|
||
|
||
```json
|
||
{
|
||
"total": 1,
|
||
"items": [
|
||
{
|
||
"id": 1,
|
||
"name": "红烧鸡块",
|
||
"code": "DISH-001",
|
||
"category": "大荤",
|
||
"price": 4,
|
||
"status": "已学习",
|
||
"confidence": 96.5,
|
||
"picks": 3809,
|
||
"created_at": "2026-09-16 10:00:00",
|
||
"updated_at": "2026-09-28 09:30:00"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 8.2 按菜品名称更新学习状态
|
||
|
||
```http
|
||
PATCH /api/public/dishes/learning-status
|
||
Content-Type: application/json
|
||
X-API-Key: <THIRD_PARTY_API_KEY>
|
||
```
|
||
|
||
完整地址:
|
||
|
||
```text
|
||
https://cpsb.ruimeida.cc/api/public/dishes/learning-status
|
||
```
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"name": "红烧鸡块",
|
||
"status": "已学习"
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `name` | string | 是 | 菜品名称,按名称精确匹配 |
|
||
| `status` | string | 是 | 学习状态,只能是 `已学习` 或 `未学习`;也兼容 `learned`、`unlearned` |
|
||
|
||
cURL 示例:
|
||
|
||
```bash
|
||
curl -X PATCH "https://cpsb.ruimeida.cc/api/public/dishes/learning-status" \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-API-Key: <THIRD_PARTY_API_KEY>" \
|
||
-d '{"name":"红烧鸡块","status":"已学习"}'
|
||
```
|
||
|
||
成功返回:
|
||
|
||
```json
|
||
{
|
||
"message": "菜品学习状态已更新",
|
||
"item": {
|
||
"id": 1,
|
||
"name": "红烧鸡块",
|
||
"code": "DISH-001",
|
||
"category": "大荤",
|
||
"price": 4,
|
||
"status": "已学习",
|
||
"confidence": 96.5,
|
||
"picks": 3809,
|
||
"created_at": "2026-09-16 10:00:00",
|
||
"updated_at": "2026-09-28 09:30:00"
|
||
}
|
||
}
|
||
```
|
||
|
||
菜品名称不存在时返回 `404`;状态不合法或菜品名称为空时返回 `400`。
|
||
|
||
## 9. 获取全部基地信息
|
||
|
||
### 请求
|
||
|
||
```http
|
||
GET /api/public/bases
|
||
```
|
||
|
||
完整地址:
|
||
|
||
```text
|
||
https://cpsb.ruimeida.cc/api/public/bases
|
||
```
|
||
|
||
### cURL 示例
|
||
|
||
```bash
|
||
curl -X GET "https://cpsb.ruimeida.cc/api/public/bases" \
|
||
-H "X-API-Key: <THIRD_PARTY_API_KEY>"
|
||
```
|
||
|
||
### 返回示例
|
||
|
||
```json
|
||
{
|
||
"items": [
|
||
{
|
||
"id": 1364,
|
||
"branchName": "安仁街分部",
|
||
"name": "上海路基地",
|
||
"code": "上海路基地-1788059884828-e55vu",
|
||
"province": "",
|
||
"city": "",
|
||
"district": "",
|
||
"address": "",
|
||
"contact": "",
|
||
"phone": "",
|
||
"longitude": null,
|
||
"latitude": null,
|
||
"description": "",
|
||
"status": 1,
|
||
"sortOrder": 0
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 字段说明
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| --- | --- | --- |
|
||
| `id` | number | 基地 ID,可用于排餐查询的 `baseId` 参数 |
|
||
| `branchName` | string | 分部名称 |
|
||
| `name` | string | 基地名称,可用于排餐查询的 `baseName` 参数 |
|
||
| `code` | string | 基地编码,可用于排餐查询的 `baseCode` 参数 |
|
||
| `province` / `city` / `district` | string | 所属地区 |
|
||
| `address` | string | 详细地址 |
|
||
| `contact` | string | 联系人 |
|
||
| `phone` | string | 联系电话 |
|
||
| `longitude` / `latitude` | number \| null | 经纬度 |
|
||
| `description` | string | 基地备注 |
|
||
| `status` | number | `1` 启用,`0` 禁用 |
|
||
| `sortOrder` | number | 排序值 |
|
||
|
||
## 10. 获取当天排餐信息
|
||
|
||
### 请求
|
||
|
||
```http
|
||
GET /api/public/meal-schedules/today
|
||
```
|
||
|
||
兼容地址:
|
||
|
||
```http
|
||
GET /api/meal-schedules/today
|
||
```
|
||
|
||
接口默认返回中国时区(`Asia/Shanghai`)当天的数据,并包含所有基地、早餐、中餐和晚餐。
|
||
|
||
### 查询参数
|
||
|
||
所有查询参数均为可选:
|
||
|
||
| 参数 | 类型 | 说明 |
|
||
| --- | --- | --- |
|
||
| `date` | string | 指定日期,格式为 `YYYY-MM-DD`;不传时使用中国时区当天日期 |
|
||
| `baseName` | string | 按基地名称精确查询,推荐使用;中文需要进行 URL 编码 |
|
||
| `baseId` | number | 按基地 ID 查询 |
|
||
| `baseCode` | string | 按基地编码精确查询 |
|
||
|
||
基地筛选参数只需要传一个。如果同时传多个参数,优先级为:`baseId` > `baseCode` > `baseName`。
|
||
|
||
### 调用示例
|
||
|
||
查询当天所有基地:
|
||
|
||
```bash
|
||
curl -X GET "https://cpsb.ruimeida.cc/api/public/meal-schedules/today" \
|
||
-H "X-API-Key: <THIRD_PARTY_API_KEY>"
|
||
```
|
||
|
||
按基地名称查询:
|
||
|
||
```bash
|
||
curl -G "https://cpsb.ruimeida.cc/api/public/meal-schedules/today" \
|
||
-H "X-API-Key: <THIRD_PARTY_API_KEY>" \
|
||
--data-urlencode "baseName=上海路基地"
|
||
```
|
||
|
||
查询指定日期和基地:
|
||
|
||
```bash
|
||
curl -G "https://cpsb.ruimeida.cc/api/public/meal-schedules/today" \
|
||
-H "X-API-Key: <THIRD_PARTY_API_KEY>" \
|
||
--data-urlencode "date=2026-09-16" \
|
||
--data-urlencode "baseName=上海路基地"
|
||
```
|
||
|
||
### 返回示例
|
||
|
||
```json
|
||
{
|
||
"date": "2026-09-16",
|
||
"timezone": "Asia/Shanghai",
|
||
"mealPeriods": [
|
||
{
|
||
"id": 1,
|
||
"name": "早餐",
|
||
"startTime": "07:00",
|
||
"endTime": "09:00"
|
||
},
|
||
{
|
||
"id": 2,
|
||
"name": "中餐",
|
||
"startTime": "11:30",
|
||
"endTime": "13:30"
|
||
},
|
||
{
|
||
"id": 3,
|
||
"name": "晚餐",
|
||
"startTime": "17:30",
|
||
"endTime": "19:00"
|
||
}
|
||
],
|
||
"bases": [
|
||
{
|
||
"id": 1364,
|
||
"code": "上海路基地-1788059884828-e55vu",
|
||
"name": "上海路基地",
|
||
"branchName": "安仁街分部",
|
||
"status": 1,
|
||
"meals": [
|
||
{
|
||
"mealPeriodId": 1,
|
||
"mealPeriodName": "早餐",
|
||
"startTime": "07:00",
|
||
"endTime": "09:00",
|
||
"dishes": []
|
||
},
|
||
{
|
||
"mealPeriodId": 2,
|
||
"mealPeriodName": "中餐",
|
||
"startTime": "11:30",
|
||
"endTime": "13:30",
|
||
"dishes": [
|
||
{
|
||
"name": "米粉蒸肉",
|
||
"price": 4,
|
||
"learningStatus": "未学习",
|
||
"sortOrder": 0
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"mealPeriodId": 3,
|
||
"mealPeriodName": "晚餐",
|
||
"startTime": "17:30",
|
||
"endTime": "19:00",
|
||
"dishes": []
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 排餐字段说明
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| --- | --- | --- |
|
||
| `date` | string | 查询日期 |
|
||
| `timezone` | string | 日期使用的时区 |
|
||
| `mealPeriods` | array | 当天配置的餐段列表 |
|
||
| `bases` | array | 基地列表 |
|
||
| `bases[].meals` | array | 当前基地的各餐段;没有菜品时仍返回该餐段 |
|
||
| `meals[].mealPeriodId` | number | 餐段 ID |
|
||
| `meals[].mealPeriodName` | string | 餐段名称 |
|
||
| `meals[].startTime` / `endTime` | string | 餐段开始、结束时间,格式为 `HH:mm` |
|
||
| `meals[].dishes` | array | 当前基地当前餐段的菜品 |
|
||
| `dishes[].name` | string | 菜品名称 |
|
||
| `dishes[].price` | number | 菜品价格 |
|
||
| `dishes[].learningStatus` | string | `已学习` 或 `未学习` |
|
||
| `dishes[].sortOrder` | number | 菜品在餐段中的顺序 |
|
||
|
||
## 11. HTTP 状态码
|
||
|
||
| 状态码 | 说明 |
|
||
| --- | --- |
|
||
| `200` | 请求成功 |
|
||
| `400` | 请求参数格式错误,例如日期或 `baseId` 格式错误 |
|
||
| `401` | API Key 缺失或错误 |
|
||
| `503` | 服务端尚未配置第三方 API Key |
|
||
| `500` | 服务端内部错误 |
|
||
|
||
错误返回格式:
|
||
|
||
```json
|
||
{
|
||
"message": "第三方接口认证失败"
|
||
}
|
||
```
|
||
|
||
## 12. 对接建议
|
||
|
||
1. 第三方系统应将 API Key 保存在服务端配置中,不要放在浏览器前端代码中。
|
||
2. 建议每次调用排餐接口时传入 `baseName` 或 `baseId`,减少返回数据量。
|
||
3. 排餐接口会返回没有菜品的餐段,第三方系统应将 `dishes: []` 识别为当天该基地该餐段暂无排餐。
|
||
4. 日期不传时按 `Asia/Shanghai` 计算,不要使用第三方服务器的本地时区替代接口返回的 `date`。
|