From a8d4390ff3dadd7a2129b027686081de463bd6ec Mon Sep 17 00:00:00 2001 From: toom1996 Date: Tue, 29 Jul 2025 11:28:34 +0800 Subject: [PATCH] update --- app/Controller/admin/api/NewsController.php | 37 +- app/Helpers/ArticleHelper.php | 111 ++++++ app/Helpers/TitleHelper.php | 355 -------------------- app/Rpc/v1/NewsService.php | 7 +- storage/view/news/import.blade.php | 37 +- 5 files changed, 176 insertions(+), 371 deletions(-) create mode 100644 app/Helpers/ArticleHelper.php delete mode 100755 app/Helpers/TitleHelper.php diff --git a/app/Controller/admin/api/NewsController.php b/app/Controller/admin/api/NewsController.php index 115c02a..9275cc6 100755 --- a/app/Controller/admin/api/NewsController.php +++ b/app/Controller/admin/api/NewsController.php @@ -7,6 +7,7 @@ use App\Enums\ArticlePublishedStatusEnum; use App\FormModel\admin\articles\ModifyModel; use App\FormModel\admin\news\NewsFormModel; use App\Helpers\AppHelper; +use App\Helpers\ArticleHelper; use App\Model\AppArticle; use App\Model\AppBrand; use App\Model\AppNews; @@ -105,19 +106,24 @@ class NewsController extends AbstractController $platform = $this->request->post('platform', 0); $column = $this->request->post('column', 0); $column2 = $this->request->post('column2', 0); - // 随机图片 - $directory = env('COVER_ROOT'); // 文件夹路径 - $images = glob($directory . '/*.{jpg,jpeg,png,gif,bmp}', GLOB_BRACE); // 获取图片文件 + $cover = $this->request->post('cover', ''); $imagesArr = []; - if (count($images) > 0) { - foreach ($images as $image) { - $imagesArr[] = basename($image); - } - } + // 自动选封面 + if (!$cover) { + // 随机图片 + $directory = env('COVER_ROOT'); // 文件夹路径 + $images = glob($directory . '/*.{jpg,jpeg,png,gif,bmp}', GLOB_BRACE); // 获取图片文件 - if (!$imagesArr) { - return $this->response->json(['code' => 400, 'msg' => 'not content.']); + if (count($images) > 0) { + foreach ($images as $image) { + $imagesArr[] = basename($image); + } + } + + if (!$imagesArr) { + return $this->response->json(['code' => 400, 'msg' => 'not content.']); + } } if (!$content) { @@ -126,19 +132,24 @@ class NewsController extends AbstractController $content = json_decode($content, true); foreach ($content as $item) { - $randIndex = mt_rand(1,count($imagesArr)); - $cover = $imagesArr[$randIndex]; + if ($imagesArr) { + $randIndex = mt_rand(1,count($imagesArr)); + $cover = env('APP_DOMAIN') . '/uploads/cover/' . $imagesArr[$randIndex]; + } + $model = new AppNews(); $model->title = is_array($item['title']) ? current($item['title']) : $item['title']; $model->description = $item['desc']; $model->keywords = $item['keywords']; $model->platform = $platform; - $model->cover = env('APP_DOMAIN') . '/uploads/cover/' . $cover; + $model->cover = $cover; $model->content = strtr($item['content'], [ '' => <<

