Skip to content

Commit 4126454

Browse files
committed
分类改为非必填
1 parent 33855da commit 4126454

File tree

5 files changed

+46
-71
lines changed

5 files changed

+46
-71
lines changed

src/Http/Controllers/Api/BlogController.php

Lines changed: 11 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@
22

33
namespace NexaMerchant\Blog\Http\Controllers\Api;
44

5-
use Illuminate\Support\Str;
65
use Illuminate\Http\Request;
76
use Illuminate\Support\Carbon;
87
use Illuminate\Validation\Rule;
98
use Illuminate\Support\Facades\DB;
109
use Illuminate\Support\Facades\Log;
1110
use Maatwebsite\Excel\Facades\Excel;
1211
use Illuminate\Support\Facades\Cache;
13-
use Illuminate\Support\Facades\Storage;
1412
use NexaMerchant\Blog\Models\BlogArticle;
1513
use NexaMerchant\Blog\Models\BlogCategory;
1614
use NexaMerchant\Blog\Http\Requests\StoreBlogArticleRequest;
@@ -86,7 +84,7 @@ public function storeArticle(StoreBlogArticleRequest $request)
8684
$validated = $request->validated();
8785

8886
// 自动从content提取封面图
89-
$coverImage = $this->extractFirstImageFromContent($validated['content']);
87+
$coverImage = BlogArticle::extractFirstImageFromContent($validated['content']);
9088

9189
// 合并数据
9290
$validated = array_merge($validated, [
@@ -267,8 +265,6 @@ public function recommendArticles(Request $request)
267265
{
268266
$validated = $request->validate([
269267
'limit' => 'nullable|integer|min:1|max:20',
270-
// 'exclude_id' => 'nullable|integer|exists:blog_articles,id',
271-
// 'exclude_id' => 'integer|exists:blog_articles,id',
272268
'type' => 'nullable|in:latest,popular'
273269
]);
274270

@@ -293,10 +289,9 @@ public function recommendArticles(Request $request)
293289
->where('status', 1) // 只推荐已发布文章
294290
->when($validated['seo_url_key'] ?? false, function ($q) use ($validated) {
295291
$q->where('seo_url_key', '!=', $validated['seo_url_key']); // 排除当前文章
296-
})
297-
->when($validated['type'] === 'popular', function ($q) {
292+
})->when($validated['type'] === 'popular', function ($q) {
298293
$q->orderBy('view_count', 'desc');
299-
}, function ($q) {
294+
})->when($validated['type'] === 'latest', function ($q) {
300295
$q->latest();
301296
})
302297
->take($validated['limit'] ?? 3)
@@ -313,54 +308,11 @@ public function recommendArticles(Request $request)
313308
], 200);
314309
}
315310

