request->post(); $paths = $params['paths'] ?? []; if (empty($paths) || !is_array($paths)) { return json(['code' => 1, 'msg' => '路径参数不能为空或格式不正确']); } // 设置基础路径和压缩目录路径 $basePath = ROOT_PATH . 'public/'; $zipDir = $basePath . 'uploads/operate/ai/zip/'; if (!is_dir($zipDir)) { mkdir($zipDir, 0755, true); } // 压缩包文件名及完整路径 $fileName = 'images_' . date('Ymd_His') . '.zip'; $zipPath = $zipDir . $fileName; // 创建 Zip 文件 $zip = new \ZipArchive(); if ($zip->open($zipPath, \ZipArchive::CREATE) !== TRUE) { return json(['code' => 1, 'msg' => '无法创建压缩包']); } // 添加文件到压缩包 $addCount = 0; foreach ($paths as $relativePath) { $relativePath = ltrim($relativePath, '/'); $fullPath = $basePath . $relativePath; if (file_exists($fullPath)) { $zip->addFile($fullPath, basename($fullPath)); // 仅保存文件名 $addCount++; } } $zip->close(); if ($addCount === 0) { return json(['code' => 1, 'msg' => '未找到有效图片,未生成压缩包']); } // 返回下载地址(注意路径与保存路径一致) $downloadUrl = request()->domain() . '/uploads/operate/ai/zip/' . $fileName; return json([ 'code' => 0, 'msg' => '打包成功', 'download_url' => $downloadUrl ]); } catch (\Exception $e) { return json([ 'code' => 1, 'msg' => '异常错误:' . $e->getMessage() ]); } } public function getlsit() { // 获取前端传入的图片路径参数 $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') ->where('old_image_url', $params) ->where('img_name', '<>', '') ->order('id desc') ->select(); return json(['code' => 0, 'msg' => '查询成功', 'data' => $res,'count'=>count($res)]); } //获取指定目录所有图片 public function getPreviewimg() { $page = (int)$this->request->param('page', 1); $limit = (int)$this->request->param('limit', 50); $status = $this->request->param('status', ''); $relativePath = $this->request->param('path', ''); $basePath = ROOT_PATH . 'public/'; $fullPath = $basePath . $relativePath; if (!is_dir($fullPath)) { return json(['code' => 1, 'msg' => '原图目录不存在']); } // 1. 获取所有图片路径 $allImages = glob($fullPath . '/*.{jpg,jpeg,png}', GLOB_BRACE); if (empty($allImages)) { return json(['code' => 0, 'msg' => '暂无图片', 'data' => [], 'total' => 0]); } // 2. 构建路径信息映射(路径 => 文件信息) $imageInfoMap = []; foreach ($allImages as $imgPath) { $relative = str_replace('\\', '/', trim(str_replace($basePath, '', $imgPath), '/')); $info = @getimagesize($imgPath); $imageInfoMap[$relative] = [ 'width' => $info[0] ?? 0, 'height' => $info[1] ?? 0, 'size_kb' => round(filesize($imgPath) / 1024, 2), 'created_time' => date('Y-m-d H:i:s', filectime($imgPath)) ]; } $relativeImages = array_keys($imageInfoMap); // 3. 获取数据库记录 $dbRecords = Db::name('text_to_image') ->whereIn('old_image_url', $relativeImages) ->field('id as img_id, old_image_url, new_image_url, custom_image_url, chinese_description, english_description, img_name, status') ->select(); // 4. 构建映射表:路径 => 整条数据库记录 $processedMap = []; foreach ($dbRecords as $item) { $key = str_replace('\\', '/', trim($item['old_image_url'], '/')); $processedMap[$key] = $item; } // 5. 获取 same_count 统计 $sameCountMap = Db::name('text_to_image') ->whereIn('old_image_url', $relativeImages) ->where('status', 1) ->group('old_image_url') ->column('count(*) as cnt', 'old_image_url'); // 6. 构建结果数据 $allData = []; foreach ($relativeImages as $path) { $item = $processedMap[$path] ?? []; $info = $imageInfoMap[$path]; $isProcessed = !empty($item['img_name']) && !empty($item['custom_image_url']); $dbStatus = isset($item['status']) ? (int)$item['status'] : 0; // 状态过滤(0:未出图,1:已出图) if ($status !== '' && (int)$status !== $dbStatus) { continue; } $allData[] = [ 'path' => $path,//原图路径 'status' => $dbStatus,//状态 'same_count' => $sameCountMap[$path] ?? 0, // 出图数量 'is_processed' => $isProcessed ? 1 : 0, 'new_image_url' => $item['new_image_url'] ?? '', 'custom_image_url' => $item['custom_image_url'] ?? '', 'chinese_description' => $item['chinese_description'] ?? '', 'english_description' => $item['english_description'] ?? '', 'img_name' => $item['img_name'] ?? '', 'width' => $info['width'], 'height' => $info['height'], 'size_kb' => $info['size_kb'], 'created_time' => $info['created_time'] ]; } // 7. 分页处理 $total = count($allData); $pagedData = array_slice(array_values($allData), ($page - 1) * $limit, $limit); foreach ($pagedData as $i => &$row) { $row['id'] = ($page - 1) * $limit + $i + 1; } return json([ 'code' => 0, 'msg' => '获取成功', 'data' => $pagedData, 'total' => $total, 'page' => $page, 'limit' => $limit ]); } // public function getPreviewimg() // { // $page = (int)$this->request->param('page', 1); // $limit = (int)$this->request->param('limit', 50); // $status = $this->request->param('status', ''); // $relativePath = $this->request->param('path', ''); // // $basePath = ROOT_PATH . 'public/'; // $fullPath = $basePath . $relativePath; // // if (!is_dir($fullPath)) { // return json(['code' => 1, 'msg' => '原图目录不存在']); // } // // // 1. 获取所有图片路径 // $allImages = glob($fullPath . '/*.{jpg,jpeg,png}', GLOB_BRACE); // if (empty($allImages)) { // return json(['code' => 0, 'msg' => '暂无图片', 'data' => [], 'total' => 0]); // } // // // 2. 构建路径信息映射(路径 => 文件信息) // $imageInfoMap = []; // foreach ($allImages as $imgPath) { // $relative = str_replace('\\', '/', trim(str_replace($basePath, '', $imgPath), '/')); // $info = @getimagesize($imgPath); // $imageInfoMap[$relative] = [ // 'width' => $info[0] ?? 0, // 'height' => $info[1] ?? 0, // 'size_kb' => round(filesize($imgPath) / 1024, 2), // 'created_time' => date('Y-m-d H:i:s', filectime($imgPath)) // ]; // } // // $relativeImages = array_keys($imageInfoMap); // // // 3. 获取数据库记录 // $dbRecords = Db::name('text_to_image') // ->whereIn('old_image_url', $relativeImages) // ->field('id as img_id, old_image_url, new_image_url, custom_image_url, chinese_description, english_description, img_name,status') // ->select(); // // // 4. 构建映射表:路径 => 整条数据库记录 // $processedMap = []; // foreach ($dbRecords as $item) { // $key = str_replace('\\', '/', trim($item['old_image_url'], '/')); // $processedMap[$key] = $item; // } // // // 5. 获取 same_count 统计 // $sameCountMap = Db::name('text_to_image') // ->whereIn('old_image_url', $relativeImages) // ->where('status', 1) // ->group('old_image_url') // ->column('count(*) as cnt', 'old_image_url'); // // // 6. 构建结果数据 // $allData = []; // foreach ($relativeImages as $path) { // $item = $processedMap[$path] ?? []; // $info = $imageInfoMap[$path]; // // $isProcessed = !empty($item['img_name']) && !empty($item['custom_image_url']); // // // 状态过滤 // if ($status === '1') { // if (!$isProcessed) continue; // } elseif ($status === '2') { // if ($isProcessed) continue; // } // // $allData[] = [ // 'path' => $path, // 'status' => (int)($item['status'] ?? 0), // 'same_count' => $sameCountMap[$path] ?? 0,//出图数量 // 'is_processed' => $isProcessed ? 1 : 0, // 'new_image_url' => $item['new_image_url'] ?? '', // 'custom_image_url' => $item['custom_image_url'] ?? '', // 'chinese_description' => $item['chinese_description'] ?? '', // 'english_description' => $item['english_description'] ?? '', // 'img_name' => $item['img_name'] ?? '', // 'width' => $info['width'], // 'height' => $info['height'], // 'size_kb' => $info['size_kb'], // 'created_time' => $info['created_time'] // ]; // } // // // 7. 分页处理 // $total = count($allData); // $pagedData = array_slice(array_values($allData), ($page - 1) * $limit, $limit); // foreach ($pagedData as $i => &$row) { // $row['id'] = ($page - 1) * $limit + $i + 1; // } // // return json([ // 'code' => 0, // 'msg' => '获取成功', // 'data' => $pagedData, // 'total' => $total, // 'page' => $page, // 'limit' => $limit // ]); // } // public function getPreviewimg() // { // $page = (int)$this->request->param('page', 1); // $limit = (int)$this->request->param('limit', 50); // $status = $this->request->param('status', ''); // // $relativePath = $this->request->param('path', ''); // $basePath = ROOT_PATH . 'public/'; // $fullPath = $basePath . $relativePath; // // if (!is_dir($fullPath)) { // return json(['code' => 1, 'msg' => '目录不存在']); // } // // // 1. 获取所有图片路径(不再全部加载到内存) // $allImages = glob($fullPath . '/*.{jpg,jpeg,png}', GLOB_BRACE); // if (empty($allImages)) { // return json(['code' => 0, 'msg' => '暂无图片', 'data' => [], 'total' => 0]); // } // // ✅ 加入排序:按照创建时间从新到旧 // usort($allImages, function ($a, $b) { // return filectime($b) - filectime($a); // }); // // 构建相对路径数组 // $relativeImages = array_map(function ($imgPath) use ($basePath) { // return str_replace($basePath, '', $imgPath); // }, $allImages); // // // 2. 提前构建是否已出图map // $dbRecords = Db::name('text_to_image') // ->whereIn('old_image_url', $relativeImages) // ->where('img_name', '<>', '') // ->where('custom_image_url', '<>', '') // ->where('status',1) // ->field('id,old_image_url,new_image_url,custom_image_url,chinese_description,english_description,img_name') // ->select(); // // $processedMap = []; // foreach ($dbRecords as $item) { // $processedMap[$item['old_image_url']] = $item; // } // // // 3. 提前获取 same_count 的统计 // $sameCountMap = Db::name('text_to_image') // ->whereIn('old_image_url', $relativeImages) // ->where('img_name', '<>', '') // ->where('custom_image_url', '<>', '') // ->group('old_image_url') // ->where('status',1) // ->column('count(*) as cnt', 'old_image_url'); // // // 4. 构造最终筛选数据(分页前进行状态筛选) // $filtered = []; // foreach ($allImages as $imgPath) { // $relative = str_replace($basePath, '', $imgPath); // $processed = $processedMap[$relative] ?? null; // $isProcessed = $processed ? 1 : 0; // // // 状态过滤 // if ($status === 'processed' && !$isProcessed) continue; // if ($status === 'unprocessed' && $isProcessed) continue; // // $info = @getimagesize($imgPath); // 加@防止报错 // $sizeKB = round(filesize($imgPath) / 1024, 2); // $ctime = date('Y-m-d H:i:s', filectime($imgPath)); // // $filtered[] = [ // 'path' => $relative, // 'width' => $info[0] ?? 0, // 'height' => $info[1] ?? 0, // 'size_kb' => $sizeKB, // 'created_time' => $ctime, // 'img_name' => $processed['img_name'] ?? '', // 'is_processed' => $isProcessed, // 'new_image_url' => $processed['new_image_url'] ?? '', // 'custom_image_url' => $processed['custom_image_url'] ?? '', // 'chinese_description' => ($processed['chinese_description'] ?? '') . ($processed['english_description'] ?? ''), // 'english_description' => ($processed['english_description'] ?? '') . ($processed['english_description'] ?? ''), // 'same_count' => $sameCountMap[$relative] ?? 0 // ]; // } // // // 5. 手动分页(对少量已筛选后的数据) // $total = count($filtered); // $pagedData = array_slice($filtered, ($page - 1) * $limit, $limit); // foreach ($pagedData as $index => &$item) { // $item['id'] = ($page - 1) * $limit + $index + 1; // } // // return json([ // 'code' => 0, // 'msg' => '获取成功', // 'data' => $pagedData, // 'total' => $total, // 'page' => $page, // 'limit' => $limit // ]); // } /** * 获取原图目录及每个目录下的图片数量 */ public function getPreviewSubDirs() { $baseDir = rtrim(str_replace('\\', '/', ROOT_PATH), '/') . '/public/uploads/operate/ai/Preview'; $baseRelativePath = 'uploads/operate/ai/Preview'; if (!is_dir($baseDir)) { return json(['code' => 1, 'msg' => '目录不存在']); } $dirs = []; $index = 1; /** * 递归扫描目录,提取含图片的子目录信息 */ $scanDir = function ($dirPath, $relativePath) use (&$scanDir, &$dirs, &$index) { $items = scandir($dirPath); foreach ($items as $item) { if ($item === '.' || $item === '..') continue; $fullPath = $dirPath . '/' . $item; $relPath = $relativePath . '/' . $item; if (is_dir($fullPath)) { // 递归子目录 $scanDir($fullPath, $relPath); } else { // 匹配图片文件 if (preg_match('/\.(jpg|jpeg|png)$/i', $item)) { $parentDir = dirname($fullPath); $relativeDir = dirname($relPath); $key = md5($parentDir); if (!isset($dirs[$key])) { $ctime = filectime($parentDir); // 数据库统计:已处理图片数量 $hasData = Db::name('text_to_image') ->where('custom_image_url', '<>', '') ->where('img_name', '<>', '') ->whereLike('old_image_url', $relativeDir . '/%') ->where('status',1) ->whereNotNull('custom_image_url') ->count(); // 当前目录下图片数量 $imageFiles = glob($parentDir . '/*.{jpg,jpeg,png}', GLOB_BRACE); $imageCount = is_array($imageFiles) ? count($imageFiles) : 0; $dirs[$key] = [ 'id' => $index++, 'name' => basename($parentDir), 'count' => $hasData, 'ctime' => $ctime, // 时间戳,用于排序 'ctime_text' => date('Y-m-d H:i:s', $ctime), // 格式化日期,用于显示 'image_count' => $imageCount, 'new_image_url' => "/uploads/operate/ai/dall-e/", 'old_image_url' => $relativeDir ]; } } } } }; // 执行目录扫描 $scanDir($baseDir, $baseRelativePath); // 排序:按照创建时间(从新到旧) $dirList = array_values($dirs); usort($dirList, function ($a, $b) { return $b['ctime'] - $a['ctime']; }); return json([ 'code' => 0, 'msg' => '获取成功', 'data' => $dirList ]); } /** * 图片上传 * @return void */ public function ImgUpload() { // 处理 CORS OPTIONS 预检请求 if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: POST, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type, Authorization'); header('Access-Control-Max-Age: 86400'); exit(204); } // 实际请求必须返回 CORS 头 header('Access-Control-Allow-Origin: *'); // 获取上传的文件 $file = request()->file('image'); if ($file) { // 指定目标目录(你想上传到的目录) $targetPath = ROOT_PATH . 'public' . DS . 'uploads' . DS . 'operate' . DS . 'ai' . DS . 'Preview'; // 若目录不存在则创建 if (!is_dir($targetPath)) { mkdir($targetPath, 0755, true); } // 移动文件到指定目录,并验证大小/格式 $info = $file->validate([ 'size' => 10485760, // 最大10MB 'ext' => 'jpg,png' ])->move($targetPath); if ($info) { $fileName = $info->getSaveName(); $imageUrl = '/uploads/operate/ai/Preview/' . str_replace('\\', '/', $fileName); return json(['code' => 0, 'msg' => '成功', 'data' => ['url' => $imageUrl]]); } else { $res = $file->getError(); return json(['code' => 1, 'msg' => '失败', 'data' => $res]); } } return json(['code' => 1, 'msg' => '没有文件上传', 'data' => null]); } /** * 模版 */ public function Template(){ $Template = Db::name("template")->find(); return json([ 'code' => 0, 'msg' => '模版', 'data' => $Template ]); } /** * 更新模版 */ public function updatetemplate(){ if (Request::instance()->isPost() == false){ $this->error('非法请求'); } $params = Request::instance()->post(); // 验证传入的参数是否存在,避免空值 if (empty($params['textareaContent']) || empty($params['width']) || empty($params['height'])) { return json(['code' => 1, 'msg' => '参数缺失']); } // 更新模板数据 $Template = Db::name("template") ->where('id', 1) // 假设模板 ID 是 1,需根据实际情况修改 ->update([ 'english_content' => $params['english_content'], // 更新文生文模版内容 'content' => $params['textareaContent'], // 更新图生文模版内容 'width' => $params['width'], // 更新宽度 'height' => $params['height'], // 更新宽度 ]); // 判断数据库更新是否成功 if ($Template){ return json(['code' => 0, 'msg' => '成功']); }else{ return json(['code' => 1, 'msg' => '失败']); } } }