{
  "openapi": "3.0.0",
  "info": {
    "title": "智慧营养健康餐厅人脸同步接口契约修订",
    "version": "2026-10-10"
  },
  "paths": {
    "/p/api/userdata": {
      "post": {
        "summary": "人员数据同步(人脸/卡片)",
        "deprecated": false,
        "description": "## 接口概述\n\n设备同步人员、人脸照片及卡片数据。张家港设备端学习使用 `type=1` 全量：读取 `data.face_learning_mode`，模式 `2` 下有照片但尚无特征的人员仍以 `status=1` 下发，由设备下载照片并学习；学习成功后调用 `/p/api/facedataLearnResult` 回传。`type=0` 增量沿用原有消息队列逻辑，本期不改造增量下发。\n\n## 接口信息\n\n| 项目 | 内容 |\n| --- | --- |\n| 地址 | `POST /p/api/userdata` |\n| Content-Type | `application/x-www-form-urlencoded` |\n| 调用方 | 消费机等安卓设备 |\n\n## 请求头（Header）\n\n`Content-Type: application/x-www-form-urlencoded`。历史可选 `Access-Token` 头仍保留；当前业务方法以设备编码核对设备是否存在，不校验该头。\n\n## 请求参数（Body）\n\n| 字段 | 必填 | 说明 |\n| --- | --- | --- |\n| `code` | 是 | 已登记且未删除的设备编码。 |\n| `type` | 否 | `1` 全量，`0` 增量；默认 `0`，其他值按 `0` 处理。 |\n\n## 响应格式\n\n成功示例（模式 2、待设备学习）：\n\n```json\n{\n  \"code\": 0,\n  \"message\": \"查询成功\",\n  \"data\": {\n    \"face_data\": [\n      {\n        \"id\": 123,\n        \"staff_uuid\": \"11111111-2222-3333-4444-555555555555\",\n        \"name\": \"示例人员\",\n        \"head_img_url\": \"http://example.invalid/static/upload/face/example.jpg\",\n        \"feature\": \"\",\n        \"face_token\": \"\",\n        \"hardware_uuid\": \"66666666-7777-8888-9999-000000000000\",\n        \"status\": 1,\n        \"card_id\": \"\"\n      }\n    ],\n    \"face_learning_mode\": 2\n  },\n  \"trace_id\": \"<本次请求追踪ID>\"\n}\n```\n\n失败示例：\n\n```json\n{\n  \"code\": 1,\n  \"message\": \"设备不存在\",\n  \"data\": null,\n  \"trace_id\": \"<本次请求追踪ID>\"\n}\n```\n\n增量成功时 `data.face_data` 为消息队列中的待同步记录，具体记录字段按消息类型变化。\n\n## 状态码与设备处理\n\nHTTP 通常为 200，必须以顶层 `code` 判定业务结果。`data.face_learning_mode=1` 表示服务端学习，`2` 表示设备端学习；该字段在成功响应中返回，**不在响应最外层**。模式 2 下，有照片且 `face_token` 为空时，设备下载照片并学习；有 token 时按既有设备逻辑保存。无照片也无有效卡号时 `status=3`；有有效卡号时仍可作为有效人员。全量查询更新设备同步时间并处理积累消息。\n\n## 响应字段说明\n\n`data.face_data` 是人员、人脸和卡片列表；`id` 为 `ydy_staff.id`，学习结果回传时传作 `staff_id`；`head_img_url` 是完整照片地址，回传时须原样传入；`feature`、`face_token` 在未学习时可以为空；`card_id` 可为空。全量记录的 `status=1` 为有效，`status=3` 为删除/无有效人脸或卡号；增量状态沿用原消息。`data.face_learning_mode` 为 `1` 或 `2`。`trace_id` 在成功和业务失败响应中均由项目统一补充。\n\n## trace_id 排查说明\n\n排查时提供 `trace_id`、设备编码和请求时间，以便关联服务端日志；不要在工单中传播真实人脸特征值。\n",
        "tags": [],
        "parameters": [
          {
            "name": "Access-Token",
            "in": "header",
            "description": "",
            "required": false,
            "example": "{{terminal_token}}",
            "schema": {
              "type": "string",
              "default": "{{terminal_token}}"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "description": "设备编号",
                    "type": "string",
                    "example": "0013"
                  },
                  "type": {
                    "description": "同步方式：0增量1全量",
                    "type": "string",
                    "example": "1"
                  }
                },
                "required": [
                  "code"
                ]
              },
              "example": {
                "code": "0013",
                "type": "1"
              }
            }
          }
        },
        "responses": {
          "200": {
            "x-apifox-name": "成功",
            "x-apifox-ordering": 0,
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "message",
                    "data",
                    "trace_id"
                  ],
                  "properties": {
                    "code": {
                      "type": "integer",
                      "enum": [
                        0,
                        1
                      ],
                      "description": "0成功，1业务失败。"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "face_data": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "staff_uuid": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "head_img_url": {
                                "type": "string"
                              },
                              "feature": {
                                "type": "string"
                              },
                              "face_token": {
                                "type": "string"
                              },
                              "hardware_uuid": {
                                "type": "string"
                              },
                              "status": {
                                "type": "integer"
                              },
                              "card_id": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "face_learning_mode": {
                          "type": "integer",
                          "enum": [
                            1,
                            2
                          ],
                          "description": "成功响应：1服务端学习，2设备端学习。"
                        }
                      }
                    },
                    "trace_id": {
                      "type": "string",
                      "description": "固定返回的请求追踪ID。"
                    }
                  }
                },
                "examples": {
                  "deviceLearning": {
                    "summary": "模式2：待设备学习的人员",
                    "value": {
                      "code": 0,
                      "message": "查询成功",
                      "data": {
                        "face_data": [
                          {
                            "id": 123,
                            "staff_uuid": "11111111-2222-3333-4444-555555555555",
                            "name": "示例人员",
                            "head_img_url": "http://example.invalid/static/upload/face/example.jpg",
                            "feature": "",
                            "face_token": "",
                            "hardware_uuid": "66666666-7777-8888-9999-000000000000",
                            "status": 1,
                            "card_id": ""
                          }
                        ],
                        "face_learning_mode": 2
                      },
                      "trace_id": "<本次请求追踪ID>"
                    }
                  },
                  "businessError": {
                    "summary": "设备不存在",
                    "value": {
                      "code": 1,
                      "message": "设备不存在",
                      "data": null,
                      "trace_id": "<本次请求追踪ID>"
                    }
                  }
                }
              }
            },
            "headers": {}
          }
        },
        "security": [],
        "x-apifox-folder": "",
        "x-apifox-status": "developing",
        "x-run-in-apifox": "https://app.apifox.com/web/project/5737553/apis/api-386797026-run"
      }
    }
  }
}
