| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- <?php
- namespace App\Services\Simulation;
- use App\Constants\HttpStatus;
- use App\Support\MemberAudience;
- use Exception;
- use Illuminate\Support\Facades\DB;
- /** 模拟管理的设置(config 表 simulation_* 键)以及每个写操作都要过的两道检查。 */
- final class SimulationSettings
- {
- /** 键 => [默认值, 最小, 最大];最小为 null 的是字符串。 */
- public const KEYS = [
- 'simulation_enabled' => ['0', 0, 1],
- 'simulation_max_concurrency' => ['2', 1, 10],
- 'simulation_rate_per_minute' => ['30', 1, 120],
- 'simulation_max_members_per_task' => ['20', 1, 200],
- 'simulation_max_members_total' => ['500', 1, 5000],
- 'simulation_max_amount' => ['10000', 1, 1000000],
- 'simulation_initial_balance' => ['0', 0, 1000000],
- 'simulation_wager_bypass' => ['1', 0, 1],
- 'simulation_default_domain' => ['sim.local', null, null],
- ];
- public static function all(): array
- {
- $stored = DB::table('config')->whereIn('field', array_keys(self::KEYS))->pluck('val', 'field');
- $out = [];
- foreach (self::KEYS as $key => [$default]) $out[$key] = (string) ($stored[$key] ?? $default);
- return $out;
- }
- public static function get(string $key): string
- {
- return self::all()[$key];
- }
- public static function save(array $input): array
- {
- $before = self::all();
- foreach (self::KEYS as $key => [, $min, $max]) {
- if (!array_key_exists($key, $input)) continue;
- $value = trim((string) $input[$key]);
- if ($min === null) {
- if ($value === '' || strlen($value) > 100) throw new Exception('域名格式不正确', HttpStatus::CUSTOM_ERROR);
- } elseif (!is_numeric($value) || $value < $min || $value > $max) {
- throw new Exception("{$key} 应在 {$min} 到 {$max} 之间", HttpStatus::CUSTOM_ERROR);
- }
- $exists = DB::table('config')->where('field', $key)->exists();
- if ($exists) DB::table('config')->where('field', $key)->update(['val' => $value]);
- else DB::table('config')->insert(['field' => $key, 'val' => $value]);
- }
- return ['before' => $before, 'after' => self::all()];
- }
- public static function enabled(): bool
- {
- return self::get('simulation_enabled') === '1';
- }
- public static function assertEnabled(): void
- {
- if (!MemberAudience::enabled()) throw new Exception('用户类型字段尚未迁移,无法使用模拟管理', HttpStatus::CUSTOM_ERROR);
- if (!self::enabled()) throw new Exception('模拟功能未开启,请先在“模拟设置”中开启', HttpStatus::CUSTOM_ERROR);
- }
- /** 写操作的目标必须是后台模拟会员,返回该会员。 */
- public static function member($memberId): object
- {
- $user = DB::table('users')->where('member_id', (string) $memberId)->where('user_type', MemberAudience::TYPE_SIMULATED)->first();
- if (!$user) throw new Exception('只能操作模拟会员', HttpStatus::CUSTOM_ERROR);
- return $user;
- }
- public static function assertAmount($amount): string
- {
- if (!is_numeric($amount) || $amount <= 0) throw new Exception('金额格式不正确', HttpStatus::CUSTOM_ERROR);
- if ($amount > (float) self::get('simulation_max_amount')) throw new Exception('金额超过模拟设置的单次上限', HttpStatus::CUSTOM_ERROR);
- return number_format((float) $amount, 2, '.', '');
- }
- }
|