Yii框架适合构建工单系统,通过状态机(如yii2-workflow)、RBAC+自定义Rule权限控制、事件驱动自动化、结构化审计日志及状态常量规范化实现高可维护性。

工单系统的核心是业务流转逻辑,Yii 框架凭借其组件化、行为(Behavior)、状态机(通过扩展或自定义)和事件驱动能力,非常适合构建可维护、可扩展的工单生命周期管理。关键不在于“能不能做”,而在于如何把状态变更、权限控制、操作日志、自动触发等要素组织得清晰可靠。
用状态机模型管理工单生命周期
避免用一堆 if-else 判断状态跳转,推荐引入 yii2-workflow 或轻量自定义状态机。每个工单绑定一个 workflow,预定义状态(如 draft → submitted → assigned → processing → resolved → closed)及合法转移规则(transition)。
- 在工单模型(Ticket)中集成 WorkflowBehavior,声明当前状态字段(如 status)
- 转移动作封装为方法(如
$ticket->submit()、$ticket->assignTo($user)),内部调用$workflow->apply('submit') - 转移前自动校验权限、必填字段、前置条件(例如:只有创建者能 submit,只有管理员能 close)
- 状态变更时触发
WorkflowEvent::EVENT_AFTER_APPLY,统一记录日志、发通知、更新关联数据
基于 RBAC + 规则(Rule)实现动态操作权限
不同角色(客服、工程师、主管、客户)在不同状态下可执行的操作差异大。Yii 的 RBAC 需配合自定义 Rule 才能精准控制。
- 定义权限项如
updateOwnTicket、reassignTicket、forceCloseTicket - 编写
TicketOwnershipRule:判断当前用户是否为工单创建者或指派人;TicketStatusRule:检查当前状态是否允许某操作 - 在控制器 action 中使用
$this->checkAccess('reassignTicket', ['ticket' => $ticket]),规则自动传入 ticket 实例做上下文判断 - 前端按钮显隐也应复用同一权限检查结果(可通过 View 层注入或 API 返回操作白名单)
事件驱动串联自动化动作
工单流转常伴随自动行为:指派后发站内信、超时未处理触发升级、解决后自动归档附件。Yii 的事件机制天然适合解耦这些逻辑。
- 在 Ticket 模型中定义事件名,如
Ticket::EVENT_STATUS_ASSIGNED、Ticket::EVENT_STATUS_RESOLVED - 注册监听器(可放在模块 init() 或单独 EventSubscriber 类):发送邮件、调用第三方 IM 接口、写入审计表、触发定时任务(如延迟检查超时)
- 关键动作(如状态变更、评论提交)统一走
save()并在 beforeSave/afterSave 中触发事件,确保事务一致性 - 异步任务建议用 Yii 的
yii\queue(如 DB/Redis 驱动)包裹耗时操作,避免阻塞主流程
历史追溯与操作留痕设计
工单审计不是附加功能,而是业务刚需。需结构化记录“谁、何时、对哪个工单、做了什么、前后值是什么”。
- 建表
ticket_history:含 ticket_id、user_id、event_type('status_change'/'assign'/'comment_add')、data(JSON,存旧值/新值/备注) - 所有核心变更(包括状态机转移、指派、加评论)都调用统一方法
TicketHistory::log($ticket, $type, $data) - 利用 ActiveRecord 的
oldAttributes自动捕获字段变更,比如 status 从 'processing' → 'resolved',data 字段可存{"old":"processing","new":"resolved"} - 提供后台「操作时间线」视图,按时间倒序展示完整轨迹,支持导出 PDF/Excel
不复杂但容易忽略:状态码用英文常量(如 Ticket::STATUS_PROCESSING),数据库字段用 tinyint 存储,配合 getStatusLabel() 方法映射中文显示;所有对外接口(API/导出)返回的状态值统一走该方法,避免硬编码散落各处。


















