Просмотр исходного кода

优化分段剧本中资产库的显示和使用

lh 2 недель назад
Родитель
Сommit
6546d7f3c0
2 измененных файлов с 143 добавлено и 25 удалено
  1. 87 25
      app/Http/Controllers/Anime/AnimeController.php
  2. 56 0
      app/Services/Anime/AnimeService.php

+ 87 - 25
app/Http/Controllers/Anime/AnimeController.php

@@ -2875,47 +2875,109 @@ class AnimeController extends BaseController
         $videoResolution = !empty($episode->video_resolution) ? $episode->video_resolution : '720p';
         $generate_audio = getProp($data, 'generate_audio', 1);
 
-        // 合并角色、场景和道具作为products,统一字段名为product_name
+        // 合并角色、场景、道具、extra_products和当前集mappings作为products,统一字段名为product_name
+        // 优先级:mappings > extra_products > 剧集中的roles/scenes/props
         $products = [];
         $roles = json_decode(getProp($episode, 'roles'), true) ?: [];
         $scenes = json_decode(getProp($episode, 'scenes'), true) ?: [];
         $props = json_decode(getProp($episode, 'props'), true) ?: [];
-        
-        // 处理角色数组
+        $extra_products = json_decode(getProp($episode, 'extra_products', '[]'), true) ?: [];
+
+        $normalizeProductName = function($name) {
+            return trim(preg_replace(
+                '/^[\s*\[\]【】[]{}{}\x{3000}]+|[\s*\[\]【】[]{}{}\x{3000}]+$/u',
+                '',
+                trim((string)$name)
+            ));
+        };
+
+        // 最低优先级:roles/scenes/props
         foreach ($roles as $role) {
+            $role_name = getProp($role, 'role');
+            if (!$role_name) continue;
+
             $product = $role;
-            // 将role字段重命名为product_name
-            if (isset($product['role'])) {
-                $product['product_name'] = $product['role'];
-                unset($product['role']);
-            }
+            $product['product_name'] = $role_name;
+            unset($product['role']);
             $product['product'] = 1; // 标记类型为角色
-            $products[] = $product;
+            $products[$normalizeProductName($role_name)] = $product;
         }
-        
-        // 处理场景数组
+
         foreach ($scenes as $scene) {
+            $scene_name = getProp($scene, 'scene');
+            if (!$scene_name) continue;
+
             $product = $scene;
-            // 将scene字段重命名为product_name
-            if (isset($product['scene'])) {
-                $product['product_name'] = $product['scene'];
-                unset($product['scene']);
-            }
+            $product['product_name'] = $scene_name;
+            unset($product['scene']);
             $product['product'] = 2; // 标记类型为场景
-            $products[] = $product;
+            $products[$normalizeProductName($scene_name)] = $product;
         }
-        
-        // 处理道具数组
+
         foreach ($props as $prop) {
+            $prop_name = getProp($prop, 'prop');
+            if (!$prop_name) continue;
+
             $product = $prop;
-            // 将prop字段重命名为product_name
-            if (isset($product['prop'])) {
-                $product['product_name'] = $product['prop'];
-                unset($product['prop']);
-            }
+            $product['product_name'] = $prop_name;
+            unset($product['prop']);
             $product['product'] = 3; // 标记类型为道具
-            $products[] = $product;
+            $products[$normalizeProductName($prop_name)] = $product;
+        }
+
+        // 中间优先级:extra_products(覆盖roles/scenes/props中的同名资产)
+        // 使用array_merge保留原资产的voice_prompt、description等extra_products没有的字段
+        foreach ($extra_products as $extra_product) {
+            $extra_name = getProp($extra_product, 'product_name');
+            if (!$extra_name) continue;
+
+            $normalized_extra_name = $normalizeProductName($extra_name);
+            $products[$normalized_extra_name] = array_merge(
+                isset($products[$normalized_extra_name]) ? $products[$normalized_extra_name] : [],
+                $extra_product
+            );
         }
