diff --git a/app/Blog/Support/PageCacheMiddleware.php b/app/Blog/Support/PageCacheMiddleware.php index 70c45f8..2250490 100644 --- a/app/Blog/Support/PageCacheMiddleware.php +++ b/app/Blog/Support/PageCacheMiddleware.php @@ -28,12 +28,16 @@ class PageCacheMiddleware $ttl = (int) config('blog.page_cache_ttl', 300); if ($cached = Cache::get($key)) { + self::increment('hits'); + return response($cached['body'], 200, [ 'Content-Type' => $cached['type'], 'Cache-Control' => 'public, max-age='.$ttl, ]); } + self::increment('misses'); + $response = $next($request); if ($response->getStatusCode() === 200) { @@ -61,6 +65,35 @@ class PageCacheMiddleware return count((array) Cache::get(self::TAG.'_keys', [])); } + /** + * 命中/未命中统计(按日滚动),用于判断前台缓存效果。 + */ + public static function stats(): array + { + $hits = (int) Cache::get(self::TAG.'_hits', 0); + $misses = (int) Cache::get(self::TAG.'_misses', 0); + $total = $hits + $misses; + + return [ + 'hits' => $hits, + 'misses' => $misses, + 'count' => self::count(), + 'rate' => $total > 0 ? round($hits / $total * 100, 1) : 0.0, + ]; + } + + public static function resetStats(): void + { + Cache::forget(self::TAG.'_hits'); + Cache::forget(self::TAG.'_misses'); + } + + private static function increment(string $metric): void + { + $key = self::TAG.'_'.$metric; + Cache::put($key, (int) Cache::get($key, 0) + 1, now()->addDay()); + } + private static function rememberKey(string $key): void { $keys = (array) Cache::get(self::TAG.'_keys', []); diff --git a/app/Blog/Support/PluginManager.php b/app/Blog/Support/PluginManager.php index 1766b08..fc1296d 100644 --- a/app/Blog/Support/PluginManager.php +++ b/app/Blog/Support/PluginManager.php @@ -81,6 +81,7 @@ class PluginManager 'title' => $manifest['title'] ?? $name, 'version' => $manifest['version'] ?? '0.0.0', 'description' => $manifest['description'] ?? '', + 'usage' => $manifest['usage'] ?? '', 'author' => $manifest['author'] ?? '', 'enabled' => $this->isEnabled($basename), 'requires' => $requires, diff --git a/app/Filament/Widgets/BlogStats.php b/app/Filament/Widgets/BlogStats.php index ace94d6..69482e1 100644 --- a/app/Filament/Widgets/BlogStats.php +++ b/app/Filament/Widgets/BlogStats.php @@ -17,6 +17,8 @@ class BlogStats extends BaseWidget protected function getStats(): array { + $cache = \App\Blog\Support\PageCacheMiddleware::stats(); + return [ Stat::make('文章', Post::published()->count()) ->description('总浏览量 '.number_format((float) Post::sum('views'))) @@ -26,6 +28,9 @@ class BlogStats extends BaseWidget ->icon('heroicon-o-chat-bubble-left-right'), Stat::make('用户', User::count()) ->icon('heroicon-o-users'), + Stat::make('页面缓存', $cache['count'].' 条') + ->description('命中率 '.$cache['rate'].'%(命中 '.$cache['hits'].' / 未命中 '.$cache['misses'].',按日滚动)') + ->icon('heroicon-o-bolt'), ]; } } diff --git a/docs/plugins.md b/docs/plugins.md index d3d9795..a714e94 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -21,6 +21,7 @@ plugins/{vendor}.{name}/ "title": "插件标题", "version": "1.0.0", "description": "插件描述", + "usage": "使用说明(多行文本,后台插件卡片「使用说明」折叠展示)", "author": "作者", "type": "core", "provider": "Plugins\\Vendor\\Name\\ServiceProvider", @@ -34,6 +35,7 @@ plugins/{vendor}.{name}/ |------|------| | `provider` | 入口类 FQCN;缺省时自动推断 `src/ServiceProvider.php` | | `requires` | 依赖的其他插件(如会员依赖支付),按 `vendor.name` 引用 | +| `usage` | 使用说明(换行文本),后台插件卡片可折叠查看 | | `filament_pages` / `filament_resources` | 注册到后台的页面/资源(由 `PluginPages` 汇总,统一归入「插件」导航分组) | ## 依赖管理(requires 强制校验) diff --git a/plugins/neatstudio.ai-moderation/plugin.json b/plugins/neatstudio.ai-moderation/plugin.json index 1fe2f1f..8290968 100644 --- a/plugins/neatstudio.ai-moderation/plugin.json +++ b/plugins/neatstudio.ai-moderation/plugin.json @@ -7,5 +7,6 @@ "provider": "Plugins\\Neatstudio\\AiModeration\\ServiceProvider", "filament_pages": [ "Plugins\\Neatstudio\\AiModeration\\Filament\\Pages\\AiSettings" - ] + ], + "usage": "1. 后台「AI 设置」配置 Base URL / API Key / 模型(OpenAI 兼容,支持 DeepSeek/通义等)\n2. 新评论会自动进入 AI 审核队列(可在「AI 设置」页实时查看进度)\n3. 文章列表点「AI 润色」生成润色稿,确认后采纳\n4. 需要消费者运行:php artisan workerman:serve 或 php artisan queue:work --queue=default,ai" } diff --git a/plugins/neatstudio.blog-seo/plugin.json b/plugins/neatstudio.blog-seo/plugin.json index 0649bee..83726d3 100644 --- a/plugins/neatstudio.blog-seo/plugin.json +++ b/plugins/neatstudio.blog-seo/plugin.json @@ -4,5 +4,6 @@ "description": "完善 SEO(结构化数据/OG 标签)+ GEO(llms.txt / Markdown 导出,面向 AI 搜索引擎优化)", "author": "LaraLog", "type": "core", - "provider": "Plugins\\Neatstudio\\BlogSeo\\ServiceProvider" + "provider": "Plugins\\Neatstudio\\BlogSeo\\ServiceProvider", + "usage": "无需额外配置,启用即生效:\n- SEO:页面 title/description/keywords、OG/Twitter 标签、JSON-LD(BlogPosting/WebSite)自动输出\n- GEO:/llms.txt 站点摘要、/posts/{slug}.md 文章 Markdown 导出\n- /sitemap.xml、/robots.txt 由核心路由提供\n站点名/描述等在「博客设置 → 站点」配置,社交账号在「博客设置 → 社交账号」配置" } diff --git a/plugins/neatstudio.membership/plugin.json b/plugins/neatstudio.membership/plugin.json index 84e7bab..00f4cc1 100644 --- a/plugins/neatstudio.membership/plugin.json +++ b/plugins/neatstudio.membership/plugin.json @@ -5,9 +5,12 @@ "author": "LaraLog", "type": "core", "provider": "Plugins\\Neatstudio\\Membership\\ServiceProvider", - "requires": ["neatstudio.payment"], + "requires": [ + "neatstudio.payment" + ], "filament_resources": [ "Plugins\\Neatstudio\\Membership\\Filament\\Resources\\MembershipPlanResource", "Plugins\\Neatstudio\\Membership\\Filament\\Resources\\SubscriptionResource" - ] + ], + "usage": "1. 后台创建会员套餐(价格/时长/权限)\n2. 文章编辑页「付费设置」可设单篇价格或会员专享;正文用 [paid]...[/paid] 标记付费块\n3. 前台 /membership 展示套餐,游客解锁或开通会员后可见付费内容\n4. 依赖支付插件:先配置支付或开启沙箱" } diff --git a/plugins/neatstudio.payment/plugin.json b/plugins/neatstudio.payment/plugin.json index 6d53fb0..bbf7583 100644 --- a/plugins/neatstudio.payment/plugin.json +++ b/plugins/neatstudio.payment/plugin.json @@ -10,5 +10,6 @@ ], "filament_resources": [ "Plugins\\Neatstudio\\Payment\\Filament\\Resources\\PaymentResource" - ] + ], + "usage": "1. 后台「支付设置」配置支付宝/微信凭据,或开启沙箱模式(模拟支付,无需密钥)\n2. 会员套餐、单篇付费文章、市场商品购买都会创建订单并跳转支付\n3. 支付结果在「订单」页查看;沙箱模式走模拟收银台\n4. 真实支付需公网可访问的回调地址(部署后或内网穿透)" } diff --git a/resources/views/filament/pages/plugins.blade.php b/resources/views/filament/pages/plugins.blade.php index ce35941..4ad3be5 100644 --- a/resources/views/filament/pages/plugins.blade.php +++ b/resources/views/filament/pages/plugins.blade.php @@ -17,6 +17,13 @@
{{ $plugin['description'] }}
v{{ $plugin['version'] }} · {{ $plugin['vendor'] }}.{{ $plugin['name'] }}
+ @if(! empty($plugin['usage'])) +