From 4cb3411eca3a34347d4b1974b5951cfd54565fc7 Mon Sep 17 00:00:00 2001 From: pengjie <2413927716@qq.com> Date: Mon, 6 Jul 2026 15:45:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(emergency):=20=E6=96=B0=E5=A2=9E=E7=A7=BB?= =?UTF-8?q?=E5=8A=A8=E7=AB=AF=E5=AE=A3=E6=95=99=E8=AF=A6=E6=83=85=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=EF=BC=8C=E6=95=B4=E7=90=86=E7=A7=BB=E5=8A=A8=E7=AB=AF?= =?UTF-8?q?API=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 FirstAidResourceApiController,提供 GET /api/emergency/firstAid/resource/queryById - RequestPrefix 新增 FIRST_AID_RESOURCE 路径常量 - API文档-应急群聊拉人.md 合并入新文档 API文档-移动端接口.md(含群聊拉人 + 宣教资源) - API文档-急救宣教资源管理v3.md 保持管理后台接口 --- health-emergency/API文档-应急群聊拉人.md | 292 ------- .../API文档-急救宣教资源管理v3.md | 752 ++++++++++++++++++ health-emergency/API文档-移动端接口.md | 275 +++++++ .../renkang/emergency/api/RequestPrefix.java | 2 + .../FirstAidResourceApiController.java | 39 + 5 files changed, 1068 insertions(+), 292 deletions(-) delete mode 100644 health-emergency/API文档-应急群聊拉人.md create mode 100644 health-emergency/API文档-急救宣教资源管理v3.md create mode 100644 health-emergency/API文档-移动端接口.md create mode 100644 health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/controller/FirstAidResourceApiController.java diff --git a/health-emergency/API文档-应急群聊拉人.md b/health-emergency/API文档-应急群聊拉人.md deleted file mode 100644 index b2ce3f1..0000000 --- a/health-emergency/API文档-应急群聊拉人.md +++ /dev/null @@ -1,292 +0,0 @@ -# 应急群聊拉人 API 接口文档(移动端联调) - -> 本次新增/变更的接口,Base URL: `{host}/health-emergency/api/emergency` - ---- - -## 1. 搜索专家(专业人员) - -> 搜索可邀请的专家列表 - -**GET** `/health-emergency/api/emergency/order/searchExpert` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|:---:|------| -| realname | String | 否 | 姓名,模糊搜索 | -| centerId | String | 否 | 应急中心ID | -| excludeSessionId | String | 否 | 群组ID,用于排除已在群中的人 | -| pageNo | Integer | 否 | 页码,默认1 | -| pageSize | Integer | 否 | 每页条数,默认10 | - -**Response**: - -```json -{ - "success": true, - "result": { - "records": [ - { - "userId": "xxx", - "realname": "张医生", - "avatar": "https://...", - "type": "6", - "centerId": "xxx", - "post": "主任医师", - "school": "北京大学", - "edu": "博士", - "goodAt": "心血管内科", - "deptName": "急诊科" - } - ], - "total": 50, - "size": 10, - "current": 1 - } -} -``` - -| 字段 | 说明 | -|------|------| -| userId | 用户ID,邀请时传入 memberList | -| realname | 姓名 | -| avatar | 头像 | -| type | 类型,"6"=专业人员 | -| centerId | 应急中心ID | -| post | 职称 | -| school | 毕业院校 | -| edu | 学历 | -| goodAt | 擅长领域 | -| deptName | 科室 | - ---- - -## 2. 搜索员工 - -> 搜索可邀请的员工列表 - -**GET** `/health-emergency/api/emergency/order/searchEmployee` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|:---:|------| -| realname | String | 否 | 姓名,模糊搜索 | -| orgCode | String | 否 | 部门编码 | -| workNo | String | 否 | 工号 | -| phone | String | 否 | 手机号 | -| excludeSessionId | String | 否 | 群组ID,用于排除已在群中的人 | -| pageNo | Integer | 否 | 页码,默认1 | -| pageSize | Integer | 否 | 每页条数,默认10 | - -**Response**: - -```json -{ - "success": true, - "result": { - "records": [ - { - "userId": "xxx", - "realname": "张三", - "avatar": "https://...", - "orgCode": "650000001001", - "orgName": "新疆油田公司", - "deptName": "安全环保部", - "phone": "13800000000", - "workNo": "A00123" - } - ], - "total": 200, - "size": 10, - "current": 1 - } -} -``` - -| 字段 | 说明 | -|------|------| -| userId | 用户ID,邀请时传入 memberList | -| realname | 姓名 | -| avatar | 头像 | -| orgCode | 部门编码 | -| orgName | 单位名称(二级单位) | -| deptName | 部门名称 | -| phone | 手机号 | -| workNo | 工号 | - ---- - -## 3. 邀请进群 - -> 拉专家或员工加入应急群聊 - -**POST** `/health-emergency/api/emergency/addGroupUser` - -**Request Body** (JSON): - -```json -{ - "groupId": "1907659384834752513", - "memberList": ["userId1", "userId2"], - "memberType": 1 -} -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|:---:|------| -| groupId | String | 是 | 群组ID(即 `createGroupMag` 返回的 `groupId`) | -| memberList | List\ | 是 | 要邀请的用户ID列表,最多100个 | -| memberType | Integer | 否 | `0`=专家/专业人员, `1`=员工,**默认0** | - -**Response**: - -```json -{ - "success": true, - "message": "", - "result": true -} -``` - -> **注意**: 已在群中的人员会自动跳过,不会报错。所有选中的人都在群中时返回失败。 - ---- - -## 4. 移除群成员 - -> 将成员移出应急群聊 - -**POST** `/health-emergency/api/emergency/removeGroupUser` - -**Request Body** (JSON): - -```json -{ - "groupId": "1907659384834752513", - "memberList": ["userId1"] -} -``` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|:---:|------| -| groupId | String | 是 | 群组ID | -| memberList | List\ | 是 | 要移除的用户ID列表 | - -**Response**: - -```json -{ - "success": true, - "message": "", - "result": true -} -``` - -> **注意**: 只能移除后续拉入的协助人员,不能移除发起人和初始操作/专业人员。 - ---- - -## 5. 群成员列表 - -> 获取当前群成员及可邀请的专业人员 - -**GET** `/health-emergency/api/emergency/order/getGroupMemberList` - -| 参数 | 类型 | 必填 | 说明 | -|------|------|:---:|------| -| sessionId | String | 是 | 群组ID | - -**Response**: - -```json -{ - "success": true, - "result": [ - { - "orderId": "1765357845598556162", - "userId": "发起人id", - "userName": "李四", - "avatar": "https://...", - "isGroupMember": 1, - "memberType": -1 - }, - { - "orderId": "1765357845598556162", - "userId": "操作人员id", - "userName": "王五", - "avatar": "https://...", - "isGroupMember": 1, - "memberType": 0 - }, - { - "orderId": "1765357845598556162", - "userId": "专业人员id", - "userName": "张医生", - "avatar": "https://...", - "isGroupMember": 1, - "memberType": 1 - }, - { - "orderId": "1765357845598556162", - "userId": "员工id", - "userName": "张三", - "avatar": "https://...", - "isGroupMember": 1, - "memberType": 2 - }, - { - "orderId": "1765357845598556162", - "userId": "其他专业人id", - "userName": "赵医生", - "avatar": "https://...", - "isGroupMember": 0, - "memberType": 1 - } - ] -} -``` - -| 字段 | 说明 | -|------|------| -| orderId | 应急单ID | -| userId | 用户ID | -| userName | 姓名 | -| avatar | 头像 | -| isGroupMember | `1`=在群中, `0`=可邀请 | -| memberType | `-1`=发起人, `0`=操作人员, `1`=专业人员, `2`=员工 | - ---- - -## memberType 字典 - -| 值 | 含义 | 场景 | -|:---:|------|------| -| -1 | 发起人 | 创建应急的人 | -| 0 | 操作人员 | 应急中心调度员 | -| 1 | 专业人员 | 专家/医生 | -| 2 | 员工 | 普通员工(被拉入群) | - ---- - -## 典型调用流程 - -``` -1. 查看当前成员 - GET /health-emergency/api/emergency/order/getGroupMemberList?sessionId={groupId} - → 展示群成员列表(按 memberType 区分标签展示) - → isGroupMember=0 的显示为"可邀请" - -2. 搜索要拉的人 - GET /health-emergency/api/emergency/order/searchExpert?realname=张&excludeSessionId={groupId} - GET /health-emergency/api/emergency/order/searchEmployee?realname=李&excludeSessionId={groupId} - → 展示搜索结果,用户勾选 - -3. 确认邀请 - POST /health-emergency/api/emergency/addGroupUser - {"groupId": "{groupId}", "memberList": ["id1","id2"], "memberType": 0} - -4. 移除成员 - POST /health-emergency/api/emergency/removeGroupUser - {"groupId": "{groupId}", "memberList": ["id1"]} - -5. 刷新成员列表 - GET /health-emergency/api/emergency/order/getGroupMemberList?sessionId={groupId} -``` diff --git a/health-emergency/API文档-急救宣教资源管理v3.md b/health-emergency/API文档-急救宣教资源管理v3.md new file mode 100644 index 0000000..8f2ddd0 --- /dev/null +++ b/health-emergency/API文档-急救宣教资源管理v3.md @@ -0,0 +1,752 @@ +# 急救宣教资源管理 API 文档 v3 + +> **基础信息** +> 网关地址: `http://{gateway-host}:{port}`(前端加 `/health-emergency` 前缀) +> 服务直连: `http://{host}:7011`(调试用,不加前缀) +> 认证方式: 请求头 `X-Access-Token: {token}` +> Content-Type: `application/json; charset=utf-8` +> 统一响应格式: `{"success": bool, "message": "...", "code": 200, "result": {...}, "timestamp": ...}` +> 日期格式: `yyyy-MM-dd HH:mm:ss`(东八区) + +--- + +## V3 变更说明(相比 V2) + +| # | 变更项 | 说明 | +|---|--------|------| +| 1 | **审批与上架分离** | 审核通过(`approve`)后不再自动发布,需单独调用 `publish` 上架;`publish` 要求 `auditStatus=11`(已通过),否则报错;新增状态"已通过" | +| 2 | **分类扁平化** | 分类仅一级(无子分类),标签绑定到分类下,`listRoot` 返回全部分类,`listChildren` 返回分类下的标签 | +| 3 | **分类标签联动** | 新增 `GET /category/listWithTags` 返回分类+嵌套标签,前端一次请求即可实现分类/标签联动选择 | +| 4 | **标签绑定分类** | 标签新增/编辑时 `parentId`(所属分类)必填;标签列表 `listAll` 支持 `parentId` 筛选 | +| 5 | **批量发布行为变更** | `batchPublish` 仅对 `auditStatus=11` 的资源生效,跳过未审核通过的 | +| 6 | **导出状态映射修正** | `auditStatus=11` 但未上架的资源导出显示"已通过"而非"已发布" | + +--- + +## 目录 + +1. [通用枚举说明](#通用枚举说明) +2. [状态流转](#状态流转) +3. [分类管理](#1-分类管理-emergencyfirstaidcategory) +4. [标签管理](#2-标签管理-emergencyfirstaidtag) +5. [资源管理](#3-资源管理-emergencyfirstaidresource) +6. [审核管理](#4-审核管理-emergencyfirstaidaudit) +7. [推送管理](#5-推送管理-emergencyfirstaidpush) +8. [收藏管理](#6-收藏管理-emergencyfirstaidfavorite) +9. [版本管理](#7-版本管理-emergencyfirstaidversion) +10. [响应数据结构](#响应数据结构) + +--- + +## 通用枚举说明 + +### 内容类型 `contentType` + +| 值 | 说明 | +|----|------| +| `IMAGE_TEXT` | 图文 | +| `VIDEO` | 视频 | +| `AUDIO` | 音频 | +| `PDF` | PDF | + +### 复合状态查询 `combinedStatus`(资源列表筛选用) + +前端一个下拉框统一筛选,后端根据值域自动分发: + +| 下拉选项 | 传值 | 分发逻辑 | +|---------|:---:|---------| +| 草稿 | `0` | 查 `status` | +| 已发布 | `1` | 查 `status` | +| 已下架 | `2` | 查 `status` | +| 待审核 | `10` | 查 `auditStatus` | +| 已通过 | `11` | 查 `auditStatus` | +| 已驳回 | `12` | 查 `auditStatus` | + +> **规则**:`combinedStatus ≤ 9` 分发到 `status`,`combinedStatus ≥ 10` 分发到 `auditStatus`。 +> `combinedStatus` 与 `status` / `auditStatus` 参数互斥——同时传时 `combinedStatus` 优先。 + +### 发布状态 `status` + +| 值 | 说明 | +|:--:|------| +| 0 | 草稿 | +| 1 | 已发布 | +| 2 | 已下架 | + +### 审核状态 `auditStatus` + +| 值 | 说明 | +|:--:|------| +| `null` | 无审核动作(新建/编辑后) | +| 10 | 待审核 | +| 11 | 已通过 | +| 12 | 已驳回 | + +### 综合状态展示对照表(V3 新增) + +> 前端列表的状态列按此表展示: + +| auditStatus | status | 前端显示 | +|:-----------:|:------:|---------| +| `null` | 0 | 草稿 | +| 10 | 0 | 待审核 | +| 11 | 0 | **已通过**(V3 新增) | +| 11 | 1 | 已发布 | +| 11 | 2 | 已下架 | +| 12 | 0 | 已驳回 | + +### 分类/标签类型 `type` + +| 值 | 说明 | +|:--:|------| +| 1 | 分类(扁平,仅一级) | +| 2 | 标签(绑定到分类) | + +### 通用状态(分类/标签) + +| 值 | 说明 | +|:--:|------| +| 1 | 正常 | +| 2 | 冻结 | + +### 用户行为类型 + +| 值 | 说明 | +|:--:|------| +| 1 | 阅读 | +| 2 | 收藏 | + +--- + +## 状态流转 + +``` +新建 ──→ 草稿 (status=0, auditStatus=null) + │ + └── 提交审核 ──→ 待审核 (status=0, auditStatus=10) + │ + ├── 审核通过 ──→ 已通过 (status=0, auditStatus=11) ← V3 变更 + │ │ + │ ├── 上架 ──→ 已发布 (status=1, auditStatus=11) + │ │ │ + │ │ ├── 下架 ──→ 已下架 (status=2, auditStatus=11) + │ │ │ │ + │ │ │ └── 上架 ──→ 已发布 (status=1, auditStatus=11) + │ │ │ + │ │ └── 编辑 ──→ 草稿 (status=0, auditStatus=null) + │ │ + │ └── 编辑 ──→ 草稿 (status=0, auditStatus=null) + │ + └── 审核驳回 ──→ 已驳回 (status=0, auditStatus=12) + │ + └── 编辑 ──→ 草稿 (status=0, auditStatus=null) + +复制 ──→ 草稿 (status=0, auditStatus=null),标题+" - 副本" +回滚 ──→ 草稿 (status=0, auditStatus=null) +``` + +> **V3 关键变更**:审核通过后资源进入"已通过"状态,需运营人员点击"上架"才变为"已发布"。编辑/回滚后需重新提交审核。 + +--- + +## 1. 分类管理 `emergency/firstAid/category` + +分类为扁平结构(仅一级),标签通过 `parentId` 绑定到分类下。 + +### 1.1 分页列表 `GET /category/list` + +| 参数 | 类型 | 必填 | 默认值 | 说明 | +|------|------|:---:|--------|------| +| pageNo | Integer | 否 | 1 | 页码 | +| pageSize | Integer | 否 | 10 | 每页条数 | +| name | String | 否 | - | 名称模糊搜索 | +| status | Integer | 否 | - | 状态(1=正常/2=冻结) | + +```json +// 响应 result +{ + "records": [ + { + "id": "...", + "name": "心肺复苏", + "type": 1, + "parentId": null, + "description": "...", + "sortNo": 0, + "status": 1, + "resourceCount": 5, + "createTime": "2026-06-22 10:00:00" + } + ], + "total": 6, "size": 10, "current": 1, "pages": 1 +} +``` + +### 1.2 全部列表(树形) `GET /category/listAll` + +无参数。返回全部分类及其下标签的嵌套树,`tags` 为标签数组,`resourceCount` 为使用量。 + +```json +[ + { + "id": "cat1", "name": "心肺复苏", "resourceCount": 5, + "tags": [ + { "id": "tag1", "name": "成人", "resourceCount": 3 }, + { "id": "tag2", "name": "儿童", "resourceCount": 2 } + ] + }, + { + "id": "cat2", "name": "创伤急救", "resourceCount": 3, + "tags": [...] + } +] +``` + +### 1.3 分类列表 `GET /category/listRoot` + +无参数,返回全部分类(`type=1`)扁平列表(含 `resourceCount`)。 + +### 1.4 标签列表(按分类) `GET /category/listChildren` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| parentId | String | 是 | 分类ID | + +> 返回指定分类下的标签(`type=2`),含 `resourceCount`。 + +### 1.5 分类及标签嵌套列表 `GET /category/listWithTags` 🆕 V3 新增 + +与 `listAll` 返回结构相同,无参数,返回全部分类及其下标签的嵌套结构。 + +### 1.6 详情 `GET /category/queryById` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| id | String | 是 | 分类ID | + +### 1.7 新增 `POST /category/add` + +```json +{ + "name": "分类名称", + "description": "描述(可选)", + "sortNo": 1, + "status": 1 +} +``` + +> 分类不再需要 `parentId`(扁平化,仅一级)。 + +### 1.8 编辑 `POST /category/edit` + +```json +{ + "id": "分类ID", + "name": "新名称", + "description": "新描述", + "sortNo": 2, + "status": 1 +} +``` + +### 1.9 删除 `POST /category/delete` + +```json +{"id": "分类ID"} +``` + +> **级联校验**:分类下存在标签或资源时拒绝删除。 + +### 1.10 批量删除 `POST /category/deleteBatch` + +```json +["id1", "id2"] +``` + +### 1.11 导出Excel `GET /category/exportXls` + +参数与分页列表一致。返回 Excel 文件流。 + +### 1.12 导入Excel `POST /category/importExcel` + +文件上传,格式与导出一致。 + +--- + +## 2. 标签管理 `emergency/firstAid/tag` + +标签与分类共用 `QH_EME_FIRST_AID_RESOURCE_CATEGORY` 表,`type=2` 区分。标签通过 `parentId` 绑定到分类。 + +### 2.1 分页列表 `GET /tag/list` + +| 参数 | 类型 | 必填 | 默认值 | 说明 | +|------|------|:---:|--------|------| +| pageNo | Integer | 否 | 1 | 页码 | +| pageSize | Integer | 否 | 10 | 每页条数 | +| name | String | 否 | - | 名称模糊搜索 | +| parentId | String | 否 | - | 所属分类ID | + +### 2.2 全部列表 `GET /tag/listAll` + +| 参数 | 类型 | 必填 | 默认值 | 说明 | +|------|------|:---:|--------|------| +| parentId | String | 否 | - | 所属分类ID(传则只返回该分类下的标签,不传返回全部) | + +返回标签列表(含 `resourceCount` 引用数量)。 + +### 2.3 详情 `GET /tag/queryById` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| id | String | 是 | 标签ID | + +### 2.4 新增 `POST /tag/add` + +```json +{ + "name": "标签名称", + "parentId": "所属分类ID(必填)", + "description": "描述(可选)", + "sortNo": 1, + "status": 1 +} +``` + +### 2.5 编辑 `POST /tag/edit` + +```json +{ + "id": "标签ID", + "name": "新名称", + "parentId": "所属分类ID", + "description": "新描述", + "sortNo": 2, + "status": 1 +} +``` + +### 2.6 删除 `POST /tag/delete` + +```json +{"id": "标签ID"} +``` + +> **级联校验**:标签已被资源引用时拒绝删除。 + +### 2.7 批量删除 `POST /tag/deleteBatch` + +```json +["id1", "id2"] +``` + +### 2.8 导出Excel `GET /tag/exportXls` + +参数与分页列表一致。返回 Excel 文件流。 + +### 2.9 导入Excel `POST /tag/importExcel` + +文件上传,格式与导出一致。 + +--- + +## 3. 资源管理 `emergency/firstAid/resource` + +### 3.1 分页列表 `GET /resource/list` + +| 参数 | 类型 | 必填 | 默认值 | 说明 | +|------|------|:---:|--------|------| +| pageNo | Integer | 否 | 1 | 页码 | +| pageSize | Integer | 否 | 10 | 每页条数 | +| title | String | 否 | - | 标题模糊搜索 | +| categoryId | String | 否 | - | 分类ID精确匹配 | +| contentType | String | 否 | - | 内容类型:`IMAGE_TEXT`/`VIDEO`/`AUDIO`/`PDF` | +| combinedStatus | Integer | 否 | - | 复合状态筛选(≤9查status,≥10查auditStatus) | +| status | Integer | 否 | - | 发布状态(审核页独立筛选用) | +| auditStatus | Integer | 否 | - | 审核状态(审核页独立筛选用) | +| tags | String | 否 | - | 标签ID,逗号分隔 | + +> **互斥规则**:`combinedStatus` 与 `status`/`auditStatus` 互斥,同时传时 `combinedStatus` 优先。 + +### 3.2 详情 `GET /resource/queryById` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| id | String | 是 | 资源ID | + +响应额外填充:`categoryName`、`tagNameList`、`isFavorited`。 + +### 3.3 新增 `POST /resource/add` + +```json +{ + "title": "资源标题(必填)", + "summary": "摘要简介", + "contentType": "IMAGE_TEXT", + "categoryId": "分类ID", + "applicableScenario": "适用场景描述", + "tags": "标签ID1,标签ID2", + "content": "

