From 452af4bd2f148743c83b027733ee1292ce79c44e Mon Sep 17 00:00:00 2001 From: kuaifan Date: Wed, 21 Jan 2026 03:12:52 +0000 Subject: [PATCH] fix(ai): address issues from second code review - Add STATUS_APPLIED and STATUS_DISMISSED constants to model - Add markApplied() and markDismissed() methods - Update event status after apply/dismiss actions (prevent duplicate ops) - Validate related_task_id exists and user has permission - Filter empty or overly long subtask names before creation Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Co-Authored-By: Happy --- .../Controllers/Api/ProjectController.php | 19 ++++++++++++++++ app/Models/ProjectTaskAiEvent.php | 22 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/app/Http/Controllers/Api/ProjectController.php b/app/Http/Controllers/Api/ProjectController.php index 2e8dc9445..1d7e11b41 100755 --- a/app/Http/Controllers/Api/ProjectController.php +++ b/app/Http/Controllers/Api/ProjectController.php @@ -3889,6 +3889,14 @@ class ProjectController extends AbstractController case ProjectTaskAiEvent::EVENT_SUBTASKS: // 创建子任务 $subtasks = $result['content'] ?? []; + // 过滤无效的子任务名称 + $subtasks = array_filter(array_map(function ($name) { + $name = trim((string)$name); + return (empty($name) || mb_strlen($name) > 100) ? null : $name; + }, $subtasks)); + if (empty($subtasks)) { + return Base::retError('没有有效的子任务名称'); + } // 检查子任务数量限制 $existingCount = ProjectTask::where('parent_id', $task->id) ->whereNull('deleted_at') @@ -3930,6 +3938,11 @@ class ProjectController extends AbstractController if ($relatedTaskId <= 0) { return Base::retError('请选择关联任务'); } + // 验证关联任务存在且有权限 + $relatedTask = ProjectTask::userTask($relatedTaskId); + if (!$relatedTask) { + return Base::retError('关联任务不存在或无权限'); + } ProjectTaskRelation::firstOrCreate([ 'task_id' => $task->id, 'related_task_id' => $relatedTaskId, @@ -3944,6 +3957,9 @@ class ProjectController extends AbstractController return Base::retError('未知的建议类型'); } + // 标记事件为已采纳 + $event->markApplied(); + // 更新消息状态 if ($msgId > 0 && $task->dialog_id) { AiTaskSuggestion::updateMessageStatus($msgId, $task->dialog_id, $type, 'applied'); @@ -3996,6 +4012,9 @@ class ProjectController extends AbstractController return Base::retError('建议不存在或已处理'); } + // 标记事件为已忽略 + $event->markDismissed(); + // 更新消息状态 if ($msgId > 0 && $task->dialog_id) { AiTaskSuggestion::updateMessageStatus($msgId, $task->dialog_id, $type, 'dismissed'); diff --git a/app/Models/ProjectTaskAiEvent.php b/app/Models/ProjectTaskAiEvent.php index 4c1deb80e..cc646fd77 100644 --- a/app/Models/ProjectTaskAiEvent.php +++ b/app/Models/ProjectTaskAiEvent.php @@ -31,6 +31,8 @@ class ProjectTaskAiEvent extends AbstractModel const STATUS_COMPLETED = 'completed'; const STATUS_FAILED = 'failed'; const STATUS_SKIPPED = 'skipped'; + const STATUS_APPLIED = 'applied'; + const STATUS_DISMISSED = 'dismissed'; const MAX_RETRY = 3; @@ -129,4 +131,24 @@ class ProjectTaskAiEvent extends AbstractModel return $this->status === self::STATUS_FAILED && $this->retry_count < self::MAX_RETRY; } + + /** + * 标记为已采纳 + */ + public function markApplied(): bool + { + return $this->update([ + 'status' => self::STATUS_APPLIED, + ]); + } + + /** + * 标记为已忽略 + */ + public function markDismissed(): bool + { + return $this->update([ + 'status' => self::STATUS_DISMISSED, + ]); + } }