Преглед изворни кода

1.新增解析剧本资产任务中心2.解析资产适配任务表逻辑3.可选剧本增加是否创建资产筛选

lh пре 1 месец
родитељ
комит
8b162320b0

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

@@ -546,6 +546,17 @@ class DeepSeekController extends BaseController
         return $this->success($result);
     }
 
+    /**
+     * 获取剧本资产生成任务列表
+     * @param Request $request
+     * @return mixed
+     */
+    public function getScriptGenerateTasks(Request $request) {
+        $data = $request->all();
+        $result = $this->deepseekService->getScriptGenerateTasks($data);
+        return $this->success($result, [new DeepSeekTransformer(), 'newBuildScriptGenerateTaskList']);
+    }
+
     // 保存剧本沟通记录
     public function saveScriptChatHistory(Request $request) {
         $data = $request->all();

+ 28 - 0
app/Models/MpScriptGenerateTask.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+class MpScriptGenerateTask extends Model
+{
+    protected $table = 'mp_script_generate_tasks';
+
+    const STATUS_PENDING = 'pending';
+    const STATUS_PROCESSING = 'processing';
+    const STATUS_SUCCESS = 'success';
+    const STATUS_FAILED = 'failed';
+
+    protected $fillable = [
+        'id',
+        'uid',
+        'script_id',
+        'sequence',
+        'status',
+        'prompt',
+        'result',
+        'error_message',
+        'started_at',
+        'completed_at',
+    ];
+}

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

@@ -7833,6 +7833,12 @@ class AnimeService
 
             // 批量插入映射数据(使用 insertOrIgnore 避免重复插入)
             $insertedCount = DB::table('mp_script_product_mappings')->insertOrIgnore($mappingRecords);
+
+            // 剧本已有资产,同步更新is_products标记
+            DB::table('mp_scripts')->where('id', $script_id)->update([
+                'is_products' => 1,
+                'updated_at' => $now
+            ]);
             
             // 如果需要自动生成图片,在事务中创建图片生成任务
             $productTaskMap = [];

+ 128 - 53
app/Services/DeepSeek/DeepSeekService.php

@@ -282,12 +282,12 @@ class DeepSeekService
         $script_name = pathinfo($originalName, PATHINFO_FILENAME);
         
         if (!$script_name) {
-            $script_name = '剧本_' . date('YmdHis');
+            Utils::throwError('20003:未识别到剧本名,请联系管理员');
         }
         
-        // 如果剧本名称已存在,添加时间戳后缀
-        if (DB::table('mp_scripts')->where('script_name', $script_name)->where('is_deleted', 0)->exists()) {
-            $script_name .= '_' . date('YmdHis');
+        // 如果同一用户的剧本名存在则提示
+        if (DB::table('mp_scripts')->where('script_name', $script_name)->where('user_id', $uid)->where('is_deleted', 0)->exists()) {
+            Utils::throwError('20003:你已上传过该剧本,请修改文件名后上传');
         }
         
         // 插入数据到mp_scripts表
@@ -538,57 +538,109 @@ class DeepSeekService
             }
         }
         
+        // 新增: 如果提供了script_id,创建剧本资产生成任务
+        $generateTaskId = 0;
+        if ($script_id > 0) {
+            $uid = Site::getUid();
+            $existingTask = DB::table('mp_script_generate_tasks')
+                ->where('uid', $uid)
+                ->where('script_id', $script_id)
+                ->orderByDesc('id')
+                ->first();
+
+            // 如果已有生成中的任务,则提示该剧本资产正在生成
+            if ($existingTask && in_array(getProp($existingTask, 'status'), ['pending', 'processing'])) {
+                Utils::throwError('20003:该剧本资产正在生成中,请稍后重试');
+            }
+
+            // 创建新的生成任务
+            $generateTaskId = DB::table('mp_script_generate_tasks')->insertGetId([
+                'uid'        => $uid,
+                'script_id'  => $script_id,
+                'sequence'   => $sequence,
+                'status'     => 'processing',
+                'prompt'     => getProp($data, 'prompt', ''),
+                'started_at' => date('Y-m-d H:i:s'),
+                'created_at' => date('Y-m-d H:i:s'),
+                'updated_at' => date('Y-m-d H:i:s')
+            ]);
+        }
+
         // 根据模型类型选择调用方法(复用现有的chatOnly方法)
