feat: 审计修复 Phase 6-7 — SSE 推送/工作流补全/消息群发/前端收尾
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

Phase 6 功能补全:
- P1-3: 消息 SSE 实时推送端点 + 前端 EventSource 连接
- P1-6: ServiceTask HTTP 调用能力 (reqwest GET/POST)
- P1-7: user.deleted 事件处理 — 终止相关流程实例
- P1-8: 任务认领 (claim) 端点 + handler
- P1-9: 超时检查器发布 task.timeout 事件
- P1-15: 组织/部门名称唯一性校验 (create + update)
- P1-18: 消息群发 fan-out (role/department/all 批量投递)

Phase 7 P3-P4 收尾:
- PluginAdmin purge 按钮状态修复
- ChangePassword 最小 8 字符 + 新旧密码不同验证
- AuditLogViewer 用户名缓存 + 扩展资源类型
- InstanceMonitor 通过 definition 缓存解析 node_name
- NotificationPreferences DND 时间范围校验
This commit is contained in:
iven
2026-04-26 19:44:04 +08:00
parent 83fe89cbcd
commit b05b7c27a0
28 changed files with 996 additions and 67 deletions

View File

@@ -376,6 +376,52 @@ impl TaskService {
Ok(id)
}
/// 认领任务:将 pending 状态的任务分配给当前用户。
///
/// 适用于 candidate_groups 群组任务池中的任务,用户主动认领后
/// 任务状态变为 in_progressassignee_id 设置为认领用户。
pub async fn claim(
id: Uuid,
tenant_id: Uuid,
user_id: Uuid,
db: &sea_orm::DatabaseConnection,
) -> WorkflowResult<TaskResp> {
let task_model = task::Entity::find_by_id(id)
.one(db)
.await
.map_err(|e| WorkflowError::Validation(e.to_string()))?
.filter(|t| t.tenant_id == tenant_id && t.deleted_at.is_none())
.ok_or_else(|| WorkflowError::NotFound(format!("任务不存在: {id}")))?;
if task_model.status != "pending" {
return Err(WorkflowError::InvalidState(format!(
"任务状态不是 pending当前状态: {}),无法认领",
task_model.status
)));
}
let current_version = task_model.version;
let mut active: task::ActiveModel = task_model.into();
active.assignee_id = Set(Some(user_id));
active.status = Set("in_progress".to_string());
active.version = Set(current_version + 1);
active.updated_at = Set(Utc::now());
active.updated_by = Set(user_id);
let updated = active
.update(db)
.await
.map_err(|e| WorkflowError::Validation(e.to_string()))?;
audit_service::record(
AuditLog::new(tenant_id, Some(user_id), "task.claim", "task").with_resource_id(id),
db,
)
.await;
Ok(Self::model_to_resp(&updated))
}
fn model_to_resp(m: &task::Model) -> TaskResp {
TaskResp {
id: m.id,