Files
senmesh-zc/docs/接口文档-用户管理与记录查询.md
leijiaping c305ca946e feat: 用户启停/注销、机构账号查询、手机号查记录、机构上传配置
1. 用户管理:新增启用(user/enable)/禁用(user/disable)/注销(user/admin_cancel)接口,
   平台超管可操作全部用户,机构管理员限本机构;注销带分布式锁、禁自己/超管守卫
2. 禁用/注销立即踢下线:Redis黑名单(user:disabled:{uid}) + JWT过滤器拦截,
   TTL与token有效期一致
3. 系统管理员查看各机构账号:GET user/page/org_account(机构/账号/手机号等筛选)
4. 按手机号查上传/发送/接收记录:GET user_file/record/page_by_phone,
   发送/接收方向按部署侧 file.transfer.location 自动映射
5. 机构上传配置:新表 x_upload_config + upload_config/info|modify|check 接口,
   上传总开关/后缀白名单/单文件大小限制,网盘落库时强制校验
6. 加固:UserInfoDTO.setPassword 缺省密码未配置时不再抛 rawPassword cannot be null
7. 新增 x_upload_config 建表脚本(upgrade-20260915-release.sql 为上线版)、
   生产部署说明、前端接口文档×2、运维脚本 sfile-ctl.sh、AGENTS.md
2026-09-15 12:14:27 +08:00