316-
/**
317-
* 从HTML内容中提取第一张图片URL
318-
*/
319-
public function extractFirstImageFromContent(string $content): ?string
320-
{
321-
// 方案1:正则匹配(简单HTML内容)
322-
preg_match('/<img[^>]+src="([^">]+)"/', $content, $matches);
323-
$imageUrl = $matches[1] ?? '';
324-
325-
// 方案2:DOM解析(更复杂的HTML)
326-
/*
327-
$dom = new \DOMDocument();
328-
@$dom->loadHTML($content);
329-
$images = $dom->getElementsByTagName('img');
330-
$imageUrl = $images->length > 0 ? $images->item(0)->getAttribute('src') : null;
331-
*/
332-
333-
// 如果是本地相对路径,转换为存储路径
334-
if ($imageUrl && !Str::startsWith($imageUrl, ['http://', 'https://'])) {
335-
return Storage::url(ltrim(parse_url($imageUrl, PHP_URL_PATH), '/'));
336-
}
337-
338-
return $imageUrl;
339-
}
340-
341311
public function showArticle($id)
342312
{
343313
try {
344-
// 验证ID有效性
345-
// $validated = $request->validate([
346-
// 'with_category' => 'nullable|boolean',
347-
// 'with_related' => 'nullable|integer|min:1|max:5' // 相关文章数量
348-
// ]);
349-
350-
// 构建查询
351-
$article = BlogArticle::query()
352-
// ->when($request->boolean('with_category'), function ($query) {
353-
// $query->with(['category' => function ($q) {
354-
// $q->select('id', 'name', 'seo_url_key');
355-
// }]);
356-
// })
357-
// ->when($request->filled('with_related'), function ($query) use ($id, $request) {
358-
// $query->with(['relatedArticles' => function ($q) use ($request) {
359-
// $q->limit($request->input('with_related', 3))
360-
// ->select('id', 'title', 'seo_url_key', 'created_at');
361-
// }]);
362-
// })
363-
->findOrFail($id);
314+
315+
$article = BlogArticle::query()->findOrFail($id);
364316

365317
// 记录访问量(队列处理)
366318
dispatch(function () use ($id) {
@@ -393,10 +345,6 @@ public function showArticle($id)
393345
public function showCategory($id)
394346
{
395347
try {
396-
// $validated = $request->validate([
397-
// 'with_latest' => 'nullable|integer|min:1|max:5' // 最新文章数量
398-
// ]);
399-
400348
$category = BlogCategory::query()->withCount(['articles' => function ($q) {
401349
$q->where('status', 1); // 只统计已发布文章
402350
}])->with(['latestArticles' => function ($q) {
@@ -508,7 +456,6 @@ protected function formatArticleResponse($article)
508456
'category' => $article->category ?: null,
509457
'view_count' => $article->view_count,
510458
'related_articles' => $article->relatedArticles->isEmpty() ? null : $article->relatedArticles,
511-
// 'recommended_articles' => BlogArticle::query()->latest('updated_at')->take(3)->get(),
512459
'seo_meta' => [
513460
'title' => $article->seo_meta_title,
514461
'keywords' => $article->seo_meta_keywords,
@@ -771,6 +718,12 @@ public function batchDeleteCategory(Request $request)
771718
});
772719
}
773720

721+
/**
722+
* @description: 批量上传文章
723+
* @param {Request} $request
724+
* @Author: rickon
725+
* @Date: 2025-04-29 10:22:17
726+
*/
774727
public function articlesUpload(Request $request)
775728
{
776729
$this->validate($request, [

src/Http/Requests/StoreBlogArticleRequest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function rules()
1717
'title' => 'required|string|max:512',
1818
'content' => 'required|string',
1919
'description' => 'nullable|string',
20-
'category_id' => 'required|integer|exists:blog_categories,id',
20+
'category_id' => 'nullable|integer|exists:blog_categories,id',
2121
'seo_meta_title' => 'nullable|string|max:512',
2222
'seo_meta_keywords' => 'nullable|string|max:512',
2323
'seo_meta_description' => 'nullable|string',

src/Http/Requests/UpdateBlogArticleRequest.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Illuminate\Validation\Rule;
66
use Illuminate\Foundation\Http\FormRequest;
7+
use NexaMerchant\Blog\Models\BlogArticle;
78

89
class UpdateBlogArticleRequest extends FormRequest
910
{
@@ -20,7 +21,7 @@ public function rules()
2021
'title' => 'sometimes|string|max:512',
2122
'description' => 'sometimes|string',
2223
'content' => 'sometimes|string',
23-
'category_id' => 'sometimes|integer|exists:blog_categories,id',
24+
'category_id' => 'nullable|integer|exists:blog_categories,id',
2425
'status' => 'sometimes|integer|in:1,2',
2526
'seo_meta_title' => 'sometimes|string|max:512',
2627
'seo_meta_keywords' => 'sometimes|string|max:512',
@@ -31,22 +32,16 @@ public function rules()
3132
'max:255',
3233
Rule::unique('blog_articles', 'seo_url_key')->ignore($articleId)
3334
],
34-
'cover_image' => 'nullable|string|max:255'
35+
'cover_image' => 'nullable|string|max:512'
3536
];
3637
}
3738

3839
public function prepareForValidation()
3940
{
4041
if ($this->has('content') && !$this->has('cover_image')) {
4142
$this->merge([
42-
'cover_image' => $this->extractFirstImage($this->input('content'))
43+
'cover_image' => BlogArticle::extractFirstImageFromContent($this->input('content'))
4344
]);
4445
}
4546
}
46-
47-
protected function extractFirstImage($content)
48-
{
49-
preg_match('/<img[^>]+src="([^">]+)"/', $content, $matches);
50-
return $matches[1] ?? null;
51-
}
5247
}

src/Import/ArticleImport.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public function rules(): array
1616
'*.title' => 'required|string|max:512',
1717
'*.content' => 'required|string',
1818
// '*.description' => 'nullable|string',
19-
'*.category_id' => 'required|integer|exists:blog_categories,id',
19+
'*.category_id' => 'nullable|integer|exists:blog_categories,id',
2020
'*.seo_meta_title' => 'nullable|string|max:512',
2121
'*.seo_meta_keywords' => 'nullable|string|max:512',
2222
'*.seo_meta_description' => 'nullable|string',
@@ -26,10 +26,10 @@ public function rules(): array
2626

2727
public function model(array $row)
2828
{
29-
$blogController = new BlogController();
30-
$row['cover_image'] = $blogController->extractFirstImageFromContent($row['content']);
29+
$row['cover_image'] = BlogArticle::extractFirstImageFromContent($row['content']);
3130
// desc from content 截取200个字符
3231
$row['description'] = mb_substr(self::getBodyTextByHtml($row['content']), 0, 200);
32+
$row['category_id'] = $row['category_id'] ?: 0;
3333
$row['seo_meta_title'] = $row['seo_meta_title'] ?: '';
3434
$row['seo_meta_keywords'] = $row['seo_meta_keywords'] ?: '';
3535
$row['seo_meta_description'] = $row['seo_meta_description'] ?: '';

src/Models/BlogArticle.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
namespace NexaMerchant\Blog\Models;
44

5+
use Illuminate\Support\Str;
56
use Illuminate\Database\Eloquent\Model;
7+
use Illuminate\Support\Facades\Storage;
68

79
class BlogArticle extends Model
810
{
@@ -35,4 +37,29 @@ public function relatedArticles()
3537
->where('id', '!=', $this->id)
3638
->orderBy('created_at', 'desc');
3739
}
40+
41+
/**
42+
* 从HTML内容中提取第一张图片URL
43+
*/
44+
public static function extractFirstImageFromContent(string $content): ?string
45+
{
46+
// 方案1:正则匹配(简单HTML内容)
47+
preg_match('/<img[^>]+src="([^">]+)"/', $content, $matches);
48+
$imageUrl = $matches[1] ?? '';
49+
50+
// 方案2:DOM解析(更复杂的HTML)
51+
/*
52+
$dom = new \DOMDocument();
53+
@$dom->loadHTML($content);
54+
$images = $dom->getElementsByTagName('img');
55+
$imageUrl = $images->length > 0 ? $images->item(0)->getAttribute('src') : null;
56+
*/
57+
58+
// 如果是本地相对路径,转换为存储路径
59+
if ($imageUrl && !Str::startsWith($imageUrl, ['http://', 'https://'])) {
60+
return Storage::url(ltrim(parse_url($imageUrl, PHP_URL_PATH), '/'));
61+
}
62+
63+
return $imageUrl;
64+
}
3865
}

0 commit comments

Comments
 (0)