Skip to content

Commit 5886826

Browse files
author
xboard
committed
feat: enhance plugin management
- Add command support for plugin management - Optimize plugin management page layout - Add email copy functionality for users - Convert payment methods and Telegram Bot to plugin system
1 parent 02d853d commit 5886826

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+3677
-1329
lines changed

app/Console/Commands/XboardInstall.php

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

33
namespace App\Console\Commands;
44

5+
use App\Services\Plugin\PluginManager;
56
use Illuminate\Console\Command;
67
use Illuminate\Encryption\Encrypter;
78
use App\Models\User;
@@ -15,6 +16,8 @@
1516
use function Laravel\Prompts\text;
1617
use function Laravel\Prompts\note;
1718
use function Laravel\Prompts\select;
19+
use App\Models\Plugin;
20+
use Illuminate\Support\Str;
1821

1922
class XboardInstall extends Command
2023
{
@@ -157,6 +160,11 @@ public function handle()
157160
if (!self::registerAdmin($email, $password)) {
158161
abort(500, '管理员账号注册失败,请重试');
159162
}
163+
self::restoreProtectedPlugins($this);
164+
$this->info('正在安装默认插件...');
165+
PluginManager::installDefaultPlugins();
166+
$this->info('默认插件安装完成');
167+
160168
$this->info('🎉:一切就绪');
161169
$this->info("管理员邮箱:{$email}");
162170
$this->info("管理员密码:{$password}");
@@ -356,4 +364,64 @@ private function configurePostgresql(): array
356364
}
357365
}
358366
}
367+
368+
/**
369+
* 还原内置受保护插件(可在安装和更新时调用)
370+
*/
371+
public static function restoreProtectedPlugins(Command $console = null)
372+
{
373+
exec("git config core.filemode false", $output, $returnVar);
374+
$cmd = "git status --porcelain plugins/ 2>/dev/null";
375+
exec($cmd, $output, $returnVar);
376+
if (!empty($output)) {
377+
$hasNonNewFiles = false;
378+
foreach ($output as $line) {
379+
$status = trim(substr($line, 0, 2));
380+
if ($status !== 'A') {
381+
$hasNonNewFiles = true;
382+
break;
383+
}
384+
}
385+
if ($hasNonNewFiles) {
386+
if ($console)
387+
$console->info("检测到 plugins 目录有变更,正在还原...");
388+
389+
foreach ($output as $line) {
390+
$status = trim(substr($line, 0, 2));
391+
$filePath = trim(substr($line, 3));
392+
393+
if (strpos($filePath, 'plugins/') === 0 && $status !== 'A') {
394+
$relativePath = substr($filePath, 8);
395+
if ($console) {
396+
$action = match ($status) {
397+
'M' => '修改',
398+
'D' => '删除',
399+
'R' => '重命名',
400+
'C' => '复制',
401+
default => '变更'
402+
};
403+
$console->info("还原插件文件 [{$relativePath}] ({$action})");
404+
}
405+
406+
$cmd = "git checkout HEAD -- {$filePath}";
407+
exec($cmd, $gitOutput, $gitReturnVar);
408+
409+
if ($gitReturnVar === 0) {
410+
if ($console)
411+
$console->info("插件文件 [{$relativePath}] 已还原。");
412+
} else {
413+
if ($console)
414+
$console->error("插件文件 [{$relativePath}] 还原失败。");
415+
}
416+
}
417+
}
418+
} else {
419+
if ($console)
420+
$console->info("plugins 目录状态正常,无需还原。");
421+
}
422+
} else {
423+
if ($console)
424+
$console->info("plugins 目录状态正常,无需还原。");
425+
}
426+
}
359427
}

app/Console/Commands/XboardUpdate.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
use App\Services\UpdateService;
77
use Illuminate\Console\Command;
88
use Illuminate\Support\Facades\Artisan;
9-
use Illuminate\Support\Facades\DB;
9+
use App\Services\Plugin\PluginManager;
10+
use App\Models\Plugin;
11+
use Illuminate\Support\Str;
12+
use App\Console\Commands\XboardInstall;
1013

