aiImageGenerationService = $aiImageGenerationService; } /** * 创建图片生成任务 * * @param Request $request * @return JsonResponse */ public function createTask(Request $request): JsonResponse { $data = $request->all(); // 首先验证基本参数 $baseRules = [ 'prompt' => 'required|string|max:2000', 'width' => 'required|numeric|between:1024,4096', 'height' => 'required|numeric|between:1024,4096', 'image_num' => 'required|numeric|between:1,4', 'scale' => 'required|numeric|between:0,100', ]; $baseMessages = [ 'prompt.required' => '提示词不能为空', 'prompt.max' => '提示词不能超过2000个字符', 'width.required' => '宽不能为空', 'width.numeric' => '宽必须是数字', 'width.between' => '宽必须在1024到4096之间', 'height.required' => '高不能为空', 'height.numeric' => '高必须是数字', 'height.between' => '高必须在1024到4096之间', 'image_num.required' => '生成图片数量不能为空', 'image_num.numeric' => '生成图片数量必须是数字', 'image_num.between' => '生成图片数量必须在1到4之间', 'scale.required' => '缩放比例不能为空', 'scale.numeric' => '缩放比例必须是数字', 'scale.between' => '缩放比例必须在0到100之间', ]; // 根据传入参数决定验证规则 if (isset($data['ref_img_url'])) { // URL 方式 - 支持单个或多个URL(逗号分隔或数组) $validationRules = array_merge($baseRules, [ 'ref_img_url' => 'required', ]); $validationMessages = array_merge($baseMessages, [ 'ref_img_url.required' => '参考图片URL不能为空', ]); } else { // 上传文件方式 - 支持多个文件 $validationRules = array_merge($baseRules, [ 'ref_img_file' => 'required', 'ref_img_file.*' => 'image|mimes:jpeg,png|max:4800', ]); $validationMessages = array_merge($baseMessages, [ 'ref_img_file.required' => '参考图片不能为空', 'ref_img_file.*.image' => '参考图片必须是图片文件', 'ref_img_file.*.mimes' => '参考图片必须是jpeg,png格式', 'ref_img_file.*.max' => '参考图片大小不能超过4.7MB', ]); } $validator = Validator::make($data, $validationRules, $validationMessages); if ($validator->fails()) { Utils::throwError('1002:'.$validator->errors()->first()); } $refImgUrls = []; $refImgBase64List = []; // 处理上传的图片 if ($request->hasFile('ref_img_file')) { $refImgFiles = is_array($request->file('ref_img_file')) ? $request->file('ref_img_file') : [$request->file('ref_img_file')]; foreach ($refImgFiles as $index => $refImgFile) { // 验证图片分辨率和比例 $refImgInfo = @getimagesize($refImgFile->getPathname()); if (!$refImgInfo) { Utils::throwError('1003:图片' . ($index + 1) . '格式无效'); } $refImg = [ 'width' => $refImgInfo[0], 'height' => $refImgInfo[1], 'size' => $refImgFile->getSize(), ]; // 验证图片规格 $this->validateImageSpecs($refImg, $index + 1); // 上传图片到服务器并获取URL $filename = randStr(10) . '.' . $refImgFile->getClientOriginalExtension(); $uploaded_url = uploadStreamByTos('image', file_get_contents($refImgFile->getPathname()), $filename); if (!$uploaded_url) { Utils::throwError('1003:图片' . ($index + 1) . '保存失败'); } $refImgUrls[] = $uploaded_url; } } else { // 使用URL方式,支持逗号分隔的字符串或数组 $urls = is_array($data['ref_img_url']) ? $data['ref_img_url'] : array_map('trim', explode(',', $data['ref_img_url'])); foreach ($urls as $index => $url) { if (empty($url)) { continue; } // 验证URL格式 if (!filter_var($url, FILTER_VALIDATE_URL)) { Utils::throwError('1003:图片URL' . ($index + 1) . '格式无效'); } // 验证远程图片 $refImg = Utils::getRemoteImageInfo($url, true); if (!$refImg) { Utils::throwError('1003:图片' . ($index + 1) . '获取失败'); } // 验证图片规格 $this->validateImageSpecs($refImg, $index + 1); $refImgUrls[] = $url; } } if (empty($refImgUrls)) { Utils::throwError('1003:至少需要一张参考图片'); } // 将处理后的URL存入data(支持多个) $data['ref_img_urls'] = $refImgUrls; $data['ref_img_url'] = $refImgUrls[0]; // 保持向后兼容 try { $task = $this->aiImageGenerationService->createImageGenerationTask($data); return $this->success(['task_id' => $task->task_id, 'status' => $task->status]); } catch (\Exception $e) { Utils::throwError('1001:'.$e->getMessage()); } } /** * 验证图片规格 * * @param array $refImg * @param int $index * @return void */ private function validateImageSpecs(array $refImg, int $index): void { // 判断图片是否满足以下条件: // 1.图片文件最大4.7MB // 2.图片分辨率最大: 4096*4096, 最短边不低于320 // 3.图片长边与短边比例在3以内 if ($refImg['size'] > 4.7 * 1024 * 1024) { Utils::throwError('1003:图片' . $index . '大小不能超过4.7MB'); } $minDimension = min($refImg['width'], $refImg['height']); $maxDimension = max($refImg['width'], $refImg['height']); if ($maxDimension > 4096 || $minDimension < 320) { Utils::throwError('1003:图片' . $index . '分辨率不能超过4096*4096,且最短边不能低于320'); } if ($maxDimension / $minDimension > 3) { Utils::throwError('1003:图片' . $index . '长边与短边比例不能超过3'); } } /** * 查询任务状态 * * @param string $taskId * @return JsonResponse */ public function taskStatus(string $taskId): JsonResponse { $task = \App\Models\MpGeneratePicTask::where('task_id', $taskId)->first(); if (!$task) { return response()->json([ 'success' => false, 'message' => '任务不存在' ], 404); } return response()->json([ 'success' => true, 'data' => [ 'task_id' => $task->task_id, 'status' => $task->status, 'result_url' => $task->result_url, 'error_message' => $task->error_message, 'created_at' => $task->created_at, 'started_at' => $task->started_at, 'completed_at' => $task->completed_at ] ]); } /** * 获取任务列表 * * @param Request $request * @return mixed */ public function taskList(Request $request) { $data = $request->all(); $result = $this->aiImageGenerationService->getTaskList($data); return $this->success($result, [new AIGenerationTransformer(), 'newBuildTaskList']); } /** * 批量上传图片 * * @param Request $request * @return void */ public function batchUploadImg(Request $request) { $refImgUrls = []; // 处理上传的图片 if ($request->hasFile('ref_img_file')) { $refImgFiles = is_array($request->file('ref_img_file')) ? $request->file('ref_img_file') : [$request->file('ref_img_file')]; foreach ($refImgFiles as $index => $refImgFile) { // 验证图片分辨率和比例 $refImgInfo = @getimagesize($refImgFile->getPathname()); if (!$refImgInfo) { Utils::throwError('1003:图片' . ($index + 1) . '格式无效'); } $refImg = [ 'width' => $refImgInfo[0], 'height' => $refImgInfo[1], 'size' => $refImgFile->getSize(), ]; // 验证图片规格 $this->validateImageSpecs($refImg, $index + 1); // 上传图片到服务器并获取URL $filename = randStr(10) . '.' . $refImgFile->getClientOriginalExtension(); $uploaded_url = uploadStreamByTos('image', file_get_contents($refImgFile->getPathname()), $filename); if (!$uploaded_url) { Utils::throwError('1003:图片' . ($index + 1) . '保存失败'); } $refImgUrls[] = $uploaded_url; } } return $this->success(['image_urls' => $refImgUrls]); } }