mirror of
https://github.com/lkddi/Xboard.git
synced 2026-04-14 19:40:53 +08:00
feat: add AnyTLS support and improve system functionality
- Add AnyTLS protocol support - Add system logs viewing in admin panel - Refactor client subscription delivery code - Refactor hook mechanism - Add plugin support for Shadowsocks protocol - Add CSV export option for batch user creation - Fix mobile admin login page width display issue
This commit is contained in:
@@ -21,24 +21,51 @@ class SystemController extends Controller
|
||||
$data = [
|
||||
'schedule' => $this->getScheduleStatus(),
|
||||
'horizon' => $this->getHorizonStatus(),
|
||||
'schedule_last_runtime' => Cache::get(CacheKey::get('SCHEDULE_LAST_CHECK_AT', null))
|
||||
'schedule_last_runtime' => Cache::get(CacheKey::get('SCHEDULE_LAST_CHECK_AT', null)),
|
||||
'logs' => $this->getLogStatistics()
|
||||
];
|
||||
return $this->success($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取日志统计信息
|
||||
*
|
||||
* @return array 各级别日志的数量统计
|
||||
*/
|
||||
protected function getLogStatistics(): array
|
||||
{
|
||||
// 初始化日志统计数组
|
||||
$statistics = [
|
||||
'info' => 0,
|
||||
'warning' => 0,
|
||||
'error' => 0,
|
||||
'total' => 0
|
||||
];
|
||||
|
||||
if (class_exists(LogModel::class) && LogModel::count() > 0) {
|
||||
$statistics['info'] = LogModel::where('level', 'info')->count();
|
||||
$statistics['warning'] = LogModel::where('level', 'warning')->count();
|
||||
$statistics['error'] = LogModel::where('level', 'error')->count();
|
||||
$statistics['total'] = LogModel::count();
|
||||
|
||||
return $statistics;
|
||||
}
|
||||
return $statistics;
|
||||
}
|
||||
|
||||
public function getQueueWorkload(WorkloadRepository $workload)
|
||||
{
|
||||
return $this->success(collect($workload->get())->sortBy('name')->values()->toArray());
|
||||
}
|
||||
|
||||
protected function getScheduleStatus():bool
|
||||
protected function getScheduleStatus(): bool
|
||||
{
|
||||
return (time() - 120) < Cache::get(CacheKey::get('SCHEDULE_LAST_CHECK_AT', null));
|
||||
}
|
||||
|
||||
protected function getHorizonStatus():bool
|
||||
protected function getHorizonStatus(): bool
|
||||
{
|
||||
if (! $masters = app(MasterSupervisorRepository::class)->all()) {
|
||||
if (!$masters = app(MasterSupervisorRepository::class)->all()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -88,7 +115,7 @@ class SystemController extends Controller
|
||||
*/
|
||||
protected function totalPausedMasters()
|
||||
{
|
||||
if (! $masters = app(MasterSupervisorRepository::class)->all()) {
|
||||
if (!$masters = app(MasterSupervisorRepository::class)->all()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -97,7 +124,8 @@ class SystemController extends Controller
|
||||
})->count();
|
||||
}
|
||||
|
||||
public function getSystemLog(Request $request) {
|
||||
public function getSystemLog(Request $request)
|
||||
{
|
||||
$current = $request->input('current') ? $request->input('current') : 1;
|
||||
$pageSize = $request->input('page_size') >= 10 ? $request->input('page_size') : 10;
|
||||
$builder = LogModel::orderBy('created_at', 'DESC')
|
||||
@@ -110,4 +138,25 @@ class SystemController extends Controller
|
||||
'total' => $total
|
||||
]);
|
||||
}
|
||||
|
||||
public function getHorizonFailedJobs(Request $request, JobRepository $jobRepository)
|
||||
{
|
||||
$current = max(1, (int) $request->input('current', 1));
|
||||
$pageSize = max(10, (int) $request->input('page_size', 20));
|
||||
$offset = ($current - 1) * $pageSize;
|
||||
|
||||
$failedJobs = collect($jobRepository->getFailed())
|
||||
->sortByDesc('failed_at')
|
||||
->slice($offset, $pageSize)
|
||||
->values();
|
||||
|
||||
$total = $jobRepository->countFailed();
|
||||
|
||||
return response()->json([
|
||||
'data' => $failedJobs,
|
||||
'total' => $total,
|
||||
'current' => $current,
|
||||
'page_size' => $pageSize,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@ class UserController extends Controller
|
||||
return $this->success(true);
|
||||
}
|
||||
if ($request->input('generate_count')) {
|
||||
$this->multiGenerate($request);
|
||||
return $this->multiGenerate($request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,15 +406,44 @@ class UserController extends Controller
|
||||
Log::error($e);
|
||||
return $this->fail([500, '生成失败']);
|
||||
}
|
||||
$data = "账号,密码,过期时间,UUID,创建时间,订阅地址\r\n";
|
||||
foreach ($users as $user) {
|
||||
$expireDate = $user['expired_at'] === NULL ? '长期有效' : date('Y-m-d H:i:s', $user['expired_at']);
|
||||
$createDate = date('Y-m-d H:i:s', $user['created_at']);
|
||||
$password = $request->input('password') ?? $user['email'];
|
||||
$subscribeUrl = Helper::getSubscribeUrl('/api/v1/client/subscribe?token=' . $user['token']);
|
||||
$data .= "{$user['email']},{$password},{$expireDate},{$user['uuid']},{$createDate},{$subscribeUrl}\r\n";
|
||||
|
||||
// 判断是否导出 CSV
|
||||
if ($request->input('download_csv')) {
|
||||
$headers = [
|
||||
'Content-Type' => 'text/csv',
|
||||
'Content-Disposition' => 'attachment; filename="users.csv"',
|
||||
];
|
||||
$callback = function () use ($users, $request) {
|
||||
$handle = fopen('php://output', 'w');
|
||||
fputcsv($handle, ['账号', '密码', '过期时间', 'UUID', '创建时间', '订阅地址']);
|
||||
foreach ($users as $user) {
|
||||
$expireDate = $user['expired_at'] === NULL ? '长期有效' : date('Y-m-d H:i:s', $user['expired_at']);
|
||||
$createDate = date('Y-m-d H:i:s', $user['created_at']);
|
||||
$password = $request->input('password') ?? $user['email'];
|
||||
$subscribeUrl = Helper::getSubscribeUrl('/api/v1/client/subscribe?token=' . $user['token']);
|
||||
fputcsv($handle, [$user['email'], $password, $expireDate, $user['uuid'], $createDate, $subscribeUrl]);
|
||||
}
|
||||
fclose($handle);
|
||||
};
|
||||
return response()->streamDownload($callback, 'users.csv', $headers);
|
||||
}
|
||||
echo $data;
|
||||
|
||||
// 默认返回 JSON
|
||||
$data = collect($users)->map(function ($user) use ($request) {
|
||||
return [
|
||||
'email' => $user['email'],
|
||||
'password' => $request->input('password') ?? $user['email'],
|
||||
'expired_at' => $user['expired_at'] === NULL ? '长期有效' : date('Y-m-d H:i:s', $user['expired_at']),
|
||||
'uuid' => $user['uuid'],
|
||||
'created_at' => date('Y-m-d H:i:s', $user['created_at']),
|
||||
'subscribe_url' => Helper::getSubscribeUrl('/api/v1/client/subscribe?token=' . $user['token']),
|
||||
];
|
||||
});
|
||||
return response()->json([
|
||||
'code' => 0,
|
||||
'message' => '批量生成成功',
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
public function sendMail(UserSendMail $request)
|
||||
|
||||
Reference in New Issue
Block a user