富文本HTML正文

", + "coverImage": "https://example.com/cover.jpg", + "fileUrl": "[\"https://example.com/file1.pdf\"]", + "effectiveTime": "2026-07-01 00:00:00", + "expiryTime": "2026-12-31 23:59:59" +} +``` + +> 新建后 `status=0`(草稿)、`auditStatus=null`。 + +### 3.4 编辑 `POST /resource/edit` + +```json +{ + "id": "资源ID", + "title": "新标题", + "contentType": "IMAGE_TEXT", + "categoryId": "分类ID", + "tags": "标签ID1,标签ID2", + "content": "

新内容

", + "...": "其他字段同上" +} +``` + +> 编辑后自动退回草稿 + 清除审核状态(`status=0, auditStatus=null`),并保存编辑前后各一条版本快照("编辑前版本"和"编辑更新")。 + +### 3.5 删除 `POST /resource/delete` + +```json +{"id": "资源ID"} +``` + +> 逻辑删除(`delFlag=1`)。 + +### 3.6 批量删除 `POST /resource/deleteBatch` + +```json +["id1", "id2"] +``` + +### 3.7 提交审核 `POST /resource/submitForReview` + +```json +{"id": "资源ID"} +``` + +> `auditStatus` 变为 `10`(待审核)。 + +### 3.8 下架 `POST /resource/takeDown` + +```json +{"id": "资源ID"} +``` + +> `status` 变为 `2`(已下架)。 + +### 3.9 上架 `POST /resource/publish` ⚠️ V3 变更 + +```json +{"id": "资源ID"} +``` + +> **V3 行为变更**:仅 `auditStatus=11`(已通过)的资源可上架,否则返回错误 `"该资源尚未通过审核,无法上架"`。上架后 `status=1`,审核字段不变。下架操作无前置校验,任意状态均可下架。 + +### 3.10 批量下架 `POST /resource/batchTakeDown` + +```json +["id1", "id2"] +``` + +### 3.11 批量上架 `POST /resource/batchPublish` ⚠️ V3 变更 + +```json +["id1", "id2"] +``` + +> **V3 行为变更**:仅对 `auditStatus=11` 的资源设置 `status=1`,跳过未通过审核的。 + +### 3.12 记录阅读 `POST /resource/incrementView` + +```json +{"id": "资源ID"} +``` + +> 同一用户重复阅读不累计,返回 `"已阅读过"`。 + +### 3.13 复制资源 `POST /resource/copy` + +```json +{"id": "源资源ID"} +``` + +> 标题追加 `" - 副本"`,`status=0, auditStatus=null`,浏览/收藏归零。 + +### 3.14 导出Excel `GET /resource/exportXls` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| selections | String | 否 | 勾选的ID列表(逗号分隔),不传则导出全部 | +| title | String | 否 | 标题筛选 | +| categoryId | String | 否 | 分类筛选 | +| contentType | String | 否 | 类型筛选 | +| status | Integer | 否 | 状态筛选 | + +导出字段:标题、摘要、分类、类型、标签、状态、阅读/收藏、创建时间。 + +### 3.15 导入Excel `POST /resource/importExcel` + +文件上传,格式与导出一致。 + +--- + +## 4. 审核管理 `emergency/firstAid/audit` + +### 4.1 待审核列表 `GET /audit/pending` + +| 参数 | 类型 | 必填 | 默认值 | 说明 | +|------|------|:---:|--------|------| +| pageNo | Integer | 否 | 1 | 页码 | +| pageSize | Integer | 否 | 10 | 每页条数 | +| title | String | 否 | - | 标题搜索 | +| categoryId | String | 否 | - | 分类筛选 | +| contentType | String | 否 | - | 内容类型筛选 | + +### 4.2 已通过列表 `GET /audit/passed` + +参数同上。 + +### 4.3 已驳回列表 `GET /audit/rejected` + +参数同上。 + +### 4.4 审核通过 `POST /audit/approve` ⚠️ V3 变更 + +```json +{"id": "资源ID"} +``` + +> **V3 行为变更**:仅设置 `auditStatus=11`(已通过)、审核人、审核时间,并清除 `auditRejectReason`,**不再同时设置 `status=1`**。审核后资源进入"已通过"状态,需单独调用上架接口发布。 + +### 4.5 审核驳回 `POST /audit/reject` + +```json +{"id": "资源ID", "reason": "驳回原因"} +``` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| id | String | 是 | 资源ID | +| reason | String | 是 | 驳回原因 | + +> `auditStatus` 变为 `12`,记录驳回原因和审核信息。 + +### 4.6 审核记录列表 `GET /audit/records` + +| 参数 | 类型 | 必填 | 默认值 | 说明 | +|------|------|:---:|--------|------| +| pageNo | Integer | 否 | 1 | 页码 | +| pageSize | Integer | 否 | 10 | 每页条数 | +| resourceTitle | String | 否 | - | 资源标题搜索 | +| auditStatus | Integer | 否 | - | 审核状态:`11`=通过/`12`=驳回 | +| startDate | String | 否 | - | 开始日期(yyyy-MM-dd) | +| endDate | String | 否 | - | 结束日期(yyyy-MM-dd) | + +> 从审核记录表查询,按审核时间倒序。 + +--- + +## 5. 推送管理 `emergency/firstAid/push` + +应急调度员在「正在应急」页面右侧面板搜索宣教资源,推送给求助者。 + +### 5.1 可推送资源列表 `GET /push/resourceList` + +| 参数 | 类型 | 必填 | 默认值 | 说明 | +|------|------|:---:|--------|------| +| orderId | String | 否 | - | 工单ID(用于标记推送状态) | +| keyword | String | 否 | - | 关键词搜索(标题/内容) | +| categoryId | String | 否 | - | 分类筛选 | +| contentType | String | 否 | - | 内容类型筛选 | +| pageNo | Integer | 否 | 1 | 页码 | +| pageSize | Integer | 否 | 20 | 每页条数 | + +> 仅展示 `status=1 && auditStatus=11` 且未失效的资源。传 `orderId` 时,列表项的 `pushed` 字段标记该工单下是否已推送。 + +### 5.2 推送单条 `POST /push/send` + +```json +{ + "resourceId": "资源ID", + "orderId": "工单ID" +} +``` + +> 校验资源状态为 `status=1 && auditStatus=11`,否则返回 `"仅已发布且审核通过的资源可推送"`。同一工单+同一资源不允许重复推送,重复返回 `"该资源已推送,请勿重复操作"`。 + +### 5.3 一键推送(批量) `POST /push/batchSend` + +```json +{ + "orderId": "工单ID(必填)", + "resourceIds": ["id1", "id2"], + "filterParams": { + "keyword": "搜索关键词", + "categoryId": "分类ID", + "contentType": "IMAGE_TEXT" + } +} +``` + +> `resourceIds` 与 `filterParams` 二选一: +> - 传 `resourceIds`:仅推送指定ID +> - 传 `filterParams`:按条件查询后全量推送 +> +> 部分失败不影响其他条,响应返回成功计数 `{"count": 3}`。 + +--- + +## 6. 收藏管理 `emergency/firstAid/favorite` + +### 6.1 切换收藏 `POST /favorite/toggle` + +```json +{"id": "资源ID"} +``` + +> 已收藏则取消,未收藏则收藏。返回 `{"favorited": true/false}`。 + +### 6.2 查询收藏状态 `GET /favorite/isFavorited` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| resourceId | String | 是 | 资源ID | + +> 返回 `{"favorited": true/false}`。 + +### 6.3 我的收藏列表 `GET /favorite/myList` + +| 参数 | 类型 | 必填 | 默认值 | 说明 | +|------|------|:---:|--------|------| +| pageNo | Integer | 否 | 1 | 页码 | +| pageSize | Integer | 否 | 10 | 每页条数 | + +--- + +## 7. 版本管理 `emergency/firstAid/version` + +### 7.1 版本历史列表 `GET /version/list` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| resourceId | String | 是 | 资源ID | + +> 按版本号倒序,每条含:`id`, `resourceId`, `versionNo`, `title`, `content`, `changeDescription`, `isCurrent`, `createBy`, `createTime`。 + +### 7.2 回滚 `POST /version/rollback` + +```json +{"id": "版本记录ID"} +``` + +> 将目标版本的内容覆盖到资源,重置 `status=0, auditStatus=null`,并保存一条新的版本记录(标记为"回滚到版本N")。 + +### 7.3 版本差异对比 `GET /version/diff` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| versionId1 | String | 是 | 版本1的ID | +| versionId2 | String | 是 | 版本2的ID(须同一资源) | + +> 返回两个版本的完整信息用于前端差异对比。 + +--- + +## 响应数据结构 + +### 通用列表分页 + +```json +{ + "success": true, + "message": "", + "code": 200, + "result": { + "records": [ ... ], + "total": 100, + "size": 10, + "current": 1, + "pages": 10 + }, + "timestamp": 1782196719184 +} +``` + +### 通用操作响应 + +```json +{ + "success": true, + "message": "已上架", + "code": 200, + "result": "已上架", + "timestamp": 1782196719184 +} +``` + +### 资源列表项关键字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| id | String | 资源ID | +| title | String | 标题 | +| summary | String | 摘要 | +| contentType | String | 内容类型 | +| categoryId | String | 分类ID | +| categoryName | String | 分类名称(非持久) | +| tags | String | 标签ID(逗号分隔) | +| tagNameList | List\ | 标签名称数组(非持久) | +| content | String | 富文本正文 | +| coverImage | String | 封面图URL | +| fileUrl | String | 附件JSON数组字符串 | +| status | Integer | 发布状态(0=草稿/1=已发布/2=已下架) | +| auditStatus | Integer | 审核状态(null/10=待审核/11=已通过/12=已驳回) | +| auditRejectReason | String | 驳回原因 | +| auditBy | String | 审核人 | +| auditById | String | 审核人ID | +| auditTime | Date | 审核时间 | +| viewCount | Integer | 浏览次数 | +| favoriteCount | Integer | 收藏次数 | +| isFavorited | Boolean | 当前用户是否已收藏(非持久) | +| pushed | Boolean | 当前工单下是否已推送(非持久,仅推送列表) | +| effectiveTime | Date | 生效时间 | +| expiryTime | Date | 失效时间 | +| createTime | Date | 创建时间 | +| updateTime | Date | 更新时间 | + +### 分类/标签项关键字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| id | String | ID | +| name | String | 名称 | +| type | Integer | 类型(1=分类/2=标签) | +| parentId | String | 所属分类ID(标签有值,分类为null) | +| parentName | String | 所属分类名称(非持久) | +| description | String | 描述 | +| sortNo | Integer | 排序号 | +| status | Integer | 状态(1=正常/2=冻结) | +| resourceCount | Integer | 关联资源数量(非持久,listAll/listWithTags 返回) | +| tags | List\ | 标签列表(非持久,listAll/listWithTags 返回) | +| createTime | Date | 创建时间 | + +### 审核记录项关键字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| id | String | 记录ID | +| resourceId | String | 资源ID | +| resourceTitle | String | 资源标题(非持久,查询时填充) | +| auditStatus | Integer | 审核状态(11=通过/12=驳回) | +| auditRejectReason | String | 驳回原因 | +| auditBy | String | 审核人 | +| auditById | String | 审核人ID | +| auditTime | Date | 审核时间 | +| createTime | Date | 记录创建时间 | diff --git a/health-emergency/API文档-移动端接口.md b/health-emergency/API文档-移动端接口.md new file mode 100644 index 0000000..afd0aea --- /dev/null +++ b/health-emergency/API文档-移动端接口.md @@ -0,0 +1,275 @@ +# 急救模块移动端 API 文档 + +> **基础信息** +> 网关地址: `http://{gateway-host}:{port}`(前端加 `/health-emergency` 前缀) +> 服务直连: `http://{host}:7011`(调试用,不加前缀) +> 认证方式: 请求头 `X-Access-Token: {token}` +> Content-Type: `application/json; charset=utf-8` +> 统一响应格式: `{"success": bool, "message": "...", "code": 200, "result": {...}, "timestamp": ...}` +> 日期格式: `yyyy-MM-dd HH:mm:ss`(东八区) + +--- + +## 目录 + +1. [应急群聊拉人](#1-应急群聊拉人-apiemergency) +2. [宣教资源](#2-宣教资源-apiemergencyfirstaidresource) + +--- + +## 1. 应急群聊拉人 `api/emergency` + +> 网关完整路径: `/health-emergency/api/emergency` + +### 1.1 搜索专家(专业人员) `GET /order/searchExpert` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| realname | String | 否 | 姓名,模糊搜索 | +| centerId | String | 否 | 应急中心ID | +| excludeSessionId | String | 否 | 群组ID,用于排除已在群中的人 | +| pageNo | Integer | 否 | 页码,默认1 | +| pageSize | Integer | 否 | 每页条数,默认10 | + +```json +// 响应 result +{ + "records": [ + { + "userId": "xxx", "realname": "张医生", "avatar": "https://...", + "type": "6", "centerId": "xxx", + "post": "主任医师", "school": "北京大学", "edu": "博士", + "goodAt": "心血管内科", "deptName": "急诊科" + } + ], + "total": 50, "size": 10, "current": 1 +} +``` + +| 字段 | 说明 | +|------|------| +| userId | 用户ID,邀请时传入 memberList | +| realname | 姓名 | +| avatar | 头像 | +| type | 类型,"6"=专业人员 | +| centerId | 应急中心ID | +| post | 职称 | +| school | 毕业院校 | +| edu | 学历 | +| goodAt | 擅长领域 | +| deptName | 科室 | + +### 1.2 搜索员工 `GET /order/searchEmployee` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| realname | String | 否 | 姓名,模糊搜索 | +| orgCode | String | 否 | 部门编码 | +| workNo | String | 否 | 工号 | +| phone | String | 否 | 手机号 | +| excludeSessionId | String | 否 | 群组ID,用于排除已在群中的人 | +| pageNo | Integer | 否 | 页码,默认1 | +| pageSize | Integer | 否 | 每页条数,默认10 | + +```json +// 响应 result +{ + "records": [ + { + "userId": "xxx", "realname": "张三", "avatar": "https://...", + "orgCode": "650000001001", "orgName": "新疆油田公司", + "deptName": "安全环保部", "phone": "13800000000", "workNo": "A00123" + } + ], + "total": 200, "size": 10, "current": 1 +} +``` + +| 字段 | 说明 | +|------|------| +| userId | 用户ID,邀请时传入 memberList | +| realname | 姓名 | +| avatar | 头像 | +| orgCode | 部门编码 | +| orgName | 单位名称(二级单位) | +| deptName | 部门名称 | +| phone | 手机号 | +| workNo | 工号 | + +### 1.3 创建群聊 `GET /createGroupMag` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| name | String | 是 | 群聊名称 | +| longitude | String | 是 | 经度 | +| latitude | String | 是 | 纬度 | +| type | String | 否 | 类型 | + +> 返回 `groupId`(群组ID),作为后续拉人接口的入参。 + +### 1.4 邀请进群 `POST /addGroupUser` + +拉专家或员工加入应急群聊。 + +```json +// Request Body +{ + "groupId": "1907659384834752513", + "memberList": ["userId1", "userId2"], + "memberType": 1 +} +``` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| groupId | String | 是 | 群组ID(即 `createGroupMag` 返回的 `groupId`) | +| memberList | List\ | 是 | 要邀请的用户ID列表,最多100个 | +| memberType | Integer | 否 | `0`=专家/专业人员, `1`=员工,**默认0** | + +```json +// 响应 +{"success": true, "message": "", "result": true} +``` + +> 已在群中的人员会自动跳过,不会报错。所有选中的人都在群中时返回失败。 + +### 1.5 移除群成员 `POST /removeGroupUser` + +```json +// Request Body +{ "groupId": "1907659384834752513", "memberList": ["userId1"] } +``` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| groupId | String | 是 | 群组ID | +| memberList | List\ | 是 | 要移除的用户ID列表 | + +```json +// 响应 +{"success": true, "message": "", "result": true} +``` + +> 只能移除后续拉入的协助人员,不能移除发起人和初始操作/专业人员。 + +### 1.6 群成员列表 `GET /order/getGroupMemberList` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| sessionId | String | 是 | 群组ID | + +```json +// 响应 result +[ + { "orderId": "...", "userId": "发起人id", "userName": "李四", "avatar": "https://...", "isGroupMember": 1, "memberType": -1 }, + { "orderId": "...", "userId": "操作人员id", "userName": "王五", "avatar": "https://...", "isGroupMember": 1, "memberType": 0 }, + { "orderId": "...", "userId": "专业人员id", "userName": "张医生", "avatar": "https://...", "isGroupMember": 1, "memberType": 1 }, + { "orderId": "...", "userId": "员工id", "userName": "张三", "avatar": "https://...", "isGroupMember": 1, "memberType": 2 }, + { "orderId": "...", "userId": "其他专业人id", "userName": "赵医生", "avatar": "https://...", "isGroupMember": 0, "memberType": 1 } +] +``` + +| 字段 | 说明 | +|------|------| +| orderId | 应急单ID | +| userId | 用户ID | +| userName | 姓名 | +| avatar | 头像 | +| isGroupMember | `1`=在群中, `0`=可邀请 | +| memberType | `-1`=发起人, `0`=操作人员, `1`=专业人员, `2`=员工 | + +### 1.7 memberType 字典 + +| 值 | 含义 | 场景 | +|:---:|------|------| +| -1 | 发起人 | 创建应急的人 | +| 0 | 操作人员 | 应急中心调度员 | +| 1 | 专业人员 | 专家/医生 | +| 2 | 员工 | 普通员工(被拉入群) | + +### 典型调用流程 + +``` +1. 创建群聊 + GET /health-emergency/api/emergency/createGroupMag?name=xxx&longitude=xxx&latitude=xxx + +2. 查看当前成员 + GET /health-emergency/api/emergency/order/getGroupMemberList?sessionId={groupId} + → 展示群成员列表(按 memberType 区分标签展示) + → isGroupMember=0 的显示为"可邀请" + +3. 搜索要拉的人 + GET /health-emergency/api/emergency/order/searchExpert?realname=张&excludeSessionId={groupId} + GET /health-emergency/api/emergency/order/searchEmployee?realname=李&excludeSessionId={groupId} + → 展示搜索结果,用户勾选 + +4. 确认邀请 + POST /health-emergency/api/emergency/addGroupUser + {"groupId": "{groupId}", "memberList": ["id1","id2"], "memberType": 0} + +5. 移除成员 + POST /health-emergency/api/emergency/removeGroupUser + {"groupId": "{groupId}", "memberList": ["id1"]} + +6. 刷新成员列表 + GET /health-emergency/api/emergency/order/getGroupMemberList?sessionId={groupId} +``` + +--- + +## 2. 宣教资源 `api/emergency/firstAid/resource` + +> 网关完整路径: `/health-emergency/api/emergency/firstAid/resource` + +### 2.1 根据宣教ID查询详情 `GET /resource/queryById` + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| id | String | 是 | 宣教资源ID | + +```json +// 响应 result +{ + "id": "...", + "title": "心肺复苏指南", + "summary": "摘要简介", + "contentType": "IMAGE_TEXT", + "categoryId": "cat1", + "categoryName": "心肺复苏", + "applicableScenario": "适用场景", + "tags": "tag1,tag2", + "tagNameList": ["成人", "初级"], + "content": "

