liuhairui 5 сар өмнө
parent
commit
887cda6721

+ 1 - 1
application/api/controller/Facility.php

@@ -19,7 +19,7 @@ class Facility extends Api
         $params = $this->request->param('path', '');
         // 查询数据库
         $res = Db::name('text_to_image')
-            ->field('id,chinese_description,english_description,new_image_url,custom_image_url,size,old_image_url,img_name,model')
+            ->field('id,chinese_description,english_description,new_image_url,custom_image_url,size,old_image_url,img_name,model,imgtoimg_url')
             ->where('old_image_url', $params)
             ->where('img_name', '<>', '')
             ->order('id desc')

+ 135 - 57
application/api/controller/WorkOrder.php

@@ -14,37 +14,6 @@ class WorkOrder extends Api
     protected $noNeedLogin = ['*'];
     protected $noNeedRight = ['*'];
 
-    /**
-     * 通过店铺ID-查询对应店铺表数据
-     *
-     */
-    public function PatternApi()
-    {
-        $params = $this->request->param('pattern_id', '');
-        $tableName = 'pattern-' . $params;
-
-        // 连接 MongoDB
-        $mongo = Db::connect('mongodb');
-
-        // 查询指定 skc 的数据
-        $data = $mongo->table($tableName)
-            ->field('
-                name,
-                skc,
-                file
-            ')
-            ->where("skc", '0853004152036')
-            ->select();
-
-        $data = json_decode(json_encode($data), true);  // 数组
-
-        return json([
-            'code' => 0,
-            'msg' => '获取成功',
-            'data' => $data
-        ]);
-    }
-
     /**
      * 出图接口
      * 此方法处理图像转换为文本的请求,将图像信息存入队列以供后续处理。
@@ -64,46 +33,40 @@ class WorkOrder extends Api
      */
     public function imgtowimg()
     {
-        $prompt = $this->request->param('prompt', '');
-        $denoising = (float)$this->request->param('denoising_strength', 0.2);
-        $scale = (float)$this->request->param('scale', 2.0);
-        $modelName = $this->request->param('model', 'realisticVisionV51_v51VAE-inpainting.safetensors [f0d4872d24]');
-
-        // 原图路径
-        $imgRelPath = 'uploads/operate/ai/Preview/arr/0828004096727.png';
+        //原图路径
+        $imgRelPath = 'uploads/operate/ai/Preview/arr/该图案传递了旅行和无忧无虑的心情采用明快的色调充满活力的复古.png';
         $imgPath = ROOT_PATH . 'public/' . $imgRelPath;
 
         if (!file_exists($imgPath)) {
             return json(['code' => 1, 'msg' => '原图不存在:' . $imgRelPath]);
         }
 
-        // 获取原图尺寸 × 倍数
-        list($originW, $originH) = getimagesize($imgPath);
-        $targetW = intval($originW * $scale);
-        $targetH = intval($originH * $scale);
-
-        // base64 编码
+        // 原图 base64 编码
         $imgData = file_get_contents($imgPath);
         $base64Img = base64_encode($imgData);
         $initImage = 'data:image/png;base64,' . $base64Img;
 
-        // 请求体
+        // 参数设置
         $postData = json_encode([
-            'prompt' => $prompt,
-            'steps' => 30,
+            'prompt' => '',
+            'sampler_name' => 'DPM++ 2M SDE Heun',
+            'seed' =>  -1,
+            'steps' => 20,
             'cfg_scale' => 7,
-            'denoising_strength' => $denoising,
-            'width' => $targetW,
-            'height' => $targetH,
-            'resize_mode' => 1,
-            'inpaint_full_res' => true,
+            'denoising_strength' => 0.2,
+            'width' => 1024,
+            'height' => 2048,
             'inpainting_fill' => 1,
+            'resize_mode' => 0, // 自动等比缩放+填充
+            'inpaint_full_res' => true,
             'init_images' => [$initImage],
             'override_settings' => [
-                'sd_model_checkpoint' => $modelName
+                'sd_model_checkpoint' => 'realisticVisionV51_v51VAE-inpainting.safetensors [f0d4872d24]',
+                'sd_vae' => 'anything-v4.5.vae.pt'  // 设置外挂 VAE 模型
             ]
         ]);
 
+        //调用接口
         $apiUrl = "http://20.0.17.233:45001/sdapi/v1/img2img";
         $headers = ['Content-Type: application/json'];
 
@@ -124,10 +87,10 @@ class WorkOrder extends Api
 
         $data = json_decode($response, true);
         if (!isset($data['images'][0])) {
-            return json(['code' => 1, 'msg' => '接口未返回图像数据']);
+            return json(['code' => 1, 'msg' => '未返回图像数据']);
         }
 
-        // 保存图像:原图名 + -1
+        // 保存结果图像
         $resultImg = base64_decode($data['images'][0]);
         $saveDir = ROOT_PATH . 'public/uploads/img2img/';
         if (!is_dir($saveDir)) {
@@ -135,19 +98,105 @@ class WorkOrder extends Api
         }
 
         $originalBaseName = pathinfo($imgRelPath, PATHINFO_FILENAME);
-        $fileName = $originalBaseName . '-1.png';
+        $fileName = $originalBaseName . '.png';
         $savePath = $saveDir . $fileName;
         file_put_contents($savePath, $resultImg);
 
         return json([
             'code' => 0,
-            'msg' => '图像生成成功',
+            'msg' => '图像上下扩展生成成功',
             'data' => [
                 'origin_url' => '/uploads/img2img/' . $fileName
             ]
         ]);
     }
 
+//    public function imgtowimg()
+//    {
+//        $prompt = $this->request->param('prompt', '');
+//        $denoising = (float)$this->request->param('denoising_strength', 0.2);
+//        $scale = (float)$this->request->param('scale', 2.0);
+//        $modelName = $this->request->param('model', 'realisticVisionV51_v51VAE-inpainting.safetensors [f0d4872d24]');
+//
+//        // 原图路径
+//        $imgRelPath = 'uploads/operate/ai/Preview/arr/0828004096727.png';
+//        $imgPath = ROOT_PATH . 'public/' . $imgRelPath;
+//
+//        if (!file_exists($imgPath)) {
+//            return json(['code' => 1, 'msg' => '原图不存在:' . $imgRelPath]);
+//        }
+//
+//        // 获取原图尺寸 × 倍数
+//        list($originW, $originH) = getimagesize($imgPath);
+//        $targetW = intval($originW * $scale);
+//        $targetH = intval($originH * $scale);
+//
+//        // base64 编码
+//        $imgData = file_get_contents($imgPath);
+//        $base64Img = base64_encode($imgData);
+//        $initImage = 'data:image/png;base64,' . $base64Img;
+//
+//        // 请求体
+//        $postData = json_encode([
+//            'prompt' => $prompt,
+//            'steps' => 30,
+//            'cfg_scale' => 7,
+//            'denoising_strength' => $denoising,
+//            'width' => $targetW,
+//            'height' => $targetH,
+//            'resize_mode' => 1,
+//            'inpaint_full_res' => true,
+//            'inpainting_fill' => 1,
+//            'init_images' => [$initImage],
+//            'override_settings' => [
+//                'sd_model_checkpoint' => $modelName
+//            ]
+//        ]);
+//
+//        $apiUrl = "http://20.0.17.233:45001/sdapi/v1/img2img";
+//        $headers = ['Content-Type: application/json'];
+//
+//        $ch = curl_init();
+//        curl_setopt($ch, CURLOPT_URL, $apiUrl);
+//        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+//        curl_setopt($ch, CURLOPT_POST, true);
+//        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+//        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
+//        curl_setopt($ch, CURLOPT_TIMEOUT, 90);
+//        $response = curl_exec($ch);
+//        $error = curl_error($ch);
+//        curl_close($ch);
+//
+//        if ($error) {
+//            return json(['code' => 1, 'msg' => '请求失败:' . $error]);
+//        }
+//
+//        $data = json_decode($response, true);
+//        if (!isset($data['images'][0])) {
+//            return json(['code' => 1, 'msg' => '接口未返回图像数据']);
+//        }
+//
+//        // 保存图像:原图名 + -1
+//        $resultImg = base64_decode($data['images'][0]);
+//        $saveDir = ROOT_PATH . 'public/uploads/img2img/';
+//        if (!is_dir($saveDir)) {
+//            mkdir($saveDir, 0755, true);
+//        }
+//
+//        $originalBaseName = pathinfo($imgRelPath, PATHINFO_FILENAME);
+//        $fileName = $originalBaseName . '-1.png';
+//        $savePath = $saveDir . $fileName;
+//        file_put_contents($savePath, $resultImg);
+//
+//        return json([
+//            'code' => 0,
+//            'msg' => '图像生成成功',
+//            'data' => [
+//                'origin_url' => '/uploads/img2img/' . $fileName
+//            ]
+//        ]);
+//    }
+
     /**
      * 后期图像处理
      * /sdapi/v1/extra-single-image
@@ -435,6 +484,35 @@ class WorkOrder extends Api
 //            ]);
 //        }
 //    }
+    /**
+     * 通过店铺ID-查询对应店铺表数据
+     *
+     */
+    public function PatternApi()
+    {
+        $params = $this->request->param('pattern_id', '');
+        $tableName = 'pattern-' . $params;
+
+        // 连接 MongoDB
+        $mongo = Db::connect('mongodb');
 
+        // 查询指定 skc 的数据
+        $data = $mongo->table($tableName)
+            ->field('
+                name,
+                skc,
+                file
+            ')
+            ->where("skc", '0853004152036')
+            ->select();
+
+        $data = json_decode(json_encode($data), true);  // 数组
+
+        return json([
+            'code' => 0,
+            'msg' => '获取成功',
+            'data' => $data
+        ]);
+    }
 
 }

+ 3 - 0
application/job/ImageArrJob.php

@@ -63,6 +63,9 @@ class ImageArrJob
                 case '文生图':
                     Queue::push('app\job\TextToImageJob', array_merge($value, ['chain_next' => $chain_next]), 'txttoimg');
                     break;
+                case '图生图':
+                    Queue::push('app\job\ImageToImageJob', array_merge($value, ['chain_next' => $chain_next]), 'imgtoimg');
+                    break;
                 default:
                     \think\Log::warning("未识别的任务类型:" . json_encode($value, JSON_UNESCAPED_UNICODE));
                     break;

+ 193 - 0
application/job/ImageToImageJob.php

@@ -0,0 +1,193 @@
+<?php
+namespace app\job;
+use app\service\AIGatewayService;
+use think\Db;
+use think\queue\Job;
+use think\Queue;
+
+class ImageToImageJob{
+
+    public function fire(Job $job, $data)
+    {
+
+        $logId = $data['log_id'] ?? null;
+
+        try {
+            // 任务类型校验(必须是图生图)
+            if (!isset($data['type']) || $data['type'] !== '图生图') {
+                $job->delete();
+                return;
+            }
+
+            $startTime = date('Y-m-d H:i:s');
+            echo "━━━━━━━━━━ ▶ 图生图任务开始处理━━━━━━━━━━\n";
+            echo "处理时间:{$startTime}\n";
+
+            // 更新日志状态:处理中
+            if ($logId) {
+                Db::name('image_task_log')->where('id', $logId)->update([
+                    'status' => 1,
+                    'log' => '图生图处理中',
+                    'update_time' => $startTime
+                ]);
+            }
+
+            //拼接原图文件路径 + 图片名称
+            $old_image_url = rtrim($data['sourceDir'], '/') . '/' . ltrim($data['file_name'], '/');
+
+            $list = Db::name("text_to_image")
+                ->where('old_image_url', $old_image_url)
+                ->where('img_name', '<>', '')
+                ->where('status', 1)
+                ->select();
+
+            if (!empty($list)) {
+                $total = count($list);
+                echo "📊 共需处理:{$total} 条记录\n\n";
+
+                foreach ($list as $index => $row) {
+                    $currentIndex = $index + 1;
+                    $begin = date('Y-m-d H:i:s');
+                    echo "处理时间:{$begin}\n";
+                    echo "👉 正在处理第 {$currentIndex} 条,ID: {$row['id']}\n";
+
+                    // 调用生成图像方法
+                    $result = $this->ImageToImage(
+                        $data["file_name"],
+                        $data["outputDir"],
+                        $row["new_image_url"],
+                        1024,
+                        2048
+                    );
+
+                    $resultText = ($result === true || $result === 1 || $result === '成功') ? '成功' : '失败或无返回';
+                    echo "✅ 处理结果:{$resultText}\n";
+
+                    $end = date('Y-m-d H:i:s');
+                    echo "完成时间:{$end}\n";
+                    echo "Processed: " . static::class . "\n";
+                    echo "图生图已处理完成\n\n";
+                }
+
+                // 更新日志状态:成功
+                if ($logId) {
+                    Db::name('image_task_log')->where('id', $logId)->update([
+                        'status' => 2,
+                        'log' => '图生图处理成功',
+                        'update_time' => date('Y-m-d H:i:s')
+                    ]);
+                }
+
+                echo date('Y-m-d H:i:s') . " 图生图任务全部完成\n";
+            } else {
+
+                echo "未找到可处理的数据,跳过执行\n";
+                if ($logId) {
+                    Db::name('image_task_log')->where('id', $logId)->update([
+                        'status' => 2,
+                        'log' => '无数据可处理,已跳过'.$old_image_url,
+                        'update_time' => date('Y-m-d H:i:s')
+                    ]);
+                }
+            }
+
+            // 如果还有链式任务,继续推送
+            if (!empty($data['chain_next'])) {
+                $nextType = array_shift($data['chain_next']);
+                $data['type'] = $nextType;
+
+                Queue::push('app\job\ImageArrJob', [
+                    'task_id' => $data['task_id'],
+                    'data' => [$data]
+                ], 'arrimage');
+            }
+
+            $job->delete();
+
+        }  catch (\Exception $e) {
+            //异常处理,记录失败日志
+            echo "错误信息: " . $e->getMessage() . "\n";
+            echo "文件: " . $e->getFile() . "\n";
+            echo "行号: " . $e->getLine() . "\n";
+
+            // 删除当前任务
+            $job->delete();
+        }
+    }
+
+    /**
+     * 失败回调(可用于后续通知或重试机制)
+     */
+    public function failed($data)
+    {
+        echo "ImageJob failed: " . json_encode($data);
+    }
+
+
+    public function ImageToImage($fileName, $outputDirRaw, $new_image_url, $width, $height)
+    {
+        // 统一路径分隔符
+        $rootPath = str_replace('\\', '/', ROOT_PATH);
+
+        // 输出目录,如:ROOT/public/uploads/operate/ai/dall-e/hua/
+        $outputDir = rtrim($rootPath . 'public/' . $outputDirRaw, '/') . '/';
+
+        // 当前日期目录,如:2025-06-16/
+        $dateDir = date('Y-m-d') . '/';
+
+        // 完整基本路径,如:ROOT/public/uploads/operate/ai/dall-e/hua/2025-06-16/
+        $fullBaseDir = $outputDir . $dateDir;
+
+        // 创建输出目录,包括原图目录、1024x2048目录、自定义尺寸目录
+        foreach ([$fullBaseDir, $fullBaseDir . '1024x2048/', $fullBaseDir . "{$width}x{$height}/"] as $dir) {
+            if (!is_dir($dir)) {
+                mkdir($dir, 0755, true);
+            }
+        }
+
+        // 从数据库中查询原图记录
+        $record = Db::name('text_to_image')
+            ->where('old_image_url', 'like', "%{$fileName}")
+            ->order('id desc')
+            ->find();
+
+        if (!$record) {
+            return json([
+                'code' => 1,
+                'msg' => '没有找到匹配的图像记录'
+            ]);
+        }
+
+        // 调用图生图 API
+        $ai = new AIGatewayService();
+        $res = $ai->imgtoimgGptApi('', $new_image_url);
+
+        // 检查返回结果
+        if (!isset($res['code']) || $res['code'] !== 0) {
+            return json([
+                'code' => 1,
+                'msg' => $res['msg'] ?? '图像生成失败'
+            ]);
+        }
+
+        // 解码图像 base64 数据
+        $originalBaseName = pathinfo($new_image_url, PATHINFO_FILENAME);
+        $finalFileName = $originalBaseName . '.png';
+
+        // 保存到 1024x2048 子目录
+        $targetDir = $fullBaseDir . '1024x2048/';
+        $savePath = $targetDir . $finalFileName;
+        file_put_contents($savePath, base64_decode($res['data']['url']));
+
+        // ✅ 修正:数据库中记录相对路径一致
+        Db::name('text_to_image')->where('id', $record['id'])->update([
+            'imgtoimg_url' => $outputDirRaw . '/' . $dateDir . '1024x2048/' . $finalFileName,
+            'status_name' => '图生图',
+            'error_msg' => '',
+            'update_time' => date('Y-m-d H:i:s')
+        ]);
+
+        return '成功';
+    }
+
+}

+ 2 - 1
application/job/TextToImageJob.php

@@ -48,6 +48,7 @@ class TextToImageJob
                 ->where('img_name', '<>', '')
                 ->where('status', 0)
                 ->select();
+          
 
             if (!empty($list)) {
                 $total = count($list);
@@ -95,7 +96,7 @@ class TextToImageJob
                 if ($logId) {
                     Db::name('image_task_log')->where('id', $logId)->update([
                         'status' => 2,
-                        'log' => '无数据可处理,已跳过',
+                        'log' => '无数据可处理,已跳过'.$old_image_url,
                         'update_time' => date('Y-m-d H:i:s')
                     ]);
                 }