WorkOrder.php 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\controller\Api;
  4. use app\job\ImageJob;
  5. use app\service\AIGatewayService;
  6. use app\service\ImageService;
  7. use think\App;
  8. use think\Db;
  9. use think\Exception;
  10. use think\Log;
  11. use think\Queue;
  12. use think\queue\job\Redis;
  13. use think\Request;
  14. class WorkOrder extends Api{
  15. protected $noNeedLogin = ['*'];
  16. protected $noNeedRight = ['*'];
  17. public function index(){echo '访问成功';}
  18. /**
  19. * AI队列入口处理 出图接口
  20. * 此方法处理图像转换为文本的请求,将图像信息存入队列以供后续处理。
  21. */
  22. public function imageToText()
  23. {
  24. $params = $this->request->param();
  25. $service = new ImageService();
  26. $service->handleImage($params);
  27. $this->success('任务成功提交至队列');
  28. }
  29. /**
  30. * 将远程图片保存到本地指定路径
  31. * @param string $url 远程图片URL
  32. * @return string|null 本地保存的相对路径,如果保存失败则返回null
  33. */
  34. private function saveImageFromUrl($url) {
  35. if (!function_exists('curl_init')) {
  36. return null;
  37. }
  38. // 设置保存路径:/uploads/operate/ai/dall-e/default/年月日/
  39. $date = date('Ymd');
  40. $basePath = '/uploads/operate/ai/dall-e/default/' . $date . '/';
  41. $savePath = ROOT_PATH . 'public' . $basePath;
  42. // 创建目录结构
  43. if (!is_dir($savePath)) {
  44. if (!mkdir($savePath, 0777, true)) {
  45. return null;
  46. }
  47. }
  48. // 生成唯一的文件名
  49. $extension = pathinfo($url, PATHINFO_EXTENSION);
  50. if (empty($extension)) {
  51. $extension = 'png';
  52. }
  53. $filename = uniqid() . '.' . $extension;
  54. $fullPath = $savePath . $filename;
  55. // 使用curl下载图片
  56. $ch = curl_init();
  57. curl_setopt($ch, CURLOPT_URL, $url);
  58. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  59. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  60. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  61. curl_setopt($ch, CURLOPT_TIMEOUT, 30);
  62. curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36');
  63. $imageData = curl_exec($ch);
  64. curl_close($ch);
  65. // 检查下载是否成功
  66. if (empty($imageData)) {
  67. return null;
  68. }
  69. // 保存图片到本地
  70. if (file_put_contents($fullPath, $imageData)) {
  71. // 返回相对路径
  72. return $basePath . $filename;
  73. } else {
  74. return null;
  75. }
  76. }
  77. /**
  78. * 图片下载接口
  79. * 该方法用于从远程URL下载图片并返回给客户端
  80. */
  81. public function download_image() {
  82. $imageUrl = $this->request->post('image_url');
  83. if (!$imageUrl) {
  84. return json(['code' => 1, 'message' => '图片URL不能为空']);
  85. }
  86. // 使用curl获取图片数据
  87. if (!function_exists('curl_init')) {
  88. return json(['code' => 1, 'message' => '服务器不支持curl']);
  89. }
  90. $ch = curl_init();
  91. curl_setopt($ch, CURLOPT_URL, $imageUrl);
  92. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  93. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  94. curl_setopt($ch, CURLOPT_TIMEOUT, 30);
  95. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  96. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  97. $imageData = curl_exec($ch);
  98. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  99. $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
  100. curl_close($ch);
  101. if ($httpCode != 200 || empty($imageData)) {
  102. return json(['code' => 1, 'message' => '图片下载失败']);
  103. }
  104. $extension = 'png';
  105. if (strpos($contentType, 'image/jpeg') !== false) {
  106. $extension = 'jpg';
  107. } elseif (strpos($contentType, 'image/png') !== false) {
  108. $extension = 'png';
  109. } elseif (strpos($contentType, 'image/gif') !== false) {
  110. $extension = 'gif';
  111. }
  112. // 设置响应头
  113. header('Content-Type: application/octet-stream');
  114. header('Content-Disposition: attachment; filename="generated-image-' . date('YmdHis') . '.' . $extension . '"');
  115. header('Content-Length: ' . strlen($imageData));
  116. // 输出图片数据
  117. echo $imageData;
  118. exit;
  119. }
  120. //扩写文本内容提示词
  121. public function GetTxtToTxt(){
  122. $params = $this->request->param();
  123. if($params['status_val'] == '文生图'){
  124. $service = new ImageService();
  125. $result = $service->handleTextToImg($params);
  126. // 处理文生图结果
  127. if ($result['success']) {
  128. $remoteUrl = $result['url'];
  129. // // 保存图片到本地指定路径
  130. // $localFilePath = $this->saveImageFromUrl($remoteUrl);
  131. //
  132. // // 保存图片信息到product表
  133. // $productData = [
  134. // 'chinese_description' => $params['prompt'],
  135. // 'txt_image_url' => $localFilePath,
  136. // 'create_time' => date('Y-m-d H:i:s')
  137. // ];
  138. // $productId = Db::name('product')->insertGetId($productData);
  139. $this->success('图片生成成功', [
  140. // 'local_url' => $localFilePath,
  141. // 'product_id' => $productId,
  142. 'url' => $remoteUrl
  143. ]);
  144. } else {
  145. $this->error('文生图请求失败', ['message' => $result['message']]);
  146. }
  147. }elseif($params['status_val'] == '文生文'){
  148. $fullPrompt = $params['prompt'];
  149. // 优化提示词指令:放在所有内容之后,明确要求生成连续的一段话
  150. $fullPrompt .= "
  151. 请根据上述内容生成一段完整的话术,要求:
  152. 1. 内容必须是连贯的一段话,不要使用列表、分隔线或其他结构化格式
  153. 2. 不要包含非文本元素的描述
  154. 3. 不要添加任何额外的引导语、解释或开场白
  155. 4. 语言流畅自然";
  156. $textToTextParams = [
  157. 'prompt' => $fullPrompt,
  158. 'model' => $params['model'] ?? 'gemini-2.0-flash' // 默认使用文生文gtp-4模型
  159. ];
  160. $service = new ImageService();
  161. $result = $service->handleTextToText($textToTextParams);
  162. if ($result['success']) {
  163. $this->success('文生文生成成功', [
  164. 'content' => $result['data']
  165. ]);
  166. } else {
  167. $this->error('文生文请求失败', $result['message']);
  168. }
  169. }else{
  170. $this->error('请求失败');
  171. }
  172. }
  173. //获取服务器URL IP地址:端口
  174. public function GetHttpUrl(){
  175. $data = Db::name('http_url')->find();
  176. $fullUrl = "http://" . $data['baseUrl'] . ":" . $data['port'];
  177. $res = [
  178. 'code' => 0,
  179. 'msg' => '成功',
  180. 'data' => [
  181. 'full_url' => $fullUrl,
  182. 'id' => $data['id'],
  183. 'baseUrl' => $data['baseUrl'],
  184. 'port' => $data['port']
  185. ]
  186. ];
  187. return json($res);
  188. }
  189. //获取视频列表
  190. public function Getvideolist(){
  191. if (!$this->request->isGet()) {
  192. $this->error('请求方式错误');
  193. }
  194. $params = $this->request->param();
  195. $search = input('search', '');
  196. $page = isset($params['page']) ? (int)$params['page'] : 1;
  197. $limit = isset($params['limit']) ? (int)$params['limit'] : 50;
  198. $where = [];
  199. if (!empty($search)) {
  200. $where['prompt'] = ['like', '%' . $search . '%'];
  201. }
  202. $list = Db::name('video')->where('mod_rq', null)
  203. ->where($where)
  204. ->order('id desc')
  205. ->limit(($page - 1) * $limit, $limit)
  206. ->select();
  207. $total = Db::name('video')->where('mod_rq', null)
  208. ->where($where)
  209. ->count();
  210. $res['code'] = 0;
  211. $res['msg'] = '成功';
  212. $res['count'] = $total;
  213. $res['data'] = $list;
  214. return json($res);
  215. }
  216. //文生视频
  217. public function video(){
  218. $params = $this->request->param();
  219. $apiUrl = 'https://chatapi.onechats.ai/v1/videos';
  220. $apiKey = 'sk-sWW1GFlnjbrDRb1DkMEzePIxgdvLK6cZt0Qg93yDMVP2z1yN';
  221. $postData = [
  222. 'prompt' => $params['prompt'],
  223. 'model' => $params['model'],
  224. 'seconds' => $params['seconds'],
  225. 'size' => $params['size'],
  226. ];
  227. // 初始化CURL
  228. $ch = curl_init();
  229. curl_setopt($ch, CURLOPT_URL, $apiUrl);
  230. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  231. curl_setopt($ch, CURLOPT_POST, true);
  232. curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
  233. curl_setopt($ch, CURLOPT_HTTPHEADER, [
  234. 'Authorization: Bearer ' . $apiKey
  235. ]);
  236. curl_setopt($ch, CURLOPT_TIMEOUT, 300);
  237. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  238. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
  239. curl_setopt($ch, CURLOPT_HEADER, true); // 获取响应头
  240. curl_setopt($ch, CURLOPT_VERBOSE, true); // 启用详细输出以进行调试
  241. // 创建临时文件来捕获详细的cURL输出
  242. $verbose = fopen('php://temp', 'w+');
  243. curl_setopt($ch, CURLOPT_STDERR, $verbose);
  244. // 执行请求
  245. $response = curl_exec($ch);
  246. //HTTP状态码
  247. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  248. // 获取详细的cURL调试信息
  249. rewind($verbose);
  250. //CURL调试信息
  251. $verboseLog = stream_get_contents($verbose);
  252. fclose($verbose);
  253. // 分离头部和主体
  254. $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
  255. //响应头部
  256. $header = substr($response, 0, $header_size);
  257. //响应主体
  258. $body = substr($response, $header_size);
  259. // 检查CURL错误
  260. $curlError = curl_error($ch);
  261. curl_close($ch);
  262. $responseData = json_decode($body, true);
  263. // 检查API是否返回了错误信息
  264. if (isset($responseData['error'])) {
  265. $errorMessage = isset($responseData['error']['message']) ? $responseData['error']['message'] : 'API请求失败';
  266. return json([
  267. 'code' => 1,
  268. 'msg' => '视频生成请求失败',
  269. 'data' => [
  270. 'error_type' => isset($responseData['error']['type']) ? $responseData['error']['type'] : 'unknown',
  271. 'error_code' => isset($responseData['error']['code']) ? $responseData['error']['code'] : 'unknown',
  272. 'error_message' => $errorMessage
  273. ]
  274. ]);
  275. }
  276. // 检查是否有自定义错误格式
  277. if (isset($responseData['code']) && $responseData['code'] === 'fail_to_fetch_task' && isset($responseData['message'])) {
  278. return json([
  279. 'code' => 1,
  280. 'msg' => '视频生成请求失败',
  281. 'data' => [
  282. 'error_code' => $responseData['code'],
  283. 'error_message' => $responseData['message']
  284. ]
  285. ]);
  286. }
  287. // 检查是否存在id字段
  288. if (!isset($responseData['id'])) {
  289. return json([
  290. 'code' => 1,
  291. 'msg' => '无法获取视频ID',
  292. 'data' => [
  293. 'response_data' => $responseData,
  294. 'http_code' => $httpCode
  295. ]
  296. ]);
  297. }
  298. $videoData = [
  299. 'video_id' => $responseData['id'],
  300. 'prompt' => $postData['prompt'],
  301. 'model' => $postData['model'],
  302. 'seconds' => $postData['seconds'],
  303. 'size' => $postData['size'],
  304. 'sys_rq' => date("Y-m-d H:i:s")
  305. ];
  306. // 尝试插入数据
  307. try {
  308. $res = Db::name('video')->insert($videoData);
  309. return json([
  310. 'code' => 0,
  311. 'msg' => '视频正在生成中',
  312. 'data ' => [
  313. 'video_id' => $responseData['id'],
  314. 'insert_result' => $res
  315. ]
  316. ]);
  317. } catch (Exception $e) {
  318. return json([
  319. 'code' => 1,
  320. 'msg' => '数据库操作失败',
  321. 'data' => [
  322. 'error_message' => $e->getMessage()
  323. ]
  324. ]);
  325. }
  326. }
  327. /**
  328. * 获取视频内容
  329. * 下载已完成的视频内容
  330. */
  331. public function videoContent(){
  332. // 从请求参数获取video_id,如果没有则使用默认值
  333. $video_id = input('get.video_id');
  334. $apiKey = 'sk-sWW1GFlnjbrDRb1DkMEzePIxgdvLK6cZt0Qg93yDMVP2z1yN';
  335. // 1. 先检查视频状态
  336. $statusUrl = 'https://chatapi.onechats.ai/v1/videos/' . $video_id;
  337. $statusData = $this->fetchVideoStatus($statusUrl, $apiKey);
  338. // 检查视频状态
  339. if ($statusData['status'] !== 'completed') {
  340. return json([
  341. 'code' => 202,
  342. 'msg' => '视频尚未生成完成',
  343. 'data' => [
  344. 'video_id' => $video_id,
  345. 'status' => $statusData['status'],
  346. 'progress' => $statusData['progress'],
  347. 'created_at' => $statusData['created_at'],
  348. 'message' => '请稍后再试,视频仍在' . ($statusData['status'] === 'queued' ? '排队中' : '处理中')
  349. ]
  350. ]);
  351. }
  352. // 2. 视频生成完成,准备下载
  353. $apiUrl = 'https://chatapi.onechats.ai/v1/videos/' . $video_id . '/content';
  354. // 获取可选的variant参数
  355. $variant = input('get.variant', '');
  356. if (!empty($variant)) {
  357. $apiUrl .= '?variant=' . urlencode($variant);
  358. }
  359. // 创建保存目录
  360. $saveDir = ROOT_PATH . 'public' . DS . 'uploads' . DS . 'videos' . DS . date('Ymd');
  361. if (!is_dir($saveDir)) {
  362. mkdir($saveDir, 0755, true);
  363. }
  364. // 生成唯一文件名
  365. $filename = $video_id . '.mp4';
  366. $localPath = DS . 'uploads' . DS . 'videos' . DS . date('Ymd') . DS . $filename;
  367. $fullPath = $saveDir . DS . $filename;
  368. // 3. 下载视频
  369. $videoData = $this->downloadVideo($apiUrl, $apiKey);
  370. // 4. 保存视频文件
  371. if (file_put_contents($fullPath, $videoData) === false) {
  372. throw new Exception('视频保存失败');
  373. }
  374. // 确保路径使用正斜杠,并只保存相对路径部分
  375. $localPath = str_replace('\\', '/', $localPath);
  376. // 移除开头的斜杠,确保路径格式为uploads/videos/...
  377. $savePath = ltrim($localPath, '/');
  378. // 将正确格式的文件路径存入数据库
  379. Db::name('video')->where('video_id', $video_id)->update([
  380. 'web_url' => $savePath
  381. ]);
  382. // 返回成功响应
  383. return json([
  384. 'code' => 0,
  385. 'msg' => '视频下载成功',
  386. 'data' => [
  387. 'video_id' => $video_id,
  388. 'local_path' => $localPath,
  389. 'web_url' => $savePath,
  390. 'file_size' => filesize($fullPath)
  391. ]
  392. ]);
  393. }
  394. /**
  395. * 获取视频状态
  396. */
  397. private function fetchVideoStatus($url, $apiKey) {
  398. $ch = curl_init();
  399. curl_setopt($ch, CURLOPT_URL, $url);
  400. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  401. curl_setopt($ch, CURLOPT_HTTPGET, true);
  402. curl_setopt($ch, CURLOPT_HTTPHEADER, [
  403. 'Authorization: Bearer ' . $apiKey,
  404. 'Accept: application/json'
  405. ]);
  406. curl_setopt($ch, CURLOPT_TIMEOUT, 30);
  407. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  408. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
  409. $response = curl_exec($ch);
  410. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  411. $error = curl_error($ch);
  412. curl_close($ch);
  413. if ($error) {
  414. throw new Exception('获取视频状态失败: ' . $error);
  415. }
  416. if ($httpCode < 200 || $httpCode >= 300) {
  417. throw new Exception('获取视频状态失败,HTTP状态码: ' . $httpCode);
  418. }
  419. $data = json_decode($response, true);
  420. if (!is_array($data)) {
  421. throw new Exception('视频状态数据格式错误');
  422. }
  423. return $data;
  424. }
  425. /**
  426. * 下载视频文件
  427. */
  428. private function downloadVideo($url, $apiKey) {
  429. $ch = curl_init();
  430. curl_setopt($ch, CURLOPT_URL, $url);
  431. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  432. curl_setopt($ch, CURLOPT_HTTPGET, true);
  433. curl_setopt($ch, CURLOPT_HTTPHEADER, [
  434. 'Authorization: Bearer ' . $apiKey
  435. ]);
  436. curl_setopt($ch, CURLOPT_TIMEOUT, 300);
  437. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  438. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
  439. $response = curl_exec($ch);
  440. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  441. $error = curl_error($ch);
  442. curl_close($ch);
  443. if ($error) {
  444. throw new Exception('视频下载失败: ' . $error);
  445. }
  446. if ($httpCode < 200 || $httpCode >= 300) {
  447. throw new Exception('视频下载失败,HTTP状态码: ' . $httpCode);
  448. }
  449. return $response;
  450. }
  451. public function textToImage()
  452. {
  453. $outputDirRaw = 'uploads/operate/ai/Preview/undefined_BRdP4/3';
  454. $img_name = '42131321';
  455. $rootPath = str_replace('\\', '/', ROOT_PATH);
  456. $outputDir = rtrim($rootPath . 'public/' . $outputDirRaw, '/') . '/';
  457. $dateDir = date('Y-m-d') . '/';
  458. $fullBaseDir = $outputDir . $dateDir;
  459. // 确保目录存在
  460. if (!is_dir($fullBaseDir . '2048x2048/')) {
  461. mkdir($fullBaseDir . '2048x2048/', 0755, true);
  462. }
  463. // // API配置
  464. // $config = [
  465. // 'api_url' => 'https://chatapi.onechats.ai/mj/submit/imagine',
  466. // 'fetch_url' => 'https://chatapi.onechats.ai/mj/task/',
  467. // 'api_key' => 'sk-iURfrAgzAjhZ4PpPLwzmWIAhM7zKfrkwDvyxk4RVBQ4ouJNK',
  468. // 'default_prompt' => '恐怖的树状怪物,拥有尖牙利爪和血红眼睛,在蓝色背景下显得阴森可怕,风格为黑暗奇幻。'
  469. // ];
  470. //
  471. // // 1. 准备请求数据
  472. // $prompt = $config['default_prompt'];
  473. // $postData = [
  474. // 'botType' => 'MID_JOURNEY',
  475. // 'prompt' => $prompt,
  476. // 'base64Array' => [],
  477. // 'accountFilter' => [
  478. // 'channelId' => "",
  479. // 'instanceId' => "",
  480. // 'modes' => [],
  481. // 'remark' => "",
  482. // 'remix' => true,
  483. // 'remixAutoConsidered' => true
  484. // ],
  485. // 'notifyHook' => "",
  486. // 'state' => ""
  487. // ];
  488. // // 2. 提交生成请求
  489. // $generateResponse = $this->sendApiRequest($config['api_url'], $postData, $config['api_key']);
  490. // echo "<pre>";
  491. // print_r($generateResponse);
  492. // echo "<pre>";
  493. // $generateData = json_decode($generateResponse, true);
  494. // echo "<pre>";
  495. // print_r($generateData);
  496. // echo "<pre>";
  497. // if (empty($generateData['result'])) {
  498. // throw new Exception('生成失败: '.($generateData['message'] ?? '未知错误'));
  499. // }
  500. //
  501. // die;
  502. // $taskId = "1755229064353588";
  503. $taskId = "1755234114253556";
  504. // $taskId = "1755224966357751";
  505. // 3. 等待图片生成完成
  506. sleep(3);
  507. $imageUrl = $this->getImageSeed($taskId);
  508. echo "<pre>";
  509. print_r($imageUrl);
  510. echo "<pre>";die;
  511. $img_name = mb_substr(preg_replace('/[^\x{4e00}-\x{9fa5}A-Za-z0-9_\- ]/u', '', $img_name), 0, 30);
  512. $filename = $img_name . '.png';
  513. $path512 = $fullBaseDir . '2048x2048/' . $filename;
  514. // 下载并保存图片
  515. // file_get_contents($imageUrl['data']['imageUrl']);
  516. // 下载并保存图片到本地文件夹中
  517. $imageData = file_get_contents($imageUrl['data']['imageUrl']);
  518. $result = file_put_contents($path512, $imageData);
  519. if ($result === false) {
  520. die('保存图片失败,请检查目录权限');
  521. }
  522. // 数据库更新
  523. Db::name('text_to_image')->where('id', '10694')->update([
  524. 'new_image_url' => str_replace($rootPath . 'public/', '', $path512),
  525. 'img_name' => $img_name,
  526. 'model' => 'MID_JOURNEY',
  527. 'status' => trim($img_name) === '' ? 0 : 1,
  528. 'status_name' => "文生图",
  529. 'size' => "2048",
  530. 'quality' => 'standard',
  531. 'style' => 'vivid',
  532. 'error_msg' => '',
  533. 'update_time' => date('Y-m-d H:i:s')
  534. ]);
  535. return "成功";
  536. }
  537. public function getImageSeed($taskId)
  538. {
  539. // 配置参数
  540. $apiUrl = 'https://chatapi.onechats.ai/mj/task/' . $taskId . '/fetch';
  541. $apiKey = 'sk-iURfrAgzAjhZ4PpPLwzmWIAhM7zKfrkwDvyxk4RVBQ4ouJNK';
  542. try {
  543. // 初始化cURL
  544. $ch = curl_init();
  545. // 设置cURL选项
  546. curl_setopt_array($ch, [
  547. CURLOPT_URL => $apiUrl,
  548. CURLOPT_RETURNTRANSFER => true,
  549. CURLOPT_CUSTOMREQUEST => 'GET', // 明确指定GET方法
  550. CURLOPT_HTTPHEADER => [
  551. 'Authorization: Bearer ' . $apiKey,
  552. 'Accept: application/json',
  553. 'Content-Type: application/json'
  554. ],
  555. CURLOPT_SSL_VERIFYPEER => false,
  556. CURLOPT_SSL_VERIFYHOST => false,
  557. CURLOPT_TIMEOUT => 60,
  558. CURLOPT_FAILONERROR => true // 添加失败时返回错误
  559. ]);
  560. // 执行请求
  561. $response = curl_exec($ch);
  562. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  563. // 错误处理
  564. if (curl_errno($ch)) {
  565. throw new Exception('cURL请求失败: ' . curl_error($ch));
  566. }
  567. // 关闭连接
  568. curl_close($ch);
  569. // 验证HTTP状态码
  570. if ($httpCode < 200 || $httpCode >= 300) {
  571. throw new Exception('API返回错误状态码: ' . $httpCode);
  572. }
  573. // 解析JSON响应
  574. $responseData = json_decode($response, true);
  575. if (json_last_error() !== JSON_ERROR_NONE) {
  576. throw new Exception('JSON解析失败: ' . json_last_error_msg());
  577. }
  578. // 返回结构化数据
  579. return [
  580. 'success' => true,
  581. 'http_code' => $httpCode,
  582. 'data' => $responseData
  583. ];
  584. } catch (Exception $e) {
  585. // 确保关闭cURL连接
  586. if (isset($ch) && is_resource($ch)) {
  587. curl_close($ch);
  588. }
  589. return [
  590. 'success' => false,
  591. 'error' => $e->getMessage(),
  592. 'http_code' => $httpCode ?? 0
  593. ];
  594. }
  595. }
  596. private function sendPostRequest($url, $data, $apiKey)
  597. {
  598. $ch = curl_init();
  599. curl_setopt($ch, CURLOPT_URL, $url);
  600. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  601. curl_setopt($ch, CURLOPT_POST, true);
  602. curl_setopt($ch, CURLOPT_HTTPHEADER, [
  603. 'Authorization: Bearer ' . $apiKey,
  604. 'Accept: application/json',
  605. 'Content-Type: application/json'
  606. ]);
  607. curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  608. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  609. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  610. curl_setopt($ch, CURLOPT_TIMEOUT, 60); // 延长超时时间
  611. $response = curl_exec($ch);
  612. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  613. $error = curl_error($ch);
  614. curl_close($ch);
  615. return [
  616. 'response' => $response,
  617. 'http_code' => $httpCode,
  618. 'error' => $error
  619. ];
  620. }
  621. /**
  622. * 文本生成图片并保存第一张结果
  623. * @param array $params 请求参数
  624. * @return array 返回结果
  625. */
  626. public function txttowimg()
  627. {
  628. // API配置
  629. $config = [
  630. 'api_url' => 'https://chatapi.onechats.ai/mj/submit/imagine',
  631. 'fetch_url' => 'https://chatapi.onechats.ai/mj/task/',
  632. 'api_key' => 'sk-iURfrAgzAjhZ4PpPLwzmWIAhM7zKfrkwDvyxk4RVBQ4ouJNK',
  633. 'default_prompt' => '一个猫',
  634. 'wait_time' => 3 // 等待生成完成的秒数
  635. ];
  636. try {
  637. // 1. 准备请求数据
  638. $prompt = $config['default_prompt'];
  639. $postData = [
  640. 'botType' => 'MID_JOURNEY',
  641. 'prompt' => $prompt,
  642. 'base64Array' => [],
  643. 'accountFilter' => [
  644. 'channelId' => "",
  645. 'instanceId' => "",
  646. 'modes' => [],
  647. 'remark' => "",
  648. 'remix' => true,
  649. 'remixAutoConsidered' => true
  650. ],
  651. 'notifyHook' => "",
  652. 'state' => ""
  653. ];
  654. // 2. 提交生成请求
  655. $generateResponse = $this->sendApiRequest($config['api_url'], $postData, $config['api_key']);
  656. $generateData = json_decode($generateResponse, true);
  657. if (empty($generateData['result'])) {
  658. throw new Exception('生成失败: '.($generateData['message'] ?? '未知错误'));
  659. }
  660. $taskId = $generateData['result'];
  661. // 3. 等待图片生成完成
  662. sleep($config['wait_time']);
  663. // 4. 获取生成结果
  664. $fetchUrl = $config['fetch_url'].$taskId.'/fetch';
  665. $fetchResponse = $this->sendApiRequest($fetchUrl, [], $config['api_key'], 'GET');
  666. $fetchData = json_decode($fetchResponse, true);
  667. if (empty($fetchData['imageUrl'])) {
  668. throw new Exception('获取图片失败: '.($fetchData['message'] ?? '未知错误'));
  669. }
  670. // 5. 处理返回的图片数组(取第一张)
  671. $imageUrls = is_array($fetchData['imageUrl']) ? $fetchData['imageUrl'] : [$fetchData['imageUrl']];
  672. $firstImageUrl = $imageUrls[0];
  673. // 6. 保存图片到本地
  674. $savePath = $this->saveImage($firstImageUrl);
  675. // 7. 返回结果
  676. return [
  677. 'code' => 200,
  678. 'msg' => '图片生成并保存成功',
  679. 'data' => [
  680. 'local_path' => $savePath,
  681. 'web_url' => request()->domain().$savePath,
  682. 'task_id' => $taskId
  683. ]
  684. ];
  685. } catch (Exception $e) {
  686. // 错误处理
  687. return [
  688. 'code' => 500,
  689. 'msg' => '处理失败: '.$e->getMessage(),
  690. 'data' => null
  691. ];
  692. }
  693. }
  694. /**
  695. * 发送API请求
  696. * @param string $url 请求地址
  697. * @param array $data 请求数据
  698. * @param string $apiKey API密钥
  699. * @param string $method 请求方法
  700. * @return string 响应内容
  701. * @throws Exception
  702. */
  703. private function sendApiRequest($url, $data, $apiKey, $method = 'POST')
  704. {
  705. $ch = curl_init();
  706. curl_setopt_array($ch, [
  707. CURLOPT_URL => $url,
  708. CURLOPT_RETURNTRANSFER => true,
  709. CURLOPT_CUSTOMREQUEST => $method,
  710. CURLOPT_HTTPHEADER => [
  711. 'Authorization: Bearer '.$apiKey,
  712. 'Accept: application/json',
  713. 'Content-Type: application/json'
  714. ],
  715. CURLOPT_POSTFIELDS => $method === 'POST' ? json_encode($data) : null,
  716. CURLOPT_SSL_VERIFYPEER => false,
  717. CURLOPT_SSL_VERIFYHOST => false,
  718. CURLOPT_TIMEOUT => 60,
  719. CURLOPT_FAILONERROR => true
  720. ]);
  721. $response = curl_exec($ch);
  722. $error = curl_error($ch);
  723. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  724. curl_close($ch);
  725. if ($error) {
  726. throw new Exception('API请求失败: '.$error);
  727. }
  728. if ($httpCode < 200 || $httpCode >= 300) {
  729. throw new Exception('API返回错误状态码: '.$httpCode);
  730. }
  731. return $response;
  732. }
  733. /**
  734. * 保存图片到本地
  735. * @param string $imageUrl 图片URL
  736. * @return string 本地保存路径
  737. * @throws Exception
  738. */
  739. private function saveImage($imageUrl)
  740. {
  741. // 1. 创建存储目录
  742. $saveDir = ROOT_PATH.'public'.DS.'uploads'.DS.'midjourney'.DS.date('Ymd');
  743. if (!is_dir($saveDir)) {
  744. mkdir($saveDir, 0755, true);
  745. }
  746. // 2. 生成唯一文件名
  747. $filename = uniqid().'.png';
  748. $localPath = DS.'uploads'.DS.'midjourney'.DS.date('Ymd').DS.$filename;
  749. $fullPath = $saveDir.DS.$filename;
  750. // 3. 下载图片
  751. $ch = curl_init($imageUrl);
  752. curl_setopt_array($ch, [
  753. CURLOPT_RETURNTRANSFER => true,
  754. CURLOPT_FOLLOWLOCATION => true,
  755. CURLOPT_SSL_VERIFYPEER => false,
  756. CURLOPT_CONNECTTIMEOUT => 15
  757. ]);
  758. $imageData = curl_exec($ch);
  759. $error = curl_error($ch);
  760. curl_close($ch);
  761. if (!$imageData) {
  762. throw new Exception('图片下载失败: '.$error);
  763. }
  764. // 4. 验证图片类型
  765. $imageInfo = getimagesizefromstring($imageData);
  766. if (!in_array($imageInfo['mime'] ?? '', ['image/png', 'image/jpeg'])) {
  767. throw new Exception('下载内容不是有效图片');
  768. }
  769. // 5. 保存文件
  770. if (!file_put_contents($fullPath, $imageData)) {
  771. throw new Exception('图片保存失败');
  772. }
  773. return $localPath;
  774. }
  775. /**
  776. * 图生图本地测试
  777. */
  778. public function imgtowimg()
  779. {
  780. $prompt = $this->request->param('prompt', '');
  781. $imgRelPath = 'uploads/operate/ai/Preview/arr/0835006071623.png';
  782. $imgPath = ROOT_PATH . 'public/' . $imgRelPath;
  783. if (!file_exists($imgPath)) {
  784. return json(['code' => 1, 'msg' => '原图不存在:' . $imgRelPath]);
  785. }
  786. $imgData = file_get_contents($imgPath);
  787. $base64Img = 'data:image/png;base64,' . base64_encode($imgData);
  788. $params = [
  789. 'prompt' => $prompt,
  790. 'negative_prompt' => '(deformed, distorted, disfigured:1.3), poorly drawn, bad anatomy',
  791. 'steps' => 20,
  792. 'sampler_name' => 'DPM++ 2M SDE',
  793. 'cfg_scale' => 7,
  794. 'seed' => -1,
  795. 'width' => 1024,
  796. 'height' => 1303,
  797. 'override_settings' => [
  798. 'sd_model_checkpoint' => 'realisticVisionV51_v51VAE-inpainting',
  799. 'sd_vae' => 'vae-ft-mse-840000-ema-pruned',
  800. 'CLIP_stop_at_last_layers' => 2
  801. ],
  802. 'clip_skip' => 2,
  803. 'alwayson_scripts' => [
  804. 'controlnet' => [
  805. 'args' => [[
  806. 'enabled' => true,
  807. 'input_image' => $base64Img,
  808. 'module' => 'inpaint_only+lama',
  809. 'model' => 'control_v11p_sd15_inpaint_fp16 [be8bc0ed]',
  810. 'weight' => 1,
  811. 'resize_mode' => 'Resize and Fill',
  812. 'pixel_perfect' => false,
  813. 'control_mode' => 'ControlNet is more important',
  814. 'starting_control_step' => 0,
  815. 'ending_control_step' => 1
  816. ]]
  817. ]
  818. ]
  819. ];
  820. $apiUrl = "http://20.0.17.188:45001/sdapi/v1/txt2img";
  821. $headers = ['Content-Type: application/json'];
  822. $ch = curl_init();
  823. curl_setopt($ch, CURLOPT_URL, $apiUrl);
  824. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  825. curl_setopt($ch, CURLOPT_POST, true);
  826. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  827. curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params, JSON_UNESCAPED_UNICODE));
  828. curl_setopt($ch, CURLOPT_TIMEOUT, 180);
  829. $response = curl_exec($ch);
  830. $error = curl_error($ch);
  831. curl_close($ch);
  832. if ($error) {
  833. return json(['code' => 1, 'msg' => '请求失败:' . $error]);
  834. }
  835. $data = json_decode($response, true);
  836. if (!isset($data['images'][0])) {
  837. return json(['code' => 1, 'msg' => '接口未返回图像数据']);
  838. }
  839. $resultImg = base64_decode($data['images'][0]);
  840. $saveDir = ROOT_PATH . 'public/uploads/img2img/';
  841. if (!is_dir($saveDir)) {
  842. mkdir($saveDir, 0755, true);
  843. }
  844. $originalBaseName = pathinfo($imgRelPath, PATHINFO_FILENAME);
  845. $fileName = $originalBaseName . '-' . time() . '-1024x1248.png';
  846. $savePath = $saveDir . $fileName;
  847. file_put_contents($savePath, $resultImg);
  848. return json([
  849. 'code' => 0,
  850. 'msg' => '图像生成成功',
  851. 'data' => [
  852. 'origin_url' => '/uploads/img2img/' . $fileName
  853. ]
  854. ]);
  855. }
  856. /**
  857. * 后期图像处理-单张图片高清放大处理
  858. */
  859. public function extra_image()
  860. {
  861. // 配置参数
  862. $config = [
  863. 'input_dir' => 'uploads/img2img/',
  864. 'output_dir' => 'uploads/extra_image/',
  865. 'api_url' => 'http://20.0.17.188:45001/sdapi/v1/extra-single-image',
  866. 'timeout' => 120, // 增加超时时间,高清处理可能耗时较长
  867. 'upscale_params' => [
  868. 'resize_mode' => 0,
  869. 'show_extras_results' => true,
  870. 'gfpgan_visibility' => 0, // 人脸修复关闭
  871. 'codeformer_visibility' => 0, // 人脸修复关闭
  872. 'codeformer_weight' => 0,
  873. 'upscaling_resize' => 2.45, // 放大倍数
  874. 'upscaling_crop' => true,
  875. 'upscaler_1' => 'R-ESRGAN 4x+ Anime6B', // 主放大模型
  876. 'upscaler_2' => 'None', // 不使用第二放大器
  877. 'extras_upscaler_2_visibility' => 0,
  878. 'upscale_first' => false,
  879. ]
  880. ];
  881. // 输入文件处理
  882. $imgRelPath = '0835006071623-1757406184-1024x1248.png';
  883. $imgPath = ROOT_PATH . 'public/' . $config['input_dir'] . $imgRelPath;
  884. if (!file_exists($imgPath)) {
  885. return json(['code' => 1, 'msg' => '原图不存在:' . $imgRelPath]);
  886. }
  887. // 读取并编码图片
  888. try {
  889. $imgData = file_get_contents($imgPath);
  890. if ($imgData === false) {
  891. throw new Exception('无法读取图片文件');
  892. }
  893. $base64Img = base64_encode($imgData);
  894. } catch (Exception $e) {
  895. return json(['code' => 1, 'msg' => '图片处理失败:' . $e->getMessage()]);
  896. }
  897. // 准备API请求数据
  898. $postData = array_merge($config['upscale_params'], ['image' => $base64Img]);
  899. $jsonData = json_encode($postData);
  900. if ($jsonData === false) {
  901. return json(['code' => 1, 'msg' => 'JSON编码失败']);
  902. }
  903. // 调用API进行高清放大
  904. $ch = curl_init();
  905. curl_setopt_array($ch, [
  906. CURLOPT_URL => $config['api_url'],
  907. CURLOPT_RETURNTRANSFER => true,
  908. CURLOPT_POST => true,
  909. CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
  910. CURLOPT_POSTFIELDS => $jsonData,
  911. CURLOPT_TIMEOUT => $config['timeout'],
  912. CURLOPT_CONNECTTIMEOUT => 30,
  913. ]);
  914. $response = curl_exec($ch);
  915. $error = curl_error($ch);
  916. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  917. curl_close($ch);
  918. if ($error) {
  919. return json(['code' => 1, 'msg' => 'API请求失败:' . $error]);
  920. }
  921. if ($httpCode !== 200) {
  922. return json(['code' => 1, 'msg' => 'API返回错误状态码:' . $httpCode]);
  923. }
  924. $data = json_decode($response, true);
  925. if (json_last_error() !== JSON_ERROR_NONE) {
  926. return json(['code' => 1, 'msg' => 'API返回数据解析失败']);
  927. }
  928. if (!isset($data['image']) || empty($data['image'])) {
  929. return json(['code' => 1, 'msg' => '接口未返回有效的图像数据']);
  930. }
  931. // 保存处理后的图片
  932. try {
  933. $resultImg = base64_decode($data['image']);
  934. if ($resultImg === false) {
  935. throw new Exception('Base64解码失败');
  936. }
  937. $saveDir = ROOT_PATH . 'public/' . $config['output_dir'];
  938. if (!is_dir($saveDir) && !mkdir($saveDir, 0755, true)) {
  939. throw new Exception('无法创建输出目录');
  940. }
  941. $originalBaseName = pathinfo($imgRelPath, PATHINFO_FILENAME);
  942. $fileName = $originalBaseName . '-hd.png'; // 使用-hd后缀更明确
  943. $savePath = $saveDir . $fileName;
  944. if (file_put_contents($savePath, $resultImg) === false) {
  945. throw new Exception('无法保存处理后的图片');
  946. }
  947. // 返回成功响应
  948. return json([
  949. 'code' => 0,
  950. 'msg' => '图像高清放大处理成功',
  951. 'data' => [
  952. 'url' => '/' . $config['output_dir'] . $fileName,
  953. 'original_size' => filesize($imgPath),
  954. 'processed_size' => filesize($savePath),
  955. 'resolution' => getimagesize($savePath), // 返回新图片的分辨率
  956. ]
  957. ]);
  958. } catch (Exception $e) {
  959. return json(['code' => 1, 'msg' => '保存结果失败:' . $e->getMessage()]);
  960. }
  961. }
  962. /**
  963. * 查询队列列表
  964. * 统计文件对应的队列情况
  965. */
  966. public function get_queue_logs()
  967. {
  968. $params = $this->request->param('old_image_file', '');
  969. $queue_logs = Db::name('queue_logs')
  970. ->where('old_image_file', $params)
  971. ->order('id desc')
  972. ->select();
  973. $result = []; //初始化变量,避免未定义错误
  974. foreach ($queue_logs as &$log) {
  975. $taskId = $log['id'];
  976. $statusCount = Db::name('image_task_log')
  977. ->field('status, COUNT(*) as count')
  978. ->where('task_id', $taskId)
  979. ->where('mod_rq', null)
  980. ->group('status')
  981. ->select();
  982. $log['已完成数量'] = 0;
  983. $log['处理中数量'] = 0;
  984. $log['排队中的数量'] = 0;
  985. $log['失败数量'] = 0;
  986. foreach ($statusCount as $item) {
  987. switch ($item['status']) {
  988. case 0:
  989. $log['排队中的数量'] = $item['count'];
  990. break;
  991. case 1:
  992. $log['处理中数量'] = $item['count'];
  993. break;
  994. case 2:
  995. $log['已完成数量'] = $item['count'];
  996. break;
  997. case -1:
  998. $log['失败数量'] = $item['count'];
  999. break;
  1000. }
  1001. }
  1002. // if ($log['排队中的数量'] >$log['已完成数量']) {
  1003. // $result[] = $log;
  1004. // }
  1005. if ($log['排队中的数量']) {
  1006. $result[] = $log;
  1007. }
  1008. // if ($log['处理中数量'] >= 0) {
  1009. // $result[] = $log;
  1010. // }
  1011. }
  1012. return json([
  1013. 'code' => 0,
  1014. 'msg' => '查询成功',
  1015. 'data' => $result,
  1016. 'count' => count($result)
  1017. ]);
  1018. }
  1019. /**
  1020. * 查询总队列状态(统计当前处理的数据量)
  1021. */
  1022. public function queueStats()
  1023. {
  1024. $statusList = Db::name('image_task_log')
  1025. ->field('status, COUNT(*) as total')
  1026. ->where('mod_rq', null)
  1027. ->where('create_time', '>=', date('Y-m-d 00:00:00'))
  1028. ->group('status')
  1029. ->select();
  1030. $statusCount = [];
  1031. foreach ($statusList as $item) {
  1032. $statusCount[$item['status']] = $item['total'];
  1033. }
  1034. // 总数为所有状态和
  1035. $total = array_sum($statusCount);
  1036. //获取队列当前状态
  1037. $statusText = Db::name('queue_logs')->order('id desc')->value('status');
  1038. return json([
  1039. 'code' => 0,
  1040. 'msg' => '获取成功',
  1041. 'data' => [
  1042. '总任务数' => $total,
  1043. '待处理' => $statusCount[0] ?? 0,
  1044. '处理中' => $statusCount[1] ?? 0,
  1045. '成功' => $statusCount[2] ?? 0,
  1046. '失败' => $statusCount[-1] ?? 0,
  1047. '当前状态' => $statusText
  1048. ]
  1049. ]);
  1050. }
  1051. /**
  1052. * 显示当前运行中的队列监听进程
  1053. */
  1054. public function viewQueueStatus()
  1055. {
  1056. $redis = new \Redis();
  1057. $redis->connect('127.0.0.1', 6379);
  1058. $redis->auth('123456');
  1059. $redis->select(15);
  1060. $key = 'queues:imgtotxt';
  1061. // 判断 key 是否存在,避免报错
  1062. if (!$redis->exists($key)) {
  1063. return json([
  1064. 'code' => 0,
  1065. 'msg' => '查询成功,队列为空',
  1066. 'count' => 0,
  1067. 'tasks_preview' => []
  1068. ]);
  1069. }
  1070. $count = $redis->lLen($key);
  1071. $list = $redis->lRange($key, 0, 9);
  1072. // 解码 JSON 内容,确保每一项都有效
  1073. $parsed = array_filter(array_map(function ($item) {
  1074. return json_decode($item, true);
  1075. }, $list), function ($item) {
  1076. return !is_null($item);
  1077. });
  1078. return json([
  1079. 'code' => 0,
  1080. 'msg' => '查询成功',
  1081. 'count' => $count,
  1082. 'tasks_preview' => $parsed
  1083. ]);
  1084. }
  1085. /**
  1086. * 清空队列并删除队列日志记录
  1087. */
  1088. public function stopQueueProcesses()
  1089. {
  1090. Db::name('image_task_log')
  1091. ->where('log', '队列中')
  1092. ->whereOr('status', 1)
  1093. ->where('create_time', '>=', date('Y-m-d 00:00:00'))
  1094. ->update([
  1095. 'status' => "-1",
  1096. 'log' => '清空取消队列',
  1097. 'mod_rq' => date('Y-m-d H:i:s')
  1098. ]);
  1099. Db::name('image_task_log')
  1100. ->whereLike('log', '%处理中%')
  1101. ->where('create_time', '>=', date('Y-m-d 00:00:00'))
  1102. ->update([
  1103. 'status' => "-1",
  1104. 'log' => '清空取消队列',
  1105. 'mod_rq' => date('Y-m-d H:i:s')
  1106. ]);
  1107. $redis = new \Redis();
  1108. $redis->connect('127.0.0.1', 6379);
  1109. $redis->auth('123456');
  1110. $redis->select(15);
  1111. $key_txttoimg = 'queues:txttoimg:reserved';
  1112. $key_txttotxt = 'queues:txttotxt:reserved';
  1113. $key_imgtotxt = 'queues:imgtotxt:reserved';
  1114. $key_imgtoimg = 'queues:imgtoimg:reserved';
  1115. // 清空 Redis 队列
  1116. $redis->del($key_txttoimg);
  1117. $redis->del($key_txttotxt);
  1118. $redis->del($key_imgtotxt);
  1119. $redis->del($key_imgtoimg);
  1120. $count = $redis->lLen($key_txttoimg) + $redis->lLen($key_txttotxt) + $redis->lLen($key_imgtotxt) + $redis->lLen($key_imgtoimg);
  1121. // if ($count === 0) {
  1122. // return json([
  1123. // 'code' => 1,
  1124. // 'msg' => '暂无队列需要停止'
  1125. // ]);
  1126. // }
  1127. return json([
  1128. 'code' => 0,
  1129. 'msg' => '成功停止队列任务'
  1130. ]);
  1131. }
  1132. /**
  1133. * 开启队列任务
  1134. * 暂时用不到、服务器已开启自动开启队列模式
  1135. */
  1136. // public function kaiStats()
  1137. // {
  1138. // // 判断是否已有监听进程在运行
  1139. // $check = shell_exec("ps aux | grep 'queue:listen' | grep -v grep");
  1140. // if ($check) {
  1141. // return json([
  1142. // 'code' => 1,
  1143. // 'msg' => '监听进程已存在,请勿重复启动'
  1144. // ]);
  1145. // }
  1146. // // 启动监听
  1147. // $command = 'nohup php think queue:listen --queue --timeout=300 --sleep=3 --memory=256 > /var/log/job_queue.log 2>&1 &';
  1148. // exec($command, $output, $status);
  1149. // if ($status === 0) {
  1150. // return json([
  1151. // 'code' => 0,
  1152. // 'msg' => '队列监听已启动'
  1153. // ]);
  1154. // } else {
  1155. // return json([
  1156. // 'code' => 1,
  1157. // 'msg' => '队列启动失败',
  1158. // 'output' => $output
  1159. // ]);
  1160. // }
  1161. // }
  1162. /**
  1163. * 通过店铺ID-查询对应店铺表数据
  1164. *
  1165. */
  1166. public function PatternApi()
  1167. {
  1168. $params = $this->request->param('pattern_id', '');
  1169. $tableName = 'pattern-' . $params;
  1170. // 连接 MongoDB
  1171. $mongo = Db::connect('mongodb');
  1172. // 查询指定 skc 的数据
  1173. $data = $mongo->table($tableName)
  1174. ->field('
  1175. name,
  1176. skc,
  1177. file
  1178. ')
  1179. ->where("skc", '0853004152036')
  1180. ->select();
  1181. $data = json_decode(json_encode($data), true); // 数组
  1182. return json([
  1183. 'code' => 0,
  1184. 'msg' => '获取成功',
  1185. 'data' => $data
  1186. ]);
  1187. }
  1188. }