408 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 前端接口文档 —— 用户管理增强 & 机构账号查询 & 按手机号查询文件记录
> 版本:v1.0(2026-09-14)
> 适用后端:s-file(alita-bjy-uygur)
> Swagger 分组:「用户」「用户文件」
---
## 0. 通用约定
### 0.1 请求与认证
- 所有接口均需**登录后调用**,认证 token 按现有方式携带(header 或 cookie,与系统其他接口一致)。
- 新增接口均要求**平台管理员(超管)身份**(`uc_user.supeiror = true`),非管理员调用统一返回失败,提示「当前用户无操作权限」。
### 0.2 统一返回结构 `AlitaResult<T>`
```json
{
"requestId": "xxx",
"code": "200",
"success": true,
"msg": null,
"data": { ... }
}
```
| 字段 | 说明 |
|---|---|
| code | `"200"` 成功;业务失败时 success=false,msg 为错误提示(如「不能禁用当前登录账号」) |
| success | 是否成功 |
| data | 业务数据,失败时为 null |
### 0.3 分页请求与返回
分页查询接口通过 **URL query 参数** 传递分页信息,返回结构 `Page<T>`:
```
pageNo 第几页,默认 1
pageSize 页宽,默认 20,上限 1000
needPage 是否分页,默认 true(无需传)
```
```json
{
"pageNo": 1,
"pageSize": 20,
"pageCount": 5,
"totalCount": 88,
"entityList": [ ... ]
}
```
### 0.4 通用枚举(前后端共用)
**用户状态 `status`**
| 值 | 含义 |
|---|---|
| 1 | 待激活 |
| 2 | 已激活 |
| 3 | 已注销 |
**是否启用 `enabled`**:`true` 启用,`false` 禁用。
**文件状态 `fileStatus`**
| 值 | 含义 |
|---|---|
| 1 | 正常 |
| 2 | 失效 |
| 11 | 解析中 |
| 12 | 待审核 |
| 13 | 传输中 |
| 14 | 失败 |
**记录类型 `recordType`**(本文档 3.4 节专用)
| 值 | 含义 |
|---|---|
| 1 | 上传记录 |
| 2 | 发送记录(本端发起文件传输) |
| 3 | 接收记录(本端接收文件传输) |
> 发送/接收与部署侧有关,但**前端无需关心**:传入 `recordType` 后,后端按部署配置(内网/外网)自动映射到对应的 `root_type`;返回列表中每条记录也已回填 `recordType` / `recordTypeDesc`。
---
## 1. 用户管理:启用 / 禁用 / 注销
### 1.1 启用用户
将被禁用的账号重新启用(幂等:已启用的账号重复调用仍返回成功)。
- **URL**:`POST /user/enable`
- **权限**:平台管理员
- **Body**(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| userId | Long | 是 | 目标用户 id |
- **返回**:`AlitaResult<Boolean>`,data 为 `true`
- **失败场景**:用户不存在;账号已注销(提示「已注销账号不可启用」);非管理员
**请求示例**
```json
POST /user/enable
{ "userId": 10086 }
```
**返回示例**
```json
{ "code": "200", "success": true, "data": true }
```
### 1.2 禁用用户
禁用账号,禁用后该用户无法登录/使用系统(后端登录态校验会实时读取启用状态,被禁用用户下次请求即被拒绝)。幂等:已禁用的账号重复调用仍返回成功。
- **URL**:`POST /user/disable`
- **权限**:平台管理员
- **Body**(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| userId | Long | 是 | 目标用户 id |
- **返回**:`AlitaResult<Boolean>`,data 为 `true`
- **失败场景**:
- 用户不存在
- `userId` 为当前登录人(提示「不能禁用当前登录账号」)
- 目标是超级管理员(提示「不能禁用超级管理员账号」)
- 目标已注销(提示「已注销账号无需禁用」)
**请求示例**
```json
POST /user/disable
{ "userId": 10086 }
```
### 1.3 注销用户(管理员直接注销)
管理员将账号直接置为**已注销**(status=3)并同步禁用(enabled=false),**不进入注销申请审批流程**。注销后账号不可恢复、不可登录。幂等:已注销账号重复调用返回成功。
- **URL**:`POST /user/admin_cancel`
- **权限**:平台管理员
- **Body**(application/json)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| userId | Long | 是 | 目标用户 id |
- **返回**:`AlitaResult<Void>`,data 为 null
- **失败场景**:
- 用户不存在
- `userId` 为当前登录人(提示「不能注销当前登录账号」)
- 目标是超级管理员(提示「不能注销超级管理员账号」)
- 并发重复操作(提示「该用户正在注销,请勿重复操作」)
**请求示例**
```json
POST /user/admin_cancel
{ "userId": 10086 }
```
> **与既有接口的区别**:既有 `POST /user/cancel` 为机构内注销(限定当前登录机构、且要求目标账号启用中),供原「注销申请/同意」流程使用,保持不变;本接口供系统管理员在用户管理页面跨机构直接注销。
---
## 2. 系统管理员:查看各机构下的账号信息
### 2.1 分页查询机构账号
按机构维度查看账号信息。一行 = 一个机构下的一个账号(同一账号属于多个机构时会出现多行)。不传 `orgId` 时查询全部机构,传 `orgId` 时查看指定机构。
- **URL**:`GET /user/page/org_account`
- **权限**:平台管理员
- **参数**(URL query)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| orgId | Long | 否 | 机构 id,不传查全部机构 |
| orgNameLike | String | 否 | 机构名称,模糊匹配 |
| usernameLike | String | 否 | 账号,模糊匹配 |
| realNameLike | String | 否 | 真实姓名,模糊匹配 |
| phoneLike | String | 否 | 手机号,模糊匹配 |
| enabled | Boolean | 否 | 是否启用:true/false |
| status | Integer | 否 | 用户状态:1 待激活 / 2 已激活 / 3 已注销 |
| createTimeStart | String | 否 | 创建时间起,格式 `yyyy-MM-dd HH:mm:ss` |
| createTimeEnd | String | 否 | 创建时间止,格式 `yyyy-MM-dd HH:mm:ss` |
| pageNo / pageSize | Integer | 否 | 分页参数,默认 1 / 20 |
- **返回**:`AlitaResult<Page<OrgAccountDTO>>`
**OrgAccountDTO 字段**
| 字段 | 类型 | 说明 |
|---|---|---|
| orgId | Long | 机构 id |
| orgName | String | 机构名称 |
| administrator | Boolean | 是否该机构的管理员 |
| userId | Long | 用户 id(可传给 1.1/1.2/1.3 接口做启停/注销操作) |
| username | String | 账号 |
| nickname | String | 昵称 |
| realName | String | 真实姓名 |
| phone | String | 手机号 |
| email | String | 邮箱 |
| userType | Integer | 用户类型:1 企业用户 / 2 个人用户 |
| enabled | Boolean | 是否启用 |
| status | Integer | 状态:1 待激活 / 2 已激活 / 3 已注销 |
| createTime | String | 创建时间 `yyyy-MM-dd HH:mm:ss` |
- **排序规则**:机构 id 升序,机构管理员排前面,同机构内按用户 id 倒序。
**请求示例**
```
GET /user/page/org_account?orgNameLike=教育&phoneLike=138&enabled=false&pageNo=1&pageSize=20
```
**返回示例**
```json
{
"code": "200",
"success": true,
"data": {
"pageNo": 1,
"pageSize": 20,
"pageCount": 1,
"totalCount": 2,
"entityList": [
{
"orgId": 12,
"orgName": "XX市教育局",
"administrator": true,
"userId": 1001,
"username": "admin_xx",
"nickname": "张三",
"realName": "张三",
"phone": "13800000001",
"email": "zhang@xx.gov.cn",
"userType": 1,
"enabled": false,
"status": 2,
"createTime": "2026-08-01 10:00:00"
},
{
"orgId": 12,
"orgName": "XX市教育局",
"administrator": false,
"userId": 1002,
"username": "user_xx01",
"nickname": "李四",
"realName": "李四",
"phone": "13800000002",
"email": null,
"userType": 1,
"enabled": true,
"status": 2,
"createTime": "2026-08-03 14:30:00"
}
]
}
}
```
---
## 3. 按手机号查询文件记录(上传 / 发送 / 接收)
### 3.1 分页查询
输入手机号,精确匹配该手机号名下(可能是多个账号)的全部文件记录,可按记录类型筛选。
- **URL**:`GET /user_file/record/page_by_phone`
- **权限**:平台管理员
- **参数**(URL query)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| phone | String | **是** | 用户手机号,精确匹配,同一手机号关联的所有账号均会命中 |
| recordType | Integer | 否 | 1 上传记录 / 2 发送记录 / 3 接收记录,**不传查全部三类** |
| fileNameLike | String | 否 | 文件名,模糊匹配 |
| fileType | String | 否 | 文件类型:`1` 文件 / `2` 文件夹 |
| fileStatus | String | 否 | 文件状态:1 正常 / 2 失效 / 11 解析中 / 12 待审核 / 13 传输中 / 14 失败 |
| createTimeBegin | String | 否 | 记录时间起,格式 `yyyy-MM-dd HH:mm:ss` |
| createTimeEnd | String | 否 | 记录时间止,格式 `yyyy-MM-dd HH:mm:ss` |
| pageNo / pageSize | Integer | 否 | 分页参数,默认 1 / 20 |
- **返回**:`AlitaResult<Page<UserFileRecordDTO>>`
**UserFileRecordDTO 字段**(继承用户文件全部字段,以下为主要字段)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | Long | 记录 id |
| phone | String | 归属手机号 |
| username | String | 归属账号 |
| realName | String | 归属真实姓名 |
| userType | Integer | 归属用户类型:1 企业用户 / 2 个人用户 |
| recordType | Integer | 记录类型:1 上传 / 2 发送 / 3 接收 |
| recordTypeDesc | String | 记录类型描述(「上传记录」「发送记录」「接收记录」) |
| userId | Long | 归属用户 id |
| rootType | String | 原始根类型:1 普通 / 2 内穿外 / 3 外传内(调试用,前端一般用 recordType 即可) |
| fileType | String | 文件大类:1 文件 / 2 文件夹 |
| fileName | String | 文件名 |
| fileCode | String | 物理文件编码 |
| fileSize | Long | 文件大小(字节) |
| fileStatus | String | 文件状态:1 正常 / 2 失效 / 11 解析中 / 12 待审核 / 13 传输中 / 14 失败 |
| createTime | String | 记录时间(上传/发送/接收发起时间)`yyyy-MM-dd HH:mm:ss` |
| endTime | String | 有效期(分享类记录使用),可能为 null |
| fileCategory | String | 文件种类(文档/图片/视频等,按后缀归类) |
| maxRiskLevel | String | 最高风险等级:1 重度 / 2 中度 / 3 轻度,可能为 null |
- **排序**:记录 id 倒序(即时间倒序)。
- **失败场景**:phone 为空;recordType 非法(提示「记录类型不合法,仅支持1上传/2发送/3接收」);非管理员。
**请求示例**
```
GET /user_file/record/page_by_phone?phone=13800000001&recordType=2&pageNo=1&pageSize=10
```
**返回示例**
```json
{
"code": "200",
"success": true,
"data": {
"pageNo": 1,
"pageSize": 10,
"pageCount": 1,
"totalCount": 2,
"entityList": [
{
"id": 9001,
"phone": "13800000001",
"username": "user_xx01",
"realName": "李四",
"userType": 1,
"recordType": 2,
"recordTypeDesc": "发送记录",
"userId": 1002,
"rootType": "2",
"fileType": "2",
"fileName": "2026年预算材料_20260912103000",
"fileCode": null,
"fileSize": null,
"fileStatus": "1",
"createTime": "2026-09-12 10:30:00",
"endTime": null,
"fileCategory": null,
"maxRiskLevel": null
},
{
"id": 8802,
"phone": "13800000001",
"username": "user_xx01",
"realName": "李四",
"userType": 1,
"recordType": 1,
"recordTypeDesc": "上传记录",
"userId": 1002,
"rootType": "1",
"fileType": "1",
"fileName": "工作总结.docx",
"fileCode": "fc_3a7d92",
"fileSize": 1048576,
"fileStatus": "1",
"createTime": "2026-09-10 09:12:00",
"endTime": null,
"fileCategory": "文档",
"maxRiskLevel": null
}
]
}
}
```
> **记录类型口径说明**(便于前端理解,无需处理):
> - 上传记录:用户在网盘中上传的文件/文件夹(rootType=1)。
> - 发送记录:用户发起的文件传输(文件夹整体外发,传输中状态为 13,完成后变 1,失败为 14)。
> - 接收记录:对端传来的文件在本端解包后归属到该手机号用户的记录(若开启风险审查,先为 12 待审核,通过后为 1)。
---
## 4. 错误处理建议
前端统一按 `success=false` 判定失败并 toast `msg`;特殊 code 沿用系统既有约定(`401` 未登录等,与现有接口一致)。
涉及本批接口的典型业务错误文案:
| 场景 | msg |
|---|---|
| 非平台管理员操作 | 当前用户无操作权限 |
| 启用已注销账号 | 已注销账号不可启用 |
| 禁用/注销自己 | 不能禁用当前登录账号 / 不能注销当前登录账号 |
| 禁用/注销超管 | 不能禁用超级管理员账号 / 不能注销超级管理员账号 |
| recordType 非法 | 记录类型不合法,仅支持1上传/2发送/3接收 |
| phone 为空 | 手机号不能为空 |