原有的 /task/list 等接口同时被 APP 端和后台管理端使用,导致以下问题:
1. 权限混乱:后台管理员无法查看所有任务,只能看到当前用户相关的任务
2. 业务逻辑冲突:APP 端需要过滤用户数据,后台需要查看全部数据
3. 安全隐患:APP 端和管理端共用接口,权限控制困难
保留原有 APP 端接口,同时新增后台管理端独立接口:
- APP 端接口:保持原有路径 /task/*,无权限注解,自动过滤当前用户数据
- 后台管理端接口:新增路径前缀 /task/admin/*,带权限注解,管理员可查看所有数据
文件路径: ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskController.java
文件路径: app/api/task.js
文件路径: ruoyi-ui/src/api/task.js
| 功能 | 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} |
删除任务 |
| 功能 | 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端使用 |
| 功能 | 后台管理端 | 说明 |
|---|---|---|
| 导出任务 | POST /task/admin/export |
仅后台管理端支持 |
| 导出任务(兼容) | POST /task/export |
兼容旧接口 |
/**
* 查询任务管理列表(后台管理端)
* 管理员权限,可以查看所有任务
*/
@PreAuthorize("@ss.hasPermi('task:task:list')")
@GetMapping("/admin/list")
public TableDataInfo adminList(TaskQueryVO queryVO) {
startPage();
List<SysTask> list = sysTaskService.selectSysTaskList(queryVO);
return getDataTable(list);
}
特点:
- ✅ 带 @PreAuthorize 权限注解
- ✅ 直接使用前端传递的查询条件
- ✅ 管理员可以查看所有任务
- ✅ 支持按部门、创建人、执行人等条件过滤
/**
* 查询任务列表(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<SysTask> list = sysTaskService.selectSysTaskList(queryVO);
return getDataTable(list);
}
特点:
- ✅ 无权限注解(已在 permission.js 中配置白名单)
- ✅ 强制使用当前登录用户信息过滤
- ✅ 自动限制数据范围,保证数据安全
- ✅ 用户只能看到自己相关的任务
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())); }
// 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('状态更新成功')
})
```
// 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('状态更新成功')
})
```
在 ruoyi-ui/src/views/task/general/index.vue 中需要配置权限:
// 需要的权限标识
const permissions = [
'task:task:list', // 查询任务列表
'task:task:query', // 查询任务详情
'task:task:add', // 新增任务
'task:task:edit', // 修改任务
'task:task:remove', // 删除任务
'task:task:export' // 导出任务
]
在 app/permission.js 中配置白名单(无需权限验证):
const whiteList = [
'/task/app/list',
'/task/app/my',
'/task/app/overdue',
'/task/app/statistics',
// ... 其他APP端接口
]
实现方式:
1. 后端强制使用当前登录用户的 userId 和 deptId
2. 前端传递的过滤条件会被后端覆盖
3. SQL 查询时使用 OR 条件组合:
- dept_id = currentDeptId(同机构)
- creator_id = currentUserId(自己创建)
- assignee_id = currentUserId(分配给自己)
SQL 示例:xml <select id="selectSysTaskList" resultMap="SysTaskResult"> SELECT ... FROM sys_task t WHERE 1=1 <if test="deptId != null"> AND ( t.dept_id = #{deptId} OR t.creator_id = #{creatorId} OR t.assignee_id = #{assigneeId} ) </if> <!-- 其他条件 --> </select>
实现方式:
1. 使用 @PreAuthorize 注解进行权限校验
2. 管理员可以自由指定查询条件
3. 支持跨部门、跨用户查询
4. 通过角色权限控制访问范围
由于前端 API 文件已经更新,现有的 APP 页面代码无需修改:
// 原有代码保持不变
import { listTask } from '@/api/task'
listTask(query).then(response => {
// 自动使用新的 /task/app/list 接口
})
后台管理页面代码也无需修改:
// 原有代码保持不变
import { listTask } from '@/api/task'
listTask(query).then(response => {
// 自动使用新的 /task/admin/list 接口
})
APP 端测试:
1. 登录 APP,查看任务列表
2. 确认只能看到自己相关的任务
3. 尝试更新任务状态,验证 GPS 位置上报
后台管理端测试:
1. 登录后台管理系统
2. 以管理员身份查看任务列表
3. 确认可以看到所有任务
4. 验证权限控制是否生效
/task/list 等旧接口路径/task/app/ 或 /task/admin/ 前缀答:不能。APP 端接口强制使用当前登录用户的部门ID进行过滤,即使前端传递其他部门ID,也会被后端覆盖。
答:使用后台管理端接口 /task/admin/list,不传递任何过滤条件即可查看所有任务。需要确保用户拥有 task:task:list 权限。
答:通过接口路径前缀区分:
- APP 端:/task/app/*
- 后台管理端:/task/admin/*
答:不受影响。旧系统同步等功能使用的是独立的接口,与任务管理接口无关。
答:遵循以下规则:
1. APP 端接口:路径使用 /task/app/*,无权限注解,强制过滤当前用户
2. 后台管理端接口:路径使用 /task/admin/*,添加权限注解,支持全局查询
通过本次接口拆分,实现了:
文档版本: v1.0
创建日期: 2025-01-XX
最后更新: 2025-01-XX
维护人员: 系统管理员