+
+        // 暂不确定是否启用,先保留
+        // // 最高优先级:当前集对应的mp_script_product_mappings(关联mp_products获取资产库最新数据)
+        // $script_id = (int)DB::table('mp_animes')->where('id', $animeId)->value('script_id');
+        // if ($script_id) {
+        //     $mapping_items = DB::table('mp_script_product_mappings as mapping')
+        //         ->join('mp_products as product', 'mapping.product_id', '=', 'product.id')
+        //         ->where('mapping.script_id', $script_id)
+        //         ->where('mapping.episode_number', $episodeNumber)
+        //         ->where('product.is_deleted', 0)
+        //         ->select(
+        //             'mapping.product_id',
+        //             'product.product_name',
+        //             'product.product',
+        //             'product.pic_prompt',
+        //             'product.url',
+        //             'product.three_view_image_url',
+        //         )
+        //         ->get();
+
+        //     foreach ($mapping_items as $mapping_item) {
+        //         $mapping_name = $normalizeProductName($mapping_item->product_name);
+        //         if ($mapping_name === '') continue;
+
+        //         $mapping_product = [
+        //             'product_id'           => (int)$mapping_item->product_id,
+        //             'product_name'         => $mapping_item->product_name,
+        //             'product'              => (int)$mapping_item->product,
+        //             'pic_prompt'           => $mapping_item->pic_prompt ?? '',
+        //             'url'                  => $mapping_item->url ?? '',
+        //             'three_view_image_url' => $mapping_item->three_view_image_url ?? '',
+        //         ];
+
+        //         $products[$mapping_name] = array_merge(
+        //             isset($products[$mapping_name]) ? $products[$mapping_name] : [],
+        //             $mapping_product
+        //         );
+        //     }
+        // }
+
+        $products = array_values($products);
         
         // 处理视频模型(在循环外统一处理)
         // $model = getProp($data, 'model');

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

@@ -10091,6 +10091,62 @@ class AnimeService
             }
         }
 
+        // mp_script_product_mappings 信息优先级更高:
+        // 获取当前剧集所属动漫剧本下、与本集资产同名的资产库最新数据(url/三视图/提示词等),
+        // 覆盖分集 JSON 中保存的同名旧快照;分集内独有的 description、voice_prompt 等字段保留
+        $anime = DB::table('mp_animes')->where('id', getProp($episode, 'anime_id'))->first();
+        $script_id = $anime ? (int)getProp($anime, 'script_id', 0) : 0;
+
+        if ($script_id && !empty($products)) {
+            $currentProductNames = array_keys($products);
+
+            $normalizeName = function($name) {
+                return trim(preg_replace(
+                    '/^[\s*\[\]【】[]{}{}\x{3000}]+|[\s*\[\]【】[]{}{}\x{3000}]+$/u',
+                    '',
+                    trim((string)$name)
+                ));
+            };
+
+            $mappingItems = DB::table('mp_script_product_mappings as mapping')
+                ->join('mp_products as product', 'mapping.product_id', '=', 'product.id')
+                ->where('mapping.script_id', $script_id)
+                ->where('product.is_deleted', 0)
+                ->whereIn('product.product_name', $currentProductNames)
+                ->select(
+                    'mapping.product_id',
+                    'product.product_name',
+                    'product.product',
+                    'product.pic_prompt',
+                    'product.url',
+                    'product.three_view_image_url',
+                )
+                ->get();
+
+            $mappingByName = [];
+            foreach ($mappingItems as $mappingItem) {
+                $normalizedName = $normalizeName($mappingItem->product_name);
+                if (!$normalizedName) continue;
+
+                $mappingByName[$normalizedName] = [
+                    'product_id'            => (int)$mappingItem->product_id,
+                    'product_name'          => $mappingItem->product_name,
+                    'product'               => (int)$mappingItem->product,
+                    'pic_prompt'            => $mappingItem->pic_prompt ?? '',
+                    'url'                   => $mappingItem->url ?? '',
+                    'three_view_image_url'  => $mappingItem->three_view_image_url ?? '',
+                ];
+            }
+
+            foreach ($products as $key => &$product) {
+                $normalizedKey = $normalizeName($key);
+                if ($normalizedKey && isset($mappingByName[$normalizedKey])) {
+                    $product = array_merge($product, $mappingByName[$normalizedKey]);
+                }
+            }
+            unset($product);
+        }
+
         // 兼容返回 three_view_image_url 字段(旧数据可能没有该键,统一补空值)
         foreach ($products as &$product) {
             if (!isset($product['three_view_image_url'])) {