fix: resolve known issues and improve code standards

- Fix known bugs in user, plan, and server modules
- Standardize code formatting and structure
- Optimize database queries and model relationships
- Improve request validation and error handling
- Update admin controllers for better consistency
This commit is contained in:
xboard
2025-06-22 17:38:17 +08:00
parent 733cc7e9a5
commit 44d92ac1c6
20 changed files with 56 additions and 51 deletions
+10 -9
View File
@@ -4,32 +4,33 @@ namespace App\Console\Commands;
use App\Services\TrafficResetService; use App\Services\TrafficResetService;
use App\Utils\Helper; use App\Utils\Helper;
use Carbon\Carbon;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
class ResetTraffic extends Command class ResetTraffic extends Command
{ {
/** /**
* The name and signature of the console command. * The name and signature of the console command.
*/ */
protected $signature = 'reset:traffic {--batch-size=100 : 分批处理的批次大小} {--dry-run : 预演模式,不实际执行重置} {--max-time=300 : 最大执行时间(秒)}'; protected $signature = 'reset:traffic {--batch-size=100 : 分批处理的批次大小} {--dry-run : 预演模式,不实际执行重置} {--max-time=300 : 最大执行时间(秒)}';
/** /**
* The console command description. * The console command description.
*/ */
protected $description = '流量重置 - 分批处理所有需要重置的用户'; protected $description = '流量重置 - 分批处理所有需要重置的用户';
/** /**
* 流量重置服务 * 流量重置服务
*/ */
private TrafficResetService $trafficResetService; private TrafficResetService $trafficResetService;
/** /**
* Create a new command instance. * Create a new command instance.
*/ */
public function __construct(TrafficResetService $trafficResetService) public function __construct(TrafficResetService $trafficResetService)
{ {
parent::__construct(); parent::__construct();
$this->trafficResetService = $trafficResetService; $this->trafficResetService = $trafficResetService;
} }
@@ -177,7 +178,7 @@ class ResetTraffic extends Command
'ID' => $user->id, 'ID' => $user->id,
'邮箱' => substr($user->email, 0, 20) . (strlen($user->email) > 20 ? '...' : ''), '邮箱' => substr($user->email, 0, 20) . (strlen($user->email) > 20 ? '...' : ''),
'套餐' => $user->plan->name ?? 'N/A', '套餐' => $user->plan->name ?? 'N/A',
'下次重置' => $user->next_reset_at->format('m-d H:i'), '下次重置' => Carbon::createFromTimestamp($user->next_reset_at)->format('Y-m-d H:i:s'),
'当前流量' => Helper::trafficConvert(($user->u ?? 0) + ($user->d ?? 0)), '当前流量' => Helper::trafficConvert(($user->u ?? 0) + ($user->d ?? 0)),
'重置次数' => $user->reset_count, '重置次数' => $user->reset_count,
]; ];
+1 -1
View File
@@ -52,7 +52,7 @@ class SendRemindMail extends Command
} }
$startTime = microtime(true); $startTime = microtime(true);
$progressBar = $this->output->createProgressBar(ceil($totalUsers / $chunkSize)); $progressBar = $this->output->createProgressBar((int) ceil($totalUsers / $chunkSize));
$progressBar->start(); $progressBar->start();
$statistics = $mailService->processUsersInChunks($chunkSize, function () use ($progressBar) { $statistics = $mailService->processUsersInChunks($chunkSize, function () use ($progressBar) {
@@ -13,6 +13,7 @@ use Laravel\Horizon\Contracts\MetricsRepository;
use Laravel\Horizon\Contracts\SupervisorRepository; use Laravel\Horizon\Contracts\SupervisorRepository;
use Laravel\Horizon\Contracts\WorkloadRepository; use Laravel\Horizon\Contracts\WorkloadRepository;
use Laravel\Horizon\WaitTimeCalculator; use Laravel\Horizon\WaitTimeCalculator;
use App\Helpers\ResponseEnum;
class SystemController extends Controller class SystemController extends Controller
{ {
@@ -257,7 +258,7 @@ class SystemController extends Controller
]); ]);
} catch (\Exception $e) { } catch (\Exception $e) {
return $this->error('清除日志失败:' . $e->getMessage()); return $this->fail(ResponseEnum::HTTP_ERROR, null, '清除日志失败:' . $e->getMessage());
} }
} }
@@ -293,7 +294,7 @@ class SystemController extends Controller
return $this->success($stats); return $this->success($stats);
} catch (\Exception $e) { } catch (\Exception $e) {
return $this->error('获取统计信息失败:' . $e->getMessage()); return $this->fail(ResponseEnum::HTTP_ERROR, null, '获取统计信息失败:' . $e->getMessage());
} }
} }
} }
@@ -71,7 +71,7 @@ class TrafficResetController extends Controller
$logs = $query->paginate($perPage); $logs = $query->paginate($perPage);
// 格式化数据 // 格式化数据
$logs->getCollection()->transform(function ($log) { $formattedLogs = $logs->getCollection()->map(function (TrafficResetLog $log) {
return [ return [
'id' => $log->id, 'id' => $log->id,
'user_id' => $log->user_id, 'user_id' => $log->user_id,
@@ -99,7 +99,7 @@ class TrafficResetController extends Controller
}); });
return response()->json([ return response()->json([
'data' => $logs->items(), 'data' => $formattedLogs->toArray(),
'pagination' => [ 'pagination' => [
'current_page' => $logs->currentPage(), 'current_page' => $logs->currentPage(),
'last_page' => $logs->lastPage(), 'last_page' => $logs->lastPage(),
@@ -198,7 +198,8 @@ class TrafficResetController extends Controller
$history = $this->trafficResetService->getUserResetHistory($user, $limit); $history = $this->trafficResetService->getUserResetHistory($user, $limit);
$data = $history->map(function ($log) { /** @var \Illuminate\Database\Eloquent\Collection<int, \App\Models\TrafficResetLog> $history */
$data = $history->map(function (TrafficResetLog $log) {
return [ return [
'id' => $log->id, 'id' => $log->id,
'reset_type' => $log->reset_type, 'reset_type' => $log->reset_type,
+3 -3
View File
@@ -18,12 +18,12 @@ class UserUpdate extends FormRequest
'password' => 'nullable|min:8', 'password' => 'nullable|min:8',
'transfer_enable' => 'numeric', 'transfer_enable' => 'numeric',
'expired_at' => 'nullable|integer', 'expired_at' => 'nullable|integer',
'banned' => 'in:0,1', 'banned' => 'bool',
'plan_id' => 'nullable|integer', 'plan_id' => 'nullable|integer',
'commission_rate' => 'nullable|integer|min:0|max:100', 'commission_rate' => 'nullable|integer|min:0|max:100',
'discount' => 'nullable|integer|min:0|max:100', 'discount' => 'nullable|integer|min:0|max:100',
'is_admin' => 'required|in:0,1', 'is_admin' => 'boolean',
'is_staff' => 'required|in:0,1', 'is_staff' => 'boolean',
'u' => 'integer', 'u' => 'integer',
'd' => 'integer', 'd' => 'integer',
'balance' => 'numeric', 'balance' => 'numeric',
+2 -1
View File
@@ -14,7 +14,8 @@ class Coupon extends Model
'created_at' => 'timestamp', 'created_at' => 'timestamp',
'updated_at' => 'timestamp', 'updated_at' => 'timestamp',
'limit_plan_ids' => 'array', 'limit_plan_ids' => 'array',
'limit_period' => 'array' 'limit_period' => 'array',
'show' => 'boolean',
]; ];
public function getLimitPeriodAttribute($value) public function getLimitPeriodAttribute($value)
+2 -1
View File
@@ -10,6 +10,7 @@ class InviteCode extends Model
protected $dateFormat = 'U'; protected $dateFormat = 'U';
protected $casts = [ protected $casts = [
'created_at' => 'timestamp', 'created_at' => 'timestamp',
'updated_at' => 'timestamp' 'updated_at' => 'timestamp',
'status' => 'boolean',
]; ];
} }
+1 -1
View File
@@ -23,7 +23,7 @@ use Illuminate\Database\Eloquent\Relations\HasOne;
* @property array|null $prices 价格配置 * @property array|null $prices 价格配置
* @property int $sort 排序 * @property int $sort 排序
* @property string|null $content 套餐描述 * @property string|null $content 套餐描述
* @property int $reset_traffic_method 流量重置方式 * @property int|null $reset_traffic_method 流量重置方式
* @property int|null $capacity_limit 订阅人数限制 * @property int|null $capacity_limit 订阅人数限制
* @property int|null $device_limit 设备数量限制 * @property int|null $device_limit 设备数量限制
* @property int $created_at * @property int $created_at
+5 -1
View File
@@ -11,6 +11,10 @@ class Plugin extends Model
protected $guarded = [ protected $guarded = [
'id', 'id',
'created_at', 'created_at',
'updated_at' 'updated_at',
];
protected $casts = [
'is_enabled' => 'boolean'
]; ];
} }
+2 -1
View File
@@ -23,7 +23,7 @@ use Illuminate\Database\Eloquent\Casts\Attribute;
* @property array|null $group_ids 分组IDs * @property array|null $group_ids 分组IDs
* @property array|null $route_ids 路由IDs * @property array|null $route_ids 路由IDs
* @property array|null $tags 标签 * @property array|null $tags 标签
* @property string|null $show 是否显示 * @property boolean $show 是否显示
* @property string|null $allow_insecure 是否允许不安全 * @property string|null $allow_insecure 是否允许不安全
* @property string|null $network 网络类型 * @property string|null $network 网络类型
* @property int|null $parent_id 父节点ID * @property int|null $parent_id 父节点ID
@@ -112,6 +112,7 @@ class Server extends Model
'protocol_settings' => 'array', 'protocol_settings' => 'array',
'last_check_at' => 'integer', 'last_check_at' => 'integer',
'last_push_at' => 'integer', 'last_push_at' => 'integer',
'show' => 'boolean',
'created_at' => 'timestamp', 'created_at' => 'timestamp',
'updated_at' => 'timestamp' 'updated_at' => 'timestamp'
]; ];
+5 -3
View File
@@ -37,8 +37,8 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
* @property int|null $last_login_at 最后登录时间 * @property int|null $last_login_at 最后登录时间
* @property int|null $parent_id 父账户ID * @property int|null $parent_id 父账户ID
* @property int|null $is_admin 是否管理员 * @property int|null $is_admin 是否管理员
* @property \Carbon\Carbon|null $next_reset_at 下次流量重置时间 * @property int|null $next_reset_at 下次流量重置时间
* @property \Carbon\Carbon|null $last_reset_at 上次流量重置时间 * @property int|null $last_reset_at 上次流量重置时间
* @property int $reset_count 流量重置次数 * @property int $reset_count 流量重置次数
* @property int $created_at * @property int $created_at
* @property int $updated_at * @property int $updated_at
@@ -64,7 +64,9 @@ class User extends Authenticatable
protected $casts = [ protected $casts = [
'created_at' => 'timestamp', 'created_at' => 'timestamp',
'updated_at' => 'timestamp', 'updated_at' => 'timestamp',
'banned' => 'integer', 'banned' => 'boolean',
'is_admin' => 'boolean',
'is_staff' => 'boolean',
'remind_expire' => 'boolean', 'remind_expire' => 'boolean',
'remind_traffic' => 'boolean', 'remind_traffic' => 'boolean',
'commission_auto_check' => 'boolean', 'commission_auto_check' => 'boolean',
+2 -2
View File
@@ -53,10 +53,10 @@ class UserObserver
$nextResetTime = $this->trafficResetService->calculateNextResetTime($user); $nextResetTime = $this->trafficResetService->calculateNextResetTime($user);
if ($nextResetTime) { if ($nextResetTime) {
$user->next_reset_at = $nextResetTime->timestamp; $user->setAttribute('next_reset_at', $nextResetTime->timestamp);
} else { } else {
// 如果计算结果为空,清除重置时间 // 如果计算结果为空,清除重置时间
$user->next_reset_at = null; $user->setAttribute('next_reset_at', null);
} }
} catch (\Exception $e) { } catch (\Exception $e) {
+1 -1
View File
@@ -16,7 +16,7 @@ class SettingServiceProvider extends ServiceProvider
public function register() public function register()
{ {
$this->app->scoped(Setting::class, function (Application $app) { $this->app->scoped(Setting::class, function (Application $app) {
return new Setting(); return Setting::getInstance();
}); });
} }
-7
View File
@@ -87,13 +87,6 @@ class ServerService
public static function getRoutes(array $routeIds) public static function getRoutes(array $routeIds)
{ {
$routes = ServerRoute::select(['id', 'match', 'action', 'action_value'])->whereIn('id', $routeIds)->get(); $routes = ServerRoute::select(['id', 'match', 'action', 'action_value'])->whereIn('id', $routeIds)->get();
// TODO: remove on 1.8.0
foreach ($routes as $k => $route) {
$array = json_decode($route->match, true);
if (is_array($array))
$routes[$k]['match'] = $array;
}
// TODO: remove on 1.8.0
return $routes; return $routes;
} }
+1 -1
View File
@@ -109,7 +109,6 @@ class TrafficResetService
Plan::RESET_TRAFFIC_MONTHLY => $this->getNextMonthlyReset($user, $now), Plan::RESET_TRAFFIC_MONTHLY => $this->getNextMonthlyReset($user, $now),
Plan::RESET_TRAFFIC_FIRST_DAY_YEAR => $this->getNextYearFirstDay($now), Plan::RESET_TRAFFIC_FIRST_DAY_YEAR => $this->getNextYearFirstDay($now),
Plan::RESET_TRAFFIC_YEARLY => $this->getNextYearlyReset($user, $now), Plan::RESET_TRAFFIC_YEARLY => $this->getNextYearlyReset($user, $now),
Plan::RESET_TRAFFIC_NEVER => null,
default => null, default => null,
}; };
} }
@@ -251,6 +250,7 @@ class TrafficResetService
Plan::RESET_TRAFFIC_MONTHLY => TrafficResetLog::TYPE_MONTHLY, Plan::RESET_TRAFFIC_MONTHLY => TrafficResetLog::TYPE_MONTHLY,
Plan::RESET_TRAFFIC_FIRST_DAY_YEAR => TrafficResetLog::TYPE_FIRST_DAY_YEAR, Plan::RESET_TRAFFIC_FIRST_DAY_YEAR => TrafficResetLog::TYPE_FIRST_DAY_YEAR,
Plan::RESET_TRAFFIC_YEARLY => TrafficResetLog::TYPE_YEARLY, Plan::RESET_TRAFFIC_YEARLY => TrafficResetLog::TYPE_YEARLY,
Plan::RESET_TRAFFIC_NEVER => TrafficResetLog::TYPE_MANUAL,
default => TrafficResetLog::TYPE_MANUAL, default => TrafficResetLog::TYPE_MANUAL,
}; };
} }
+2 -2
View File
@@ -145,8 +145,8 @@ class UserService
'total_available' => $user->transfer_enable ?? 0, 'total_available' => $user->transfer_enable ?? 0,
'remaining' => $user->getRemainingTraffic(), 'remaining' => $user->getRemainingTraffic(),
'usage_percentage' => $user->getTrafficUsagePercentage(), 'usage_percentage' => $user->getTrafficUsagePercentage(),
'next_reset_at' => $user->next_reset_at?->timestamp, 'next_reset_at' => $user->next_reset_at,
'last_reset_at' => $user->last_reset_at?->timestamp, 'last_reset_at' => $user->last_reset_at,
'reset_count' => $user->reset_count, 'reset_count' => $user->reset_count,
]; ];
} }
+2 -2
View File
@@ -135,9 +135,9 @@ class Setting
// 处理JSON格式的值 // 处理JSON格式的值
foreach ($settings as $key => $value) { foreach ($settings as $key => $value) {
if (is_string($value) && $value !== null) { if (is_string($value)) {
$decoded = json_decode($value, true); $decoded = json_decode($value, true);
if (json_last_error() === JSON_ERROR_NONE) { if (json_last_error() === JSON_ERROR_NONE && $decoded !== null) {
$settings[$key] = $decoded; $settings[$key] = $decoded;
} }
} }
@@ -122,7 +122,7 @@ return new class extends Migration {
$table->integer('group_id')->change(); $table->integer('group_id')->change();
$table->integer('transfer_enable')->change(); $table->integer('transfer_enable')->change();
$table->integer('speed_limit')->nullable()->change(); $table->integer('speed_limit')->nullable()->change();
$table->boolean('reset_traffic_method')->nullable()->change(); $table->integer('reset_traffic_method')->nullable()->change();
$table->integer('capacity_limit')->nullable()->change(); $table->integer('capacity_limit')->nullable()->change();
}); });
} }
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long