瀏覽代碼

新增单一增加或调整剧本资产关联关系的接口

lh 1 月之前
父節點
當前提交
98e6c449ab
共有 3 個文件被更改,包括 214 次插入21 次删除
  1. 11 0
      app/Http/Controllers/Anime/AnimeController.php
  2. 202 21
      app/Services/Anime/AnimeService.php
  3. 1 0
      routes/api.php

+ 11 - 0
app/Http/Controllers/Anime/AnimeController.php

@@ -2217,6 +2217,17 @@ class AnimeController extends BaseController
         return $this->success($result);
     }
 
+    /**
+     * 获取剧本总集数
+     * @param Request $request
+     * @return mixed
+     */
+    public function getScriptTotalEpisodes(Request $request) {
+        $data = $request->all();
+        $result = $this->AnimeService->getScriptTotalEpisodes($data);
+        return $this->success($result);
+    }
+
     private function handleVideoTimePointEnd() {
         // 处理音频时长,循环查询dub_video_task_queue列表中的任务
         $queueLength = Redis::llen('dub_video_task_queue');

+ 202 - 21
app/Services/Anime/AnimeService.php

@@ -6831,6 +6831,16 @@ class AnimeService
         // 根据is_public参数确定存储的user_id(公共库user_id=0,cpid保持不变)
         $store_uid = $is_public ? 0 : $uid;
         
+        // 新增参数:剧本ID和剧集序号(多个序号用英文逗号隔开)
+        $script_id = (int)getProp($data, 'script_id', 0);
+        $episode_number = trim(getProp($data, 'episode_number', ''));
+        if ($script_id && $episode_number === '') {
+            Utils::throwError('20003:剧集序号不能为空');
+        }
+        if (!$script_id && $episode_number !== '') {
+            Utils::throwError('20003:请提供剧本ID');
+        }
+        
         $product_name = trim(getProp($data, 'product_name'));
         if (!$product_name) Utils::throwError('20003:名称不能为空');
         $product_name = preg_replace('/^[\s*\[\]【】[]{}{}\x{3000}]+|[\s*\[\]【】[]{}{}\x{3000}]+$/u', '', $product_name);
@@ -6877,23 +6887,38 @@ class AnimeService
             $parent_level = $parent->level;
         }
 
-        $id = DB::table('mp_products')->insertGetId([
-            'user_id'       => $store_uid,
-            'cpid'          => $cpid,
-            'type'          => 1, // 1=角色图片
-            'parent_id'     => $parent_id,
-            'level'         => $parent_level + 1,
-            'product_name'  => $product_name,
-            'url'           => $url,
-            'pic_prompt'    => $pic_prompt,
-            'product'       => $product,
-            'versions'      => json_encode($versions, 256),
-            'sort_order'    => time(), // 使用时间戳作为排序权重
-            'created_at'    => date('Y-m-d H:i:s'),
-            'updated_at'    => date('Y-m-d H:i:s')
-        ]);
+        // 创建资产并保存剧本资产关联关系(同一事务)
+        DB::beginTransaction();
+        try {
+            $id = DB::table('mp_products')->insertGetId([
+                'user_id'       => $store_uid,
+                'cpid'          => $cpid,
+                'type'          => 1, // 1=角色图片
+                'parent_id'     => $parent_id,
+                'level'         => $parent_level + 1,
+                'product_name'  => $product_name,
+                'url'           => $url,
+                'pic_prompt'    => $pic_prompt,
+                'product'       => $product,
+                'versions'      => json_encode($versions, 256),
+                'sort_order'    => time(), // 使用时间戳作为排序权重
+                'created_at'    => date('Y-m-d H:i:s'),
+                'updated_at'    => date('Y-m-d H:i:s')
+            ]);
 
-        if (!$id) Utils::throwError('20003:创建失败');
+            if (!$id) Utils::throwError('20003:创建失败');
+            
+            // 保存剧本资产关联关系
+            if ($script_id) {
+                $this->saveProductScriptMapping($id, $script_id, $episode_number);
+            }
+            
+            DB::commit();
+        } catch (\Exception $e) {
+            DB::rollback();
+            throw $e;
+        }
+        
         return [
             'id'            => $id,
             'type'          => 1,
@@ -6916,6 +6941,16 @@ class AnimeService
         $versions = getProp($data, 'versions');
         $is_public = getProp($data, 'is_public', 0); // 0=个人资产库 1=公共资产库
         
+        // 新增参数:剧本ID和剧集序号(多个序号用英文逗号隔开)
+        $script_id = (int)getProp($data, 'script_id', 0);
+        $episode_number = trim(getProp($data, 'episode_number', ''));
+        if ($script_id && $episode_number === '') {
+            Utils::throwError('20003:剧集序号不能为空');
+        }
+        if (!$script_id && $episode_number !== '') {
+            Utils::throwError('20003:请提供剧本ID');
+        }
+        
         // 根据is_public参数确定查询的user_id(公共库user_id=0,cpid保持不变)
         $query_uid = $is_public ? 0 : $uid;
         
@@ -6976,7 +7011,7 @@ class AnimeService
             $updateData['pic_prompt'] = $pic_prompt;
         }
         
-        if (empty($updateData)) {
+        if (empty($updateData) && !$script_id) {
             Utils::throwError('20003:没有需要更新的数据');
         }
         
@@ -7030,11 +7065,157 @@ class AnimeService
             $updateData['versions'] = json_encode($versions, 256);
         }
         
-        $updateData['updated_at'] = date('Y-m-d H:i:s');
+        if (!empty($updateData)) {
+            $updateData['updated_at'] = date('Y-m-d H:i:s');
+        }
         