富文本HTML正文

", + "coverImage": "https://example.com/cover.jpg", + "fileUrl": "[\"https://example.com/file1.pdf\"]", + "viewCount": 100, + "favoriteCount": 20, + "isFavorited": false, + "effectiveTime": "2026-07-01 00:00:00", + "expiryTime": "2026-12-31 23:59:59", + "createTime": "2026-07-01 10:00:00", + "updateTime": "2026-07-05 14:30:00" +} +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| id | String | 资源ID | +| title | String | 标题 | +| summary | String | 摘要/简介 | +| contentType | String | 内容类型:`IMAGE_TEXT`/`VIDEO`/`AUDIO`/`PDF` | +| categoryId | String | 分类ID | +| categoryName | String | 分类名称 | +| applicableScenario | String | 适用场景 | +| tags | String | 标签ID(逗号分隔) | +| tagNameList | List\ | 标签名称列表 | +| content | String | 富文本正文HTML | +| coverImage | String | 封面图URL | +| fileUrl | String | 附件URL列表(JSON数组字符串) | +| viewCount | Integer | 浏览次数 | +| favoriteCount | Integer | 收藏次数 | +| isFavorited | Boolean | 当前用户是否已收藏 | +| effectiveTime | Date | 生效时间 | +| expiryTime | Date | 失效时间 | +| createTime | Date | 创建时间 | +| updateTime | Date | 更新时间 | diff --git a/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/RequestPrefix.java b/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/RequestPrefix.java index 4785e51..8bb5204 100644 --- a/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/RequestPrefix.java +++ b/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/RequestPrefix.java @@ -12,6 +12,8 @@ public interface RequestPrefix { String DISEASE = BASE + "/disease"; + String FIRST_AID_RESOURCE = BASE + "/firstAid/resource"; + // 不鉴权路径 String API = "/api"; String ANON = API + "/anon/aed"; diff --git a/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/controller/FirstAidResourceApiController.java b/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/controller/FirstAidResourceApiController.java new file mode 100644 index 0000000..f053955 --- /dev/null +++ b/health-emergency/health-emergency-biz/src/main/java/com/renkang/emergency/api/controller/FirstAidResourceApiController.java @@ -0,0 +1,39 @@ +package com.renkang.emergency.api.controller; + +import com.renkang.emergency.api.RequestPrefix; +import com.renkang.emergency.entity.FirstAidResource; +import com.renkang.emergency.service.IFirstAidResourceService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.jeecg.common.api.vo.Result; +import org.jeecg.global.GlobalUtils; +import org.jeecg.common.system.vo.LoginUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * 移动端-急救宣教资源 + * + * @author pengjie + * @date 2026-07-06 + */ +@Tag(name = "移动端-急救宣教资源") +@RestController +@RequestMapping(RequestPrefix.FIRST_AID_RESOURCE) +public class FirstAidResourceApiController { + + @Autowired + private IFirstAidResourceService resourceService; + + @Operation(summary = "根据宣教ID查询详情") + @GetMapping("/queryById") + public Result queryById(@RequestParam("id") String id) { + LoginUser loginUser = GlobalUtils.getLoginUser(); + String userId = loginUser != null ? loginUser.getId() : null; + FirstAidResource entity = resourceService.getDetail(id, userId); + return entity == null ? Result.error("未找到对应数据") : Result.OK(entity); + } +}