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;