ImageService.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <?php
  2. namespace app\service;
  3. use think\Db;
  4. use think\Queue;
  5. /**
  6. * ImageService 类用于处理图像任务和存放日志队列。
  7. * 该类将前端传过来的多个图像信息推送到处理队列中。
  8. */
  9. class ImageService{
  10. /**
  11. * 推送图像任务到队列(支持链式和单独模式)
  12. * @param array $params 请求参数,包含图像批次、模型类型、尺寸等
  13. */
  14. public function handleImage($params) {
  15. if (!isset($params["batch"])) {return false;}
  16. $arr = [];
  17. // 获取图像批量信息
  18. $batch = $params["batch"];
  19. // 获取执行次数数量
  20. $num = $params["num"];
  21. /*获取ids为1模板
  22. * english_content 文生文提示词
  23. * content 图生文提示词
  24. * */
  25. $template = Db::name('template')
  26. ->field('id,english_content,content,ids')
  27. ->where('ids',1)
  28. ->find();
  29. // 构建任务基础结构(每图生成 N 份任务)
  30. foreach ($batch as $k => $v) {
  31. $baseItem = [
  32. "sourceDir" => $this->sourceDir($v, 1),
  33. "outputDir" => $this->sourceDir($v, 2),
  34. "file_name" => $this->sourceDir($v, 3),
  35. "type" => $params['type'] ?? '',
  36. "selectedOption" => $params['selectedOption'],
  37. "prompt" => $template['content'],
  38. "width" => $params['width'],
  39. "height" => $params['height']
  40. ];
  41. // 创建$num个相同的项目并合并到$arr
  42. $arr = array_merge($arr, array_fill(0, $num, $baseItem));
  43. }
  44. // 插入队列日志
  45. $insertData = [
  46. 'create_time' => date('Y-m-d H:i:s'),
  47. 'old_image_file' => $params['old_image_file'],
  48. 'status' => '等待中',
  49. 'image_count' => count($arr),
  50. 'params' => json_encode($params, JSON_UNESCAPED_UNICODE)
  51. ];
  52. //模型任务类型处理
  53. if (empty($params['type'])) {
  54. /*
  55. * 执行全部任务时一键链式任务队列
  56. * 用于存放队列日志
  57. * 链式任务:图生文 → 文生文 → 文生图
  58. * */
  59. $insertData['model'] = "gpt-4-vision-preview,"."gpt-4,".$params['selectedOption'];
  60. $insertData['model_name'] = '文生图';
  61. $task_id = Db::name('queue_logs')->insertGetId($insertData);
  62. $arr = array_map(function ($item) use ($task_id) {
  63. $item['type'] = '图生文';
  64. $item['chain_next'] = ['文生文', '文生图','图生图'];
  65. $item['task_id'] = $task_id;
  66. return $item;
  67. }, $arr);
  68. $payload = [
  69. 'task_id' => $task_id,
  70. 'data' => $arr
  71. ];
  72. Queue::push('app\job\ImageArrJob', $payload, "arrimage");
  73. } else {
  74. // 指定单个独立任务类型
  75. switch ($params['type']) {
  76. case '图生文':
  77. $insertData['model'] = 'gpt-4-vision-preview';
  78. $insertData['model_name'] = '图生文';
  79. break;
  80. case '文生文':
  81. $insertData['model'] = 'gpt-4';
  82. $insertData['model_name'] = '文生文';
  83. break;
  84. case '文生图':
  85. $insertData['model'] = $params['selectedOption'];
  86. $insertData['model_name'] = '文生图';
  87. break;
  88. case '图生图':
  89. $insertData['model'] = "realisticVisionV51_v51VAE-inpainting.safetensors [f0d4872d24]";
  90. $insertData['model_name'] = '图生图';
  91. break;
  92. default:
  93. return false;
  94. }
  95. //将一组队列存放queue_logs任务表中,将新增id最为任务id记录
  96. $task_id = Db::name('queue_logs')->insertGetId($insertData);
  97. $arr = array_map(function ($item) use ($params, $task_id) {
  98. $item['type'] = $params['type'];
  99. $item['task_id'] = $task_id;
  100. return $item;
  101. }, $arr);
  102. // 投递任务到队列
  103. $payload = [
  104. 'task_id' => $task_id,
  105. 'data' => $arr
  106. ];
  107. Queue::push('app\job\ImageArrJob', $payload, "arrimage");
  108. }
  109. return true;
  110. }
  111. /**
  112. * 解析图像路径,返回不同组成部分
  113. *
  114. * @param string $filePath 图像路径(如 uploads/operate/ai/Preview/20240610/xxx.png)
  115. * @param int $type 返回内容类型:
  116. * 1 = 基础路径(去掉日期+文件名)
  117. * sourceDir 源目录uploads/operate/ai/Preview/
  118. * 2 = 输出路径(Preview 替换为 dall-e,并加日期代表当天数据存到当天文件夹中)
  119. * outputDir 输出目录/uploads/operate/ai/dall-e/hua/并加日期
  120. * 3 = 文件名
  121. * file_name 文件名0194b6fdd6203fda369d5e3b74b6b454.png
  122. * @return string|null
  123. */
  124. public function sourceDir($filePath, $type) {
  125. $arr = [];
  126. $pathParts = explode('/', $filePath);
  127. $filename = array_pop($pathParts); // 最后是文件名
  128. $baseParts = $pathParts;
  129. // 查找是否有 8 位数字(即日期)文件夹
  130. $date = '';
  131. foreach ($pathParts as $index => $part) {
  132. if (preg_match('/^\d{8}$/', $part)) {
  133. $date = $part;
  134. unset($baseParts[$index]); // 日期不算在 basePath 里
  135. break;
  136. }
  137. }
  138. $arr = [
  139. 'basePath' => implode('/', $baseParts),
  140. 'date' => $date,
  141. 'filename' => $filename
  142. ];
  143. // 根据类型返回不同路径
  144. if ($type == 1) {
  145. return $arr["basePath"];
  146. }
  147. if ($type == 2) {
  148. return '/' . str_replace('/Preview/', '/dall-e/', $arr["basePath"]) . $arr["date"];
  149. }
  150. if ($type == 3) {
  151. return $arr["filename"];
  152. }
  153. }
  154. }