diff --git a/app/Tasks/LoopTask.php b/app/Tasks/LoopTask.php index 50a751bf2..9c69e1503 100644 --- a/app/Tasks/LoopTask.php +++ b/app/Tasks/LoopTask.php @@ -8,6 +8,7 @@ use App\Module\ProjectTaskHandoffRecord; use App\Models\ProjectFlow; use App\Models\ProjectFlowItem; use App\Models\ProjectTask; +use App\Models\ProjectTaskRelation; use App\Models\ProjectTaskUser; use Carbon\Carbon; @@ -50,18 +51,19 @@ class LoopTask extends AbstractTask /** * 按周期生成新任务并关闭原任务周期 * 复制、刷新周期、关闭旧周期在同一事务内,任一步失败整体回滚,不会留下 loop_at 仍在窗口内的残留副本 + * 提交后再为新旧任务建立关联,关联失败不影响已生成的任务 * @param ProjectTask $item */ private function createLoopTask(ProjectTask $item) { - AbstractModel::transaction(function () use ($item) { + $task = AbstractModel::transaction(function () use ($item) { // 锁定并复核原任务:已被并发或上一轮处理(loop_at 已变化/清空)则跳过 $source = ProjectTask::whereKey($item->id)->lockForUpdate()->first(); if (!$source || $source->parent_id > 0 || !$source->loop_at || Carbon::parse($source->loop_at)->toDateTimeString() !== Carbon::parse($item->loop_at)->toDateTimeString()) { - return; + return null; } $task = $source->copyTask(); ProjectTaskHandoffRecord::track($task, 'recurring', function () use ($task, $source) { @@ -113,7 +115,17 @@ class LoopTask extends AbstractTask $source->loop_at = null; $source->save(); $source->addLog("已创建新的周期任务ID:{$task->id},此任务关闭周期", [], $task->userid); + return $task; }); + if (!$task) { + return; + } + // 新旧任务建立关联 + try { + ProjectTaskRelation::createRelation($item->id, $task->id, null, null, $task->userid); + } catch (\Throwable $e) { + info($e); + } } public function end() diff --git a/resources/ai-kb/zh/howto/task/recurring.md b/resources/ai-kb/zh/howto/task/recurring.md index e53b1f0fa..c2451bf08 100644 --- a/resources/ai-kb/zh/howto/task/recurring.md +++ b/resources/ai-kb/zh/howto/task/recurring.md @@ -23,7 +23,7 @@ negative: - 自定义天数必须是正整数,0 或非数字会被拒绝 - 修改循环周期不会回填已生成的实例 - 所属项目已被删除或已归档时,不再自动生成新的周期任务 -last_verified: v1.9.36 +last_verified: v1.9.59 --- # 重复 / 循环任务 @@ -51,7 +51,8 @@ DooTask 任务支持循环重复(字段 `loop` 重复周期 + `loop_at` 下个 2. 到 `loop_at` 后,系统创建新任务,复制:标题、描述、负责人和协助人员、附件、优先级、可见性、子任务 3. 新任务开始时间等于原任务的 `loop_at`,时长与原任务相同;状态为未完成(项目有工作流则回到起始状态),子任务也重置为未完成 4. 新任务自己算出下一个 `loop_at`;原任务的周期被关闭(`loop` 清空),并记一条日志 -5. 创建失败时整体回滚,不会留下半成品,任务日志记「生成重复任务失败:原因」,到期后 10 分钟内每分钟重试 +5. 新任务与原任务自动建立任务关联,双方任务详情「关联任务」区可互相跳转,任务动态各记一条「关联任务」 +6. 创建失败时整体回滚,不会留下半成品,任务日志记「生成重复任务失败:原因」,到期后 10 分钟内每分钟重试 ## 不支持 - 不能为同一任务并行启用多个周期