feat: 增加员工端工作台后端能力
This commit is contained in:
+301
-4
@@ -113,9 +113,17 @@ pw111111
|
||||
| `role:manage` | 新增、修改、软删除自定义角色 |
|
||||
| `employee:view:all` | 查看全部门店员工 |
|
||||
| `employee:view:store` | 查看当前门店员工 |
|
||||
| `employee:manage` | 新增、修改、启停、移除、软删除员工和维护密码 |
|
||||
| `employee:manage` | 新增、修改、启停、移除和软删除员工 |
|
||||
| `permission:view` | 查看权限策略 |
|
||||
| `permission:manage` | 分配角色权限 |
|
||||
| `announcement:view` | 查看公告 |
|
||||
| `announcement:manage` | 新增、编辑、发布、归档公告 |
|
||||
| `task:view` | 查看任务 |
|
||||
| `task:manage` | 新建、编辑、取消任务 |
|
||||
| `shift:view` | 查看排班 |
|
||||
| `shift:manage` | 新增、编辑、取消排班 |
|
||||
| `credential:reset` | 重置下级员工密码 |
|
||||
| `credential:audit:view` | 查看凭据操作审计 |
|
||||
|
||||
### 角色权限
|
||||
|
||||
@@ -149,6 +157,7 @@ interface AuthUser {
|
||||
}>;
|
||||
permissions: string[];
|
||||
canManage: boolean;
|
||||
mustChangePassword?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -241,6 +250,7 @@ interface PermissionMenu {
|
||||
| `POST` | `/api/auth/admin/login` | 否 | 无 | 后台登录 |
|
||||
| `POST` | `/api/auth/employee/login` | 否 | 无 | 员工端登录 |
|
||||
| `GET` | `/api/auth/me` | 是 | 登录即可 | 当前用户 |
|
||||
| `PATCH` | `/api/auth/me/password` | 是 | 登录即可 | 修改本人密码 |
|
||||
| `GET` | `/api/permissions/me` | 是 | 登录即可 | 当前用户权限和菜单 |
|
||||
| `GET` | `/api/permissions/policies` | 是 | `permission:view` | 角色权限策略 |
|
||||
| `GET` | `/api/permissions/definitions` | 是 | `permission:view` | 可分配权限点定义 |
|
||||
@@ -263,8 +273,34 @@ interface PermissionMenu {
|
||||
| `PATCH` | `/api/employees/:id` | 是 | `employee:manage` | 修改员工 |
|
||||
| `PATCH` | `/api/employees/:id/status` | 是 | `employee:manage` | 修改员工状态 |
|
||||
| `PATCH` | `/api/employees/:id/password` | 是 | `employee:manage` | 修改员工密码 |
|
||||
| `PATCH` | `/api/employees/:id/password/reset` | 是 | `employee:manage` | 重置员工为初始密码 |
|
||||
| `PATCH` | `/api/employees/:id/password/reset` | 是 | `credential:reset` | 兼容旧路径,重置临时密码 |
|
||||
| `DELETE` | `/api/employees/:id` | 是 | `employee:manage` | 软删除员工 |
|
||||
| `GET` | `/api/mobile/bootstrap` | 是 | 登录即可 | 员工端首屏聚合 |
|
||||
| `GET` | `/api/mobile/announcements` | 是 | 登录即可 | 当前员工可见公告 |
|
||||
| `GET` | `/api/mobile/announcements/:id` | 是 | 登录即可 | 员工端公告详情 |
|
||||
| `POST` | `/api/mobile/announcements/:id/read` | 是 | 登录即可 | 标记公告已读 |
|
||||
| `GET` | `/api/mobile/tasks` | 是 | 登录即可 | 当前员工任务 |
|
||||
| `GET` | `/api/mobile/tasks/:id` | 是 | 登录即可 | 员工端任务详情 |
|
||||
| `POST` | `/api/mobile/tasks/:id/start` | 是 | 登录即可 | 开始处理任务 |
|
||||
| `POST` | `/api/mobile/tasks/:id/complete` | 是 | 登录即可 | 完成任务 |
|
||||
| `POST` | `/api/mobile/tasks/:id/comment` | 是 | 登录即可 | 添加任务备注 |
|
||||
| `GET` | `/api/mobile/shifts` | 是 | 登录即可 | 当前员工排班 |
|
||||
| `GET` | `/api/mobile/shifts/today` | 是 | 登录即可 | 当前员工今日排班 |
|
||||
| `GET` | `/api/admin/announcements` | 是 | `announcement:view` | 后台公告分页 |
|
||||
| `POST` | `/api/admin/announcements` | 是 | `announcement:manage` | 新建公告 |
|
||||
| `PATCH` | `/api/admin/announcements/:id` | 是 | `announcement:manage` | 编辑公告 |
|
||||
| `POST` | `/api/admin/announcements/:id/publish` | 是 | `announcement:manage` | 发布公告 |
|
||||
| `POST` | `/api/admin/announcements/:id/archive` | 是 | `announcement:manage` | 归档公告 |
|
||||
| `GET` | `/api/admin/tasks` | 是 | `task:view` | 后台任务分页 |
|
||||
| `POST` | `/api/admin/tasks` | 是 | `task:manage` | 新建任务 |
|
||||
| `PATCH` | `/api/admin/tasks/:id` | 是 | `task:manage` | 编辑任务 |
|
||||
| `POST` | `/api/admin/tasks/:id/cancel` | 是 | `task:manage` | 取消任务 |
|
||||
| `GET` | `/api/admin/shifts` | 是 | `shift:view` | 后台排班分页 |
|
||||
| `POST` | `/api/admin/shifts` | 是 | `shift:manage` | 新增排班 |
|
||||
| `PATCH` | `/api/admin/shifts/:id` | 是 | `shift:manage` | 编辑排班 |
|
||||
| `DELETE` | `/api/admin/shifts/:id` | 是 | `shift:manage` | 取消排班 |
|
||||
| `POST` | `/api/admin/employees/:id/password/reset` | 是 | `credential:reset` | 重置员工临时密码 |
|
||||
| `GET` | `/api/admin/credential-audits` | 是 | `credential:audit:view` | 凭据审计分页 |
|
||||
|
||||
## 健康检查
|
||||
|
||||
@@ -1194,7 +1230,7 @@ Authorization: Bearer <token>
|
||||
|
||||
### PATCH /api/employees/:id/password/reset
|
||||
|
||||
重置员工密码为初始密码 `pw111111`。需要 `employee:manage`。
|
||||
兼容旧路径。重置员工临时密码。需要 `credential:reset`。
|
||||
|
||||
路径参数:
|
||||
|
||||
@@ -1204,7 +1240,268 @@ Authorization: Bearer <token>
|
||||
|
||||
请求体:不需要请求体。
|
||||
|
||||
响应 `data` 为 `Employee`,不会返回密码或密码哈希。
|
||||
响应 `data.temporaryPassword` 只返回一次,后端只保存哈希,并把员工标记为必须改密。
|
||||
|
||||
## C 端员工接口
|
||||
|
||||
所有 `/api/mobile/*` 接口都只从 Bearer token 推导当前员工,不接受客户端传入 `employeeId` 做越权查询。
|
||||
|
||||
### GET /api/mobile/bootstrap
|
||||
|
||||
员工端首屏聚合,返回当前员工、门店、权限、未读公告数、待办任务数、逾期任务数、最近公告、待办任务和今日排班。
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"user": {
|
||||
"id": 2,
|
||||
"username": "13800000000",
|
||||
"displayName": "张三",
|
||||
"accountType": "EMPLOYEE",
|
||||
"storeId": 1,
|
||||
"storeName": "示例门店",
|
||||
"roles": [{ "id": 1, "code": "cashier", "name": "收银员" }],
|
||||
"permissions": ["task:view"],
|
||||
"mustChangePassword": false
|
||||
},
|
||||
"store": {
|
||||
"id": 1,
|
||||
"name": "示例门店"
|
||||
},
|
||||
"permissions": {
|
||||
"codes": ["task:view"],
|
||||
"menus": []
|
||||
},
|
||||
"counters": {
|
||||
"unreadAnnouncementCount": 2,
|
||||
"pendingTaskCount": 3,
|
||||
"overdueTaskCount": 1
|
||||
},
|
||||
"latestAnnouncements": [
|
||||
{
|
||||
"id": 10,
|
||||
"title": "端午排班通知",
|
||||
"content": "请按新排班表执行。",
|
||||
"level": "IMPORTANT",
|
||||
"status": "PUBLISHED",
|
||||
"targetType": "STORE",
|
||||
"publishedAt": "2026-06-01T02:00:00.000Z",
|
||||
"readAt": null,
|
||||
"createdAt": "2026-06-01T01:00:00.000Z",
|
||||
"updatedAt": "2026-06-01T02:00:00.000Z",
|
||||
"targets": []
|
||||
}
|
||||
],
|
||||
"tasks": [
|
||||
{
|
||||
"id": 20,
|
||||
"storeId": 1,
|
||||
"storeName": "示例门店",
|
||||
"title": "检查库存",
|
||||
"description": "盘点饮料区库存",
|
||||
"status": "PENDING",
|
||||
"priority": "NORMAL",
|
||||
"dueAt": "2026-06-01T10:00:00.000Z",
|
||||
"assignees": [{ "id": 2, "name": "张三", "phone": "13800000000" }],
|
||||
"createdAt": "2026-06-01T01:00:00.000Z",
|
||||
"updatedAt": "2026-06-01T01:00:00.000Z"
|
||||
}
|
||||
],
|
||||
"todayShifts": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
字段说明:
|
||||
|
||||
- `latestAnnouncements` 最多 3 条,按发布时间倒序返回当前员工可见的已发布公告。
|
||||
- `tasks` 最多 5 条,按截止时间优先返回当前员工被分配的 `PENDING`、`IN_PROGRESS` 任务。
|
||||
- `pendingTaskCount` 和 `overdueTaskCount` 当前都只统计已分配给当前员工的未完成任务;暂不把“门店级未指派任务”自动展开给全店员工。
|
||||
- `todayShifts` 保持数组结构,返回当前员工今日 `SCHEDULED` 班次。
|
||||
|
||||
### GET /api/mobile/announcements
|
||||
|
||||
当前员工可见公告分页。支持 `status`、`keyword`、`page`、`pageSize` 查询参数;员工端只返回已发布且命中全员、门店、角色或员工目标的公告。
|
||||
|
||||
### GET /api/mobile/announcements/:id
|
||||
|
||||
当前员工可见公告详情。不可见公告按不存在处理。
|
||||
|
||||
### POST /api/mobile/announcements/:id/read
|
||||
|
||||
标记当前员工已读公告。
|
||||
|
||||
### GET /api/mobile/tasks
|
||||
|
||||
当前员工任务分页。支持 `status`、`keyword`、`page`、`pageSize`。当前版本只返回已分配给当前员工的任务,门店级未指派任务不自动出现在员工端。
|
||||
|
||||
### GET /api/mobile/tasks/:id
|
||||
|
||||
当前员工被分配的任务详情,包含任务事件日志。
|
||||
|
||||
### POST /api/mobile/tasks/:id/start
|
||||
|
||||
开始处理当前员工被分配的待处理任务。
|
||||
|
||||
### POST /api/mobile/tasks/:id/complete
|
||||
|
||||
完成当前员工被分配的待处理或处理中任务。
|
||||
|
||||
### POST /api/mobile/tasks/:id/comment
|
||||
|
||||
为当前员工被分配的任务追加备注。
|
||||
|
||||
请求体:
|
||||
|
||||
```json
|
||||
{
|
||||
"comment": "已完成交接"
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/mobile/shifts
|
||||
|
||||
当前员工排班分页。支持 `status`、`startDate`、`endDate`、`page`、`pageSize`,日期格式为 `YYYY-MM-DD`。
|
||||
|
||||
### GET /api/mobile/shifts/today
|
||||
|
||||
当前员工今日有效排班。
|
||||
|
||||
## 后台工作台接口
|
||||
|
||||
### 公告管理
|
||||
|
||||
- `GET /api/admin/announcements`:公告分页,需要 `announcement:view`。
|
||||
- `POST /api/admin/announcements`:新建公告,需要 `announcement:manage`。
|
||||
- `PATCH /api/admin/announcements/:id`:编辑公告,需要 `announcement:manage`。
|
||||
- `POST /api/admin/announcements/:id/publish`:发布公告,需要 `announcement:manage`。
|
||||
- `POST /api/admin/announcements/:id/archive`:归档公告,需要 `announcement:manage`。
|
||||
|
||||
公告请求体核心字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "端午排班通知",
|
||||
"content": "请按新排班表执行。",
|
||||
"level": "IMPORTANT",
|
||||
"targetType": "STORE",
|
||||
"targets": [{ "type": "STORE", "id": 1 }]
|
||||
}
|
||||
```
|
||||
|
||||
`targetType` 可选 `ALL`、`STORE`、`ROLE`、`EMPLOYEE`。`ALL` 时 `targets` 必须为空,其他范围必须提交同类型目标。
|
||||
|
||||
### 任务管理
|
||||
|
||||
- `GET /api/admin/tasks`:任务分页,需要 `task:view`。
|
||||
- `POST /api/admin/tasks`:新建任务,需要 `task:manage`。
|
||||
- `PATCH /api/admin/tasks/:id`:编辑任务,需要 `task:manage`。
|
||||
- `POST /api/admin/tasks/:id/cancel`:取消任务,需要 `task:manage`。
|
||||
|
||||
任务请求体核心字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"storeId": 1,
|
||||
"title": "检查库存",
|
||||
"description": "盘点饮料区库存",
|
||||
"priority": "NORMAL",
|
||||
"dueAt": "2026-06-01T10:00:00.000Z",
|
||||
"assigneeIds": [2, 3]
|
||||
}
|
||||
```
|
||||
|
||||
### 排班管理
|
||||
|
||||
- `GET /api/admin/shifts`:排班分页,需要 `shift:view`。
|
||||
- `POST /api/admin/shifts`:新增排班,需要 `shift:manage`。
|
||||
- `PATCH /api/admin/shifts/:id`:编辑排班,需要 `shift:manage`。
|
||||
- `DELETE /api/admin/shifts/:id`:取消排班,需要 `shift:manage`。
|
||||
|
||||
排班请求体核心字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"storeId": 1,
|
||||
"employeeId": 2,
|
||||
"roleName": "收银",
|
||||
"startAt": "2026-06-01T01:00:00.000Z",
|
||||
"endAt": "2026-06-01T09:00:00.000Z",
|
||||
"status": "SCHEDULED"
|
||||
}
|
||||
```
|
||||
|
||||
排班冲突规则:
|
||||
|
||||
- `POST /api/admin/shifts` 和 `PATCH /api/admin/shifts/:id` 都会校验同一员工在同一时间段不能存在重叠的未取消班次。
|
||||
- 时间段重叠按 `existing.startAt < new.endAt && existing.endAt > new.startAt` 判断,首尾相接不算冲突。
|
||||
- 编辑排班时会排除当前排班自身;状态为 `CANCELLED` 的班次不参与冲突校验。
|
||||
- 发生冲突时返回 `409 CONFLICT`。
|
||||
|
||||
## 凭据安全接口
|
||||
|
||||
后端不提供任何明文密码查看接口。员工密码只保存哈希。
|
||||
|
||||
### PATCH /api/auth/me/password
|
||||
|
||||
当前员工修改本人密码,需要提交旧密码和新密码。成功后清除 `mustChangePassword` 状态,并写入 `credential_audits` 审计。
|
||||
|
||||
### POST /api/admin/employees/:id/password/reset
|
||||
|
||||
重置权限范围内员工的临时密码,需要 `credential:reset`。响应中的 `temporaryPassword` 只返回一次。
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"employee": {},
|
||||
"temporaryPassword": "Tmp-xxxxxx9",
|
||||
"mustChangePassword": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/admin/credential-audits
|
||||
|
||||
凭据审计分页,需要 `credential:audit:view`。
|
||||
|
||||
查询参数:
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `operatorId` | `number` | 否 | 无 | 操作者 ID,同时匹配 `actorAdminId` 或 `actorEmployeeId` |
|
||||
| `targetEmployeeId` | `number` | 否 | 无 | 被操作员工 ID |
|
||||
| `storeId` | `number` | 否 | 无 | 被操作员工所属门店 ID |
|
||||
| `startDate` | `string` | 否 | 无 | 操作开始日期,格式 `YYYY-MM-DD`,包含当天 |
|
||||
| `endDate` | `string` | 否 | 无 | 操作结束日期,格式 `YYYY-MM-DD`,包含当天 |
|
||||
| `page` | `number` | 否 | `1` | 页码 |
|
||||
| `pageSize` | `number` | 否 | `20` | 每页数量,最大 100 |
|
||||
|
||||
店长等只有当前门店员工数据范围的账号会被强制限定在自己的 `storeId`。`operatorId` 不区分超级管理员和员工操作者,后端会同时匹配 `actorAdminId` 和 `actorEmployeeId`。
|
||||
|
||||
响应 `items` 字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"actorAccountType": "SUPER_ADMIN",
|
||||
"actorAdminId": 1,
|
||||
"actorEmployeeId": null,
|
||||
"actorName": "超级管理员",
|
||||
"targetEmployeeId": 2,
|
||||
"targetEmployeeName": "张三",
|
||||
"targetEmployeePhone": "13800000000",
|
||||
"storeName": "示例门店",
|
||||
"action": "RESET_PASSWORD",
|
||||
"reason": "员工忘记密码",
|
||||
"ip": "127.0.0.1",
|
||||
"userAgent": "Mozilla/5.0",
|
||||
"createdAt": "2026-06-01T08:00:00.000Z"
|
||||
}
|
||||
```
|
||||
|
||||
### DELETE /api/employees/:id
|
||||
|
||||
|
||||
Reference in New Issue
Block a user