feat: 前台 .shtml 后缀 canonical + strict_types 全量启用 + 对外 API(Sanctum+Scramble 文档)+ pm2 ecosystem + GitHub Actions CI + 插件/主题/架构/API 文档 + REDIS_PREFIX 说明
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Controllers;
|
||||
|
||||
use App\Models\Post;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Controllers;
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Controllers;
|
||||
|
||||
use App\Models\Category;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Controllers;
|
||||
|
||||
use App\Models\Comment;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Controllers;
|
||||
|
||||
class Controller
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Controllers;
|
||||
|
||||
use App\Models\Post;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Controllers;
|
||||
|
||||
use App\Models\Post;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Controllers;
|
||||
|
||||
use App\Models\Category;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Controllers;
|
||||
|
||||
use App\Models\Link;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Controllers;
|
||||
|
||||
use App\Blog\Services\PostContentRenderer;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Controllers;
|
||||
|
||||
use App\Models\Post;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Controllers;
|
||||
|
||||
use App\Models\Post;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Controllers;
|
||||
|
||||
use App\Blog\Support\ThemeManager;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Jobs;
|
||||
|
||||
use App\Blog\Services\LlmClient;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Providers;
|
||||
|
||||
use App\Blog\Support\PluginManager;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Providers;
|
||||
|
||||
use App\Blog\Support\ThemeManager;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Services;
|
||||
|
||||
use App\Models\Post;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Services;
|
||||
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Services;
|
||||
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Services;
|
||||
|
||||
use App\Blog\Support\PluginManager;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Services;
|
||||
|
||||
use App\Models\Post;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Support;
|
||||
|
||||
use App\Models\PluginRecord;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Support;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Support;
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Support;
|
||||
|
||||
use App\Models\Setting;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\Support;
|
||||
|
||||
use Workerman\Connection\TcpConnection;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Blog\View\Composers;
|
||||
|
||||
use App\Models\Category;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Support\MediaDisk;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Post;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Blog\Services\AttachmentImporter;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Blog\Support\ThemeManager;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Pages;
|
||||
|
||||
use App\Models\Setting;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Pages;
|
||||
|
||||
use App\Blog\Services\MarketplaceClient;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Pages;
|
||||
|
||||
use App\Blog\Services\PackageInstaller;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Categories;
|
||||
|
||||
use App\Filament\Resources\Categories\Pages\CreateCategory;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Categories\Pages;
|
||||
|
||||
use App\Filament\Resources\Categories\CategoryResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Categories\Pages;
|
||||
|
||||
use App\Filament\Resources\Categories\CategoryResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Categories\Pages;
|
||||
|
||||
use App\Filament\Resources\Categories\CategoryResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Categories\Schemas;
|
||||
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Categories\Tables;
|
||||
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Comments;
|
||||
|
||||
use App\Filament\Resources\Comments\Pages\CreateComment;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Comments\Pages;
|
||||
|
||||
use App\Filament\Resources\Comments\CommentResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Comments\Pages;
|
||||
|
||||
use App\Filament\Resources\Comments\CommentResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Comments\Pages;
|
||||
|
||||
use App\Filament\Resources\Comments\CommentResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Comments\Schemas;
|
||||
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Comments\Tables;
|
||||
|
||||
use App\Models\Comment;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Links;
|
||||
|
||||
use App\Filament\Resources\Links\Pages\CreateLink;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Links\Pages;
|
||||
|
||||
use App\Filament\Resources\Links\LinkResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Links\Pages;
|
||||
|
||||
use App\Filament\Resources\Links\LinkResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Links\Pages;
|
||||
|
||||
use App\Filament\Resources\Links\LinkResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Links\Schemas;
|
||||
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Links\Tables;
|
||||
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Media;
|
||||
|
||||
use App\Filament\Resources\Media\Pages\CreateMedia;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Media\Pages;
|
||||
|
||||
use App\Filament\Resources\Media\MediaResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Media\Pages;
|
||||
|
||||
use App\Filament\Resources\Media\MediaResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Media\Pages;
|
||||
|
||||
use App\Filament\Resources\Media\MediaResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Media\Schemas;
|
||||
|
||||
use Filament\Schemas\Schema;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Media\Tables;
|
||||
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Posts\Pages;
|
||||
|
||||
use App\Filament\Resources\Posts\PostResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Posts\Pages;
|
||||
|
||||
use App\Filament\Resources\Posts\PostResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Posts\Pages;
|
||||
|
||||
use App\Filament\Resources\Posts\PostResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Posts;
|
||||
|
||||
use App\Filament\Resources\Posts\Pages\CreatePost;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Posts\Schemas;
|
||||
|
||||
use App\Support\MediaDisk;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Posts\Tables;
|
||||
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Users\Pages;
|
||||
|
||||
use App\Filament\Resources\Users\UserResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Users\Pages;
|
||||
|
||||
use App\Filament\Resources\Users\UserResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Users\Pages;
|
||||
|
||||
use App\Filament\Resources\Users\UserResource;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Users\Schemas;
|
||||
|
||||
use Filament\Forms\Components\DateTimePicker;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Users\Tables;
|
||||
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Resources\Users;
|
||||
|
||||
use App\Filament\Resources\Users\Pages\CreateUser;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use App\Models\Comment;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use App\Models\Comment;
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Blog\Services\PostContentRenderer;
|
||||
use App\Models\Category;
|
||||
use App\Models\Comment;
|
||||
use App\Models\Post;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Spatie\Tags\Tag;
|
||||
|
||||
/**
|
||||
* 对外 API:为小程序/第三方平台提供数据与评论能力。
|
||||
*/
|
||||
class ApiController extends Controller
|
||||
{
|
||||
/**
|
||||
* 站点信息。
|
||||
*
|
||||
* @response array{name: string, description: string, icp: string, url: string}
|
||||
*/
|
||||
public function site(): JsonResponse
|
||||
{
|
||||
return response()->json([
|
||||
'name' => Setting::get('site_name', config('blog.name')),
|
||||
'description' => Setting::get('site_description', config('blog.description')),
|
||||
'icp' => Setting::get('site_icp', config('blog.icp')),
|
||||
'url' => url('/'),
|
||||
'rss' => route('feed.rss'),
|
||||
'api_version' => '1.0',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 文章列表(分页)。
|
||||
*
|
||||
* @queryParam page int 页码 Example: 1
|
||||
* @queryParam per_page int 每页数量(默认 10,最大 50)Example: 10
|
||||
* @queryParam category string 分类 slug Example: tech
|
||||
* @queryParam tag string 标签名 Example: laravel
|
||||
* @queryParam q string 关键词搜索 Example: laravel
|
||||
*
|
||||
* @response array{data: array, meta: array}
|
||||
*/
|
||||
public function posts(Request $request): JsonResponse
|
||||
{
|
||||
$query = Post::published()->with('category:id,name,slug')->with('tags:id,name');
|
||||
|
||||
if ($category = $request->query('category')) {
|
||||
$query->whereHas('category', fn ($q) => $q->where('slug', $category)->orWhere('name', $category));
|
||||
}
|
||||
|
||||
if ($tag = $request->query('tag')) {
|
||||
$query->whereHas('tags', fn ($q) => $q->where('name', $tag)->orWhere('slug', $tag));
|
||||
}
|
||||
|
||||
if ($q = trim((string) $request->query('q', ''))) {
|
||||
$query->search($q);
|
||||
}
|
||||
|
||||
$perPage = min((int) $request->query('per_page', 10), 50);
|
||||
|
||||
$posts = $query->orderByDesc('published_at')->paginate($perPage);
|
||||
|
||||
return response()->json([
|
||||
'data' => $posts->through(fn (Post $post) => $this->postSummary($post))->items(),
|
||||
'meta' => [
|
||||
'current_page' => $posts->currentPage(),
|
||||
'last_page' => $posts->lastPage(),
|
||||
'per_page' => $posts->perPage(),
|
||||
'total' => $posts->total(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 文章详情。
|
||||
*
|
||||
* @urlParam slug string required 文章 slug 或 ID Example: post-1
|
||||
*
|
||||
* @response array{id: int, title: string, content_html: string, ...}
|
||||
*/
|
||||
public function post(string $slug): JsonResponse
|
||||
{
|
||||
$post = Post::query()
|
||||
->where('slug', $slug)
|
||||
->orWhere('id', (int) $slug)
|
||||
->first();
|
||||
|
||||
abort_unless($post && $post->status === 'published', 404);
|
||||
|
||||
// 会员/付费内容过滤与前台一致
|
||||
$contentHtml = app(PostContentRenderer::class)->render($post);
|
||||
|
||||
return response()->json([
|
||||
'id' => $post->id,
|
||||
'title' => $post->title,
|
||||
'slug' => $post->slug,
|
||||
'excerpt' => $post->excerpt_or_fallback,
|
||||
'content_html' => $contentHtml,
|
||||
'content_format' => $post->content_format,
|
||||
'keywords' => $post->keywords,
|
||||
'category' => $post->category ? ['id' => $post->category->id, 'name' => $post->category->name, 'slug' => $post->category->slug] : null,
|
||||
'tags' => $post->tags->map(fn ($t) => ['id' => $t->id, 'name' => $t->name, 'slug' => $t->slug])->values(),
|
||||
'views' => $post->views,
|
||||
'comment_count' => $post->comment_count,
|
||||
'published_at' => $post->published_at?->toIso8601String(),
|
||||
'url' => route('posts.show', $post->slug ?: $post->id),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分类列表。
|
||||
*
|
||||
* @response array{data: array}
|
||||
*/
|
||||
public function categories(): JsonResponse
|
||||
{
|
||||
return response()->json([
|
||||
'data' => Category::query()->orderBy('display_order')->orderBy('name')->get(['id', 'name', 'slug', 'post_count']),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 标签列表。
|
||||
*
|
||||
* @response array{data: array}
|
||||
*/
|
||||
public function tags(): JsonResponse
|
||||
{
|
||||
$counts = DB::table('taggables')
|
||||
->selectRaw('tag_id, COUNT(*) as total')
|
||||
->where('taggable_type', Post::class)
|
||||
->groupBy('tag_id')
|
||||
->pluck('total', 'tag_id');
|
||||
|
||||
return response()->json([
|
||||
'data' => Tag::query()->where('type', 'post')->get()
|
||||
->map(fn (Tag $tag) => [
|
||||
'id' => $tag->id,
|
||||
'name' => $tag->name,
|
||||
'slug' => $tag->slug,
|
||||
'post_count' => (int) ($counts[$tag->id] ?? 0),
|
||||
])
|
||||
->values(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交评论(公开)。
|
||||
*
|
||||
* @bodyParam author_name string required 昵称 Example: 访客
|
||||
* @bodyParam author_email string 邮箱 Example: guest@example.com
|
||||
* @bodyParam author_url string 网站 Example: https://example.com
|
||||
* @bodyParam content string required 评论内容 Example: 写得很好
|
||||
* @bodyParam website string 蜜罐字段,留空 Example:
|
||||
*/
|
||||
public function storeComment(Request $request): JsonResponse
|
||||
{
|
||||
$data = $request->validate([
|
||||
'post_id' => ['required', 'integer', 'exists:posts,id'],
|
||||
'author_name' => ['required', 'string', 'max:50'],
|
||||
'author_email' => ['nullable', 'email', 'max:255'],
|
||||
'author_url' => ['nullable', 'url', 'max:255'],
|
||||
'content' => ['required', 'string', 'min:'.(int) Setting::get('comment_min_len', 2), 'max:'.(int) Setting::get('comment_max_len', 6000)],
|
||||
]);
|
||||
|
||||
// 蜜罐
|
||||
if ($request->filled('website')) {
|
||||
return response()->json(['message' => '提交失败'], 422);
|
||||
}
|
||||
|
||||
$post = Post::findOrFail((int) $data['post_id']);
|
||||
|
||||
if ($post->status !== 'published' || $post->close_comment) {
|
||||
return response()->json(['message' => '该文章不允许评论'], 422);
|
||||
}
|
||||
|
||||
$status = (int) Setting::get('comment_audit', 0) === 1 ? 'pending' : 'published';
|
||||
|
||||
$comment = $post->comments()->create([
|
||||
'user_id' => $request->user()?->id,
|
||||
'author_name' => $data['author_name'],
|
||||
'author_email' => $data['author_email'] ?? null,
|
||||
'author_url' => $data['author_url'] ?? null,
|
||||
'content' => $data['content'],
|
||||
'ip' => $request->ip(),
|
||||
'status' => $status,
|
||||
]);
|
||||
|
||||
if ($status === 'published') {
|
||||
$post->increment('comment_count');
|
||||
}
|
||||
|
||||
app(\App\Blog\Support\PluginManager::class)->doAction('comment.created', $comment);
|
||||
|
||||
return response()->json([
|
||||
'message' => $status === 'published' ? '评论已发布' : '评论已提交,等待审核',
|
||||
'data' => ['id' => $comment->id, 'status' => $status],
|
||||
], 201);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前登录用户(需 Bearer Token)。
|
||||
*
|
||||
* @authenticated
|
||||
*
|
||||
* @response array{id: int, name: string, email: string, roles: array}
|
||||
*/
|
||||
public function me(Request $request): JsonResponse
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
return response()->json([
|
||||
'id' => $user->id,
|
||||
'name' => $user->name,
|
||||
'email' => $user->email,
|
||||
'roles' => $user->getRoleNames(),
|
||||
'url' => $user->url,
|
||||
]);
|
||||
}
|
||||
|
||||
private function postSummary(Post $post): array
|
||||
{
|
||||
return [
|
||||
'id' => $post->id,
|
||||
'title' => $post->title,
|
||||
'slug' => $post->slug,
|
||||
'excerpt' => $post->excerpt_or_fallback,
|
||||
'category' => $post->category?->name,
|
||||
'tags' => $post->tags->pluck('name')->values(),
|
||||
'views' => $post->views,
|
||||
'comment_count' => $post->comment_count,
|
||||
'published_at' => $post->published_at?->toIso8601String(),
|
||||
'url' => route('posts.show', $post->slug ?: $post->id),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
abstract class Controller
|
||||
{
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
abstract class Controller
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
+5
-1
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Database\Factories\UserFactory;
|
||||
@@ -9,13 +12,14 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Spatie\Permission\Traits\HasRoles;
|
||||
|
||||
class User extends Authenticatable implements FilamentUser
|
||||
{
|
||||
/** @use HasFactory<UserFactory> */
|
||||
use HasFactory, Notifiable, HasRoles;
|
||||
use HasFactory, Notifiable, HasRoles, HasApiTokens;
|
||||
|
||||
public function canAccessPanel(Panel $panel): bool
|
||||
{
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Providers\Filament;
|
||||
|
||||
use App\Filament\Pages\BlogSettings;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Support;
|
||||
|
||||
class MediaDisk
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Support;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
use App\Blog\Support\ThemeManager;
|
||||
|
||||
if (! function_exists('theme_view')) {
|
||||
|
||||
Reference in New Issue
Block a user