Преглед на файлове

大量调整动漫剧集的数据结构和请求接口,适配seko实际内容

lh преди 6 месеца
родител
ревизия
06e8847148

+ 2 - 1
app/Console/Test/TestCommand.php

@@ -50,7 +50,8 @@ class TestCommand extends Command
      */
     public function handle()
     {
-        handleScriptContent('');
+        // dd(testStoryboardParsing(''));
+        // dd(handleEpisodeContent(''));
         
         exit();
         $url = 'https://zw-audiobook.tos-cn-beijing.volces.com/video/ai_generation_1772704798_69a9541e94bef';

+ 78 - 0
app/Http/Controllers/DeepSeek/DeepSeekController.php

@@ -460,4 +460,82 @@ class DeepSeekController extends BaseController
             'Access-Control-Allow-Credentials' => 'true'
         ]);
     }
+
+    public function chat(Request $request) {
+        // 忽略所有超时限制
+        set_time_limit(0);
+        ini_set('max_execution_time', '0');
+
+        $data = $request->all();
+        return response()->stream(function () use ($data) {
+            // 禁用所有输出缓冲
+            if (ob_get_level()) {
+                ob_end_clean();
+            }
+            
+            // 设置输出缓冲为关闭
+            ini_set('output_buffering', 'off');
+            ini_set('zlib.output_compression', 'off');
+            
+            // 立即刷新
+            if (function_exists('apache_setenv')) {
+                apache_setenv('no-gzip', '1');
+            }
+
+            try {
+                $generator = $this->deepseekService->chat($data);
+                
+                foreach ($generator as $chunk) {
+                    // 发送 SSE 格式的数据
+                    $jsonData = json_encode($chunk, JSON_UNESCAPED_UNICODE);
+                    echo "data: {$jsonData}\n\n";
+                    
+                    // 强制刷新输出缓冲区
+                    if (ob_get_level() > 0) {
+                        ob_flush();
+                    }
+                    flush();
+                    
+                    // 检查客户端是否断开连接
+                    if (connection_aborted()) {
+                        break;
+                    }
+                }
+                
+                // 发送结束标记
+                echo "data: [DONE]\n\n";
+                if (ob_get_level() > 0) {
+                    ob_flush();
+                }
+                flush();
+                
+            } catch (\Exception $e) {
+                // 发送错误信息
+                $error = [
+                    'type' => 'error',
+                    'message' => $e->getMessage(),
+                    'code' => $e->getCode()
+                ];
+                $jsonError = json_encode($error, JSON_UNESCAPED_UNICODE);
+                echo "data: {$jsonError}\n\n";
+                if (ob_get_level() > 0) {
+                    ob_flush();
+                }
+                flush();
+            }
+        }, 200, [
+            'Content-Type' => 'text/event-stream',
+            'Cache-Control' => 'no-cache',
+            'Connection' => 'keep-alive',
+            'X-Accel-Buffering' => 'no', // 防止 Nginx 缓冲
+            'Access-Control-Allow-Origin' => '*',
+            'Access-Control-Allow-Credentials' => 'true'
+        ]);
+    }
+
+    public function testChat(Request $request) {
+        $data = $request->all();
+        $this->deepseekService->chat($data);
+        return $this->success(true);
+    }
 }

Файловите разлики са ограничени, защото са твърде много
+ 192 - 0
app/Libs/Helpers.php


+ 10 - 1
app/Services/Anime/AnimeService.php

@@ -16,9 +16,18 @@ use OSS\OssClient;
 class AnimeService
 {
     protected $aiImageGenerationService;
+    private $url;
+    private $api_key;
+    private $headers;
 
     public function __construct(AIImageGenerationService $aiImageGenerationService) {
         $this->aiImageGenerationService = $aiImageGenerationService;
+        $this->url = 'https://api.deepseek.com/chat/completions';
+        $this->api_key = env('DEEPSEEK_API_KEY');
+        $this->headers = [
+            'Authorization' => 'Bearer '.$this->api_key,
+            'Content-Type'  => 'application/json; charset=UTF-8'
+        ];
     }
 
     public function uploadImg($data) {
@@ -199,7 +208,7 @@ class AnimeService
     public function animeDetail($data) {
         $anime_id = getProp($data, 'anime_id');
         $anime = DB::table('mp_animes')->where('id', $anime_id)->where('is_deleted', 0)
-        ->selectRaw('id as anime_id, anime_name, intro, highlights, roles, role_relationship, core_contradiction, art_style, scenes, status, start_episode_sequence, end_episode_sequence, episode_num, remark, generate_status, created_at')->first();
+        ->selectRaw('id as anime_id, anime_name, intro, highlights, roles, role_relationship, core_contradiction, art_style, scenes, status, remark, generate_status, created_at')->first();
         if (!$anime) Utils::throwError('20003:该剧本不存在!');
         $anime = (array)$anime;
         $anime['roles'] = json_decode($anime['roles']);

Файловите разлики са ограничени, защото са твърде много
+ 448 - 20
app/Services/DeepSeek/DeepSeekService.php


+ 3 - 3
public/deepseek-stream-demo.html

@@ -321,7 +321,7 @@
                 <div class="form-row">
                     <div class="form-group">
                         <label>剧本 ID *</label>
-                        <input type="number" id="scriptId" name="script_id" value="1" required placeholder="请输入剧本ID">
+                        <input type="number" id="scriptId" name="anime_id" value="1" required placeholder="请输入剧本ID">
                     </div>
                     <div class="form-group">
                         <label>模型选择</label>
@@ -507,7 +507,7 @@
 
             // 准备表单数据
             const formData = new FormData();
-            formData.append('script_id', document.getElementById('scriptId').value);
+            formData.append('anime_id', document.getElementById('scriptId').value);
             formData.append('model', document.getElementById('model').value);
             formData.append('start_episode_sequence', document.getElementById('startEpisode').value);
             formData.append('total_episode_num', document.getElementById('totalEpisode').value);
@@ -537,7 +537,7 @@
 
             try {
                 // 发起流式请求,传入 signal 用于中断
-                const response = await fetch('/api/addChat', {
+                const response = await fetch('/api/chat', {
                     method: 'POST',
                     body: formData,
                     signal: abortController.signal // 关键:添加中断信号

+ 3 - 1
routes/api.php

@@ -127,7 +127,8 @@ Route::group(['middleware' => ['bindToken', 'bindExportToken', 'checkLogin']], f
 
     // 动漫管理
     Route::group(['prefix' => 'anime'], function () {
-        Route::post('chat', [AnimeController::class, 'chat']);
+        Route::post('addChat', [DeepSeekController::class, 'addChat']);
+        Route::post('chat', [DeepSeekController::class, 'chat']);
         Route::get('detail', [AnimeController::class, 'animeDetail']);
         Route::post('edit', [AnimeController::class, 'editAnime']);
         Route::post('batchUploadImg', [ImageGenerationController::class, 'batchUploadImg']);
@@ -138,6 +139,7 @@ Route::group(['middleware' => ['bindToken', 'bindExportToken', 'checkLogin']], f
 });
 
 Route::post('addChat', [DeepSeekController::class, 'addChat']);
+Route::post('testChat', [DeepSeekController::class, 'testChat']);
 Route::get('exportScript', [DeepSeekController::class, 'exportScript']);
 Route::get('login', [AccountController::class, 'login']); // 登录
 Route::get('logout', [AccountController::class, 'logout']); // 退出