12 KiB
待办事项中心 PRD
1. 文档信息
| 项目 | 内容 |
|---|---|
| 产品名称 | 运营商工作台待办事项中心 |
| 文档类型 | 产品需求文档(PRD) |
| 版本 | V1.0 |
| 状态 | 待评审 |
| 适用端 | RuoYi-Vue 管理后台、运营商工作台 |
2. 背景与目标
当前项目已有 RuoYi 的通知公告功能,支持管理员维护全平台公告,但不支持按用户生成业务任务、展示未处理数量和跳转处理业务。
截图中的“待办事项”属于业务任务中心:任务面向具体用户,用户需要进入业务页面完成处理,处理后任务应自动完成或由用户确认完成。
本需求目标:
- 在运营商工作台首页增加待办事项卡片。
- 展示当前登录用户未处理的待办数量。
- 支持点击待办跳转到对应业务详情或处理页面。
- 支持待办状态、优先级、已读状态和完成状态管理。
- 建立统一待办能力,后续可接入开票、提现、汇付开户、清分异常等业务。
3. 产品定位
待办事项与通知公告、站内信的关系如下:
消息中心
├── 待办事项:需要用户处理的业务任务
├── 业务通知:业务结果或状态变化提醒
├── 系统公告:面向全体用户的运营公告
└── 系统消息:登录、安全、权限等系统提醒
本期只建设“待办事项”,不替换现有 sys_notice 通知公告模块。
4. 用户与权限
4.1 用户角色
| 用户 | 权限 |
|---|---|
| 运营商负责人 | 查看和处理本人或本运营商范围内的待办 |
| 运营商财务人员 | 查看和处理财务类待办 |
| 平台运营人员 | 创建、分配、转派和关闭待办,可查看全量待办 |
| 系统管理员 | 管理待办类型、权限和异常任务 |
4.2 数据权限
默认只返回当前登录用户的待办。平台管理员是否可以查看全量待办,由现有 RuoYi 权限和数据权限控制,不允许通过修改请求参数绕过接收人过滤。
5. 首期业务范围
5.1 开票待办
首期优先实现截图中的开票场景:
| 待办类型 | 触发条件 | 处理页面 | 完成条件 |
|---|---|---|---|
| 平台采购开票 | 平台审核拒绝或要求补充材料 | 发票详情/开票申请页 | 用户重新提交或平台关闭任务 |
| 司机开票申请 | 收到司机开票申请 | 发票申请处理页 | 审核通过、驳回或关闭 |
5.2 预留业务类型
| 待办类型 | 触发条件 |
|---|---|
| 汇付企业开户审核 | 企业开户失败或需要补充资料 |
| 结算账户异常 | 结算账户创建失败、删除失败或状态不一致 |
| 提现处理 | 提现失败、人工审核或补充资料 |
| 清分异常 | 清分失败、分账配置错误或账单待处理 |
| 订单异常 | 订单退款、结算或支付异常需要人工介入 |
首期只实现开票待办,其他类型只完成通用模型和扩展接口,不要求全部接入。
6. 业务流程
6.1 创建流程
业务事件发生
↓
判断是否需要人工处理
↓
确定接收人和业务权限
↓
按幂等键创建待办
↓
首页待办数量增加
↓
用户点击待办
↓
进入业务处理页面并标记已读
↓
业务处理成功后自动完成待办
6.2 状态定义
待办状态和阅读状态分开保存:
| 字段 | 值 | 含义 |
|---|---|---|
task_status |
PENDING |
待处理 |
task_status |
PROCESSING |
处理中 |
task_status |
COMPLETED |
已完成 |
task_status |
CANCELLED |
已取消 |
task_status |
EXPIRED |
已过期 |
read_status |
0 |
未读 |
read_status |
1 |
已读 |
已读只表示用户看过,不能代表业务已经处理完成。只有业务动作完成、平台关闭或管理员取消时,待办才进入完成或取消状态。
6.3 幂等规则
同一业务任务不能重复生成待办。建议使用以下幂等键:
task_type + business_type + business_id + assignee_user_id
例如同一个发票申请给同一个用户只能有一条有效待办。任务完成或取消后,允许业务重新产生新的任务,但必须保留历史记录。
7. 首页交互设计
7.1 待办卡片
位置:运营商工作台首页右侧,与截图中的“待办事项”位置一致。
展示规则:
- 标题:
待办事项。 - 标题右侧显示未完成数量,最多显示
99+。 - 默认展示最近 3 条未完成待办。
- 按优先级倒序、创建时间倒序排列。
- 每条显示:类型、标题、简要内容、时间和箭头。
- 无待办时显示“暂无待办事项”。
- 点击“查看全部”进入待办中心。
- 点击单条任务进入业务处理页面。
7.2 待办中心
页面建议:src/views/system/todo/index.vue。
功能:
- 全部、待处理、已完成、已取消筛选。
- 全部、未读筛选。
- 按待办类型筛选。
- 关键字搜索标题和业务单号。
- 分页查询。
- 点击进入业务详情。
- 支持批量标记已读。
- 支持隐藏已完成待办,不直接物理删除历史任务。
7.3 详情处理
待办本身不重复实现业务处理表单。点击待办后跳转已有业务页面,并携带:
businessType
businessId
todoId
业务页面处理成功后调用待办完成接口,或由后端业务事务自动完成待办。
8. 数据库设计
建议新增主表 sys_todo_task:
| 字段 | 类型 | 说明 |
|---|---|---|
todo_id |
bigint | 主键 |
task_type |
varchar(64) | 待办类型编码 |
title |
varchar(200) | 待办标题 |
summary |
varchar(500) | 摘要 |
content |
text | 详细内容 |
business_type |
varchar(64) | 业务类型 |
business_id |
varchar(64) | 业务主键或单号 |
route_name |
varchar(100) | 前端路由名称 |
route_params |
varchar(1000) | 路由参数 JSON |
assignee_user_id |
bigint | 接收用户 ID |
assignee_merchant_id |
varchar(64) | 运营商 ID,可为空 |
priority |
tinyint | 优先级:1普通、2重要、3紧急 |
task_status |
varchar(20) | 任务状态 |
read_status |
char(1) | 0未读、1已读 |
read_time |
datetime | 阅读时间 |
due_time |
datetime | 截止时间,可为空 |
completed_time |
datetime | 完成时间 |
completed_by |
bigint | 完成人 |
cancel_reason |
varchar(500) | 取消原因 |
idempotent_key |
varchar(200) | 幂等键 |
create_time |
datetime | 创建时间 |
update_time |
datetime | 更新时间 |
del_flag |
char(1) | 逻辑删除 |
建议索引:
unique key uk_todo_idempotent (idempotent_key)
key idx_todo_user_status (assignee_user_id, task_status, read_status, create_time)
key idx_todo_merchant_status (assignee_merchant_id, task_status, create_time)
key idx_todo_business (business_type, business_id)
如果后续需要同一任务分配给多个用户,建议拆分为:
sys_todo_task:任务主体。sys_todo_recipient:接收人和每个接收人的阅读状态、处理状态。
V1 只有单接收人时可以先使用单表,避免过早复杂化;但字段和 Service 设计应预留多接收人扩展。
9. 后端接口设计
9.1 用户端接口
GET /system/todo/unreadCount
GET /system/todo/homeList?limit=3
GET /system/todo/list
GET /system/todo/{todoId}
PUT /system/todo/{todoId}/read
PUT /system/todo/readAll
PUT /system/todo/{todoId}/complete
PUT /system/todo/{todoId}/cancel
接口规则:
- 所有查询自动使用当前登录用户 ID,不接收任意
userId作为唯一权限依据。 read只能修改当前用户的阅读状态。complete必须校验当前用户有对应业务处理权限。complete和具体业务更新建议放在同一事务中,避免业务完成但待办仍为待处理。- 已完成任务默认仍可查询,但不计入未读数量和首页待办数量。
9.2 管理端接口
GET /system/todo/admin/list
POST /system/todo/admin/create
PUT /system/todo/admin/{todoId}/assign
PUT /system/todo/admin/{todoId}/cancel
DELETE /system/todo/admin/{todoId}
管理端用于异常任务处理和人工补发,普通业务待办优先由业务事件自动生成。
10. 待办服务设计
新增统一服务接口:
TodoTaskService.createTask(TodoTaskCreateCommand command);
TodoTaskService.markRead(Long todoId, Long userId);
TodoTaskService.complete(Long todoId, Long userId);
TodoTaskService.cancel(Long todoId, Long operatorId, String reason);
TodoTaskService.countUnread(Long userId);
业务模块只依赖 TodoTaskService,不直接操作待办表。
例如开票业务:
todoTaskService.createTask(TodoTaskCreateCommand.builder()
.taskType("INVOICE_REVIEW")
.title("司机开票申请")
.summary("有新的开票申请需要处理")
.businessType("INVOICE_APPLY")
.businessId(invoiceId.toString())
.assigneeUserId(operatorUserId)
.routeName("InvoiceApplyDetail")
.idempotentKey("INVOICE_REVIEW:" + invoiceId + ":" + operatorUserId)
.build());
11. 通知刷新策略
V1 推荐:轮询
- 登录后加载未读数量。
- 首页每 30~60 秒刷新一次数量和最近待办。
- 打开待办中心时立即刷新。
- 处理完成后主动刷新当前列表和数量。
轮询实现简单,不需要改造现有 Netty、RabbitMQ 或新增 WebSocket 基础设施,适合本项目首期落地。
V2 可选:实时推送
当待办实时性要求提高时,再增加 WebSocket 或 SSE。实时推送只负责通知前端刷新,不直接承载任务数据;前端收到事件后仍通过接口重新查询。
12. 非功能要求
- 接口必须使用当前登录用户做数据权限过滤。
- 内容字段需要进行 XSS 处理,详情页禁止直接渲染未经处理的 HTML。
- 所有状态变更记录操作人、操作时间和操作原因。
- 待办创建必须幂等,避免重复点击或重复回调产生重复任务。
- 首页查询应使用索引,目标响应时间不超过 500ms。
- 默认保留已完成任务至少 180 天,定时任务归档或清理历史数据。
- 待办跳转路由必须使用服务端生成或白名单校验,禁止直接执行前端传入的任意路由。
13. 验收标准
首页
- 用户登录后可以看到待办事项卡片。
- 未完成数量准确,数量为 0 时不显示红色数字或显示 0。
- 默认最多展示 3 条待办。
- 点击“查看全部”可以进入待办中心。
- 点击单条待办可以跳转对应业务页面。
状态
- 首次进入列表时未读待办显示未读样式。
- 点击待办后变为已读,但仍保持待处理状态。
- 业务处理成功后变为已完成,不再计入首页数量。
- 取消或过期任务不再计入待办数量。
- 重复触发同一业务事件不会产生重复有效待办。
权限
- 用户无法查询其他用户的待办。
- 无业务处理权限的用户不能完成待办。
- 管理员可以按权限查看和关闭异常待办。
首期业务
- 平台采购开票待办可以正常生成、展示、跳转和完成。
- 司机开票申请待办可以正常生成、展示、跳转和完成。
- 原有
sys_notice公告功能不受影响。
14. 实施拆分
第一期:基础能力
- 建表和索引。
- 实体、Mapper、Service、Controller。
- 未读数、首页列表、分页列表、已读和完成接口。
- 首页待办卡片和待办中心页面。
第二期:开票接入
- 接入平台采购开票事件。
- 接入司机开票申请事件。
- 配置业务路由和完成条件。
- 增加接口和页面联调测试。
第三期:平台业务扩展
- 接入汇付开户、结算账户和提现异常。
- 接入清分异常和订单异常。
- 评估 WebSocket/SSE 实时推送。
15. 与现有 RuoYi 模块的关系
sys_notice继续作为全平台通知公告管理。- 新增
sys_todo_task作为用户待办任务管理。 - 沿用 RuoYi 的
SysUser、权限注解、数据权限和分页组件。 - 沿用现有
BaseController、AjaxResult、TableDataInfo和前端request封装。 - 不建议把待办字段直接塞入
sys_notice,避免公告和业务任务互相污染。