mirror of
https://github.com/lkddi/Xboard.git
synced 2026-04-24 03:57:27 +08:00
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
This commit is contained in:
@@ -11,13 +11,16 @@ use App\Traits\HasPluginConfig;
|
||||
*/
|
||||
abstract class PluginController extends Controller
|
||||
{
|
||||
use HasPluginConfig;
|
||||
use HasPluginConfig;
|
||||
|
||||
/**
|
||||
* 执行插件操作前的检查
|
||||
*/
|
||||
protected function beforePluginAction(): ?array
|
||||
{
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 执行插件操作前的检查
|
||||
*/
|
||||
protected function beforePluginAction(): ?array
|
||||
{
|
||||
if (!$this->isPluginEnabled()) {
|
||||
return [400, '插件未启用'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,12 @@
|
||||
|
||||
namespace App\Http\Controllers\V1\Guest;
|
||||
|
||||
use App\Exceptions\ApiException;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Order;
|
||||
use App\Models\Payment;
|
||||
use App\Services\OrderService;
|
||||
use App\Services\PaymentService;
|
||||
use App\Services\TelegramService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Services\Plugin\HookManager;
|
||||
|
||||
class PaymentController extends Controller
|
||||
@@ -30,7 +28,7 @@ class PaymentController extends Controller
|
||||
}
|
||||
return (isset($verify['custom_result']) ? $verify['custom_result'] : 'success');
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
Log::error($e);
|
||||
return $this->fail([500, 'fail']);
|
||||
}
|
||||
}
|
||||
@@ -48,22 +46,7 @@ class PaymentController extends Controller
|
||||
return false;
|
||||
}
|
||||
|
||||
$payment = Payment::where('id', $order->payment_id)->first();
|
||||
$telegramService = new TelegramService();
|
||||
$message = sprintf(
|
||||
"💰成功收款%s元\n" .
|
||||
"———————————————\n" .
|
||||
"支付接口:%s\n" .
|
||||
"支付渠道:%s\n" .
|
||||
"本站订单:`%s`"
|
||||
,
|
||||
$order->total_amount / 100,
|
||||
$payment->payment,
|
||||
$payment->name,
|
||||
$order->trade_no
|
||||
);
|
||||
|
||||
$telegramService->sendMessageWithAdmin($message);
|
||||
HookManager::call('payment.notify.success', $order);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,121 +4,123 @@ namespace App\Http\Controllers\V1\Guest;
|
||||
|
||||
use App\Exceptions\ApiException;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use App\Services\Plugin\HookManager;
|
||||
use App\Services\TelegramService;
|
||||
use App\Services\UserService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TelegramController extends Controller
|
||||
{
|
||||
protected $msg;
|
||||
protected $commands = [];
|
||||
protected $telegramService;
|
||||
protected ?object $msg = null;
|
||||
protected TelegramService $telegramService;
|
||||
protected UserService $userService;
|
||||
|
||||
public function __construct(TelegramService $telegramService)
|
||||
public function __construct(TelegramService $telegramService, UserService $userService)
|
||||
{
|
||||
$this->telegramService = $telegramService;
|
||||
$this->userService = $userService;
|
||||
}
|
||||
|
||||
public function webhook(Request $request)
|
||||
public function webhook(Request $request): void
|
||||
{
|
||||
if ($request->input('access_token') !== md5(admin_setting('telegram_bot_token'))) {
|
||||
$expectedToken = md5(admin_setting('telegram_bot_token'));
|
||||
if ($request->input('access_token') !== $expectedToken) {
|
||||
throw new ApiException('access_token is error', 401);
|
||||
}
|
||||
$data = json_decode(request()->getContent(),true);
|
||||
|
||||
$data = $request->json()->all();
|
||||
|
||||
$this->formatMessage($data);
|
||||
$this->formatChatJoinRequest($data);
|
||||
$this->handle();
|
||||
}
|
||||
|
||||
private function handle()
|
||||
private function handle(): void
|
||||
{
|
||||
if (!$this->msg) return;
|
||||
if (!$this->msg)
|
||||
return;
|
||||
$msg = $this->msg;
|
||||
$commandName = explode('@', $msg->command);
|
||||
|
||||
// To reduce request, only commands contains @ will get the bot name
|
||||
if (count($commandName) == 2) {
|
||||
$botName = $this->getBotName();
|
||||
if ($commandName[1] === $botName){
|
||||
$msg->command = $commandName[0];
|
||||
}
|
||||
}
|
||||
|
||||
$this->processBotName($msg);
|
||||
try {
|
||||
foreach (glob(base_path('app//Plugins//Telegram//Commands') . '/*.php') as $file) {
|
||||
$command = basename($file, '.php');
|
||||
$class = '\\App\\Plugins\\Telegram\\Commands\\' . $command;
|
||||
if (!class_exists($class)) continue;
|
||||
$instance = new $class();
|
||||
if ($msg->message_type === 'message') {
|
||||
if (!isset($instance->command)) continue;
|
||||
if ($msg->command !== $instance->command) continue;
|
||||
$instance->handle($msg);
|
||||
return;
|
||||
}
|
||||
if ($msg->message_type === 'reply_message') {
|
||||
if (!isset($instance->regex)) continue;
|
||||
if (!preg_match($instance->regex, $msg->reply_text, $match)) continue;
|
||||
$instance->handle($msg, $match);
|
||||
return;
|
||||
}
|
||||
HookManager::call('telegram.message.before', [$msg]);
|
||||
$handled = HookManager::filter('telegram.message.handle', false, [$msg]);
|
||||
if (!$handled) {
|
||||
HookManager::call('telegram.message.unhandled', [$msg]);
|
||||
}
|
||||
HookManager::call('telegram.message.after', [$msg]);
|
||||
} catch (\Exception $e) {
|
||||
HookManager::call('telegram.message.error', [$msg, $e]);
|
||||
$this->telegramService->sendMessage($msg->chat_id, $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function getBotName()
|
||||
private function processBotName(object $msg): void
|
||||
{
|
||||
$commandParts = explode('@', $msg->command);
|
||||
|
||||
if (count($commandParts) === 2) {
|
||||
$botName = $this->getBotName();
|
||||
if ($commandParts[1] === $botName) {
|
||||
$msg->command = $commandParts[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getBotName(): string
|
||||
{
|
||||
$response = $this->telegramService->getMe();
|
||||
return $response->result->username;
|
||||
}
|
||||
|
||||
private function formatMessage(array $data)
|
||||
private function formatMessage(array $data): void
|
||||
{
|
||||
if (!isset($data['message'])) return;
|
||||
if (!isset($data['message']['text'])) return;
|
||||
$obj = new \StdClass();
|
||||
$text = explode(' ', $data['message']['text']);
|
||||
$obj->command = $text[0];
|
||||
$obj->args = array_slice($text, 1);
|
||||
$obj->chat_id = $data['message']['chat']['id'];
|
||||
$obj->message_id = $data['message']['message_id'];
|
||||
$obj->message_type = 'message';
|
||||
$obj->text = $data['message']['text'];
|
||||
$obj->is_private = $data['message']['chat']['type'] === 'private';
|
||||
if (isset($data['message']['reply_to_message']['text'])) {
|
||||
$obj->message_type = 'reply_message';
|
||||
$obj->reply_text = $data['message']['reply_to_message']['text'];
|
||||
if (!isset($data['message']['text']))
|
||||
return;
|
||||
|
||||
$message = $data['message'];
|
||||
$text = explode(' ', $message['text']);
|
||||
|
||||
$this->msg = (object) [
|
||||
'command' => $text[0],
|
||||
'args' => array_slice($text, 1),
|
||||
'chat_id' => $message['chat']['id'],
|
||||
'message_id' => $message['message_id'],
|
||||
'message_type' => 'message',
|
||||
'text' => $message['text'],
|
||||
'is_private' => $message['chat']['type'] === 'private',
|
||||
];
|
||||
|
||||
if (isset($message['reply_to_message']['text'])) {
|
||||
$this->msg->message_type = 'reply_message';
|
||||
$this->msg->reply_text = $message['reply_to_message']['text'];
|
||||
}
|
||||
$this->msg = $obj;
|
||||
}
|
||||
|
||||
private function formatChatJoinRequest(array $data)
|
||||
private function formatChatJoinRequest(array $data): void
|
||||
{
|
||||
if (!isset($data['chat_join_request'])) return;
|
||||
if (!isset($data['chat_join_request']['from']['id'])) return;
|
||||
if (!isset($data['chat_join_request']['chat']['id'])) return;
|
||||
$user = \App\Models\User::where('telegram_id', $data['chat_join_request']['from']['id'])
|
||||
->first();
|
||||
$joinRequest = $data['chat_join_request'] ?? null;
|
||||
if (!$joinRequest)
|
||||
return;
|
||||
|
||||
$chatId = $joinRequest['chat']['id'] ?? null;
|
||||
$userId = $joinRequest['from']['id'] ?? null;
|
||||
|
||||
if (!$chatId || !$userId)
|
||||
return;
|
||||
|
||||
$user = User::where('telegram_id', $userId)->first();
|
||||
|
||||
if (!$user) {
|
||||
$this->telegramService->declineChatJoinRequest(
|
||||
$data['chat_join_request']['chat']['id'],
|
||||
$data['chat_join_request']['from']['id']
|
||||
);
|
||||
$this->telegramService->declineChatJoinRequest($chatId, $userId);
|
||||
return;
|
||||
}
|
||||
$userService = new \App\Services\UserService();
|
||||
if (!$userService->isAvailable($user)) {
|
||||
$this->telegramService->declineChatJoinRequest(
|
||||
$data['chat_join_request']['chat']['id'],
|
||||
$data['chat_join_request']['from']['id']
|
||||
);
|
||||
|
||||
if (!$this->userService->isAvailable($user)) {
|
||||
$this->telegramService->declineChatJoinRequest($chatId, $userId);
|
||||
return;
|
||||
}
|
||||
$userService = new \App\Services\UserService();
|
||||
$this->telegramService->approveChatJoinRequest(
|
||||
$data['chat_join_request']['chat']['id'],
|
||||
$data['chat_join_request']['from']['id']
|
||||
);
|
||||
|
||||
$this->telegramService->approveChatJoinRequest($chatId, $userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,11 @@ use App\Http\Resources\TicketResource;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\TicketMessage;
|
||||
use App\Models\User;
|
||||
use App\Services\TelegramService;
|
||||
use App\Services\TicketService;
|
||||
use App\Utils\Dict;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Services\Plugin\HookManager;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class TicketController extends Controller
|
||||
{
|
||||
@@ -42,39 +41,20 @@ class TicketController extends Controller
|
||||
|
||||
public function save(TicketSave $request)
|
||||
{
|
||||
try{
|
||||
DB::beginTransaction();
|
||||
if (Ticket::where('status', 0)->where('user_id', $request->user()->id)->lockForUpdate()->first()) {
|
||||
DB::rollBack();
|
||||
return $this->fail([400, '存在未关闭的工单']);
|
||||
}
|
||||
$ticket = Ticket::create(array_merge($request->only([
|
||||
'subject',
|
||||
'level'
|
||||
]), [
|
||||
'user_id' => $request->user()->id
|
||||
]));
|
||||
if (!$ticket) {
|
||||
throw new \Exception(__('There are other unresolved tickets'));
|
||||
}
|
||||
$ticketMessage = TicketMessage::create([
|
||||
'user_id' => $request->user()->id,
|
||||
'ticket_id' => $ticket->id,
|
||||
'message' => $request->input('message')
|
||||
]);
|
||||
if (!$ticketMessage) {
|
||||
throw new \Exception(__('Failed to open ticket'));
|
||||
}
|
||||
DB::commit();
|
||||
try {
|
||||
$ticketService = new TicketService();
|
||||
$ticket = $ticketService->createTicket(
|
||||
$request->user()->id,
|
||||
$request->input('subject'),
|
||||
$request->input('level'),
|
||||
$request->input('message')
|
||||
);
|
||||
HookManager::call('ticket.create.after', $ticket);
|
||||
$this->sendNotify($ticket, $request->input('message'), $request->user()->id);
|
||||
return $this->success(true);
|
||||
}catch(\Exception $e){
|
||||
DB::rollBack();
|
||||
\Log::error($e);
|
||||
} catch (\Exception $e) {
|
||||
Log::error($e);
|
||||
return $this->fail([400, $e->getMessage()]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function reply(Request $request)
|
||||
@@ -95,18 +75,19 @@ class TicketController extends Controller
|
||||
return $this->fail([400, __('The ticket is closed and cannot be replied')]);
|
||||
}
|
||||
if ($request->user()->id == $this->getLastMessage($ticket->id)->user_id) {
|
||||
return $this->fail([400, __('Please wait for the technical enginneer to reply')]);
|
||||
return $this->fail(codeResponse: [400, __('Please wait for the technical enginneer to reply')]);
|
||||
}
|
||||
$ticketService = new TicketService();
|
||||
if (!$ticketService->reply(
|
||||
$ticket,
|
||||
$request->input('message'),
|
||||
$request->user()->id
|
||||
)) {
|
||||
if (
|
||||
!$ticketService->reply(
|
||||
$ticket,
|
||||
$request->input('message'),
|
||||
$request->user()->id
|
||||
)
|
||||
) {
|
||||
return $this->fail([400, __('Ticket reply failed')]);
|
||||
}
|
||||
HookManager::call('ticket.reply.user.after', [$ticket, $this->getLastMessage($ticket->id)]);
|
||||
$this->sendNotify($ticket, $request->input('message'), $request->user()->id);
|
||||
return $this->success(true);
|
||||
}
|
||||
|
||||
@@ -138,13 +119,15 @@ class TicketController extends Controller
|
||||
|
||||
public function withdraw(TicketWithdraw $request)
|
||||
{
|
||||
if ((int)admin_setting('withdraw_close_enable', 0)) {
|
||||
if ((int) admin_setting('withdraw_close_enable', 0)) {
|
||||
return $this->fail([400, 'Unsupported withdraw']);
|
||||
}
|
||||
if (!in_array(
|
||||
$request->input('withdraw_method'),
|
||||
admin_setting('commission_withdraw_method',Dict::WITHDRAW_METHOD_WHITELIST_DEFAULT)
|
||||
)) {
|
||||
if (
|
||||
!in_array(
|
||||
$request->input('withdraw_method'),
|
||||
admin_setting('commission_withdraw_method', Dict::WITHDRAW_METHOD_WHITELIST_DEFAULT)
|
||||
)
|
||||
) {
|
||||
return $this->fail([422, __('Unsupported withdrawal method')]);
|
||||
}
|
||||
$user = User::find($request->user()->id);
|
||||
@@ -152,77 +135,24 @@ class TicketController extends Controller
|
||||
if ($limit > ($user->commission_balance / 100)) {
|
||||
return $this->fail([422, __('The current required minimum withdrawal commission is :limit', ['limit' => $limit])]);
|
||||
}
|
||||
try{
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$ticketService = new TicketService();
|
||||
$subject = __('[Commission Withdrawal Request] This ticket is opened by the system');
|
||||
$ticket = Ticket::create([
|
||||
'subject' => $subject,
|
||||
'level' => 2,
|
||||
'user_id' => $request->user()->id
|
||||
]);
|
||||
if (!$ticket) {
|
||||
return $this->fail([400, __('Failed to open ticket')]);
|
||||
}
|
||||
$message = sprintf("%s\r\n%s",
|
||||
$message = sprintf(
|
||||
"%s\r\n%s",
|
||||
__('Withdrawal method') . ":" . $request->input('withdraw_method'),
|
||||
__('Withdrawal account') . ":" . $request->input('withdraw_account')
|
||||
);
|
||||
$ticketMessage = TicketMessage::create([
|
||||
'user_id' => $request->user()->id,
|
||||
'ticket_id' => $ticket->id,
|
||||
'message' => $message
|
||||
]);
|
||||
if (!$ticketMessage) {
|
||||
DB::rollBack();
|
||||
return $this->fail([400, __('Failed to open ticket')]);
|
||||
}
|
||||
DB::commit();
|
||||
}catch(\Exception $e){
|
||||
DB::rollBack();
|
||||
$ticket = $ticketService->createTicket(
|
||||
$request->user()->id,
|
||||
$subject,
|
||||
2,
|
||||
$message
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
throw $e;
|
||||
}
|
||||
$this->sendNotify($ticket, $message, $request->user()->id);
|
||||
HookManager::call('ticket.create.after', $ticket);
|
||||
return $this->success(true);
|
||||
}
|
||||
|
||||
private function sendNotify(Ticket $ticket, string $message, $user_id)
|
||||
{
|
||||
$user = User::find($user_id)->load('plan');
|
||||
$transfer_enable = $this->getFlowData($user->transfer_enable); // 总流量
|
||||
$remaining_traffic = $this->getFlowData($user->transfer_enable - $user->u - $user->d); // 剩余流量
|
||||
$u = $this->getFlowData($user->u); // 上传
|
||||
$d = $this->getFlowData($user->d); // 下载
|
||||
$expired_at = date("Y-m-d h:m:s", $user->expired_at); // 到期时间
|
||||
$money = $user->balance / 100;
|
||||
$affmoney = $user->commission_balance / 100;
|
||||
$plan = $user->plan;
|
||||
$ip = request()->ip();
|
||||
$region = filter_var($ip,FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? (new \Ip2Region())->simple($ip) : "NULL";
|
||||
$TGmessage = "📮工单提醒 #{$ticket->id}\n———————————————\n";
|
||||
$TGmessage .= "邮箱: `{$user->email}`\n";
|
||||
$TGmessage .= "用户位置: \n`{$region}`\n";
|
||||
if($user->plan){
|
||||
$TGmessage .= "套餐与流量: \n`{$plan->name} {$transfer_enable}/{$remaining_traffic}`\n";
|
||||
$TGmessage .= "上传/下载: \n`{$u}/{$d}`\n";
|
||||
$TGmessage .= "到期时间: \n`{$expired_at}`\n";
|
||||
}else{
|
||||
$TGmessage .= "套餐与流量: \n`未订购任何套餐`\n";
|
||||
}
|
||||
$TGmessage .= "余额/佣金余额: \n`{$money}/{$affmoney}`\n";
|
||||
$TGmessage .= "主题:\n`{$ticket->subject}`\n内容:\n`{$message}`\n";
|
||||
$telegramService = new TelegramService();
|
||||
$telegramService->sendMessageWithAdmin($TGmessage, true);
|
||||
}
|
||||
|
||||
private function getFlowData($b)
|
||||
{
|
||||
$m = $b / (1024 * 1024);
|
||||
if ($m >= 1024) {
|
||||
$g = $m / 1024;
|
||||
$text = round($g, 2) . "GB";
|
||||
} else {
|
||||
$text = round($m, 2) . "MB";
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,6 @@ class ConfigController extends Controller
|
||||
|
||||
public function setTelegramWebhook(Request $request)
|
||||
{
|
||||
// 判断站点网址
|
||||
$app_url = admin_setting('app_url');
|
||||
if (blank($app_url))
|
||||
return $this->fail([422, '请先设置站点网址']);
|
||||
@@ -81,17 +80,14 @@ class ConfigController extends Controller
|
||||
$telegramService = new TelegramService($request->input('telegram_bot_token'));
|
||||
$telegramService->getMe();
|
||||
$telegramService->setWebhook($hookUrl);
|
||||
$telegramService->registerBotCommands();
|
||||
return $this->success(true);
|
||||
}
|
||||
|
||||
public function fetch(Request $request)
|
||||
{
|
||||
$key = $request->input('key');
|
||||
|
||||
// 构建配置数据映射
|
||||
$configMappings = $this->getConfigMappings();
|
||||
|
||||
// 如果请求特定分组,直接返回
|
||||
if ($key && isset($configMappings[$key])) {
|
||||
return $this->success([$key => $configMappings[$key]]);
|
||||
}
|
||||
|
||||
@@ -9,16 +9,18 @@ use App\Services\PaymentService;
|
||||
use App\Utils\Helper;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class PaymentController extends Controller
|
||||
{
|
||||
public function getPaymentMethods()
|
||||
{
|
||||
$methods = [];
|
||||
foreach (glob(base_path('app//Payments') . '/*.php') as $file) {
|
||||
array_push($methods, pathinfo($file)['filename']);
|
||||
}
|
||||
return $this->success($methods);
|
||||
|
||||
$pluginMethods = PaymentService::getAllPaymentMethodNames();
|
||||
$methods = array_merge($methods, $pluginMethods);
|
||||
|
||||
return $this->success(array_unique($methods));
|
||||
}
|
||||
|
||||
public function fetch()
|
||||
@@ -37,23 +39,29 @@ class PaymentController extends Controller
|
||||
|
||||
public function getPaymentForm(Request $request)
|
||||
{
|
||||
$paymentService = new PaymentService($request->input('payment'), $request->input('id'));
|
||||
return $this->success(collect($paymentService->form())->values());
|
||||
try {
|
||||
$paymentService = new PaymentService($request->input('payment'), $request->input('id'));
|
||||
return $this->success(collect($paymentService->form()));
|
||||
} catch (\Exception $e) {
|
||||
return $this->fail([400, '支付方式不存在或未启用']);
|
||||
}
|
||||
}
|
||||
|
||||
public function show(Request $request)
|
||||
{
|
||||
$payment = Payment::find($request->input('id'));
|
||||
if (!$payment) return $this->fail([400202 ,'支付方式不存在']);
|
||||
if (!$payment)
|
||||
return $this->fail([400202, '支付方式不存在']);
|
||||
$payment->enable = !$payment->enable;
|
||||
if (!$payment->save()) return $this->fail([500 ,'保存失败']);
|
||||
if (!$payment->save())
|
||||
return $this->fail([500, '保存失败']);
|
||||
return $this->success(true);
|
||||
}
|
||||
|
||||
public function save(Request $request)
|
||||
{
|
||||
if (!admin_setting('app_url')) {
|
||||
return $this->fail([400 ,'请在站点配置中配置站点地址']);
|
||||
return $this->fail([400, '请在站点配置中配置站点地址']);
|
||||
}
|
||||
$params = $request->validate([
|
||||
'name' => 'required',
|
||||
@@ -73,18 +81,19 @@ class PaymentController extends Controller
|
||||
]);
|
||||
if ($request->input('id')) {
|
||||
$payment = Payment::find($request->input('id'));
|
||||
if (!$payment) return $this->fail([400202 ,'支付方式不存在']);
|
||||
if (!$payment)
|
||||
return $this->fail([400202, '支付方式不存在']);
|
||||
try {
|
||||
$payment->update($params);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
return $this->fail([500 ,'保存失败']);
|
||||
Log::error($e);
|
||||
return $this->fail([500, '保存失败']);
|
||||
}
|
||||
return $this->success(true);
|
||||
}
|
||||
$params['uuid'] = Helper::randomChar(8);
|
||||
if (!Payment::create($params)) {
|
||||
return $this->fail([500 ,'保存失败']);
|
||||
return $this->fail([500, '保存失败']);
|
||||
}
|
||||
return $this->success(true);
|
||||
}
|
||||
@@ -92,7 +101,8 @@ class PaymentController extends Controller
|
||||
public function drop(Request $request)
|
||||
{
|
||||
$payment = Payment::find($request->input('id'));
|
||||
if (!$payment) return $this->fail([400202 ,'支付方式不存在']);
|
||||
if (!$payment)
|
||||
return $this->fail([400202, '支付方式不存在']);
|
||||
return $this->success($payment->delete());
|
||||
}
|
||||
|
||||
@@ -105,7 +115,7 @@ class PaymentController extends Controller
|
||||
'ids.required' => '参数有误',
|
||||
'ids.array' => '参数有误'
|
||||
]);
|
||||
try{
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
foreach ($request->input('ids') as $k => $v) {
|
||||
if (!Payment::find($v)->update(['sort' => $k + 1])) {
|
||||
@@ -113,11 +123,11 @@ class PaymentController extends Controller
|
||||
}
|
||||
}
|
||||
DB::commit();
|
||||
}catch(\Exception $e){
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return $this->fail([500 ,'保存失败']);
|
||||
return $this->fail([500, '保存失败']);
|
||||
}
|
||||
|
||||
|
||||
return $this->success(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,14 +23,43 @@ class PluginController extends Controller
|
||||
$this->configService = $configService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有插件类型
|
||||
*/
|
||||
public function types()
|
||||
{
|
||||
return response()->json([
|
||||
'data' => [
|
||||
[
|
||||
'value' => Plugin::TYPE_FEATURE,
|
||||
'label' => '功能',
|
||||
'description' => '提供功能扩展的插件,如Telegram登录、邮件通知等',
|
||||
'icon' => '🔧'
|
||||
],
|
||||
[
|
||||
'value' => Plugin::TYPE_PAYMENT,
|
||||
'label' => '支付方式',
|
||||
'description' => '提供支付接口的插件,如支付宝、微信支付等',
|
||||
'icon' => '💳'
|
||||
]
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件列表
|
||||
*/
|
||||
public function index()
|
||||
public function index(Request $request)
|
||||
{
|
||||
$installedPlugins = Plugin::get()
|
||||
$type = $request->query('type');
|
||||
|
||||
$installedPlugins = Plugin::when($type, function($query) use ($type) {
|
||||
return $query->byType($type);
|
||||
})
|
||||
->get()
|
||||
->keyBy('code')
|
||||
->toArray();
|
||||
|
||||
$pluginPath = base_path('plugins');
|
||||
$plugins = [];
|
||||
|
||||
@@ -42,8 +71,14 @@ class PluginController extends Controller
|
||||
if (File::exists($configFile)) {
|
||||
$config = json_decode(File::get($configFile), true);
|
||||
$code = $config['code'];
|
||||
$pluginType = $config['type'] ?? Plugin::TYPE_FEATURE;
|
||||
|
||||
// 如果指定了类型,过滤插件
|
||||
if ($type && $pluginType !== $type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$installed = isset($installedPlugins[$code]);
|
||||
// 使用配置服务获取配置
|
||||
$pluginConfig = $installed ? $this->configService->getConfig($code) : ($config['config'] ?? []);
|
||||
$readmeFile = collect(['README.md', 'readme.md'])
|
||||
->map(fn($f) => $directory . '/' . $f)
|
||||
@@ -56,8 +91,11 @@ class PluginController extends Controller
|
||||
'version' => $config['version'],
|
||||
'description' => $config['description'],
|
||||
'author' => $config['author'],
|
||||
'type' => $pluginType,
|
||||
'is_installed' => $installed,
|
||||
'is_enabled' => $installed ? $installedPlugins[$code]['is_enabled'] : false,
|
||||
'is_protected' => in_array($code, Plugin::PROTECTED_PLUGINS),
|
||||
'can_be_deleted' => !in_array($code, Plugin::PROTECTED_PLUGINS),
|
||||
'config' => $pluginConfig,
|
||||
'readme' => $readmeContent,
|
||||
];
|
||||
@@ -236,8 +274,17 @@ class PluginController extends Controller
|
||||
'code' => 'required|string'
|
||||
]);
|
||||
|
||||
$code = $request->input('code');
|
||||
|
||||
// 检查是否为受保护的插件
|
||||
if (in_array($code, Plugin::PROTECTED_PLUGINS)) {
|
||||
return response()->json([
|
||||
'message' => '该插件为系统默认插件,不允许删除'
|
||||
], 403);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->pluginManager->delete($request->input('code'));
|
||||
$this->pluginManager->delete($code);
|
||||
return response()->json([
|
||||
'message' => '插件删除成功'
|
||||
]);
|
||||
|
||||
@@ -164,7 +164,6 @@ class UserController extends Controller
|
||||
$users = $userModel->orderBy('id', 'desc')
|
||||
->paginate($pageSize, ['*'], 'page', $current);
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$users->getCollection()->transform(function ($user): array {
|
||||
return self::transformUserData($user);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user