wip: article AI polish, category SEO fields, cover generator, membership plan seeder
CI / PHPUnit (PHP 8.3) (push) Failing after 4s
CI / PHPUnit (PHP 8.2) (push) Failing after 1m9s
CI / Deploy (manual gate) (push) Skipped

This commit is contained in:
2026-09-07 18:48:37 +00:00
parent 263b98b218
commit 3cec4c5e18
121 changed files with 4701 additions and 313 deletions
@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('articles', function (Blueprint $table): void {
if (! Schema::hasColumn('articles', 'ai_polished_content')) {
$table->longText('ai_polished_content')->nullable()->after('ai_suggestions');
}
});
}
public function down(): void
{
Schema::table('articles', function (Blueprint $table): void {
if (Schema::hasColumn('articles', 'ai_polished_content')) {
$table->dropColumn('ai_polished_content');
}
});
}
};
@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('categories', function (Blueprint $table): void {
$table->string('description')->nullable()->after('name');
$table->text('intro')->nullable()->after('description');
$table->string('keywords')->nullable()->after('intro');
$table->string('cover_path')->nullable()->after('keywords');
});
}
public function down(): void
{
Schema::table('categories', function (Blueprint $table): void {
$table->dropColumn(['description', 'intro', 'keywords', 'cover_path']);
});
}
};
+48
View File
@@ -0,0 +1,48 @@
<?php
declare(strict_types=1);
namespace Database\Seeders;
use App\Domain\Plugin\PluginManager;
use App\Settings\AiSettings;
use Illuminate\Database\Seeder;
/**
* Sync AI settings from .env into Spatie settings, and enable comment moderation.
*
* Credentials stay in .env (gitignored); this seeder only copies them into the DB
* so Filament / LlmProvider pick them up after the initial settings migration.
*/
class AiSettingsSeeder extends Seeder
{
public function run(): void
{
$settings = app(AiSettings::class);
$settings->provider = (string) env('AI_PROVIDER', 'openai_compatible');
$settings->api_base_url = env('AI_API_BASE_URL') ?: $settings->api_base_url;
$settings->api_key = env('AI_API_KEY') ?: $settings->api_key;
$settings->model = env('AI_MODEL') ?: $settings->model;
$settings->comment_moderation_enabled = true;
$settings->content_optimization_enabled = true;
$settings->save();
$plugins = app(PluginManager::class);
$plugins->syncDiscoveredPlugins();
try {
$plugins->enable('larablog/ai-comment-moderation');
} catch (\Throwable $e) {
$this->command?->warn('Could not enable ai-comment-moderation: '.$e->getMessage());
}
$this->command?->info(sprintf(
'AI settings saved: provider=%s model=%s base=%s key=%s',
$settings->provider,
$settings->model ?? '(none)',
$settings->api_base_url ?? '(none)',
filled($settings->api_key) ? '****'.substr((string) $settings->api_key, -4) : '(empty)',
));
}
}
+5 -1
View File
@@ -8,6 +8,10 @@ class DatabaseSeeder extends Seeder
{
public function run(): void
{
$this->call(DemoBlogSeeder::class);
$this->call([
AiSettingsSeeder::class,
DemoBlogSeeder::class,
MembershipPlanSeeder::class,
]);
}
}
+15 -1
View File
@@ -30,6 +30,13 @@ class DemoBlogSeeder extends Seeder
//
}
try {
$plugins->enable('larablog/payment');
$plugins->enable('larablog/membership');
} catch (\Throwable) {
//
}
$admin = User::query()
->where('email', 'admin@larablog.test')
->orWhere('username', 'admin')
@@ -54,7 +61,14 @@ class DemoBlogSeeder extends Seeder
$category = Category::query()->updateOrCreate(
['id' => 1],
['name' => '随笔', 'display_order' => 0, 'articles_count' => 2]
[
'name' => '随笔',
'display_order' => 0,
'articles_count' => 2,
'description' => '随手记下的阅读与技术笔记。',
'intro' => '这里收录日常随笔:产品、写作与站点搭建过程中的短文。',
'keywords' => '随笔,博客,笔记',
]
);
$html = Article::query()->updateOrCreate(
+23
View File
@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Schema;
use Plugins\Larablog\Membership\Database\Seeders\MembershipPlanSeeder as PluginMembershipPlanSeeder;
class MembershipPlanSeeder extends Seeder
{
public function run(): void
{
if (! Schema::hasTable('membership_plans')) {
$this->command?->warn('membership_plans missing; run migrations first.');
return;
}
$this->call(PluginMembershipPlanSeeder::class);
}
}