-        return DB::table('mp_products')
-        ->where('cpid', $cpid)
-        ->where('id', $id)->update($updateData);
+        // 更新资产并保存剧本资产关联关系(同一事务)
+        DB::beginTransaction();
+        try {
+            $updated = true;
+            if (!empty($updateData)) {
+                $updated = DB::table('mp_products')
+                    ->where('cpid', $cpid)
+                    ->where('id', $id)
+                    ->update($updateData);
+            }
+            
+            // 保存剧本资产关联关系
+            if ($script_id) {
+                $this->saveProductScriptMapping($id, $script_id, $episode_number);
+            }
+            
+            DB::commit();
+        } catch (\Exception $e) {
+            DB::rollback();
+            throw $e;
+        }
+        
+        return $updated;
+    }
+    
+    /**
+     * 保存单一资产与剧本剧集的关联关系
+     *
+     * @param int $product_id 资产ID
+     * @param int $script_id 剧本ID
+     * @param string $episode_number_str 剧集序号,多个序号用英文逗号隔开(序号从1开始)
+     * @return int 新增关联数量
+     */
+    private function saveProductScriptMapping($product_id, $script_id, $episode_number_str) {
+        // 验证剧本是否存在
+        $script = DB::table('mp_scripts')
+            ->where('id', $script_id)
+            ->where('is_deleted', 0)
+            ->first();
+        
+        if (!$script) {
+            Utils::throwError('20003:剧本不存在');
+        }
+        
+        // 使用 splitContent 拆分剧本内容获取总集数
+        $totalEpisodes = $this->getScriptTotalEpisodeCount($script);
+        
+        // 解析剧集序号(英文逗号分隔)
+        $episodes = [];
+        foreach (explode(',', $episode_number_str) as $item) {
+            $item = trim($item);
+            if ($item === '' || !is_numeric($item)) {
+                Utils::throwError('20003:剧集序号格式不正确,多个序号请用英文逗号隔开');
+            }
+            $episodes[] = (int)$item;
+        }
+        
+        // 去重并校验序号范围(序号从1开始)
+        $episodes = array_values(array_unique($episodes));
+        if (empty($episodes)) {
+            Utils::throwError('20003:剧集序号不能为空');
+        }
+        
+        foreach ($episodes as $episode) {
+            if ($episode < 1 || $episode > $totalEpisodes) {
+                Utils::throwError('20003:剧集序号 ' . $episode . ' 超出范围,剧本共 ' . $totalEpisodes . ' 集(序号从1开始)');
+            }
+        }
+        
+        $now = now();
+        
+        // 过滤已存在的关联,避免重复
+        $existingEpisodes = DB::table('mp_script_product_mappings')
+            ->where('script_id', $script_id)
+            ->where('product_id', $product_id)
+            ->whereIn('episode_number', $episodes)
+            ->pluck('episode_number')
+            ->all();
+        
+        $mappingRecords = [];
+        foreach ($episodes as $episode) {
+            if (in_array($episode, $existingEpisodes)) {
+                continue;
+            }
+            $mappingRecords[] = [
+                'script_id' => $script_id,
+                'product_id' => $product_id,
+                'episode_number' => $episode,
+                'created_at' => $now,
+                'updated_at' => $now,
+            ];
+        }
+        
+        $insertedCount = 0;
+        if (!empty($mappingRecords)) {
+            $insertedCount = DB::table('mp_script_product_mappings')->insert($mappingRecords) ? count($mappingRecords) : 0;
+        }
+        
+        return $insertedCount;
+    }
+    
+    /**
+     * 获取剧本总集数(通过 splitContent 拆分剧本内容)
+     *
+     * @param object $script 剧本记录
+     * @return int 总集数
+     */
+    private function getScriptTotalEpisodeCount($script) {
+        if (empty($script->content)) {
+            Utils::throwError('20003:剧本内容为空,无法确定剧集数量');
+        }
+        
+        $totalEpisodes = count(splitContent($script->content));
+        if ($totalEpisodes < 1) {
+            Utils::throwError('20003:剧本内容无法拆分出剧集');
+        }
+        
+        return $totalEpisodes;
+    }
+    
+    /**
+     * 获取剧本总集数
+     *
+     * @param array $data 包含 script_id(剧本ID)
+     * @return array
+     */
+    public function getScriptTotalEpisodes($data) {
+        $script_id = (int)getProp($data, 'script_id', 0);
+        if (!$script_id) {
+            Utils::throwError('20003:请提供剧本ID');
+        }
+        
+        // 验证剧本是否存在
+        $script = DB::table('mp_scripts')
+            ->where('id', $script_id)
+            ->where('is_deleted', 0)
+            ->first();
+        
+        if (!$script) {
+            Utils::throwError('20003:剧本不存在');
+        }
+        
+        return [
+            'script_id' => $script_id,
+            'script_name' => $script->script_name ?? 'script_' . $script_id,
+            'total_episodes' => $this->getScriptTotalEpisodeCount($script),
+        ];
     }
     
     /**

+ 1 - 0
routes/api.php

@@ -246,6 +246,7 @@ Route::group(['middleware' => ['bindToken', 'bindExportToken', 'checkLogin']], f
             // 剧本资产关联管理
             Route::post('saveScriptProducts', [AnimeController::class, 'saveScriptProducts']);     // 保存剧本资产
             Route::get('getScriptProducts', [AnimeController::class, 'getScriptProducts']);        // 获取剧本资产
+            Route::get('getScriptTotalEpisodes', [AnimeController::class, 'getScriptTotalEpisodes']);   // 获取剧本总集数
 
             // 提示词模板管理
             Route::get('promptTemplates', [PromptTemplateController::class, 'promptTemplates']);          // 提示词模板列表