Explorar o código

1.新增分集剧本全能模式2.前端改版

lh hai 1 mes
pai
achega
e3b1d5c9e3

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

@@ -262,6 +262,14 @@ class AnimeController extends BaseController
         return $this->success($result);
     }
 
+    // 动漫剧集(全能模式)
+    public function episodeInfoForAce(Request $request) {
+        $data = $request->all();
+
+        $result = $this->AnimeService->episodeInfoForAce($data);
+        return $this->success($result);
+    }
+
     // 分镜信息
     public function segmentInfo(Request $request) {
         $data = $request->all();

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

@@ -127,6 +127,51 @@ class AnimeService
     }
 
     /**
+     * 构建统一的分段数据结构(episodeInfoForAce格式)
+     * @param array $segments 分段数据数组
+     * @return array 返回包含acts和total_duration的数组
+     */
+    public function buildEpisodeSegmentsStructureForAce($segments) {
+        $acts = [];
+        $totalDuration = 0; // 初始化总时长
+        
+        foreach($segments as $segment) {
+            // 计算分镜时长,优先级:video_duration > audio_duration > 默认5秒
+            $videoDuration = getProp($segment, 'video_duration');
+            $audioDuration = getProp($segment, 'audio_duration');
+            
+            if (!empty($videoDuration) && is_numeric($videoDuration)) {
+                $totalDuration += floatval($videoDuration);
+            } elseif (!empty($audioDuration) && is_numeric($audioDuration)) {
+                $totalDuration += floatval($audioDuration);
+            } else {
+                $totalDuration += 5; // 默认5秒
+            }
+
+            // 构建分镜信息
+            $segmentInfo = [
+                'act_id'    => getProp($segment, 'id'),
+                'act_number'    => getProp($segment, 'act_number'),
+                'act_title'  => getProp($segment, 'act_title'),
+                'act_duration'  => getProp($segment, 'act_duration'),
+                'act_content'  => getProp($segment, 'act_content'),
+                'video_url' => getProp($segment, 'video_url'),
+                'video_duration' => getProp($segment, 'video_duration', 0),
+                'video_time_point_start' => getProp($segment, 'video_time_point_start', 0),
+                'video_time_point_end' => getProp($segment, 'video_time_point_end', getProp($segment, 'video_duration', 0)),
+                'last_frame_url' => getProp($segment, 'last_frame_url'),
+                'current_type' => getProp($segment, 'current_type'),
+            ];
+            $acts[] = $segmentInfo;
+        }
+        
+        return [
+            'acts' => array_values($acts),
+            'total_duration' => intval(round($totalDuration))
+        ];
+    }
+
+    /**
      * 验证画面比例是否有效
      * @param string $ratio 画面比例
      * @return bool
@@ -519,6 +564,38 @@ class AnimeService
         return $episode;
     }
 
+    public function episodeInfoForAce($data) {
+        $anime_id = getProp($data, 'anime_id');
+        $episode_id = getProp($data, 'episode_id');
+        if (!$anime_id || !$episode_id) {
+            Utils::throwError('1002:请选择剧集');
+        }
+
+        $episode = DB::table('mp_anime_episodes')->where('anime_id', $anime_id)->where('id', $episode_id)->select('id as episode_id', 'anime_id', 'episode_number', 'title', 'intro', 'art_style', 'roles', 'scenes', 'is_generated')->first();
+        if (!$episode) Utils::throwError('20003:该剧集不存在!');
+        $episode = (array)$episode;
+        $episode['roles'] = json_decode($episode['roles'], true);
+        foreach($episode['roles'] as &$item) {
+            if (isset($item['pic_prompt']) && mb_substr($item['pic_prompt'], 0, 11) != '写实。全景,正面拍摄。') $item['pic_prompt'] = '写实。全景,正面拍摄。'.$item['pic_prompt'];
+        }
+        $episode['scenes'] = json_decode($episode['scenes'], true);
+        foreach($episode['scenes'] as &$item) {
+            if (isset($item['pic_prompt']) && mb_substr($item['pic_prompt'], 0, 3) != '写实。') $item['pic_prompt'] = '写实。'.$item['pic_prompt'];
+        }
+        
+        // 获取分镜信息
+        $segments = DB::table('mp_episode_segments')->where('anime_id', $anime_id)->where('episode_id', getProp($episode, 'episode_id'))->orderBy('segment_number')
+        ->select('*')->get()->map(function ($value) {
+            return (array)$value;
+        })->toArray();
+        
+        $segmentsStructure = $this->buildEpisodeSegmentsStructureForAce($segments);
+        $episode['acts'] = $segmentsStructure['acts'];
+        $episode['total_duration'] = $segmentsStructure['total_duration'];
+
+        return $episode;
+    }
+
     public function segmentInfo($data) {
         $segment_id = getProp($data, 'segment_id');
         if (!$segment_id) {

+ 1 - 1
app/Services/DeepSeek/DeepSeekService.php

@@ -5712,7 +5712,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
                 foreach ($act_segments as $seg) {
                     $seg_num = getProp($seg, 'segment_number');
                     $seg_content = getProp($seg, 'segment_content');
-                    $merged_parts[] = "【镜头{$seg_num}】{$seg_content}\n";
+                    $merged_parts[] = "【镜头{$seg_num}】\n{$seg_content}\n";
                 }
                 $segments[] = [
                     'anime_id' => $anime_id,

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 1
resources/views/animeIndex.blade.php


+ 2 - 1
routes/api.php

@@ -156,9 +156,10 @@ Route::group(['middleware' => ['bindToken', 'bindExportToken', 'checkLogin']], f
             Route::get('chatList', [AnimeController::class, 'chatList']);                           // 动漫列表
             Route::get('chatHistory', [AnimeController::class, 'chatHistory']);                     // 动漫对话历史
             Route::post('chat', [DeepSeekController::class, 'chat']);                               // 动漫对话
-            Route::post('chatForAce', [DeepSeekController::class, 'chatForAce']);                         // 动漫对话(全能模式)
+            Route::post('chatForAce', [DeepSeekController::class, 'chatForAce']);                   // 动漫对话(全能模式)
             Route::get('detail', [AnimeController::class, 'animeDetail']);                          // 动漫大纲
             Route::get('episodeInfo', [AnimeController::class, 'episodeInfo']);                     // 动漫剧集
+            Route::get('episodeInfoForAce', [AnimeController::class, 'episodeInfoForAce']);         // 动漫剧集(全能模式)
             Route::get('segmentInfo', [AnimeController::class, 'segmentInfo']);                     // 分镜信息
             Route::get('copyEpisodeVersion', [AnimeController::class, 'copyEpisodeVersion']);       // 复制动漫剧集
             Route::get('episodeVersions', [AnimeController::class, 'episodeVersions']);             // 剧集版本