-        $aiResult = null;
-        if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
-            // DeepSeek 官方模型使用现有的 chatOnly 方法
-            $result = $this->chatOnly($post_data);
-            
-            // 记录实际使用的模型
-            dLog('deepseek')->info('newGenerateText使用DeepSeek模型', ['requested_model' => $model, 'actual_model' => $model]);
-            
-            $aiResult = [
-                'content' => $result['fullContent'],
-                'reasoning_content' => $result['fullReasoningContent'],
-                'usage' => $result['usage'],
-                'model' => $model,
-                'finish_reason' => 'stop'
-            ];
-        } else if (in_array($model, $this->gpt_text_models)) {
-            // GPT 模型使用现有的 gpt54ChatOnly 方法
-            $result = $this->gpt54ChatOnly($post_data);
-            
-            dLog('deepseek')->info('newGenerateText使用GPT模型', ['requested_model' => $model]);
-            
-            $aiResult = [
-                'content' => $result['fullContent'],
-                'reasoning_content' => '',
-                'usage' => $result['usage'],
-                'model' => $model,
-                'finish_reason' => 'stop'
-            ];
-        } else if (in_array($model, $this->valid_text_models)) {
-            // 火山引擎支持的模型使用火山引擎 API(非流式)
-            $post_data['stream'] = false;
-            $result = $this->volcEngineChatCompletion($post_data);
-            
-            dLog('deepseek')->info('newGenerateText使用火山引擎模型', [
-                'requested_model' => $model,
-                'result_keys' => array_keys($result),
-                'has_fullContent' => isset($result['fullContent']),
-                'has_content' => isset($result['content'])
+        try {
+            $aiResult = null;
+            if (in_array($model, ['deepseek-reasoner', 'deepseek-chat', 'deepseek-v4-flash', 'deepseek-v4-pro'])) {
+                // DeepSeek 官方模型使用现有的 chatOnly 方法
+                $result = $this->chatOnly($post_data);
+                
+                // 记录实际使用的模型
+                dLog('deepseek')->info('newGenerateText使用DeepSeek模型', ['requested_model' => $model, 'actual_model' => $model]);
+                
+                $aiResult = [
+                    'content' => $result['fullContent'],
+                    'reasoning_content' => $result['fullReasoningContent'],
+                    'usage' => $result['usage'],
+                    'model' => $model,
+                    'finish_reason' => 'stop'
+                ];
+            } else if (in_array($model, $this->gpt_text_models)) {
+                // GPT 模型使用现有的 gpt54ChatOnly 方法
+                $result = $this->gpt54ChatOnly($post_data);
+                
+                dLog('deepseek')->info('newGenerateText使用GPT模型', ['requested_model' => $model]);
+                
+                $aiResult = [
+                    'content' => $result['fullContent'],
+                    'reasoning_content' => '',
+                    'usage' => $result['usage'],
+                    'model' => $model,
+                    'finish_reason' => 'stop'
+                ];
+            } else if (in_array($model, $this->valid_text_models)) {
+                // 火山引擎支持的模型使用火山引擎 API(非流式)
+                $post_data['stream'] = false;
+                $result = $this->volcEngineChatCompletion($post_data);
+                
+                dLog('deepseek')->info('newGenerateText使用火山引擎模型', [
+                    'requested_model' => $model,
+                    'result_keys' => array_keys($result),
+                    'has_fullContent' => isset($result['fullContent']),
+                    'has_content' => isset($result['content'])
+                ]);
+                
+                // 火山引擎返回的数据结构使用 fullContent 和 fullReasoningContent
+                $aiResult = [
+                    'content' => $result['fullContent'] ?? $result['content'] ?? '',
+                    'reasoning_content' => $result['fullReasoningContent'] ?? $result['reasoning_content'] ?? '',
+                    'usage' => $result['usage'] ?? [],
+                    'model' => $model,
+                    'finish_reason' => $result['finish_reason'] ?? 'stop'
+                ];
+            } else {
+                Utils::throwError('20003:不支持的模型: ' . $model);
+            }
+        } catch (\Exception $e) {
+            // 生成失败,更新任务状态
+            if ($generateTaskId) {
+                DB::table('mp_script_generate_tasks')->where('id', $generateTaskId)->update([
+                    'status'         => 'failed',
+                    'error_message'  => $e->getMessage(),
+                    'completed_at'   => date('Y-m-d H:i:s'),
+                    'updated_at'     => date('Y-m-d H:i:s')
+                ]);
+            }
+            Utils::throwError('20003:' . str_replace(':',':',$e->getMessage()));
+        }
+
+        // 生成成功,更新任务状态
+        if ($generateTaskId && $aiResult) {
+            DB::table('mp_script_generate_tasks')->where('id', $generateTaskId)->update([
+                'status'       => 'success',
+                'result'       => getProp($aiResult, 'content', ''),
+                'completed_at' => date('Y-m-d H:i:s'),
+                'updated_at'   => date('Y-m-d H:i:s')
             ]);
-            
-            // 火山引擎返回的数据结构使用 fullContent 和 fullReasoningContent
-            $aiResult = [
-                'content' => $result['fullContent'] ?? $result['content'] ?? '',
-                'reasoning_content' => $result['fullReasoningContent'] ?? $result['reasoning_content'] ?? '',
-                'usage' => $result['usage'] ?? [],
-                'model' => $model,
-                'finish_reason' => $result['finish_reason'] ?? 'stop'
-            ];
-        } else {
-            Utils::throwError('20003:不支持的模型: ' . $model);
+            $aiResult['generate_task_id'] = $generateTaskId;
         }
         
         // 新增: 如果提供了script_id,保存对话记录
@@ -658,6 +710,23 @@ class DeepSeekService
         return $aiResult;
     }
 
+    /**
+     * 获取剧本资产生成任务列表(按用户分页,每页15条)
+     *
+     * @param array $data
+     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
+     */
+    public function getScriptGenerateTasks($data) {
+        $uid = Site::getUid();
+
+        return DB::table('mp_script_generate_tasks as t')
+            ->leftJoin('mp_scripts as s', 't.script_id', '=', 's.id')
+            ->where('t.uid', $uid)
+            ->select('t.id', 't.script_id', 's.script_name', 't.sequence', 't.status', 't.error_message', 't.started_at', 't.completed_at')
+            ->orderByDesc('t.id')
+            ->paginate(15);
+    }
+
     public function saveScriptChatHistory($data) {
         $uid = Site::getUid();
         $rid = getProp($data, 'rid');
@@ -2338,11 +2407,17 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         $uid = Site::getUid();
         $script_id = getProp($data, 'script_id');
         $script_name = getProp($data, 'script_name');
+        $is_products = getProp($data, 'is_products');
         
         $query = DB::table('mp_scripts')->where('is_deleted', 0)->where('user_id', $uid)->select('id as script_id', 'script_name');
         if ($script_id) {
             $query->where('id', $script_id);
         }
+
+        if ($is_products !== '') {
+            $query->where('is_products', $is_products);
+        }
+
         if ($script_name) {
             $query->where('script_name', 'like', "%{$script_name}%");
         }

+ 30 - 0
app/Transformer/DeepSeek/DeepSeekTransformer.php

@@ -41,5 +41,35 @@ class DeepSeekTransformer
         return $result;
     }
 
+    // 剧本资产生成任务列表
+    public function newBuildScriptGenerateTaskList($data): array
+    {
+        return [
+            'meta'      => getMeta($data),
+            'list'      => $this->newEachScriptGenerateTaskList($data),
+        ];
+    }
+
+    private function newEachScriptGenerateTaskList($list): array
+    {
+        $result = [];
+        if (empty($list)) return $result;
+
+        foreach ($list as $item) {
+            $result[] = [
+                'task_id'       => getProp($item, 'id'),
+                'script_id'     => getProp($item, 'script_id'),
+                'script_name'   => getProp($item, 'script_name'),
+                'sequence'      => getProp($item, 'sequence'),
+                'status'        => getProp($item, 'status'),
+                'error_message' => getProp($item, 'error_message'),
+                'started_at'    => transDate(getProp($item, 'started_at')),
+                'completed_at'  => transDate(getProp($item, 'completed_at')),
+            ];
+        }
+
+        return $result;
+    }
+
     
 }

+ 0 - 32
database/migrations/2026_08_05_000001_add_source_type_to_mp_assets_table.php

@@ -1,32 +0,0 @@
-<?php
-
-use Illuminate\Database\Migrations\Migration;
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Support\Facades\Schema;
-
-class AddSourceTypeToMpAssetsTable extends Migration
-{
-    /**
-     * Run the migrations.
-     *
-     * @return void
-     */
-    public function up()
-    {
-        Schema::table('mp_assets', function (Blueprint $table) {
-            $table->string('source_type', 32)->default('zhizhen')->comment('素材来源:zhizhen-智真AI, baidu-百度AI网关')->index()->after('asset_type');
-        });
-    }
-
-    /**
-     * Reverse the migrations.
-     *
-     * @return void
-     */
-    public function down()
-    {
-        Schema::table('mp_assets', function (Blueprint $table) {
-            $table->dropColumn('source_type');
-        });
-    }
-}

+ 1 - 0
routes/api.php

@@ -216,6 +216,7 @@ Route::group(['middleware' => ['bindToken', 'bindExportToken', 'checkLogin']], f
             Route::post('generateText', [DeepSeekController::class, 'generateText']);    // 文生文(通用)
             Route::post('createGenerateText', [DeepSeekController::class, 'createGenerateText']);   // 新建剧本对话
             Route::post('newGenerateText', [DeepSeekController::class, 'newGenerateText']);    // 文生文(通用-非流式)
+            Route::get('getScriptGenerateTasks', [DeepSeekController::class, 'getScriptGenerateTasks']); // 获取剧本资产生成任务列表
             
             // 监控分镜图片和音频生成任务进度(SSE)
             Route::get('segmentPicsInfo', [AnimeController::class, 'monitorSegmentTasks']);