From 6acd0ccad0c96953c51e019767830936726b5afa Mon Sep 17 00:00:00 2001 From: 7IN0SAN9 Date: Thu, 16 Apr 2026 16:20:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AF=8C=E6=96=87=E6=9C=AC=E7=BC=96?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GuideResource/Pages/ManageGuidePages.php | 14 ++-- .../Controllers/Api/TerminalApiController.php | 2 +- app/Models/GuidePage.php | 7 +- ...e_html_url_with_content_on_guide_pages.php | 24 +++++++ database/seeders/GuideSeeder.php | 57 ++++++++------- .../resources/guide/manage-pages.blade.php | 10 ++- resources/views/guides/page.blade.php | 71 +++++++++++++++++++ routes/web.php | 5 ++ 8 files changed, 150 insertions(+), 40 deletions(-) create mode 100644 database/migrations/2026_04_15_000001_replace_html_url_with_content_on_guide_pages.php create mode 100644 resources/views/guides/page.blade.php diff --git a/app/Filament/Resources/GuideResource/Pages/ManageGuidePages.php b/app/Filament/Resources/GuideResource/Pages/ManageGuidePages.php index fc5ca18..37a7520 100644 --- a/app/Filament/Resources/GuideResource/Pages/ManageGuidePages.php +++ b/app/Filament/Resources/GuideResource/Pages/ManageGuidePages.php @@ -110,7 +110,7 @@ class ManageGuidePages extends Page $this->nodes = $pages->map(fn(GuidePage $p) => [ 'id' => $p->id, 'title' => $p->title, - 'html_url' => $p->html_url, + 'uri' => $p->uri, 'is_entry' => !isset($hasIncoming[$p->id]), 'options' => $p->options ?? [], 'x' => $positions[$p->id]['x'] ?? 50, @@ -207,7 +207,7 @@ class ManageGuidePages extends Page $page = $this->getRecord()->pages()->findOrFail($arguments['id']); $form->fill([ 'title' => $page->title, - 'html_url' => $page->html_url, + 'content' => $page->content, 'options' => $page->options ?? [], ]); }) @@ -261,11 +261,13 @@ class ManageGuidePages extends Page ->required() ->maxLength(255), - Forms\Components\TextInput::make('html_url') - ->label('HTML页面URL') + Forms\Components\RichEditor::make('content') + ->label('页面内容') ->required() - ->url() - ->maxLength(500), + ->fileAttachmentsDisk('public') + ->fileAttachmentsDirectory('guide-pages') + ->fileAttachmentsVisibility('public') + ->columnSpanFull(), Forms\Components\TagsInput::make('options') ->label('分支选项') diff --git a/app/Http/Controllers/Api/TerminalApiController.php b/app/Http/Controllers/Api/TerminalApiController.php index 2d2e933..63755a8 100644 --- a/app/Http/Controllers/Api/TerminalApiController.php +++ b/app/Http/Controllers/Api/TerminalApiController.php @@ -139,7 +139,7 @@ class TerminalApiController extends Controller $pagesMap[$page->id] = [ 'id' => $page->id, 'title' => $page->title, - 'html_url' => $page->html_url, + 'uri' => $page->uri, 'next' => $next, ]; } diff --git a/app/Models/GuidePage.php b/app/Models/GuidePage.php index 582f9cc..a398ffc 100644 --- a/app/Models/GuidePage.php +++ b/app/Models/GuidePage.php @@ -9,7 +9,7 @@ class GuidePage extends Model protected $fillable = [ 'guide_id', 'title', - 'html_url', + 'content', 'options', ]; @@ -25,6 +25,11 @@ class GuidePage extends Model }); } + public function getUriAttribute(): string + { + return route('guides.pages.show', $this->id); + } + public function guide() { return $this->belongsTo(Guide::class); diff --git a/database/migrations/2026_04_15_000001_replace_html_url_with_content_on_guide_pages.php b/database/migrations/2026_04_15_000001_replace_html_url_with_content_on_guide_pages.php new file mode 100644 index 0000000..e371477 --- /dev/null +++ b/database/migrations/2026_04_15_000001_replace_html_url_with_content_on_guide_pages.php @@ -0,0 +1,24 @@ +dropColumn('html_url'); + $table->longText('content')->nullable()->after('title')->comment('富文本正文HTML'); + }); + } + + public function down(): void + { + Schema::table('guide_pages', function (Blueprint $table) { + $table->dropColumn('content'); + $table->string('html_url', 500)->after('title')->comment('HTML页面链接'); + }); + } +}; diff --git a/database/seeders/GuideSeeder.php b/database/seeders/GuideSeeder.php index 00c52e5..70ea2a6 100644 --- a/database/seeders/GuideSeeder.php +++ b/database/seeders/GuideSeeder.php @@ -11,8 +11,6 @@ use Illuminate\Database\Seeder; class GuideSeeder extends Seeder { - private const BASE_URL = 'https://ssrf.9z.work/guides'; - /** * Run the database seeds. */ @@ -46,6 +44,11 @@ class GuideSeeder extends Seeder $this->command->info(' - 关联线站数量: ' . $stations->count()); } + private function placeholder(string $title): string + { + return '

本步骤说明待补充。管理员可在 Filament 后台使用富文本编辑器完善「' . e($title) . '」的操作指引。

'; + } + private function createHowToUseBeamGuide(User $admin): Guide { $this->command->info('创建指引: 如何用光...'); @@ -60,49 +63,47 @@ class GuideSeeder extends Seeder 'published_at' => now(), ]); - $baseUrl = self::BASE_URL . '/how-to-use-beam'; - $step1 = GuidePage::create([ 'guide_id' => $guide->id, 'title' => '打开光子光闸 PS1', - 'html_url' => "{$baseUrl}/step-1.html", + 'content' => $this->placeholder('打开光子光闸 PS1'), ]); $step2 = GuidePage::create([ 'guide_id' => $guide->id, 'title' => '搜索光学棚屋', - 'html_url' => "{$baseUrl}/step-2.html", + 'content' => $this->placeholder('搜索光学棚屋'), 'options' => ['前门12', '后门'], ]); $step3a = GuidePage::create([ 'guide_id' => $guide->id, 'title' => '前门12路径 - 检查设备状态', - 'html_url' => "{$baseUrl}/step-3a.html", + 'content' => $this->placeholder('前门12路径 - 检查设备状态'), ]); $step3b = GuidePage::create([ 'guide_id' => $guide->id, 'title' => '后门路径 - 安全确认', - 'html_url' => "{$baseUrl}/step-3b.html", + 'content' => $this->placeholder('后门路径 - 安全确认'), ]); $step4a = GuidePage::create([ 'guide_id' => $guide->id, 'title' => '前门12路径 - 打开实验站光闸', - 'html_url' => "{$baseUrl}/step-4a.html", + 'content' => $this->placeholder('前门12路径 - 打开实验站光闸'), ]); $step4b = GuidePage::create([ 'guide_id' => $guide->id, 'title' => '后门路径 - 设备检查', - 'html_url' => "{$baseUrl}/step-4b.html", + 'content' => $this->placeholder('后门路径 - 设备检查'), ]); $step5 = GuidePage::create([ 'guide_id' => $guide->id, 'title' => '完成', - 'html_url' => "{$baseUrl}/step-5.html", + 'content' => $this->placeholder('完成'), ]); // step1 → step2 (sequential) @@ -185,21 +186,20 @@ class GuideSeeder extends Seeder 'published_at' => now(), ]); - $baseUrl = self::BASE_URL . '/vacuum-valve-issue'; $steps = [ - ['title' => '检查真空度', 'file' => 'step-1.html'], - ['title' => '检查联锁状态', 'file' => 'step-2.html'], - ['title' => '尝试手动复位', 'file' => 'step-3.html'], - ['title' => '检查气动系统', 'file' => 'step-4.html'], - ['title' => '联系维护人员', 'file' => 'step-5.html'], + '检查真空度', + '检查联锁状态', + '尝试手动复位', + '检查气动系统', + '联系维护人员', ]; $pages = []; - foreach ($steps as $i => $step) { + foreach ($steps as $title) { $pages[] = GuidePage::create([ 'guide_id' => $guide->id, - 'title' => $step['title'], - 'html_url' => "{$baseUrl}/{$step['file']}", + 'title' => $title, + 'content' => $this->placeholder($title), ]); } @@ -231,21 +231,20 @@ class GuideSeeder extends Seeder 'published_at' => now(), ]); - $baseUrl = self::BASE_URL . '/water-leak-alarm'; $steps = [ - ['title' => '确认报警位置', 'file' => 'step-1.html'], - ['title' => '搜索光学棚屋', 'file' => 'step-2.html'], - ['title' => '定位并处理漏水点', 'file' => 'step-3.html'], - ['title' => '复位报警', 'file' => 'step-4.html'], - ['title' => '完成', 'file' => 'step-5.html'], + '确认报警位置', + '搜索光学棚屋', + '定位并处理漏水点', + '复位报警', + '完成', ]; $pages = []; - foreach ($steps as $i => $step) { + foreach ($steps as $title) { $pages[] = GuidePage::create([ 'guide_id' => $guide->id, - 'title' => $step['title'], - 'html_url' => "{$baseUrl}/{$step['file']}", + 'title' => $title, + 'content' => $this->placeholder($title), ]); } diff --git a/resources/views/filament/resources/guide/manage-pages.blade.php b/resources/views/filament/resources/guide/manage-pages.blade.php index 49a3d90..ba217e6 100644 --- a/resources/views/filament/resources/guide/manage-pages.blade.php +++ b/resources/views/filament/resources/guide/manage-pages.blade.php @@ -88,17 +88,20 @@ padding-top: 6px; } - .df-node-actions button { + .df-node-actions button, + .df-node-actions a { font-size: 11px; color: #6b7280; cursor: pointer; background: none; border: none; padding: 2px 0; + text-decoration: none; transition: color 0.15s; } - .df-node-actions button:hover { + .df-node-actions button:hover, + .df-node-actions a:hover { color: #3b82f6; } @@ -256,11 +259,12 @@ const html = `
${node.title}
-
${node.html_url}
+
${node.uri}
${node.is_entry ? '
入口
' : ''}
+ 预览
`; diff --git a/resources/views/guides/page.blade.php b/resources/views/guides/page.blade.php new file mode 100644 index 0000000..9d08fac --- /dev/null +++ b/resources/views/guides/page.blade.php @@ -0,0 +1,71 @@ + + + + + + {{ $page->title }} + + + +
+

{{ $page->title }}

+ {!! $page->content !!} +
+ + diff --git a/routes/web.php b/routes/web.php index 18a3bae..a395f29 100644 --- a/routes/web.php +++ b/routes/web.php @@ -84,6 +84,11 @@ Route::get('/health', function () { ], $httpCode); })->name('health.check'); +// 指引步骤渲染(供终端 webview 打开,公开访问) +Route::get('/guides/pages/{page}', function (\App\Models\GuidePage $page) { + return view('guides.page', ['page' => $page]); +})->name('guides.pages.show'); + // 文档预览和下载路由(需要认证) Route::middleware(['auth'])->group(function () { Route::get('/documents/{document}/preview', [DocumentController::class, 'preview'])