EOF ]); + + $model->content = ArticleHelper::saveImagesFromArticle($model->content, srcPrefix: env('APP_DOMAIN') . '/uploads/'); $model->column_tag = $column; $model->second_column = $column2; $model->save(); diff --git a/app/Helpers/ArticleHelper.php b/app/Helpers/ArticleHelper.php new file mode 100644 index 0000000..8a29fd6 --- /dev/null +++ b/app/Helpers/ArticleHelper.php @@ -0,0 +1,111 @@ +]+src=["\']([^"\']+)["\'][^>]*>/i', $html, $matches); + + // $matches[1] 包含所有 img 标签的图片 URL + $imageUrls = $matches[1]; + + // 遍历所有图片 URL 下载并保存 + foreach ($imageUrls as $imageUrl) { + // 解析图片的文件名 + $imageName = basename(parse_url($imageUrl, PHP_URL_PATH)); + + // 获取文件扩展名(如果没有扩展名,需要根据图片内容判断) + $extension = pathinfo($imageName, PATHINFO_EXTENSION); + if (empty($extension)) { + $imageContent = file_get_contents($imageUrl); + $finfo = finfo_open(FILEINFO_MIME_TYPE); // 获取 MIME 类型 + $mimeType = finfo_buffer($finfo, $imageContent); + finfo_close($finfo); + + // 根据 MIME 类型设置文件扩展名 + if ($mimeType == 'image/jpeg') { + $extension = 'jpg'; + } elseif ($mimeType == 'image/png') { + $extension = 'png'; + } elseif ($mimeType == 'image/gif') { + $extension = 'gif'; + } elseif ($mimeType == 'image/webp') { // 添加对 webp 的支持 + $extension = 'webp'; + } else { + continue; // 如果无法判断,跳过这张图片 + } + + // 用新的扩展名更新文件名 + $imageName .= '.' . $extension; + } + + // 本地保存路径 + $localPath = $savePath . $imageName; + + // 使用带 Cookie 的 cURL 下载图片 + $result = self::downloadImageWithCookie($imageUrl, $localPath); + if ($result) { + // 更新 HTML 中 img 标签的 src 为本地路径 + $html = str_replace($imageUrl, $srcPrefix . $imageName, $html); + } + } + + return $html; + } + + private static function downloadImageWithCookie($imageUrl, $savePath) { + // 2. 构造 HTTP 请求头 (Headers) +// 复制浏览器中的大部分 Header,提高请求成功率 + $headers = [ + 'accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8', + 'accept-language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6', + 'cache-control: no-cache', + 'cookie: ASP.NET_SessionId=tcth0to5f4rctrr2ejcxoley; User_Behavior_Cache=JXO3LM97XAP5BK1EKNAENZ76L2ZOT9DY; _gid=GA1.2.1692255419.1753689656; _ga=GA1.1.574649996.1753689655; _ga_L98EL3NEEE=GS2.1.s1753694736$o2$g1$t1753695112$j60$l0$h0', + 'pragma: no-cache', + 'referer: https://news.vobao.com/', + 'sec-ch-ua: "Not)A;Brand";v="8", "Chromium";v="138", "Microsoft Edge";v="138"', + 'sec-ch-ua-mobile: ?0', + 'sec-ch-ua-platform: "Windows"', + 'sec-fetch-dest: image', + 'sec-fetch-mode: no-cors', + 'sec-fetch-site: same-site', + 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', + ]; + +// 3. 初始化 cURL + $ch = curl_init(); + +// 4. 设置 cURL 选项 + curl_setopt($ch, CURLOPT_URL, $imageUrl); // 设置请求URL + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // 设置请求头 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 将结果作为字符串返回,而不是直接输出 + curl_setopt($ch, CURLOPT_HEADER, false); // 不返回响应头部分 + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 跟随重定向 + curl_setopt($ch, CURLOPT_ENCODING, ''); // 处理所有受支持的编码,如gzip + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 禁用SSL证书验证 (在某些环境下需要) + curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 设置超时时间为30秒 + +// 5. 执行 cURL 请求 + $imageData = curl_exec($ch); + +// 6. 检查是否有错误发生 + if (curl_errno($ch)) { + echo 'cURL 请求错误: ' . curl_error($ch); + return false; + } + +// 8. 关闭 cURL 句柄 + curl_close($ch); + + return file_put_contents($savePath, $imageData); + } +} \ No newline at end of file diff --git a/app/Helpers/TitleHelper.php b/app/Helpers/TitleHelper.php deleted file mode 100755 index b09883a..0000000 --- a/app/Helpers/TitleHelper.php +++ /dev/null @@ -1,355 +0,0 @@ - [ - [ - 'preg' => '/Madrid Spring ([0-9]*?)/', - 'trans' => '春季', - 'style' => ArticleStyleEnum::NULL->value, - 'location' => LocationEnum::MADRID->value, - ],[ - 'preg' => '/Madrid Fall ([0-9]*?)/', - 'trans' => '秋季', - 'style' => ArticleStyleEnum::NULL->value, - 'location' => LocationEnum::MADRID->value, - ], - ], - 'Spain' => [ - [ - 'preg' => '/Spain Spring ([0-9]*?)/', - 'trans' => '春季', - 'style' => ArticleStyleEnum::NULL->value, - 'location' => LocationEnum::SPAIN->value, - ],[ - 'preg' => '/Spain Fall ([0-9]*?)/', - 'trans' => '秋季', - 'style' => ArticleStyleEnum::NULL->value, - 'location' => LocationEnum::SPAIN->value, - ], - ], - 'Istanbul' => [ - [ - 'preg' => '/Istanbul Spring ([0-9]*?)/', - 'trans' => '春季', - 'style' => ArticleStyleEnum::NULL->value, - 'location' => LocationEnum::ISTANBUL->value, - ],[ - 'preg' => '/Istanbul Fall ([0-9]*?)/', - 'trans' => '秋季', - 'style' => ArticleStyleEnum::NULL->value, - 'location' => LocationEnum::ISTANBUL->value, - ], - ], - 'Lagos' => [ - [ - 'preg' => '/Lagos Spring ([0-9]*?)/', - 'trans' => '春季', - 'style' => ArticleStyleEnum::NULL->value, - 'location' => LocationEnum::LAGOS->value, - ],[ - 'preg' => '/Lagos Fall ([0-9]*?)/', - 'trans' => '秋季', - 'style' => ArticleStyleEnum::NULL->value, - 'location' => LocationEnum::LAGOS->value, - ], - ], - 'Russia' => [ - [ - 'preg' => '/Russia Spring ([0-9]*?)/', - 'trans' => '春季', - 'style' => ArticleStyleEnum::NULL->value, - 'location' => LocationEnum::RUSSIA->value, - ],[ - 'preg' => '/Russia Fall ([0-9]*?)/', - 'trans' => '秋季', - 'style' => ArticleStyleEnum::NULL->value, - 'location' => LocationEnum::RUSSIA->value, - ], - ], - 'Shanghai' => [ - [ - 'preg' => '/Shanghai Spring ([0-9]*?)/', - 'trans' => '春季', - 'style' => ArticleStyleEnum::NULL->value, - 'location' => LocationEnum::SHANGHAI->value, - ],[ - 'preg' => '/Shanghai Fall ([0-9]*?)/', - 'trans' => '秋季', - 'style' => ArticleStyleEnum::NULL->value, - 'location' => LocationEnum::SHANGHAI->value, - ], - ], - 'Bridal' => [ - [ - 'preg' => '/Bridal Spring ([0-9]*?)/', - 'trans' => '春季婚纱礼服', - 'style' => ArticleStyleEnum::BRIDAL->value, - 'location' => LocationEnum::NULL->value, - ],[ - 'preg' => '/Bridal Fall ([0-9]*?)/', - 'trans' => '秋季婚纱礼服', - 'style' => ArticleStyleEnum::BRIDAL->value, - 'location' => LocationEnum::NULL->value, - ], - ], - 'Australia' => [ - [ - 'preg' => '/Australia Resort ([0-9]*)/', - 'trans' => '度假系列', - 'style' => 1, - 'location' => LocationEnum::AUSTRALIA->value, - ],[ - 'preg' => '/Australia Spring ([0-9]*)/', - 'trans' => '春季', - 'style' => 0, - 'location' => LocationEnum::AUSTRALIA->value, - ], - ], - 'Menswear' => [ - [ - 'preg' => '/Spring ([0-9]*?) Menswear/', - 'trans' => '春季男装', - 'style' => 0, - 'location' => 0, - ],[ - 'preg' => '/Fall ([0-9]*?) Menswear/', - 'trans' => '秋季男装', - 'style' => 0, - 'location' => 0, - ] - ], - 'Ukraine' => [ - [ - 'preg' => '/Ukraine Fall ([0-9]*)/', - 'trans' => '秋季', - 'style' => 0, - 'location' => LocationEnum::UKRAINE->value, // 乌克兰 - ], - [ - 'preg' => '/Ukraine Spring ([0-9]*)/', - 'trans' => '春季', - 'style' => 0, - 'location' => LocationEnum::UKRAINE->value, // 乌克兰 - ], - ], - 'Kiev' => [ - [ - 'preg' => '/Kiev Fall ([0-9]*)/', - 'trans' => '秋季', - 'style' => 0, - 'location' => LocationEnum::KIEV->value, // 基辅 - ],[ - 'preg' => '/Kiev Spring ([0-9]*)/', - 'trans' => '春季', - 'style' => 0, - 'location' => LocationEnum::KIEV->value, // 基辅 - ] - ], - 'Stockholm' => [ - [ - 'preg' => '/Stockholm Fall ([0-9]*)/', - 'trans' => '秋季', - 'style' => 0, - 'location' => LocationEnum::STOCKHOLM->value, // 斯德哥尔摩 - ], - [ - 'preg' => '/Stockholm Spring ([0-9]*)/', - 'trans' => '春季', - 'style' => 0, - 'location' => LocationEnum::STOCKHOLM->value, // 斯德哥尔摩 - ], - ], - 'Tbilisi' => [ - [ - 'preg' => '/Tbilisi Fall ([0-9]*)/', - 'trans' => '秋季', - 'style' => 0, - 'location' => LocationEnum::TBILISI->value, // 斯德哥尔摩 - ], - [ - 'preg' => '/Tbilisi Spring ([0-9]*)/', - 'trans' => '春季', - 'style' => 0, - 'location' => LocationEnum::TBILISI->value, // 斯德哥尔摩 - ], - ], - 'Mexico' => [ - [ - 'preg' => '/Mexico Fall ([0-9]*)/', - 'trans' => '秋季', - 'style' => 0, - 'location' => LocationEnum::MEXICO->value, // 斯德哥尔摩 - ],[ - 'preg' => '/Mexico Spring ([0-9]*)/', - 'trans' => '秋季', - 'style' => 0, - 'location' => LocationEnum::MEXICO->value, // 斯德哥尔摩 - ],[ - 'preg' => '/Mexico City Fall ([0-9]*)/', - 'trans' => '城市秋季', - 'style' => 0, - 'location' => LocationEnum::MEXICO->value, // 斯德哥尔摩 - ],[ - 'preg' => '/Mexico City Spring ([0-9]*)/', - 'trans' => '城市春季', - 'style' => 0, - 'location' => LocationEnum::MEXICO->value, // 斯德哥尔摩 - ], - ], - 'Tokyo' => [ - [ - 'preg' => '/Tokyo Spring ([0-9]*)/', - 'trans' => '春季', - 'style' => 0, - 'location' => LocationEnum::TOKYO->value, // 东京 - ],[ - 'preg' => '/Tokyo Fall ([0-9]*)/', - 'trans' => '秋季', - 'style' => 0, - 'location' => LocationEnum::TOKYO->value, // 东京 - ], - ], - 'Berlin' => [ - [ - 'preg' => '/Berlin Fall ([0-9]*)/', - 'trans' => '秋季', - 'style' => 0, - 'location' => LocationEnum::BERLIN->value, // 柏林 - ], - [ - 'preg' => '/Berlin Spring ([0-9]*)/', - 'trans' => '春季', - 'style' => 0, - 'location' => LocationEnum::BERLIN->value, // 柏林 - ], - ], - 'Copenhagen' => [ - [ - 'preg' => '/Copenhagen Fall ([0-9]*)/', - 'trans' => '秋季', - 'style' => 0, - 'location' => LocationEnum::COPENHAGEN->value, // 哥本哈根 - ],[ - 'preg' => '/Copenhagen Spring ([0-9]*)/', - 'trans' => '春季', - 'style' => 0, - 'location' => LocationEnum::COPENHAGEN->value, // 哥本哈根 - ], - ], - 'São Paulo' => [ - [ - 'preg' => '/São Paulo Fall ([0-9]*)/', - 'trans' => '秋季', - 'style' => 0, - 'location' => LocationEnum::SAO_PAULO->value, // 哥本哈根 - ],[ - 'preg' => '/São Paulo Spring ([0-9]*)/', - 'trans' => '春季', - 'style' => 0, - 'location' => LocationEnum::SAO_PAULO->value, // 哥本哈根 - ], - ], - 'SEOUL' => [ - [ - 'preg' => '/Seoul Spring ([0-9]*)/', - 'trans' => '春季', - 'style' => 0, - 'location' => LocationEnum::SEOUL->value, - ],[ - 'preg' => '/Seoul Fall ([0-9]*)/', - 'trans' => '秋季', - 'style' => 0, - 'location' => LocationEnum::SEOUL->value, - ], - ], - 'Spring' => [ - [ - 'preg' => '/([0-9]*?) Spring Summer/', - 'trans' => '春夏', - 'style' => 0, - 'location' => 0, - ], - ], - 'Autumn Winter' => [ - [ - 'preg' => '/([0-9]*?) Autumn Winter/', - 'trans' => '秋冬', - 'style' => 0, - 'location' => 0, - ], - ], - 'Ready-to-Wear' => [ - [ - 'preg' => '/Fall ([0-9]*?) Ready-to-Wear/', - 'trans' => '秋季成衣', - 'style' => 0, - 'location' => 0, - ],[ - 'preg' => '/Spring ([0-9]*?) Ready-to-Wear/', - 'trans' => '春季成衣', - 'style' => 0, - 'location' => 0, - ], - ], - 'Resort' => [ - [ - 'preg' => '/Resort ([0-9]*?)/', - 'trans' => '度假系列', - 'style' => ArticleStyleEnum::RESORT->value, - 'location' => LocationEnum::NULL->value, - ], - ], - 'Couture' => [ - [ - 'preg' => '/Spring ([0-9]*?) Couture/', - 'trans' => '春季高订系列', - 'style' => ArticleStyleEnum::RESORT->value, - 'location' => LocationEnum::NULL->value, - ], - [ - 'preg' => '/Fall ([0-9]*?) Couture/', - 'trans' => '秋季高订系列', - 'style' => ArticleStyleEnum::RESORT->value, - 'location' => LocationEnum::NULL->value, - ], - ], - 'Pre-Fall' => [ - [ - 'preg' => '/Pre-Fall ([0-9]*)/', - 'trans' => '早秋', - 'style' => 0, - 'location' => 0, - ], - ], - ]; - - $res = $englishTitle; - foreach ($map as $keyword => $pregMap) { - if (stripos($englishTitle, $keyword) !== false) { - foreach ($pregMap as $pregItem) { - preg_match_all($pregItem['preg'], $englishTitle, $matches); - - if (count($matches) > 1 && $matches[1]) { - $res = trim(current($matches[1]) . " {$pregItem['trans']}"); - break; - } - } - - if ($res) { - break; - } - } - } - - return $res; - } -} \ No newline at end of file diff --git a/app/Rpc/v1/NewsService.php b/app/Rpc/v1/NewsService.php index 2fee241..0c20fee 100755 --- a/app/Rpc/v1/NewsService.php +++ b/app/Rpc/v1/NewsService.php @@ -91,7 +91,11 @@ class NewsService extends BaseService $ids[] = $item->id; } - $value = AppNews::query()->whereIn('id', $ids)->orderBy('id', 'desc')->get()->toArray(); + $value = AppNews::query() + ->select(['id', 'title', 'description', 'cover', 'created_at', 'column_tag', 'second_column']) + ->whereIn('id', $ids) + ->orderBy('id', 'desc') + ->get()->toArray(); foreach ($value as &$item) { $item['created_at'] = date('Y-m-d', $item['created_at']); @@ -117,7 +121,6 @@ class NewsService extends BaseService ->orderBy('id', 'desc') ->get() ->toArray(); - return $this->getResponse()->setExtra('hot', $hot)->setExtra('total', ceil($total / $limit))->setData($value)->setCode(0)->send(); } } \ No newline at end of file diff --git a/storage/view/news/import.blade.php b/storage/view/news/import.blade.php index 073e08b..63b204b 100644 --- a/storage/view/news/import.blade.php +++ b/storage/view/news/import.blade.php @@ -51,6 +51,16 @@ $secondColumn = call_user_func(function () { +
+ +
+ + + +
+
@@ -112,21 +122,46 @@ $secondColumn = call_user_func(function () { form.render('select'); // 重新渲染 select 以应用新的选项和样式 }); + var uploadInst = upload.render({ + elem: '#test1' //绑定元素 + ,url: UPLOAD_API // 上传接口,实际使用时改成您自己的上传接口即可。 + ,done: function(res){ + //上传完毕回调 + console.log(res) + // 若上传失败 + if(res.code > 0){ + return layer.msg('上传失败'); + } + // 上传成功的一些操作 + // … + document.querySelector('[id="cover"]').src = res.data.url + $("input[name=cover]").val(res.data.url); + } + ,error: function(){ + //请求异常回调 + } + }); + layui.form.on("submit(submit)", function (data) { + var index = layer.load(); layui.$.ajax({ url: SAVE_API, type: "POST", dateType: "json", data: data.field, success: function (res) { + + layer.close(index); if (res.code) { return layui.popup.failure(res.msg); } - return layui.popup.success("操作成功", function () { parent.refreshTable(); parent.layer.close(parent.layer.getFrameIndex(window.name)); }); + }, error: function (res) { + layui.popup.failure('请求异常。'); + layer.close(index); } }); return false;