# 保险智能客服系统 — API 接口文档 > **版本**:V1.1(与需求文档 V1.0 对齐) > **基础路径**:`/api` > **认证方式**:JWT Bearer Token(Header: `Authorization: Bearer `) > **内容类型**:`application/json`(除文件上传接口外) > **接口总数**:45 个(含企微/健康检查) --- ## 一、全局约定 ### 1.1 统一响应格式 ```json { "code": 0, "message": "success", "data": { ... } } ``` - `code = 0`:成功 - `code != 0`:失败,`message` 为错误描述,`data` 为 null 或错误详情 ### 1.2 错误码表 | 错误码 | 说明 | 处理建议 | |:---:|------|---------| | 0 | 成功 | - | | 1001 | 参数错误 | 检查请求参数 | | 1002 | 未授权 | 重新登录 | | 1003 | Token 已过期 | 调用 refresh-token | | 1004 | 权限不足 | 联系管理员 | | 1005 | 资源不存在 | 检查资源 ID | | 2001 | BaoDan API 调用失败 | 检查 BaoDan 服务 | | 2002 | BaoDan API 超时 | 重试 | | 2003 | BaoDan Workflow 失败 | 检查 Workflow 配置 | | 3001 | 企微 API 调用失败 | 检查企微配置 | | 4001 | 文件上传失败 | 检查文件格式/大小 | | 9999 | 服务器内部错误 | 检查日志 | ### 1.3 分页参数 | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | page | int | 1 | 页码 | | page_size | int | 20 | 每页条数,最大 100 | ### 1.4 认证方式 所有标注"需要认证"的接口,请求 Header 必须包含: ``` Authorization: Bearer ``` JWT Token 有效期 2 小时(7200 秒),过期后调用 `/api/auth/refresh-token` 刷新。 ### 1.5 实现方式标注 | 标注 | 含义 | |------|------| | 自研(调 BaoDan) | 自研后端接口,内部调 BaoDan API | | 自研 | 完全自研 | | BaoDan 原生 | 直接使用 BaoDan,不需要自研后端 | | BaoDan + 增强 | BaoDan 有基础,需要少量增强代码 | --- ## 二、系统接口 ### 2.1 健康检查 | 项 | 值 | |----|---| | URL | `GET /api/health` | | 认证 | 不需要 | | 实现 | 自研 | **响应**: ```json { "status": "ok" } ``` ### 2.2 企微机器人回调(URL 验证) | 项 | 值 | |----|---| | URL | `GET /api/wecom/callback` | | 认证 | 不需要(企微签名校验) | | 实现 | 自研 + 企微 API | **参数**:`msg_signature`、`timestamp`、`nonce`、`echostr` **响应**:解密后的 echostr(纯文本,非 JSON) **处理逻辑**: 1. 将 Token、timestamp、nonce、echostr 按字典序排列拼接 2. SHA1 哈希,与 msg_signature 比对 3. 验证通过则返回解密后的 echostr ### 2.3 企微机器人消息接收 | 项 | 值 | |----|---| | URL | `POST /api/wecom/callback` | | 认证 | 不需要(企微签名校验) | | 实现 | 自研 + 企微 API | **请求体**:企微加密的 XML 消息体 **响应**:`success`(纯文本,必须在 5 秒内返回) **处理逻辑**: 1. 验证签名 + 解密 XML 2. 判断 MsgType:文本消息继续处理,非文本回复"暂不支持" 3. 群聊消息去掉"@机器人"前缀 4. **立即返回 `success`** 5. 异步处理:调 BaoDan Chat API → 通过企微 API 回复用户 ### 2.4 企微 OAuth 登录入口 | 项 | 值 | |----|---| | URL | `GET /api/wecom/oauth` | | 认证 | 不需要 | | 实现 | 自研 | **响应**:302 重定向到企微授权页面 ### 2.5 企微 OAuth 回调 | 项 | 值 | |----|---| | URL | `GET /api/wecom/oauth/callback` | | 认证 | 不需要 | | 实现 | 自研 | **参数**:`code`(企微授权码)、`state` **处理逻辑**: 1. 用 code 换取企微 access_token 2. 获取用户信息(userid、name、department) 3. 查找/创建 wecom_user_mapping 记录 4. 生成 JWT Token 5. 302 重定向到前端首页 --- ## 三、认证鉴权(A1) ### A1.1.1 企微登录 | 项 | 值 | |----|---| | URL | `POST /api/auth/wework-login` | | 认证 | 不需要 | | 实现 | 自研(调 BaoDan) | **请求**: ```json { "code": "企微授权回调code", "state": "随机状态值" } ``` **字段约束**: | 字段 | 类型 | 必填 | 约束 | 错误提示 | |------|------|:---:|------|---------| | code | string | 是 | 1-512 字符 | "授权码无效" | | state | string | 否 | 0-256 字符 | - | **响应**: ```json { "code": 0, "data": { "token": "eyJhbGciOiJIUzI1NiIs...", "expires_in": 7200, "user": { "id": "user-001", "username": "张三", "wecom_userid": "zhangsan", "role": "sales", "department": "上海团队" } } } ``` ### A1.1.2 账密登录 | 项 | 值 | |----|---| | URL | `POST /api/auth/password-login` | | 认证 | 不需要 | | 实现 | 自研(调 BaoDan) | **请求**: ```json { "username": "admin", "password": "hashed_password" } ``` **字段约束**: | 字段 | 类型 | 必填 | 约束 | 错误提示 | |------|------|:---:|------|---------| | username | string | 是 | 1-64 字符,非空 | "请输入用户名" | | password | string | 是 | 1-128 字符,非空 | "请输入密码" | **响应**: ```json { "code": 0, "data": { "token": "eyJhbGciOiJIUzI1NiIs...", "expires_in": 7200 } } ``` **失败响应**: ```json { "code": 1002, "message": "用户名或密码错误" } ``` ### A1.1.3 刷新 Token | 项 | 值 | |----|---| | URL | `POST /api/auth/refresh-token` | | 认证 | 需要(旧 Token) | | 实现 | 自研(调 BaoDan) | **响应**: ```json { "code": 0, "data": { "token": "eyJhbGci...", "expires_in": 7200 } } ``` ### A1.1.4 退出登录 | 项 | 值 | |----|---| | URL | `POST /api/auth/logout` | | 认证 | 需要 | | 实现 | 自研 | **处理**:将当前 Token 加入黑名单(Redis),后续请求使用该 Token 时返回 1002。 **响应**: ```json { "code": 0, "message": "success" } ``` --- ## 四、智能问答(A2) ### A2.1.1 发送消息(SSE 流式) | 项 | 值 | |----|---| | URL | `POST /api/chat/message` | | 认证 | 需要 | | 实现 | 自研(调 BaoDan) | **请求**: ```json { "session_id": "sess-001", "message": "重疾险的等待期是多少天?", "filters": { "险种": "重疾险", "保司": null } } ``` **字段约束**: | 字段 | 类型 | 必填 | 约束 | 枚举 | 错误提示 | |------|------|:---:|------|------|---------| | message | string | 是 | 1-10000 字符 | - | "请输入问题内容" | | session_id | string | 否 | UUID 格式,空串=新对话 | - | "会话ID格式无效" | | filters | object | 否 | - | - | - | | filters.险种 | string | 否 | 0-32 字符 | 重疾险/寿险/医疗险/意外险/车险/年金险/储蓄险 | "不支持的险种" | | filters.保司 | string | 否 | 0-64 字符 | - | - | **响应**(SSE 流式,`Content-Type: text/event-stream`): ``` data: {"type":"source","data":{"doc_name":"XX重疾险条款.md","chunk":"等待期为合同生效之日起90天..."}} data: {"type":"delta","data":"根据"} data: {"type":"delta","data":"XX重疾险条款规定,等待期为90天。"} data: {"type":"done","data":{"message_id":"msg-001","conversation_id":"conv-001"}} ``` **SSE 事件类型**: | type | 说明 | data 结构 | |------|------|----------| | source | 来源引用 | `{doc_name, chunk, score}` | | delta | 文本增量 | `{data: "文本片段"}` | | done | 回答完成 | `{message_id, conversation_id}` | | error | 错误 | `{message}` | ### A2.1.2 获取会话列表 | 项 | 值 | |----|---| | URL | `GET /api/chat/sessions` | | 认证 | 需要 | | 实现 | 自研(调 BaoDan) | **查询参数**:`page`、`page_size` **响应**: ```json { "code": 0, "data": { "total": 35, "items": [ { "id": "sess-001", "title": "重疾险等待期问题", "created_at": "2026-05-31T10:00:00Z", "updated_at": "2026-05-31T10:05:00Z", "message_count": 6 } ] } } ``` ### A2.1.3 创建会话 | 项 | 值 | |----|---| | URL | `POST /api/chat/sessions` | | 认证 | 需要 | | 实现 | 自研(调 BaoDan) | **响应**: ```json { "code": 0, "data": { "session_id": "sess-002" } } ``` ### A2.1.4 删除会话 | 项 | 值 | |----|---| | URL | `DELETE /api/chat/sessions/{id}` | | 认证 | 需要 | | 实现 | 自研(调 BaoDan) | **路径参数**:`id`(UUID 格式,错误提示:"会话ID格式无效") **响应**: ```json { "code": 0, "message": "success" } ``` ### A2.1.5 获取消息记录 | 项 | 值 | |----|---| | URL | `GET /api/chat/sessions/{id}/messages` | | 认证 | 需要 | | 实现 | 自研(调 BaoDan) | **响应**: ```json { "code": 0, "data": { "messages": [ { "id": "msg-001", "role": "user", "content": "重疾险的等待期是多少天?", "created_at": "2026-05-31T10:00:00Z" }, { "id": "msg-002", "role": "assistant", "content": "根据 XX 重疾险条款规定,等待期为合同生效之日起90天。", "sources": [ {"doc_name": "XX重疾险条款.md", "chunk": "等待期为..."} ], "created_at": "2026-05-31T10:00:05Z" } ] } } ``` ### A2.1.6 提交反馈 | 项 | 值 | |----|---| | URL | `POST /api/chat/messages/{id}/feedback` | | 认证 | 需要 | | 实现 | 自研(调 BaoDan) | **请求(有用)**: ```json { "rating": "helpful", "comment": null } ``` **请求(纠错)**: ```json { "rating": "not_helpful", "comment": "等待期应该是180天而不是90天" } ``` **字段约束**: | 字段 | 类型 | 必填 | 枚举 | 错误提示 | |------|------|:---:|------|---------| | rating | string | 是 | helpful / not_helpful | "评分值无效" | | comment | string | 否 | 0-2000 字符 | - | ### A2.2.1 向量检索 | 项 | 值 | |----|---| | URL | `POST /api/retrieval/search` | | 认证 | 需要 | | 实现 | 自研(调 BaoDan) | **请求**: ```json { "query": "重疾险等待期", "filters": { "险种": "重疾险", "保司": null }, "top_k": 5 } ``` **字段约束**: | 字段 | 类型 | 必填 | 约束 | 默认值 | 错误提示 | |------|------|:---:|------|--------|---------| | query | string | 是 | 1-1000 字符 | - | "请输入搜索内容" | | filters.险种 | string | 否 | 枚举值 | null | "不支持的险种" | | top_k | int | 否 | 1-20 | 5 | "top_k 应在 1-20 之间" | **响应**: ```json { "code": 0, "data": { "results": [ { "doc_name": "XX重疾险条款.md", "chunk": "等待期为合同生效之日起90天...", "score": 0.92, "metadata": { "险种": "重疾险", "保司": "XX人寿" } } ] } } ``` ### A2.2.2 推荐追问 | 项 | 值 | |----|---| | URL | `POST /api/chat/suggest` | | 认证 | 需要 | | 实现 | 自研 | **请求**: ```json { "message": "根据 XX 重疾险条款规定,等待期为90天。" } ``` **响应**: ```json { "code": 0, "data": { "suggestions": [ "重疾险的免赔额是多少?", "哪些情况不在理赔范围内?", "等待期内出险怎么处理?" ] } } ``` --- ## 五、方案生成(A3) ### A3.1.1 生成推荐方案 | 项 | 值 | |----|---| | URL | `POST /api/recommend/generate` | | 认证 | 需要 | | 实现 | 自研(调 BaoDan Workflow) | **请求**: ```json { "customer": { "name": "李四", "age": 35, "gender": "male", "health_status": "健康", "occupation": "软件工程师", "annual_income": 300000, "monthly_budget": 2000 }, "insurance_types": ["重疾险", "医疗险", "意外险"], "coverage_amount": 500000, "coverage_period": "终身", "existing_policies": [] } ``` **字段约束**: | 字段 | 类型 | 必填 | 约束 | 枚举 | 错误提示 | |------|------|:---:|------|------|---------| | customer.age | int | 是 | 0-150 | - | "年龄应在 0-150 之间" | | customer.gender | string | 是 | - | male/female | "性别值无效" | | customer.health_status | string | 是 | 1-32 字符 | 健康/有既往病史/慢性病/重大疾病史 | "健康状况值无效" | | customer.occupation | string | 是 | 1-50 字符 | - | "请输入职业" | | customer.annual_income | int | 是 | >=0 | - | "年收入不能为负数" | | customer.monthly_budget | int | 是 | >=1 | - | "月预算必须大于 0" | | insurance_types | string[] | 是 | 1-10 项 | 寿险/重疾险/医疗险/意外险/年金险/储蓄险 | "请至少选择一个险种" | | coverage_amount | int | 是 | >=1 | - | "保额必须大于 0" | | coverage_period | string | 是 | - | 定期10年/20年/30年/保至60岁/70岁/80岁/终身 | "请选择保障期限" | | existing_policies | object[] | 否 | 0-20 项 | - | - | **响应**: ```json { "code": 0, "data": { "task_id": "task-001", "status": "processing" } } ``` ### A3.1.2 轮询任务状态 | 项 | 值 | |----|---| | URL | `GET /api/recommend/generate/{task_id}` | | 认证 | 需要 | | 实现 | 自研 | **字段约束**:`task_id`(UUID 格式,错误提示:"任务ID格式无效") **响应(生成中)**: ```json { "code": 0, "data": { "task_id": "task-001", "status": "processing" } } ``` **响应(完成)**: ```json { "code": 0, "data": { "task_id": "task-001", "status": "done", "proposal": { "id": "prop-001", "plans": [ { "name": "基础方案", "total_premium": 4800, "items": [ { "product_name": "XX重疾险", "coverage": 300000, "premium": 2400, "reason": "35岁男性投保,性价比高,覆盖120种重疾" } ], "summary": "基础保障方案,覆盖重疾、医疗、意外三大类..." } ] } } } ``` **响应(失败)**: ```json { "code": 0, "data": { "task_id": "task-001", "status": "failed", "error_message": "生成超时" } } ``` ### A3.1.3 方案导出 | 项 | 值 | |----|---| | URL | `POST /api/recommend/{id}/export` | | 认证 | 需要 | | 实现 | 自研 | **请求**:`{ "format": "pdf" }` **字段约束**: | 字段 | 类型 | 必填 | 枚举 | 错误提示 | |------|------|:---:|------|---------| | format | string | 是 | pdf/pptx/docx | "不支持的导出格式" | **响应**: ```json { "code": 0, "data": { "download_url": "https://your-domain.com/api/recommend/{id}/download?token=xxx", "expire_at": "2026-06-03T10:00:00Z" } } ``` ### A3.1.4 生成分享链接 | 项 | 值 | |----|---| | URL | `POST /api/recommend/{id}/share` | | 认证 | 需要 | | 实现 | 自研 | **请求**:`{ "expire_hours": 72 }` **字段约束**:`expire_hours`(int,1-720,错误提示:"有效期应在 1-720 小时之间") **响应**: ```json { "code": 0, "data": { "share_url": "https://your-domain.com/shared/prop-001?token=xxx", "expire_at": "2026-06-03T10:00:00Z" } } ``` --- ## 六、知识库(A4) ### A4.1.1 上传文档 | 项 | 值 | |----|---| | URL | `POST /api/kb/documents/upload` | | Content-Type | multipart/form-data | | 认证 | 需要 | | 实现 | 自研(调 BaoDan) | **表单字段**: | 字段 | 类型 | 必填 | 约束 | 错误提示 | |------|------|:---:|------|---------| | files | file[] | 是 | 1-50 个文件,每个 <50MB,格式 md/word/txt | "仅支持 MD/Word/TXT 格式" | | 险种 | string | 是 | 1-32 字符 | "请选择险种" | | 保司 | string | 是 | 1-64 字符 | "请填写保司名称" | **响应**: ```json { "code": 0, "data": { "upload_id": "upload-001", "documents": [ { "doc_id": "doc-001", "filename": "file1.md", "status": "processing" } ] } } ``` ### A4.1.2 文档列表 | 项 | 值 | |----|---| | URL | `GET /api/kb/documents` | | 认证 | 需要 | | 实现 | 自研(调 BaoDan) | **查询参数**: | 参数 | 类型 | 必填 | 约束 | 枚举值 | |------|------|:---:|------|--------| | page | int | 否 | >=1,默认 1 | - | | page_size | int | 否 | 1-100,默认 20 | - | | 险种 | string | 否 | 0-32 | - | | 保司 | string | 否 | 0-64 | - | | status | string | 否 | - | pending/processing/completed/failed | | keyword | string | 否 | 0-100 | - | **响应**: ```json { "code": 0, "data": { "total": 150, "items": [ { "doc_id": "doc-001", "filename": "XX重疾险条款.md", "编号": "CJ-XX-001", "险种": "重疾险", "保司": "XX人寿", "tags": ["产品条款", "等待期"], "status": "completed", "uploaded_at": "2026-05-15T10:00:00Z", "processed_at": "2026-05-15T10:05:00Z" } ] } } ``` ### A4.1.3 文档处理状态 | 项 | 值 | |----|---| | URL | `GET /api/kb/documents/{id}/status` | | 认证 | 需要 | | 实现 | 自研(调 BaoDan) | **响应**: ```json { "code": 0, "data": { "doc_id": "doc-001", "filename": "XX重疾险条款.md", "pipeline": [ { "stage": "upload", "status": "completed", "time": "2026-05-15T10:00:01Z" }, { "stage": "format_convert", "status": "completed", "time": "2026-05-15T10:00:02Z" }, { "stage": "chunking", "status": "completed", "time": "2026-05-15T10:00:03Z", "chunk_count": 45 }, { "stage": "embedding", "status": "completed", "time": "2026-05-15T10:05:00Z" } ] } } ``` ### A4.1.4 重试失败文档 | 项 | 值 | |----|---| | URL | `POST /api/kb/documents/{id}/retry` | | 认证 | 需要 | | 实现 | 自研(调 BaoDan) | ### A4.1.5 更新文档元数据 | 项 | 值 | |----|---| | URL | `PATCH /api/kb/documents/{id}` | | 认证 | 需要 | | 实现 | 自研(调 BaoDan) | **请求**:`{ "编号": "CJ-XX-002", "tags": ["产品条款", "核保"] }` **字段约束**: | 字段 | 类型 | 必填 | 约束 | 错误提示 | |------|------|:---:|------|---------| | 编号 | string | 否 | 0-32 字符 | "编号格式无效" | | tags | string[] | 否 | 0-20 项,每项 1-32 字符 | - | ### A4.1.6 删除文档 | 项 | 值 | |----|---| | URL | `DELETE /api/kb/documents/{id}` | | 认证 | 需要 | | 实现 | 自研(调 BaoDan) | ### A4.2.1 数据源列表 | 项 | 值 | |----|---| | URL | `GET /api/kb/datasources` | | 认证 | 需要 | | 实现 | 自研 | **响应**: ```json { "code": 0, "data": [ { "id": "ds-001", "name": "XX人寿产品接口", "api_url": "https://api.xxlife.com/products", "sync_frequency": "0 2 * * *", "last_sync": "2026-05-31T02:00:00Z", "last_sync_status": "success", "last_sync_count": 156 } ] } ``` ### A4.2.2 新建数据源 | 项 | 值 | |----|---| | URL | `POST /api/kb/datasources` | | 认证 | 需要(管理员) | | 实现 | 自研 | **请求**: ```json { "name": "XX人寿产品接口", "api_url": "https://api.xxlife.com/products", "api_key": "encrypted_key_here", "sync_frequency": "0 2 * * *" } ``` ### A4.2.3 手动同步 | 项 | 值 | |----|---| | URL | `POST /api/kb/datasources/{id}/sync` | | 认证 | 需要(管理员) | | 实现 | 自研 | ### A4.2.4 同步日志 | 项 | 值 | |----|---| | URL | `GET /api/kb/datasources/{id}/logs` | | 认证 | 需要(管理员) | | 实现 | 自研 | --- ## 七、用户权限(A5) ### A5.1.1 用户管理 | 项 | 值 | |----|---| | URL | `GET/POST/PUT/DELETE /api/admin/users` | | 认证 | 需要(管理员) | | 实现 | 自研(调 BaoDan) | **GET 列表请求**:`GET /api/admin/users?page=1&page_size=20&role=sales&department=上海团队` **GET 列表响应**: ```json { "code": 0, "data": { "total": 50, "items": [ { "id": "user-001", "username": "张三", "wecom_userid": "zhangsan", "role": "sales", "department": "上海团队", "status": "active", "created_at": "2026-05-01T10:00:00Z", "last_active_at": "2026-05-31T09:30:00Z" } ] } } ``` **POST 新增请求**: ```json { "username": "李四", "wecom_userid": "lisi", "role": "sales", "department": "上海团队" } ``` **字段约束**: | 字段 | 类型 | 必填 | 约束 | 枚举 | 错误提示 | |------|------|:---:|------|------|---------| | username | string | 是 | 1-64,不可重复 | - | "用户名已存在" | | role | string | 是 | - | super_admin/admin/manager/sales | "角色值无效" | **PUT 编辑**:`PUT /api/admin/users/{id}` **DELETE 停用**:`DELETE /api/admin/users/{id}`(停用时吊销所有 Token) ### A5.1.2 批量导入用户 | 项 | 值 | |----|---| | URL | `POST /api/admin/users/batch-import` | | Content-Type | multipart/form-data | | 认证 | 需要(超级管理员) | | 实现 | 自研 | ### A5.1.3 角色管理 | 项 | 值 | |----|---| | URL | `GET/POST/PUT/DELETE /api/admin/roles` | | 认证 | 需要(超级管理员) | | 实现 | 自研 | **GET 响应**: ```json { "code": 0, "data": [ { "id": "role-001", "name": "超级管理员", "permissions": ["*"], "builtin": true }, { "id": "role-002", "name": "管理员", "permissions": ["kb_manage","log_view","user_manage","config_manage"], "builtin": true }, { "id": "role-003", "name": "销售主管", "permissions": ["chat","proposal","kb_view","team_stats"], "builtin": true }, { "id": "role-004", "name": "销售人员", "permissions": ["chat","proposal"], "builtin": true }, { "id": "role-005", "name": "客户", "permissions": ["chat"], "builtin": true } ] } ``` **字段约束**: | 字段 | 类型 | 必填 | 约束 | 错误提示 | |------|------|:---:|------|---------| | name | string | 是 | 1-32,不可重复 | "角色名已存在" | | permissions | string[] | 是 | 1-50 项 | "权限标识无效" | --- ## 八、系统配置(A6) ### A6.1.1 LLM 配置 | 项 | 值 | |----|---| | URL | `GET/POST/PUT /api/admin/llm-configs` | | 认证 | 需要(超级管理员) | | 实现 | 自研(调 BaoDan) | **POST 请求**: ```json { "provider": "deepseek", "model": "deepseek-chat", "api_key": "sk-xxxxxxxxxxxx", "base_url": "https://api.deepseek.com/v1", "is_default": true, "params": { "temperature": 0.7, "max_tokens": 4096, "top_p": 0.9 } } ``` **字段约束**: | 字段 | 类型 | 必填 | 枚举 | 错误提示 | |------|------|:---:|------|---------| | provider | string | 是 | deepseek/openai/zhipu/qwen | "不支持的供应商" | | model | string | 是 | 1-64 字符 | "请输入模型名称" | | api_key | string | 是 | 1-512 字符 | "请输入 API Key" | **POST 响应**: ```json { "code": 0, "data": { "id": "llm-001", "provider": "deepseek", "model": "deepseek-chat", "api_key_masked": "sk-xxxx****xxxx", "is_default": true, "status": "active" } } ``` ### A6.1.2 连通性测试 | 项 | 值 | |----|---| | URL | `POST /api/admin/llm-configs/{id}/ping` | | 认证 | 需要(管理员) | | 实现 | 自研(调 BaoDan) | **响应**: ```json { "code": 0, "data": { "reachable": true, "latency_ms": 320, "model": "deepseek-chat" } } ``` ### A6.1.3 Prompt 管理 | 项 | 值 | |----|---| | URL | `GET/POST/PUT /api/admin/prompts` | | 认证 | 需要(管理员) | | 实现 | 自研(调 BaoDan) | **POST 请求**: ```json { "name": "保险顾问系统提示词", "type": "system", "content": "你是一名专业的保险顾问助手...", "variables": ["险种", "保司"] } ``` **字段约束**: | 字段 | 类型 | 必填 | 约束 | 错误提示 | |------|------|:---:|------|---------| | content | string | 是 | 1-100000 字符 | "Prompt 内容不能为空" | **POST 响应**(自动生成版本快照): ```json { "code": 0, "data": { "id": "prompt-001", "name": "保险顾问系统提示词", "version": 3, "versions": [ {"version": 1, "created_at": "2026-05-01T10:00:00Z"}, {"version": 2, "created_at": "2026-05-15T10:00:00Z"}, {"version": 3, "created_at": "2026-05-31T10:00:00Z"} ] } } ``` ### A6.1.4 Prompt 测试 | 项 | 值 | |----|---| | URL | `POST /api/admin/prompts/test` | | 认证 | 需要(管理员) | | 实现 | 自研(调 BaoDan) | **请求**:`{ "prompt_id": "prompt-001", "test_query": "重疾险等待期多少天?" }` **响应**: ```json { "code": 0, "data": { "response": "根据条款规定,重疾险等待期为90天...", "latency_ms": 1200, "token_usage": { "prompt_tokens": 520, "completion_tokens": 180 } } } ``` --- ## 九、留痕日志(A7) ### A7.1.1 问答记录查询 | 项 | 值 | |----|---| | URL | `GET /api/admin/logs/chat` | | 认证 | 需要(管理员) | | 实现 | 自研(调 BaoDan) | **查询参数**: | 参数 | 类型 | 必填 | 说明 | |------|------|:---:|------| | page | int | 否 | 页码,默认 1 | | page_size | int | 否 | 每页条数,默认 50 | | user_id | string | 否 | 按用户筛选 | | start_date | string | 否 | 开始日期 YYYY-MM-DD | | end_date | string | 否 | 结束日期 YYYY-MM-DD | | keyword | string | 否 | 关键词搜索 | | rating | string | 否 | 评分筛选,枚举 helpful/not_helpful | | export | string | 否 | 设为 "csv" 时返回 CSV 文件流 | **响应(JSON 模式)**: ```json { "code": 0, "data": { "total": 1200, "items": [ { "id": "msg-001", "user_id": "user-001", "username": "张三", "question": "重疾险等待期多少天?", "answer": "等待期为合同生效之日起90天。", "sources": ["XX重疾险条款.md"], "rating": "helpful", "created_at": "2026-05-31T10:00:00Z" } ] } } ``` **响应(CSV 导出)**:当 `export=csv` 时返回文件流 ``` Content-Type: text/csv Content-Disposition: attachment; filename="chat_logs_202605.csv" ``` ### A7.1.2 导出对话记录 | 项 | 值 | |----|---| | URL | `GET /api/admin/logs/chat/export` | | 认证 | 需要(管理员) | | 实现 | 自研(调 BaoDan) | **查询参数**:同 A7.1.1 的筛选参数 **响应**:返回 CSV 文件流 ``` Content-Type: text/csv Content-Disposition: attachment; filename="chat_logs_202606.csv" ``` ### A7.1.3 系统操作日志 | 项 | 值 | |----|---| | URL | `GET /api/admin/logs/system` | | 认证 | 需要(超级管理员) | | 实现 | 自研 | **查询参数**:`page`、`page_size`、`action`、`user_id` **响应**: ```json { "code": 0, "data": { "total": 200, "items": [ { "id": "log-001", "action": "login", "user_id": "user-001", "username": "张三", "ip": "192.168.1.100", "device": "Chrome/120 Windows", "detail": "企微 OAuth 登录", "created_at": "2026-05-31T09:00:00Z" } ] } } ``` --- ## 十、统计报表(A8) ### A8.1.1 使用概览 | 项 | 值 | |----|---| | URL | `GET /api/stats/overview` | | 认证 | 需要(管理员) | | 实现 | 自研 | **响应**: ```json { "code": 0, "data": { "today_chats": 45, "active_users": 12, "kb_hit_rate": 0.87, "total_documents": 1500 } } ``` ### A8.1.2 趋势数据 | 项 | 值 | |----|---| | URL | `GET /api/stats/trend` | | 认证 | 需要(管理员) | | 实现 | 自研 | **查询参数**:`metric`(如 chat_count)、`start_date`、`end_date`、`granularity`(day/week/month) **响应**: ```json { "code": 0, "data": { "metric": "chat_count", "granularity": "day", "data": [ { "date": "2026-05-01", "value": 45 }, { "date": "2026-05-02", "value": 62 } ] } } ``` ### A8.1.3 知识库健康度 | 项 | 值 | |----|---| | URL | `GET /api/stats/kb-health` | | 认证 | 需要(管理员) | | 实现 | 自研 | **查询参数**:`days` **响应**: ```json { "code": 0, "data": { "hot_questions": [{"question": "重疾险等待期多少天", "count": 230}], "missed_questions": [{"question": "XX新产品费率", "count": 45, "handled": false}], "coverage": { "寿险": {"doc_count": 320, "status": "completed"}, "重疾险": {"doc_count": 280, "status": "completed"} } } } ``` ### A8.1.4 Token 消耗统计 | 项 | 值 | |----|---| | URL | `GET /api/stats/token-cost` | | 认证 | 需要(管理员) | | 实现 | 自研 | **查询参数**:`start_date`、`end_date`、`group_by`(model) **响应**: ```json { "code": 0, "data": { "total_tokens": 2500000, "total_cost_usd": 12.5, "by_model": [ {"model": "deepseek-chat", "input_tokens": 1500000, "output_tokens": 500000, "cost_usd": 10.0} ], "daily_trend": [ {"date": "2026-05-01", "tokens": 80000, "cost_usd": 0.4} ] } } ``` --- ## 十一、接口清单汇总 | # | 方法 | URL | 认证 | 实现 | 对应功能 | |---|------|-----|:---:|------|---------| | 1 | GET | /api/health | 否 | 自研 | 健康检查 | | 2 | GET | /api/wecom/callback | 否 | 自研+企微 | 企微回调验证 | | 3 | POST | /api/wecom/callback | 否 | 自研+企微 | 企微消息接收 | | 4 | GET | /api/wecom/oauth | 否 | 自研 | OAuth 入口 | | 5 | GET | /api/wecom/oauth/callback | 否 | 自研 | OAuth 回调 | | 6 | POST | /api/auth/wework-login | 否 | 自研(调BaoDan) | 企微登录 | | 7 | POST | /api/auth/password-login | 否 | 自研(调BaoDan) | 账密登录 | | 8 | POST | /api/auth/refresh-token | 是 | 自研(调BaoDan) | 刷新Token | | 9 | POST | /api/auth/logout | 是 | 自研 | 退出登录 | | 10 | POST | /api/chat/message | 是 | 自研(调BaoDan) | 发送消息(SSE) | | 11 | GET | /api/chat/sessions | 是 | 自研(调BaoDan) | 会话列表 | | 12 | POST | /api/chat/sessions | 是 | 自研(调BaoDan) | 创建会话 | | 13 | DELETE | /api/chat/sessions/{id} | 是 | 自研(调BaoDan) | 删除会话 | | 14 | GET | /api/chat/sessions/{id}/messages | 是 | 自研(调BaoDan) | 消息记录 | | 15 | POST | /api/chat/messages/{id}/feedback | 是 | 自研(调BaoDan) | 提交反馈 | | 16 | POST | /api/chat/suggest | 是 | 自研 | 推荐追问 | | 17 | POST | /api/retrieval/search | 是 | 自研(调BaoDan) | 向量检索 | | 18 | POST | /api/recommend/generate | 是 | 自研(调BaoDan) | 生成推荐方案 | | 19 | GET | /api/recommend/generate/{id} | 是 | 自研 | 查询方案状态 | | 20 | POST | /api/recommend/{id}/export | 是 | 自研 | 方案导出 | | 21 | POST | /api/recommend/{id}/share | 是 | 自研 | 生成分享链接 | | 22 | POST | /api/kb/documents/upload | 是 | 自研(调BaoDan) | 上传文档 | | 23 | GET | /api/kb/documents | 是 | 自研(调BaoDan) | 文档列表 | | 24 | GET | /api/kb/documents/{id}/status | 是 | 自研(调BaoDan) | 文档处理状态 | | 25 | POST | /api/kb/documents/{id}/retry | 是 | 自研(调BaoDan) | 重试文档 | | 26 | PATCH | /api/kb/documents/{id} | 是 | 自研(调BaoDan) | 更新元数据 | | 27 | DELETE | /api/kb/documents/{id} | 是 | 自研(调BaoDan) | 删除文档 | | 28 | GET | /api/kb/datasources | 是 | 自研 | 数据源列表 | | 29 | POST | /api/kb/datasources | 是 | 自研 | 新建数据源 | | 30 | POST | /api/kb/datasources/{id}/sync | 是 | 自研 | 手动同步 | | 31 | GET | /api/kb/datasources/{id}/logs | 是 | 自研 | 同步日志 | | 32 | GET/POST/PUT/DELETE | /api/admin/users | 管理员 | 自研(调BaoDan) | 用户管理 | | 33 | POST | /api/admin/users/batch-import | 超管 | 自研 | 批量导入 | | 34 | GET/POST/PUT/DELETE | /api/admin/roles | 超管 | 自研 | 角色管理 | | 35 | GET/POST/PUT | /api/admin/llm-configs | 超管 | 自研(调BaoDan) | LLM配置 | | 36 | POST | /api/admin/llm-configs/{id}/ping | 管理员 | 自研(调BaoDan) | 连通性测试 | | 37 | GET/POST/PUT | /api/admin/prompts | 管理员 | 自研(调BaoDan) | Prompt管理 | | 38 | POST | /api/admin/prompts/test | 管理员 | 自研(调BaoDan) | Prompt测试 | | 39 | GET | /api/admin/logs/chat | 管理员 | 自研(调BaoDan) | 问答日志 | | 40 | GET | /api/admin/logs/chat/export | 管理员 | 自研(调BaoDan) | 导出对话记录 | | 41 | GET | /api/admin/logs/system | 超管 | 自研 | 系统日志 | | 42 | GET | /api/stats/overview | 管理员 | 自研 | 使用概览 | | 43 | GET | /api/stats/trend | 管理员 | 自研 | 趋势数据 | | 44 | GET | /api/stats/kb-health | 管理员 | 自研 | 知识库健康度 | | 45 | GET | /api/stats/token-cost | 管理员 | 自研 | Token消耗 | | 46 | POST | /api/wecom/callback(企微内部) | - | - | 同 #3 | | 47 | POST | /api/recommend/generate(BaoDan内部) | - | - | 同 #18 | > 注:#46 和 #47 是企微/BaoDan 侧视角的接口,实际为同一端点。有效独立接口为 **45 个**。 ### 11.1 海报用户产品小册子补充接口 以下接口统一要求登录认证,资料详情、预览、修改、删除和生成时都会校验当前用户所有权。 | 方法 | URL | 用途 | |------|-----|------| | GET | `/insurance/poster/product-sources` | 查询系统产品、“我的资料”和功能开关状态 | | GET | `/insurance/poster/product-materials` | 查询当前用户上传的产品小册子 | | POST | `/insurance/poster/product-materials` | 上传 PDF 并异步解析;支持可选 `password`、`companyId`、`planType` | | GET | `/insurance/poster/product-materials/{id}` | 查询解析状态和核对数据 | | PUT | `/insurance/poster/product-materials/{id}/confirm` | 校验并确认产品规则,确认后可用于生成 | | POST | `/insurance/poster/product-materials/{id}/retry` | 解析失败后重新投递任务 | | GET | `/insurance/poster/product-materials/{id}/file` | 鉴权预览原 PDF | | DELETE | `/insurance/poster/product-materials/{id}` | 软删除本人资料 | | POST | `/insurance/poster/product-materials/{id}/submit-review` | 可选:提交公共库审核 | 文案、计划书上传和海报生成接口优先接受: ```json { "productSource": { "type": "user_material", "id": "123" } } ``` 旧请求只传 `productId` 时仍按系统产品处理。关闭 `POSTER_USER_MANUAL_UPLOAD_ENABLED` 后,前端隐藏上传入口,后端拒绝私有资料生成请求。 ### 11.2 PPT/海报优化接口(2026-07-31) 生成接口不再接受用户侧脱敏决策;即使旧客户端继续提交 `useMaskedData`,服务端也会忽略该值,并使用保司/产品配置快照。 | 方法 | URL | 用途 | |------|-----|------| | GET/POST | `/insurance/admin/ppt/scenarios` | 查询、新增 PPT 生成场景 | | PUT/DELETE | `/insurance/admin/ppt/scenarios/{code}` | 修改、软删除自定义场景;内置场景只能停用 | | DELETE | `/insurance/admin/ppt/companies/{id}` | 软删除保司;存在启用产品时拒绝 | | DELETE | `/insurance/admin/ppt/products/{id}` | 软删除产品并保留历史快照 | | DELETE | `/insurance/admin/ppt/templates/{id}` | 软删除 PPT 模板;内置模板只能停用 | | DELETE | `/insurance/admin/ppt/copy-templates/{id}` | 软删除文案模板 | | POST | `/insurance/poster/compliance-check` | 返回文案合规状态、哈希、规则编号和字符区间 | | GET/PUT | `/insurance/poster/records/{id}/document` | 读取或保存可编辑海报文档 | | GET | `/insurance/poster/records/{id}/background` | 读取 AI 背景资产 | | POST | `/insurance/poster/records/{id}/rendered` | 上传浏览器合成的最终 PNG 和文档快照 | | GET | `/insurance/ppt/preview/{sessionId}?revision={revision}` | 查看当前或指定历史版本预览 | | POST | `/insurance/ppt/preview/{sessionId}/versions/{revision}/restore` | 将历史版本复制恢复为新版本 | 保司写接口新增 `maskingEnabled`、`logoEnabled`;产品写接口新增 `maskingEnabled`。开启名称脱敏时 `maskedDisplayName` 必填。 `GET /insurance/ppt/validate/{sessionId}` 新增: ```json { "canProceed": true, "blockerCount": 0, "warningCount": 2, "infoCount": 0 } ``` 兼容期内继续返回 `validated`、`errorCount`、`warnCount`。利益演示和退保提取问题只进入警告,不影响 `canProceed`。