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

新增动漫对话列表和对话历史记录

lh 3 недель назад
Родитель
Сommit
c887a16b1d

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

@@ -64,6 +64,22 @@ class AnimeController extends BaseController
         return $this->success(['success'=>$result ? 1 : 0]);
     }
 
+    // 动漫对话列表
+    public function chatList(Request $request) {
+        $data = $request->all();
+
+        $result = $this->AnimeService->chatList($data);
+        return $this->success($result, [new AnimeTransformer(), 'newBuildChatList']);
+    }
+
+    // 动漫对话历史记录
+    public function chatHistory(Request $request) {
+        $data = $request->all();
+
+        $result = $this->AnimeService->chatHistory($data);
+        return $this->success($result);
+    }
+
     // 动漫大纲
     public function animeDetail(Request $request) {
         $data = $request->all();

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

@@ -461,6 +461,80 @@ class DeepSeekController extends BaseController
         ]);
     }
 
+    // 新建对话
+    public function reGenerateAnime(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->reGenerateAnime($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 chat(Request $request) {
         // 忽略所有超时限制
         set_time_limit(0);

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

@@ -32,6 +32,32 @@ class AnimeService
         ];
     }
 
+    public function chatList($data) {
+        $anime_name = getProp($data, 'anime_name');
+
+        $query = DB::table('mp_animes')->where('is_deleted', 0);
+        if ($anime_name) {
+            $query->where('anime_name', 'like', "%$anime_name%");
+        }
+
+        return $query->orderBy('id', 'desc')->paginate();
+    }
+
+    public function chatHistory($data) {
+        $anime_id = getProp($data, 'anime_id');
+        $sequence = getProp($data, 'sequence', 0);
+
+        if (!$anime_id) Utils::throwError('20003:请选择对话!');
+
+        $query = DB::table('mp_anime_records')->where('anime_id', $anime_id)->where('sequence', $sequence)->select('role', 'content', 'created_at');
+        
+        return $query->orderBy('id')->get()->map(function ($value) {
+            $value = (array)$value;
+            $value['created_at'] = transDate($value['created_at']);
+            return $value;
+        })->toArray();
+    }
+
     public function batchSetRoleImg($data) {
         $anime_id = getProp($data, 'anime_id');
         $episode_number = getProp($data, 'episode_number');

Разница между файлами не показана из-за своего большого размера
+ 297 - 1
app/Services/DeepSeek/DeepSeekService.php


+ 10 - 12
app/Transformer/Anime/AnimeTransformer.php

@@ -5,29 +5,27 @@ namespace App\Transformer\Anime;
 class AnimeTransformer
 {
 
-    public function newBuildChapterList($data): array
+    public function newBuildChatList($data): array
     {
         return [
-            'meta'      => getMeta($data['list']),
-            'header'    => $data['header'],
-            'list'      => $this->newEachChapterList($data['list']),
+            'meta'      => getMeta($data),
+            // 'header'    => $data['header'],
+            'list'      => $this->newEachChatList($data),
         ];
     }
 
-    private function newEachChapterList($list): array
+    private function newEachChatList($list): array
     {
         $result = [];
         if (empty($list)) return $result;
 
         foreach ($list as $item) {
             $result[] = [
-                'cid'               => getProp($item, 'cid'),
-                'chapter_name'      => getProp($item, 'chapter_name'),
-                'sequence'          => getProp($item, 'sequence'),
-                'size'              => getProp($item, 'size'),
-                'generate_status'   => getProp($item, 'generate_status'),
-                'audio_url'         => getProp($item, 'audio_url'),
-                'remark'            => getProp($item, 'remark'),
+                'anime_id'          => getProp($item, 'id'),
+                'anime_name'        => '《'.getProp($item, 'anime_name').'》',
+                'first_frame_url'   => getProp($item, 'first_frame_url'),
+                'is_multi'          => getProp($item, 'is_multi'),
+                'created_at'        => transDate(getProp($item, 'created_at')),
             ];
         }
 

+ 3 - 0
routes/api.php

@@ -128,6 +128,9 @@ Route::group(['middleware' => ['bindToken', 'bindExportToken', 'checkLogin']], f
     // 动漫管理
     Route::group(['prefix' => 'anime'], function () {
         Route::post('addChat', [DeepSeekController::class, 'addChat']);
+        Route::post('reGenerateAnime', [DeepSeekController::class, 'reGenerateAnime']);
+        Route::get('chatList', [AnimeController::class, 'chatList']);
+        Route::get('chatHistory', [AnimeController::class, 'chatHistory']);
         Route::post('chat', [DeepSeekController::class, 'chat']);
         Route::get('detail', [AnimeController::class, 'animeDetail']);
         Route::get('episodeInfo', [AnimeController::class, 'episodeInfo']);