# 任务接口拆分说明文档 ## 一、修改背景 原有的 `/task/list` 等接口同时被 APP 端和后台管理端使用,导致以下问题: 1. **权限混乱**:后台管理员无法查看所有任务,只能看到当前用户相关的任务 2. **业务逻辑冲突**:APP 端需要过滤用户数据,后台需要查看全部数据 3. **安全隐患**:APP 端和管理端共用接口,权限控制困难 ## 二、解决方案 **保留原有 APP 端接口**,同时新增后台管理端独立接口: - **APP 端接口**:保持原有路径 `/task/*`,无权限注解,自动过滤当前用户数据 - **后台管理端接口**:新增路径前缀 `/task/admin/*`,带权限注解,管理员可查看所有数据 ## 三、涉及文件 ### 1. 后端 Controller **文件路径**: `ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.java` ### 2. APP 端 API **文件路径**: `app/api/task.js` ### 3. 后台管理端 API **文件路径**: `ruoyi-ui/src/api/task.js` ## 四、接口对照表 ### 4.1 任务列表接口 | 功能 | APP 端 | 后台管理端 | 说明 | |------|--------|-----------|------| | 查询任务列表 | `GET /task/list` | `GET /task/admin/list` | APP端过滤当前用户,后台可查看全部 | | 查询任务详情 | `GET /task/{taskId}` | `GET /task/admin/{taskId}` | 获取单个任务详情 | | 新增任务 | `POST /task` | `POST /task/admin` | 创建新任务 | | 修改任务 | `PUT /task` | `PUT /task/admin` | 更新任务信息 | | 删除任务 | `DELETE /task/{taskIds}` | `DELETE /task/admin/{taskIds}` | 删除任务 | ### 4.2 任务操作接口 | 功能 | APP 端 | 后台管理端 | 说明 | |------|--------|-----------|------| | 分配任务 | `PUT /task/{taskId}/assign` | `PUT /task/admin/{taskId}/assign` | 分配执行人 | | 更新状态 | `PUT /task/{taskId}/status` | `PUT /task/admin/{taskId}/status` | APP端支持GPS位置 | | 任务统计 | `GET /task/statistics` | `GET /task/admin/statistics` | 统计信息 | | 超时任务 | `GET /task/overdue` | `GET /task/admin/overdue` | 超时任务列表 | | 我的任务 | `GET /task/my` | - | 仅APP端使用 | ### 4.3 导出接口 | 功能 | 后台管理端 | 说明 | |------|-----------|------| | 导出任务 | `POST /task/admin/export` | 仅后台管理端支持 | | 导出任务(兼容) | `POST /task/export` | 兼容旧接口 | ## 五、核心差异说明 ### 5.1 后台管理端接口特点 ```java /** * 查询任务管理列表(后台管理端) * 管理员权限,可以查看所有任务 */ @PreAuthorize("@ss.hasPermi('task:task:list')") @GetMapping("/admin/list") public TableDataInfo adminList(TaskQueryVO queryVO) { startPage(); List list = sysTaskService.selectSysTaskList(queryVO); return getDataTable(list); } ``` **特点**: - ✅ 带 `@PreAuthorize` 权限注解 - ✅ 直接使用前端传递的查询条件 - ✅ 管理员可以查看所有任务 - ✅ 支持按部门、创建人、执行人等条件过滤 ### 5.2 APP 端接口特点 ```java /** * 查询任务列表(APP端) * 仅显示当前用户相关的任务: * 1. 当前用户所在机构的任务 * 2. 当前用户创建的任务 * 3. 分配给当前用户的任务 */ @GetMapping("/app/list") public TableDataInfo appList(TaskQueryVO queryVO) { // 在后端自动获取当前用户信息,实现综合查询 Long currentUserId = getUserId(); Long currentDeptId = getDeptId(); // APP端强制使用当前登录用户信息进行过滤 queryVO.setDeptId(currentDeptId); queryVO.setCreatorId(currentUserId); queryVO.setAssigneeId(currentUserId); startPage(); List list = sysTaskService.selectSysTaskList(queryVO); return getDataTable(list); } ``` **特点**: - ✅ 无权限注解(已在 `permission.js` 中配置白名单) - ✅ 强制使用当前登录用户信息过滤 - ✅ 自动限制数据范围,保证数据安全 - ✅ 用户只能看到自己相关的任务 ### 5.3 状态更新接口差异 **APP 端**:支持 GPS 位置信息上报 ```java @PutMapping("/app/{taskId}/status") public AjaxResult appChangeTaskStatus(@PathVariable Long taskId, @RequestBody ChangeStatusRequest request) { // ... 省略状态校验 // 如果包含GPS位置信息,使用带位置的方法 if (request.getLatitude() != null && request.getLongitude() != null) { SysTaskLog locationLog = new SysTaskLog(); locationLog.setLatitude(request.getLatitude()); locationLog.setLongitude(request.getLongitude()); // ... 设置其他位置信息 return toAjax(sysTaskService.changeTaskStatusWithLocation(taskId, newStatus, request.getRemark(), locationLog)); } return toAjax(sysTaskService.changeTaskStatus(taskId, newStatus, request.getRemark())); } ``` **后台管理端**:仅支持基本状态变更 ```java @PreAuthorize("@ss.hasPermi('task:task:edit')") @PutMapping("/admin/{taskId}/status") public AjaxResult adminChangeTaskStatus(@PathVariable Long taskId, @RequestBody ChangeStatusRequest request) { TaskStatus newStatus = TaskStatus.getByCode(request.getTaskStatus()); if (newStatus == null) { return error("无效的任务状态"); } return toAjax(sysTaskService.changeTaskStatus(taskId, newStatus, request.getRemark())); } ``` ## 六、前端调用示例 ### 6.1 APP 端调用 ```javascript // app/api/task.js import request from '@/utils/request' // 查询任务列表(APP端) export function listTask(query) { return request({ url: '/task/app/list', method: 'get', params: query }) } // 更新任务状态(APP端,支持GPS) export function changeTaskStatus(taskId, data) { return request({ url: '/task/app/' + taskId + '/status', method: 'put', data: data // 可包含 latitude, longitude 等GPS信息 }) } ``` **使用示例**: ```javascript // 在 APP 页面中调用 import { listTask, changeTaskStatus } from '@/api/task' // 查询任务列表 listTask({ taskStatus: 'PENDING' }).then(response => { // 自动只返回当前用户相关的任务 this.taskList = response.rows }) // 更新任务状态并上报GPS位置 changeTaskStatus(taskId, { taskStatus: 'IN_PROGRESS', remark: '已到达现场', latitude: 23.1291, longitude: 113.2644, locationAddress: '广州市天河区' }).then(response => { this.$modal.msgSuccess('状态更新成功') }) ``` ### 6.2 后台管理端调用 ```javascript // ruoyi-ui/src/api/task.js import request from '@/utils/request' // 查询任务列表(后台管理端) export function listTask(query) { return request({ url: '/task/admin/list', method: 'get', params: query }) } // 更新任务状态(后台管理端) export function changeTaskStatus(taskId, data) { return request({ url: '/task/admin/' + taskId + '/status', method: 'put', data: data }) } ``` **使用示例**: ```javascript // 在后台管理页面中调用 import { listTask, changeTaskStatus } from '@/api/task' // 查询任务列表(管理员可查看所有任务) listTask({ deptId: 101, // 可指定部门 taskStatus: 'PENDING' }).then(response => { // 返回所有符合条件的任务 this.taskList = response.rows }) // 更新任务状态 changeTaskStatus(taskId, { taskStatus: 'COMPLETED', remark: '任务已完成' }).then(response => { this.$modal.msgSuccess('状态更新成功') }) ``` ## 七、权限配置 ### 7.1 后台管理端权限 在 `ruoyi-ui/src/views/task/general/index.vue` 中需要配置权限: ```javascript // 需要的权限标识 const permissions = [ 'task:task:list', // 查询任务列表 'task:task:query', // 查询任务详情 'task:task:add', // 新增任务 'task:task:edit', // 修改任务 'task:task:remove', // 删除任务 'task:task:export' // 导出任务 ] ``` ### 7.2 APP 端权限配置 在 `app/permission.js` 中配置白名单(无需权限验证): ```javascript const whiteList = [ '/task/app/list', '/task/app/my', '/task/app/overdue', '/task/app/statistics', // ... 其他APP端接口 ] ``` ## 八、数据安全保障 ### 8.1 APP 端数据隔离 **实现方式**: 1. 后端强制使用当前登录用户的 `userId` 和 `deptId` 2. 前端传递的过滤条件会被后端覆盖 3. SQL 查询时使用 OR 条件组合: - `dept_id = currentDeptId`(同机构) - `creator_id = currentUserId`(自己创建) - `assignee_id = currentUserId`(分配给自己) **SQL 示例**: ```xml ``` ### 8.2 后台管理端权限控制 **实现方式**: 1. 使用 `@PreAuthorize` 注解进行权限校验 2. 管理员可以自由指定查询条件 3. 支持跨部门、跨用户查询 4. 通过角色权限控制访问范围 ## 九、迁移指南 ### 9.1 现有 APP 端代码无需修改 由于前端 API 文件已经更新,现有的 APP 页面代码无需修改: ```javascript // 原有代码保持不变 import { listTask } from '@/api/task' listTask(query).then(response => { // 自动使用新的 /task/app/list 接口 }) ``` ### 9.2 后台管理端代码无需修改 后台管理页面代码也无需修改: ```javascript // 原有代码保持不变 import { listTask } from '@/api/task' listTask(query).then(response => { // 自动使用新的 /task/admin/list 接口 }) ``` ### 9.3 测试验证 **APP 端测试**: 1. 登录 APP,查看任务列表 2. 确认只能看到自己相关的任务 3. 尝试更新任务状态,验证 GPS 位置上报 **后台管理端测试**: 1. 登录后台管理系统 2. 以管理员身份查看任务列表 3. 确认可以看到所有任务 4. 验证权限控制是否生效 ## 十、注意事项 ### 10.1 接口兼容性 - ❌ **不再支持** `/task/list` 等旧接口路径 - ✅ 必须使用 `/task/app/` 或 `/task/admin/` 前缀 - ✅ 前端 API 文件已更新,无需手动修改页面代码 ### 10.2 权限配置 - ✅ APP 端接口已配置白名单,无需权限验证 - ✅ 后台管理端接口需要对应的权限标识 - ⚠️ 确保角色分配了正确的权限 ### 10.3 数据过滤 - ✅ APP 端强制过滤当前用户数据,前端无法绕过 - ✅ 后台管理端根据权限查看对应范围的数据 - ⚠️ 不要在 APP 端使用后台管理端接口 ### 10.4 GPS 位置信息 - ✅ 仅 APP 端状态更新接口支持 GPS 位置上报 - ✅ 后台管理端状态更新不需要位置信息 - ⚠️ GPS 字段为可选,无位置时不影响状态更新 ## 十一、常见问题 ### Q1: APP 端能否查看其他部门的任务? **答**:不能。APP 端接口强制使用当前登录用户的部门ID进行过滤,即使前端传递其他部门ID,也会被后端覆盖。 ### Q2: 后台管理员如何查看所有任务? **答**:使用后台管理端接口 `/task/admin/list`,不传递任何过滤条件即可查看所有任务。需要确保用户拥有 `task:task:list` 权限。 ### Q3: 如何区分 APP 端和后台管理端的调用? **答**:通过接口路径前缀区分: - APP 端:`/task/app/*` - 后台管理端:`/task/admin/*` ### Q4: 旧系统的接口调用是否受影响? **答**:不受影响。旧系统同步等功能使用的是独立的接口,与任务管理接口无关。 ### Q5: 如何添加新的任务相关接口? **答**:遵循以下规则: 1. APP 端接口:路径使用 `/task/app/*`,无权限注解,强制过滤当前用户 2. 后台管理端接口:路径使用 `/task/admin/*`,添加权限注解,支持全局查询 ## 十二、总结 通过本次接口拆分,实现了: 1. ✅ **业务分离**:APP 端和后台管理端使用独立接口 2. ✅ **权限清晰**:后台管理端统一使用权限注解 3. ✅ **数据安全**:APP 端强制过滤当前用户数据 4. ✅ **功能扩展**:APP 端支持 GPS 位置上报 5. ✅ **代码维护**:接口职责单一,易于维护 6. ✅ **向下兼容**:前端代码无需修改,自动使用新接口 --- **文档版本**: v1.0 **创建日期**: 2025-01-XX **最后更新**: 2025-01-XX **维护人员**: 系统管理员