# 05-API接口契约 BasePath: `/api` 端口: `8080` ## 全局约定 ### 响应格式 ```json {"code": 200, "message": "操作成功", "data": {}, "timestamp": 1700000000000} ``` ### 错误码 | 范围 | 含义 | |---|---| | 200 | 成功 | | 400xx | 客户端参数错误 | | 401xx | 认证/授权错误 | | 403xx | 权限不足 | | 404xx | 资源不存在 | | 500xx | 服务端内部错误 | ### 鉴权 - 所有 `/api/**` 接口默认要求 JWT;登录、版本下拉等少数白名单接口(见各接口 `Auth: 否`)匿名访问。 - 客户端将登录返回的 `accessToken` 放入请求头:`Authorization: Bearer `。 - accessToken 默认有效期 24h;过期前 30 分钟前端可用 `refreshToken` 续期(独立接口,本契约暂不展开)。 - 锁定中(`tUser.tLockedUntil` 未过期)的账号即使密码正确也无法登录,返回 `40110`。 ### 分页参数 请求查询参数(GET)或 body(POST 列表)统一: ``` pageNum: int = 1 // 页码,从 1 开始 pageSize: int = 20 // 每页条数,上限 100 ``` 响应 `data` 结构: ```json { "records": [ ... ], "total": 123, "pageNum": 1, "pageSize": 20 } ``` `pageSize > 100` 时后端自动截断为 100,并在响应 `message` 中提示 `pageSize 已截断到 100`。 ## 接口清单 ### REQ-USR-001 增加用户 - **Method**: POST - **Path**: `/api/usr/user` - **Auth**: 是 - **Permission**: `usr:user:create`(仅超级管理员或被显式授权者) - **请求**: JSON body,字段包括 `userCode`、`userName`、`employeeId`(可空)、`userType`(NORMAL/ADMIN)、`language`(zh-CN/en/zh-TW)、`canEditDoc`(bool)、`password`(明文,后端哈希后存储,缺省则使用配置项 `app.security.default-password`,默认 `666666`)、`permissionIds`(int[],权限分类主键数组,对应 `tUserPermission` 关联)。 - **响应**: `data` = `{ "userId": , "userCode": }`,对应 REQ-USR-001 输出表 1「用户号」。 #### 错误码 - `40001` — 必填字段缺失或格式不合法 - `40002` — `userName` 已存在(违反 `uk_tUser_sUserName`) - `40003` — `userCode` 已存在(违反 `uk_tUser_sUserCode`) - `40004` — `employeeId` 非法(在 `tEmployee` 中不存在或已作废) - `40005` — `permissionIds` 中某个权限分类不存在或已作废 - `40301` — 当前账号无 `usr:user:create` 权限 --- ### REQ-USR-002 修改用户 - **Method**: PUT - **Path**: `/api/usr/user/{userId}` - **Auth**: 是 - **Permission**: `usr:user:update`(管理员)或本人改本人非角色字段 - **请求**: 路径参数 `userId` + JSON body,可选字段 `employeeId` / `userType` / `language` / `canEditDoc` / `iIsDisabled` / `permissionIds`。`userName` / `userCode` / `password` 不在本接口修改。 - **响应**: `data` = `{ "userId": }`,对应 REQ-USR-002 输出表 1「用户 id」。 #### 错误码 - `40001` — 字段格式不合法 - `40006` — `userType` 变更需 `usr:user:assign-role` 权限 - `40004` — `employeeId` 非法(不存在或已作废) - `40005` — `permissionIds` 中某个权限分类不存在或已作废 - `40402` — 目标 `userId` 不存在 - `40301` — 当前账号无 `usr:user:update` 权限(且非本人) --- ### REQ-USR-003 查询用户 - **Method**: GET - **Path**: `/api/usr/user` - **Auth**: 是 - **Permission**: `usr:user:list`(管理员) - **请求**: 查询参数 `queryField`(用户名/员工名/用户号/部门/用户类型/作废/登录日期/制单人)+ `matchMode`(包含/不包含/等于)+ `queryValue`(可空,空时不过滤)+ `pageNum` + `pageSize`。 - **响应**: 分页结构,`records[]` 项对应 REQ-USR-003 输出表 1 全部字段:`index` / `userName` / `employeeName` / `userCode` / `department` / `userType` / `language` / `isDisabled` / `lastLoginDate` / `createdBy` / `createDate`。`employeeName` / `department` 由 LEFT JOIN `tEmployee` 取得。密码字段任何场景下都不返回。 #### 错误码 - `40001` — `queryField` / `matchMode` 取值非法 - `40301` — 当前账号无 `usr:user:list` 权限 --- ### REQ-USR-004 用户登录 - **Method**: POST - **Path**: `/api/auth/login` - **Auth**: 否(匿名) - **Permission**: 无 - **请求**: JSON body `{ "userName": , "password": , "companyId": }`,`companyId` 对应 `tCompany.iIncrement`(前端「版本」下拉所选项)。 - **响应**: `data` = `{ "accessToken": , "tokenType": "Bearer", "expiresIn": 86400, "user": { "userId": ..., "userName": ..., "userType": ..., "language": ..., "canEditDoc": ..., "permissions": [...] } }`。 #### 错误码 - `40001` — `userName` / `password` / `companyId` 字段缺失 - `40101` — 用户名或密码错误(统一返回,不区分具体哪个错;同时 `tUser.iLoginFailCount += 1`) - `40110` — 账号已锁定(`tLockedUntil > NOW()`),返回锁定截止时间 - `40111` — 账号已作废(`tUser.iIsDisabled = 1`) - `40404` — `companyId` 对应公司不存在或已作废