编辑 | blame | 历史 | 原始文档

任务接口拆分说明文档

一、修改背景

原有的 /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 后台管理端接口特点

/**
 * 查询任务管理列表(后台管理端)
 * 管理员权限,可以查看所有任务
 */
@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 权限注解
- ✅ 直接使用前端传递的查询条件
- ✅ 管理员可以查看所有任务
- ✅ 支持按部门、创建人、执行人等条件过滤

5.2 APP 端接口特点

/**
 * 查询任务列表(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 中配置白名单)
- ✅ 强制使用当前登录用户信息过滤
- ✅ 自动限制数据范围,保证数据安全
- ✅ 用户只能看到自己相关的任务

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 端调用

// 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 后台管理端调用

// 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 中需要配置权限:

// 需要的权限标识
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 中配置白名单(无需权限验证):

const whiteList = [
  '/task/app/list',
  '/task/app/my',
  '/task/app/overdue',
  '/task/app/statistics',
  // ... 其他APP端接口
]

八、数据安全保障

8.1 APP 端数据隔离

实现方式
1. 后端强制使用当前登录用户的 userIddeptId
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>

8.2 后台管理端权限控制

实现方式
1. 使用 @PreAuthorize 注解进行权限校验
2. 管理员可以自由指定查询条件
3. 支持跨部门、跨用户查询
4. 通过角色权限控制访问范围

九、迁移指南

9.1 现有 APP 端代码无需修改

由于前端 API 文件已经更新,现有的 APP 页面代码无需修改:

// 原有代码保持不变
import { listTask } from '@/api/task'

listTask(query).then(response => {
  // 自动使用新的 /task/app/list 接口
})

9.2 后台管理端代码无需修改

后台管理页面代码也无需修改:

// 原有代码保持不变
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
维护人员: 系统管理员