Kaynağa Gözat

1.批量创建剧集调整入参并新增重复校验报错2.剧本大纲返回批量剧集任务

lh 1 ay önce
ebeveyn
işleme
7df4c6ce0a

+ 25 - 0
app/Services/Anime/AnimeService.php

@@ -570,6 +570,31 @@ class AnimeService
 
         $anime['episodes'] = $episodes;
 
+        // 获取当前仍在批量生成中的剧集任务(只展示 episodes 中尚未出现的剧集序号)
+        $episodeNumbers = array_map('intval', array_column($episodes, 'episode_number'));
+        $episodeTasks = DB::table('mp_batch_episode_generation_details')
+            ->where('anime_id', $anime_id)
+            ->orderBy('episode_number')
+            ->get()
+            ->map(function ($task) use ($episodeNumbers) {
+                if (in_array((int)$task->episode_number, $episodeNumbers, true)) {
+                    return null;
+                }
+
+                $item = [
+                    'episode_number' => (int)$task->episode_number,
+                    'status'         => $task->status,
+                    'error_message'  => $task->status === 'failed' ? ($task->error_message ?? '') : '',
+                ];
+
+                return $item;
+            })
+            ->filter()
+            ->values()
+            ->toArray();
+
+        $anime['episode_tasks'] = $episodeTasks;
+
         return $anime;
     }
 

+ 76 - 17
app/Services/DeepSeek/DeepSeekService.php

@@ -11061,6 +11061,8 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         $cpid = Site::getCpid();
         $anime_id = getProp($data, 'anime_id');
         $generate_episode_number = (int)getProp($data, 'generate_episode_number', 1);
+        $start_episode_number = getProp($data, 'start_episode_number');
+        $end_episode_number = getProp($data, 'end_episode_number');
         
         if (!$anime_id) {
             Utils::throwError('20003:anime_id参数缺失');
@@ -11085,20 +11087,44 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         if ((int)getProp($anime, 'is_multi') !== 1) {
             Utils::throwError('20003:单剧集不支持批量生成');
         }
-        
-        // 获取当前已生成的最大集数
-        $currentMaxEpisode = DB::table('mp_anime_episodes')
-            ->where('anime_id', $anime_id)
-            ->where('is_default', 1)
-            ->max('episode_number');
-        
-        $currentMaxEpisode = $currentMaxEpisode ?: 0;
-        
-        // 确定起始集数
-        $startEpisodeNumber = $currentMaxEpisode + 1;
-        
-        // 计算结束集数
-        $endEpisodeNumber = $startEpisodeNumber + $generate_episode_number - 1;
+
+        // 指定起始/结束剧集序号时的校验
+        $hasSpecifiedRange = ($start_episode_number !== null && $start_episode_number !== '')
+            || ($end_episode_number !== null && $end_episode_number !== '');
+
+        if ($hasSpecifiedRange) {
+            if ($start_episode_number === null || $start_episode_number === ''
+                || $end_episode_number === null || $end_episode_number === '') {
+                Utils::throwError('20003:起始剧集序号和结束剧集序号必须同时提供');
+            }
+
+            $start_episode_number = (int)$start_episode_number;
+            $end_episode_number = (int)$end_episode_number;
+
+            if ($start_episode_number < 1 || $end_episode_number < $start_episode_number) {
+                Utils::throwError('20003:剧集序号范围错误,结束剧集序号不能小于起始剧集序号');
+            }
+
+            $startEpisodeNumber = $start_episode_number;
+            $endEpisodeNumber = $end_episode_number;
+        } else {
+            // 未指定范围时,以 generate_episode_number 判断要生成的集数,从当前已生成的最大集数的下一集开始
+            $currentMaxEpisode = DB::table('mp_anime_episodes')
+                ->where('anime_id', $anime_id)
+                ->where('is_default', 1)
+                ->max('episode_number');
+
+            $currentMaxEpisode = $currentMaxEpisode ?: 0;
+
+            // 确定起始集数
+            $startEpisodeNumber = $currentMaxEpisode + 1;
+
+            // 计算结束集数
+            $endEpisodeNumber = $startEpisodeNumber + $generate_episode_number - 1;
+        }
+
+        // 本次实际生成的集数
+        $totalEpisodeCount = $endEpisodeNumber - $startEpisodeNumber + 1;
         
         // 检查是否超过总集数限制
         $end_episode_sequence = getProp($anime, 'end_episode_sequence');
@@ -11106,6 +11132,37 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
             Utils::throwError("20003:总集数只有{$end_episode_sequence}集,无法生成到第{$endEpisodeNumber}集");
         }
 
