Browse Source

first commit

liuhairui 1 week ago
parent
commit
9ad3ce5e8b

+ 2 - 2
application/api/controller/Product.php

@@ -263,14 +263,14 @@ class Product extends Api
         // 6. 优化图片路径处理
         // 产品图片
         if (!empty($product['product_img'])) {
-            $product['产品图片'] = ltrim($product['product_img'], '/');
+            $product['产品图片'] = ltrim($product['product_img']);
         } else {
             $product['产品图片'] = '';  // 设置默认空值
         }
 
         // 产品效果图 - 修复变量名错误(原代码中使用了$v)
         if (!empty($product['product_new_img'])) {
-            $product['产品效果图'] = ltrim($product['product_new_img'], '/');
+            $product['产品效果图'] = ltrim($product['product_new_img']);
         } else {
             $product['产品效果图'] = '';  // 设置默认空值
         }

+ 2 - 9
application/api/controller/WorkOrder.php

@@ -33,10 +33,7 @@ class WorkOrder extends Api{
             return json($res);
         }
         // 从Redis中获取任务状态(支持文生图 text_to_image_task 和图生图 img_to_img_task)
-        $redis = new \Redis();
-        $redis->connect('127.0.0.1', 6379);
-        $redis->auth('123456');
-        $redis->select(15);
+        $redis = getTaskRedis();
         $taskData = $redis->get("img_to_img_task:{$taskId}");
         if (!$taskData) {
             $taskData = $redis->get("text_to_image_task:{$taskId}");
@@ -1240,11 +1237,7 @@ class WorkOrder extends Api{
         if (!class_exists('\Redis')) {
             return null;
         }
-        $redis = new \Redis();
-        $redis->connect('127.0.0.1', 6379);
-        $redis->auth('');
-        $redis->select(15);
-        return $redis;
+        return getTaskRedis();
     }
 
     /**

+ 19 - 0
application/common.php

@@ -356,6 +356,25 @@ if (!function_exists('hsv2rgb')) {
     }
 }
 
+if (!function_exists('getTaskRedis')) {
+    /**
+     * 获取任务状态 Redis 连接(图生图、文生图等任务状态存储)
+     * 配置来自 application/extra/queue.php,修改密码时只需改 queue.php
+     * @return \Redis
+     */
+    function getTaskRedis()
+    {
+        $config = \think\Config::get('queue');
+        $redis = new \Redis();
+        $redis->connect($config['host'], $config['port']);
+        if (!empty($config['password'])) {
+            $redis->auth($config['password']);
+        }
+        $redis->select($config['task_select'] ?? 15);
+        return $redis;
+    }
+}
+
 if (!function_exists('check_nav_active')) {
     /**
      * 检测会员中心导航是否高亮

+ 4 - 3
application/extra/queue.php

@@ -1,12 +1,13 @@
 <?php
 return [
     'connector'  => 'Redis',          // Redis 驱动
-    'expire'     => 0,             // 任务的过期时间,默认为60秒; 若要禁用,则设置为 null
+    'expire'     => 300,          // 任务 reserve 超时秒数(需>=图生图耗时);0会导致任务立即被重放回队列造成重复执行
     'default'    => 'default',    // 默认的队列名称
     'host'       => '127.0.0.1',       // redis 主机ip
     'port'       => 6379,        // redis 端口
-    'password'   => '123456',             // redis 密码
-    'select'     => 0,          // 使用哪一个 db,默认为 db0
+    'password'   => '123456',             // redis 密码(改密码时统一在此修改)
+    'select'     => 0,          // 队列使用的 db,默认为 db0
+    'task_select'=> 15,         // 任务状态(img_to_img_task等)使用的 db
     'timeout'    => 0,          // redis连接的超时时间
     'persistent' => false,
 ];

+ 2 - 5
application/job/ImageJob.php

@@ -24,11 +24,8 @@ class ImageJob{
                 return;
             }
 
-            // 创建Redis连接
-            $redis = new \Redis();
-            $redis->connect('127.0.0.1', 6379);
-            $redis->auth('123456');
-            $redis->select(15);
+            // 创建Redis连接(配置见 application/extra/queue.php)
+            $redis = getTaskRedis();
 
             // 设置锁键名
             $lockKey = "image_to_text_lock:{$taskId}";

+ 22 - 20
application/job/ImageToImageJob.php

@@ -10,27 +10,31 @@ class ImageToImageJob{
     {
         //产品图+模板图) 时走此分支
         if (isset($data['status_val']) && $data['status_val'] == '图生图' && !empty($data['product_img']) && !empty($data['template_img'])) {
+            $taskId = $data['task_id'] ?? '';
+            // 幂等:若任务已完成则跳过,避免超时重试导致重复执行
+            $redis = getTaskRedis();
+            $existing = $redis->get("img_to_img_task:{$taskId}");
+            if ($existing) {
+                $info = json_decode($existing, true);
+                if (isset($info['status']) && $info['status'] === 'completed') {
+                    echo "任务 {$taskId} 已完成,跳过重复执行\n";
+                    $job->delete();
+                    return;
+                }
+            }
             try {
 
-                // 获取任务ID
-                $taskId = $data['task_id'];
                 // 获取产品ID
                 $Id = $data['id'];
 
-                echo "━━━━━━━━━━ ▶ 图生图任务开始处理━━━━━━━━━━\n";
+                echo " 图生图任务开始处理\n";
                 echo "开始时间:" . date('Y-m-d H:i:s') . "\n";
 
                 $result = $this->get_img_to_img($data);
-                $redis = new \Redis();
-                $redis->connect('127.0.0.1', 6379);
-                $redis->auth('123456');
-                $redis->select(15);
-                $redis->set("text_to_image_task:{$taskId}", json_encode([
-                    'status' => 'completed',
-                    // 'image_url' => "/uploads/merchant/690377511/6903775111138/newimg/698550113c2b8.jpeg",
-                    'image_url' => $result,
-                    'completed_at' => date('Y-m-d H:i:s')
-                ]), ['EX' => 300]); // 5分钟过期
+                // get_img_to_img 内部已写入 img_to_img_task,此处无需重复写入
+                if (is_array($result) && isset($result['code']) && $result['code'] !== 0) {
+                    throw new \Exception($result['msg'] ?? '图生图失败');
+                }
 
                 echo "🎉 任务 {$taskId} 执行完成,图片生成成功!\n";
                 echo "结束时间:" . date('Y-m-d H:i:s') . "\n";
@@ -166,7 +170,7 @@ class ImageToImageJob{
     {
 
         $prompt = trim($data['prompt'] ?? '');
-        $size = trim($data['$size'] ?? '');
+        $size = trim($data['size'] ?? $data['$size'] ?? '');
         $product_img = trim($data['product_img'] ?? '');
         $template_img = trim($data['template_img'] ?? '');
         $model = trim($data['model'] ?? 'gemini-3-pro-image-preview');
@@ -176,7 +180,7 @@ class ImageToImageJob{
                             2. 从模板图继承版式布局、文字排版、色彩风格、背景元素;
                             3. 将模板图中的产品和文字替换为产品图的内容;
                             4. 最终生成的图片与模板图视觉风格100%统一,仅替换产品和文字。';
-        $promptContent = $prompt ?: $defaultPrompt;
+        $promptContent = $prompt ? $prompt . "\n\n" . $defaultPrompt : $defaultPrompt;
 
         $aiGateway = new AIGatewayService();
 
@@ -251,12 +255,10 @@ class ImageToImageJob{
 
         if (!empty($data['task_id'])) {
             try {
-                $redis = new \Redis();
-                $redis->connect('127.0.0.1', 6379);
-                $redis->auth('123456');
-                $redis->select(15);
+                $redis = getTaskRedis();
                 $redis->set("img_to_img_task:" . $data['task_id'], json_encode([
                     'status' => 'completed',
+                    'image' => $db_img_path,
                     'image_url' => $db_img_path,
                     'completed_at' => date('Y-m-d H:i:s')
                 ], JSON_UNESCAPED_UNICODE), ['EX' => 300]);
@@ -265,7 +267,7 @@ class ImageToImageJob{
             }
         }
 
-        return "成功";
+        return $db_img_path;
     }
 
 

+ 2 - 5
application/job/TextToImageJob.php

@@ -35,11 +35,8 @@ class TextToImageJob
                 return;
             }
             
-            //连接Redis将数据队列存到库中
-            $redis = new \Redis();
-            $redis->connect('127.0.0.1', 6379);
-            $redis->auth('123456');
-            $redis->select(15);
+            //连接Redis(配置见 application/extra/queue.php)
+            $redis = getTaskRedis();
             
             echo "\n" . date('Y-m-d H:i:s') . " 任务开始:{$taskId}\n";
 

+ 68 - 33
application/service/AIGatewayService.php

@@ -8,43 +8,78 @@ class AIGatewayService{
      * - api_key:API 调用密钥(Token)
      * - api_url:对应功能的服务端地址
      */
+//    public $config = [
+//        //图生文 gemini-3-pro-preview
+//        'gemini_imgtotxt' => [
+//            'api_key' => 'sk-R4O93k4FrJTXMLYZ2eB32WDPHWiDNbeUdlUcsLjgjeDKuzFI',
+//            'api_url' => 'https://chatapi.onechats.ai/v1beta/models/gemini-3-pro-preview:generateContent'
+//        ],
+//         //文生文 gpt-4
+//         'txttotxtgtp' => [
+//             'api_key' => 'sk-fxlawqVtbbQbNW0wInR3E4wsLo5JHozDC2XOHzMa711su6ss',
+//             'api_url' => 'https://chatapi.onechats.top/v1/chat/completions'
+//         ],
+//         //文生文 gemini-2.0-flash
+//         'txttotxtgemini' => [
+//             'api_key' => 'sk-cqfCZFiiSIdpDjIHLMBbH6uWfeg7iVsASvlubjrNEmfUXbpX',
+//             'api_url' => 'https://chatapi.onechats.ai/v1beta/models/gemini-2.0-flash:generateContent'
+//         ],
+//         //文生图 black-forest-labs/FLUX.1-kontext-pro、dall-e-3、gpt-image-1
+//         'txttoimg' => [
+//             'api_key' => 'sk-MB6SR8qNaTjO80U7HJl4ztivX3zQKPgKVka9oyfVSXIkHSYZ',
+//             'api_url' => 'https://chatapi.onechats.ai/v1/images/generations'
+//         ],
+//         //文生图 gemini-3-pro-image-preview
+//         'gemini_txttoimg' => [
+//             'api_key' => 'sk-8nTt32NDI6q7klryBehwjEfnGaGrX8m1zI0C4ddfudLtanqP',
+//             'api_url' => 'https://chatapi.onechats.ai/v1beta/models/gemini-3-pro-image-preview:streamGenerateContent'
+//         ],
+//        //图生图【gemini-3-pro-image-preview】
+//         'gemini_imgtoimg' => [
+//             'api_key' => 'sk-8nTt32NDI6q7klryBehwjEfnGaGrX8m1zI0C4ddfudLtanqP',
+//             'api_url' => 'https://chatapi.onechats.ai/v1beta/models/gemini-3-pro-image-preview:streamGenerateContent'
+//         ],
+//         //即梦AI 创建视频任务接口【首帧图 + 尾帧图 = 新效果视频】
+//         'Create_ImgToVideo' => [
+//             'api_key' => '',
+//             'api_url' => 'https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks'
+//         ]
+//     ];
+
+    //刘海瑞API接口文档秘钥
     public $config = [
-        //图生文 gemini-3-pro-preview
+        //图生文【gemini-3-pro-preview】
         'gemini_imgtotxt' => [
-            'api_key' => 'sk-R4O93k4FrJTXMLYZ2eB32WDPHWiDNbeUdlUcsLjgjeDKuzFI',
+            'api_key' => 'sk-QiakVPhSisJiOh90LQFpjx9MX27mqGGOpOQ8XjKRhekoNCyr',
             'api_url' => 'https://chatapi.onechats.ai/v1beta/models/gemini-3-pro-preview:generateContent'
         ],
-         //文生文 gpt-4
-         'txttotxtgtp' => [
-             'api_key' => 'sk-fxlawqVtbbQbNW0wInR3E4wsLo5JHozDC2XOHzMa711su6ss',
-             'api_url' => 'https://chatapi.onechats.top/v1/chat/completions'
-         ],
-         //文生文 gemini-2.0-flash
-         'txttotxtgemini' => [
-             'api_key' => 'sk-cqfCZFiiSIdpDjIHLMBbH6uWfeg7iVsASvlubjrNEmfUXbpX',
-             'api_url' => 'https://chatapi.onechats.ai/v1beta/models/gemini-2.0-flash:generateContent'
-         ],
-         //文生图 black-forest-labs/FLUX.1-kontext-pro、dall-e-3、gpt-image-1
-         'txttoimg' => [
-             'api_key' => 'sk-MB6SR8qNaTjO80U7HJl4ztivX3zQKPgKVka9oyfVSXIkHSYZ',
-             'api_url' => 'https://chatapi.onechats.ai/v1/images/generations'
-         ],
-         //文生图 gemini-3-pro-image-preview
-         'gemini_txttoimg' => [
-             'api_key' => 'sk-8nTt32NDI6q7klryBehwjEfnGaGrX8m1zI0C4ddfudLtanqP',
-             'api_url' => 'https://chatapi.onechats.ai/v1beta/models/gemini-3-pro-image-preview:streamGenerateContent'
-         ],
+        //文生文【gpt-4 (OpenAI格式)】
+        'txttotxtgtp' => [
+            'api_key' => 'sk-pAlJU9xScpzDGvj1rhYKpokYcECETaceCSqDMUtq5N7FnbnA',
+            'api_url' => 'https://chatapi.onechats.top/v1/chat/completions'
+        ],
+        //文生文【gemini-2.0-flash (Gemini格式)】
+        'txttotxtgemini' => [
+            'api_key' => 'sk-pAlJU9xScpzDGvj1rhYKpokYcECETaceCSqDMUtq5N7FnbnA',
+            'api_url' => 'https://chatapi.onechats.ai/v1beta/models/gemini-2.0-flash:generateContent'
+        ],
+        //文生图【gemini-3-pro-image-preview】
+        'gemini_txttoimg' => [
+            'api_key' => 'sk-pAlJU9xScpzDGvj1rhYKpokYcECETaceCSqDMUtq5N7FnbnA',
+            'api_url' => 'https://chatapi.onechats.ai/v1beta/models/gemini-3-pro-image-preview:streamGenerateContent'
+        ],
         //图生图【gemini-3-pro-image-preview】
-         'gemini_imgtoimg' => [
-             'api_key' => 'sk-8nTt32NDI6q7klryBehwjEfnGaGrX8m1zI0C4ddfudLtanqP',
-             'api_url' => 'https://chatapi.onechats.ai/v1beta/models/gemini-3-pro-image-preview:streamGenerateContent'
-         ],
-         //即梦AI 创建视频任务接口【首帧图 + 尾帧图 = 新效果视频】
-         'Create_ImgToVideo' => [
-             'api_key' => '',
-             'api_url' => 'https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks'
-         ]
-     ];
+        'gemini_imgtoimg' => [
+            'api_key' => 'sk-IrIWvqkTs8DwvB9MFBRSWKQHdZRawNeKTnVPHjAJ0KryBWeF',
+            'api_url' => 'https://chatapi.onechats.ai/v1beta/models/gemini-3-pro-image-preview:generateContent'
+        ],
+
+        //即梦AI 创建视频任务接口【首帧图 + 尾帧图 = 新效果视频】
+        'Create_ImgToVideo' => [
+            'api_key' => '3da64aa0-afe2-4e3b-be4e-3eea5169aa6a',
+            'api_url' => 'https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks'
+        ]
+    ];
 
 
     /**
@@ -283,7 +318,7 @@ class AIGatewayService{
             'generationConfig' => [
                 'responseModalities' => ['IMAGE'],
                 'imageConfig' => [
-                    'aspectRatio' => '5:4',
+                    'aspectRatio' => $size,
                     'quality' => 'HIGH',
                     'width' => 1000,
                     'height' => 800

+ 3 - 9
application/service/ImageService.php

@@ -59,11 +59,8 @@ class ImageService{
         $taskId = "{$id}-{$time}-{$random}";
         $params['task_id'] = $taskId;
 
-        // 将任务状态存储到Redis
-        $redis = new \Redis();
-        $redis->connect('127.0.0.1', 6379);
-        $redis->auth('123456');
-        $redis->select(15);
+        // 将任务状态存储到Redis(配置见 application/extra/queue.php)
+        $redis = getTaskRedis();
         $redis->set("text_to_image_task:{$taskId}", json_encode([
             'status' => 'pending',
             'created_at' => date('Y-m-d H:i:s')
@@ -87,10 +84,7 @@ class ImageService{
         $taskId = "{$id}-{$time}-{$random}";
         $params['task_id'] = $taskId;
 
-        $redis = new \Redis();
-        $redis->connect('127.0.0.1', 6379);
-        $redis->auth('123456');
-        $redis->select(15);
+        $redis = getTaskRedis();
         $redis->set("img_to_img_task:{$taskId}", json_encode([
             'status' => 'pending',
             'created_at' => date('Y-m-d H:i:s')