feat: 增强代理和玩家管理功能

- 在多个控制器中更新权限检查逻辑,确保管理员能够更灵活地管理代理和玩家。
- 在 AdminPlayerStoreController 中引入对玩家创建能力的验证,确保只有具备相应权限的管理员能够创建玩家。
- 更新请求验证逻辑,新增 credit_limit、rebate_rate 和 extra_rebate_rate 字段,以支持更细粒度的玩家管理。
- 在 AgentNodeProfileController 中添加对父代理能力授予的验证,确保子代理的权限在父代理范围内。
- 引入 AgentProfileFieldRules 以简化代理资料更新请求的规则定义,提升代码复用性。
This commit is contained in:
2026-06-04 18:00:50 +08:00
parent 96545f87f6
commit a44679665d
183 changed files with 10054 additions and 857 deletions

View File

@@ -97,6 +97,11 @@ final class ApiValidationErrors
return $humanized;
}
$compact = self::humanizeCompactEnglish($field, $trimmed, $locale, $attribute);
if ($compact !== null) {
return $compact;
}
return $trimmed;
}
@@ -243,6 +248,91 @@ final class ApiValidationErrors
return null;
}
/**
* Laravel 11 locale=en 时常用「{attribute} must not be greater than 1.」短句(无 "The … field" 前缀)。
*/
private static function humanizeCompactEnglish(
string $field,
string $message,
string $locale,
string $attribute,
): ?string {
if (preg_match('/^(.+?)\s+must not be greater than ([\d.]+)\.?$/i', $message, $max) === 1) {
$attribute = self::attributeLabelFromEnglish($max[1], $field, $locale);
$custom = self::customRuleLine($field, 'max', $attribute, $locale);
if ($custom !== null) {
return $custom;
}
return trans('validation.max.numeric', ['attribute' => $attribute, 'max' => $max[2]], $locale);
}
if (preg_match('/^(.+?)\s+may not be greater than ([\d.]+)\.?$/i', $message, $max) === 1) {
$attribute = self::attributeLabelFromEnglish($max[1], $field, $locale);
return trans('validation.max.numeric', ['attribute' => $attribute, 'max' => $max[2]], $locale);
}
if (preg_match('/^(.+?)\s+must be less than or equal to ([\d.]+)\.?$/i', $message, $lte) === 1) {
$attribute = self::attributeLabelFromEnglish($lte[1], $field, $locale);
return trans('validation.lte.numeric', ['attribute' => $attribute, 'value' => $lte[2]], $locale);
}
if (preg_match('/^(.+?)\s+must not be less than ([\d.]+)\.?$/i', $message, $min) === 1) {
$attribute = self::attributeLabelFromEnglish($min[1], $field, $locale);
$custom = self::customRuleLine($field, 'min', $attribute, $locale);
if ($custom !== null) {
return $custom;
}
return trans('validation.min.numeric', ['attribute' => $attribute, 'min' => $min[2]], $locale);
}
if (preg_match('/^(.+?)\s+must be at least ([\d.]+)\.?$/i', $message, $min) === 1) {
$attribute = self::attributeLabelFromEnglish($min[1], $field, $locale);
$custom = self::customRuleLine($field, 'min', $attribute, $locale);
if ($custom !== null) {
return $custom;
}
return trans('validation.min.numeric', ['attribute' => $attribute, 'min' => $min[2]], $locale);
}
if (preg_match('/^(.+?)\s+must be between ([\d.]+) and ([\d.]+)\.?$/i', $message, $between) === 1) {
$attribute = self::attributeLabelFromEnglish($between[1], $field, $locale);
return trans('validation.between.numeric', [
'attribute' => $attribute,
'min' => $between[2],
'max' => $between[3],
], $locale);
}
$compactTails = [
'must be a number' => 'validation.numeric',
'must be an integer' => 'validation.integer',
'must be a string' => 'validation.string',
'must be a boolean' => 'validation.boolean',
'must be an array' => 'validation.array',
'is required' => 'validation.required',
];
foreach ($compactTails as $suffix => $ruleKey) {
$pattern = '/^(.+?)\s+'.preg_quote($suffix, '/').'\.?$/i';
if (preg_match($pattern, $message, $match) !== 1) {
continue;
}
$attribute = self::attributeLabelFromEnglish($match[1], $field, $locale);
$line = trans($ruleKey, ['attribute' => $attribute], $locale);
return $line !== $ruleKey ? $line : null;
}
return null;
}
private static function attributeLabelFromEnglish(string $englishName, string $field, string $locale): string
{
$normalized = strtolower(trim($englishName));