1114
class XboardUpdate extends Command
1215
{
@@ -44,12 +47,17 @@ public function handle()
4447
$this->info('正在导入数据库请稍等...');
4548
Artisan::call("migrate");
4649
$this->info(Artisan::output());
47-
Artisan::call('horizon:terminate');
50+
$this->info('正在检查内置插件文件...');
51+
XboardInstall::restoreProtectedPlugins($this);
52+
$this->info('正在检查并安装默认插件...');
53+
PluginManager::installDefaultPlugins();
54+
$this->info('默认插件检查完成');
4855
Artisan::call('reset:traffic', ['--fix-null' => true]);
4956
$updateService = new UpdateService();
5057
$updateService->updateVersionCache();
5158
$themeService = app(ThemeService::class);
5259
$themeService->refreshCurrentTheme();
60+
Artisan::call('horizon:terminate');
5361
$this->info('更新完毕,队列服务已重启,你无需进行任何操作。');
5462
}
5563
}

app/Console/Kernel.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ protected function commands()
6464
{
6565
$this->load(__DIR__ . '/Commands');
6666

67+
try {
68+
app(PluginManager::class)->initializeEnabledPlugins();
69+
} catch (\Exception $e) {
70+
}
6771
require base_path('routes/console.php');
6872
}
6973
}

app/Http/Controllers/PluginController.php

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,16 @@
1111
*/
1212
abstract class PluginController extends Controller
1313
{
14-
use HasPluginConfig;
14+
use HasPluginConfig;
1515

16-
/**
17-
* 执行插件操作前的检查
18-
*/
19-
protected function beforePluginAction(): ?array
20-
{
21-
return null;
22-
}
16+
/**
17+
* 执行插件操作前的检查
18+
*/
19+
protected function beforePluginAction(): ?array
20+
{
21+
if (!$this->isPluginEnabled()) {
22+
return [400, '插件未启用'];
23+
}
24+
return null;
25+
}
2326
}

app/Http/Controllers/V1/Guest/PaymentController.php

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22

33
namespace App\Http\Controllers\V1\Guest;
44

5-
use App\Exceptions\ApiException;
65
use App\Http\Controllers\Controller;
76
use App\Models\Order;
8-
use App\Models\Payment;
97
use App\Services\OrderService;
108
use App\Services\PaymentService;
11-
use App\Services\TelegramService;
129
use Illuminate\Http\Request;
10+
use Illuminate\Support\Facades\Log;
1311
use App\Services\Plugin\HookManager;
1412

1513
class PaymentController extends Controller
@@ -30,7 +28,7 @@ public function notify($method, $uuid, Request $request)
3028
}
3129
return (isset($verify['custom_result']) ? $verify['custom_result'] : 'success');
3230
} catch (\Exception $e) {
33-
\Log::error($e);
31+
Log::error($e);
3432
return $this->fail([500, 'fail']);
3533
}
3634
}
@@ -48,22 +46,7 @@ private function handle($tradeNo, $callbackNo)
4846
return false;
4947
}
5048

51-
$payment = Payment::where('id', $order->payment_id)->first();
52-
$telegramService = new TelegramService();
53-
$message = sprintf(
54-
"💰成功收款%s元\n" .
55-
"———————————————\n" .
56-
"支付接口:%s\n" .
57-
"支付渠道:%s\n" .
58-
"本站订单:`%s`"
59-
,
60-
$order->total_amount / 100,
61-
$payment->payment,
62-
$payment->name,
63-
$order->trade_no
64-
);
65-
66-
$telegramService->sendMessageWithAdmin($message);
49+
HookManager::call('payment.notify.success', $order);
6750
return true;
6851
}
6952
}

0 commit comments

Comments
 (0)