+        // 创建任务前验重:批量任务表与剧集表中是否已存在范围内的剧集序号
+        $duplicatedBatchEpisodes = DB::table('mp_batch_episode_generation_details')
+            ->where('anime_id', $anime_id)
+            ->whereBetween('episode_number', [$startEpisodeNumber, $endEpisodeNumber])
+            ->pluck('episode_number')
+            ->unique()
+            ->sort()
+            ->values()
+            ->toArray();
+
+        $duplicatedAnimeEpisodes = DB::table('mp_anime_episodes')
+            ->where('anime_id', $anime_id)
+            ->where('is_default', 1)
+            ->whereBetween('episode_number', [$startEpisodeNumber, $endEpisodeNumber])
+            ->pluck('episode_number')
+            ->unique()
+            ->sort()
+            ->values()
+            ->toArray();
+
+        if (!empty($duplicatedBatchEpisodes) || !empty($duplicatedAnimeEpisodes)) {
+            $duplicateMessages = [];
+            if (!empty($duplicatedBatchEpisodes)) {
+                $duplicateMessages[] = '批量生成任务中已存在第' . implode('、', $duplicatedBatchEpisodes) . '集';
+            }
+            if (!empty($duplicatedAnimeEpisodes)) {
+                $duplicateMessages[] = '剧集中已存在第' . implode('、', $duplicatedAnimeEpisodes) . '集';
+            }
+            Utils::throwError('20003:' . implode(';', $duplicateMessages) . ',请勿重复创建');
+        }
+
         // 计算本次实际需要创建的任务数(跳过已存在且未失败的任务;失败任务会删除重建,算作创建)
         $existingSkippedCount = DB::table('mp_batch_episode_generation_details')
             ->where('anime_id', $anime_id)
@@ -11197,10 +11254,10 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
             'anime_id' => $anime_id,
             'start_episode' => $startEpisodeNumber,
             'end_episode' => $endEpisodeNumber,
-            'total_episodes' => $generate_episode_number,
+            'total_episodes' => $totalEpisodeCount,
             'created_episodes' => $createdTasks,
             'skipped_episodes' => $skippedTasks,
-            'message' => "已创建批量生成任务,将生成第{$startEpisodeNumber}集到第{$endEpisodeNumber}集,共{$generate_episode_number}集。" . 
+            'message' => "已创建批量生成任务,将生成第{$startEpisodeNumber}集到第{$endEpisodeNumber}集,共{$totalEpisodeCount}集。" . 
                          "已创建: " . implode(',', $createdTasks) . 
                          (!empty($skippedTasks) ? ";已跳过: " . implode(',', $skippedTasks) : ""),
             'task_center_id' => $taskCenterId
@@ -11230,10 +11287,12 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
             'end_episode'             => (int)$endEpisodeNumber,
         ];
 
-        // 验重键:入参(anime_id + generate_episode_number)+ task_type
+        // 验重键:入参 + 生成范围(anime_id + generate_episode_number + start/end)+ task_type
         $paramsMd5 = md5(json_encode([
             'anime_id'                => (int)$anime_id,
             'generate_episode_number' => (int)$generate_episode_number,
+            'start_episode'           => (int)$startEpisodeNumber,
+            'end_episode'             => (int)$endEpisodeNumber,
         ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
 
         // 验重:相同 md5 且任务未结束(pending/processing)时复用已有任务中心记录