From 66329232136027435a7d4f8a656e5a9ae2d64d0c Mon Sep 17 00:00:00 2001
From: zhenhui <1276357500@qq.com>
Date: Sat, 7 Mar 2026 14:40:33 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=B8=B8=E7=8E=A9=E8=AE=B0?=
=?UTF-8?q?=E5=BD=95DicePlayRecord?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../plugin/dice/play_record/index/index.vue | 3 +
.../play_record/index/modules/edit-dialog.vue | 21 ++++-
.../index/modules/table-search.vue | 25 ++++++
.../plugin/dice/reward_config/index/index.vue | 1 +
.../index/modules/edit-dialog.vue | 54 +++++++++--
server/app/api/controller/GameController.php | 1 +
server/app/api/logic/PlayStartLogic.php | 90 ++++++++++++++++---
.../play_record/DicePlayRecordController.php | 2 +
.../logic/play_record/DicePlayRecordLogic.php | 16 ++--
.../reward_config/DiceRewardConfigLogic.php | 33 +++++++
.../dice/model/play_record/DicePlayRecord.php | 17 ++++
.../model/reward_config/DiceRewardConfig.php | 27 +++++-
.../DiceRewardConfigValidate.php | 51 ++++++-----
13 files changed, 286 insertions(+), 55 deletions(-)
diff --git a/saiadmin-artd/src/views/plugin/dice/play_record/index/index.vue b/saiadmin-artd/src/views/plugin/dice/play_record/index/index.vue
index dde5119..4d6ec42 100644
--- a/saiadmin-artd/src/views/plugin/dice/play_record/index/index.vue
+++ b/saiadmin-artd/src/views/plugin/dice/play_record/index/index.vue
@@ -117,6 +117,8 @@
is_win: undefined,
win_coin_min: undefined,
win_coin_max: undefined,
+ roll_number_min: undefined,
+ roll_number_max: undefined,
reward_ui_text: undefined,
reward_tier: undefined,
direction: undefined
@@ -190,6 +192,7 @@
{ prop: 'start_index', label: '起始索引', width: 90 },
{ prop: 'target_index', label: '终点索引', width: 90 },
{ prop: 'roll_array', label: '摇取点数', width: 140, useSlot: true },
+ { prop: 'roll_number', label: '摇取点数和', width: 110, sortable: true },
{
prop: 'reward_config_id',
label: '奖励配置',
diff --git a/saiadmin-artd/src/views/plugin/dice/play_record/index/modules/edit-dialog.vue b/saiadmin-artd/src/views/plugin/dice/play_record/index/modules/edit-dialog.vue
index 7be20f6..b51ceb1 100644
--- a/saiadmin-artd/src/views/plugin/dice/play_record/index/modules/edit-dialog.vue
+++ b/saiadmin-artd/src/views/plugin/dice/play_record/index/modules/edit-dialog.vue
@@ -142,6 +142,17 @@
固定 5 个数,每个 1~6
+
+
+
{
@@ -319,6 +332,10 @@
}
}
})
+ // 若后端未返回 roll_number,根据摇取点数计算
+ if (formData.roll_number == null && formData.rollArrayItems.length === 5) {
+ formData.roll_number = formData.rollArrayItems.reduce((s, n) => s + (n ?? 0), 0) || null
+ }
}
/** 将接口的 roll_array 转为固定 5 项数组,不足补 null */
@@ -355,10 +372,12 @@
const payload = { ...formData } as Record
// 将 5 个输入值拼成 [1,2,3,4,5] 格式,确保每项为 1~6 的整数
const items = formData.rollArrayItems
- payload.roll_array = items.map((n) => {
+ const rollArray = items.map((n) => {
const v = n != null ? Number(n) : 1
return Math.min(6, Math.max(1, Number.isNaN(v) ? 1 : Math.floor(v)))
})
+ payload.roll_array = rollArray
+ payload.roll_number = formData.roll_number ?? rollArray.reduce((s, n) => s + n, 0)
delete payload.rollArrayItems
if (props.dialogType === 'add') {
delete payload.id
diff --git a/saiadmin-artd/src/views/plugin/dice/play_record/index/modules/table-search.vue b/saiadmin-artd/src/views/plugin/dice/play_record/index/modules/table-search.vue
index d0653a4..b7d90ae 100644
--- a/saiadmin-artd/src/views/plugin/dice/play_record/index/modules/table-search.vue
+++ b/saiadmin-artd/src/views/plugin/dice/play_record/index/modules/table-search.vue
@@ -63,6 +63,31 @@
+
+
+
+
+ 至
+
+
+
+
diff --git a/saiadmin-artd/src/views/plugin/dice/reward_config/index/index.vue b/saiadmin-artd/src/views/plugin/dice/reward_config/index/index.vue
index 0846882..4bc02ce 100644
--- a/saiadmin-artd/src/views/plugin/dice/reward_config/index/index.vue
+++ b/saiadmin-artd/src/views/plugin/dice/reward_config/index/index.vue
@@ -122,6 +122,7 @@
{ prop: 'ui_text', label: '前端显示文本', align: 'center' },
{ prop: 'real_ev', label: '真实资金结算', align: 'center' },
{ prop: 'tier', label: '所属档位', sortable: true, align: 'center' },
+ { prop: 'weight', label: '权重(%)', width: 100, align: 'center' },
// { prop: 'create_time', label: '创建时间', sortable: true, align: 'center' },
{
prop: 'operation',
diff --git a/saiadmin-artd/src/views/plugin/dice/reward_config/index/modules/edit-dialog.vue b/saiadmin-artd/src/views/plugin/dice/reward_config/index/modules/edit-dialog.vue
index d33abe4..63d89e1 100644
--- a/saiadmin-artd/src/views/plugin/dice/reward_config/index/modules/edit-dialog.vue
+++ b/saiadmin-artd/src/views/plugin/dice/reward_config/index/modules/edit-dialog.vue
@@ -34,8 +34,12 @@
+
+
+
+
void) => {
+ if (formData.tier !== 'BIGWIN') {
+ callback()
+ return
+ }
+ const n = value != null ? Number(value) : NaN
+ if (Number.isNaN(n) || n < 0 || n > 100) {
+ callback(new Error('权重仅 BIGWIN 可设定,且必须为 0-100%'))
+ return
+ }
+ callback()
+ },
+ trigger: 'blur'
+ }
+ ]
})
/**
@@ -107,6 +128,7 @@
ui_text: '',
real_ev: '',
tier: '',
+ weight: 0 as number,
remark: ''
}
@@ -141,14 +163,21 @@
}
/**
- * 初始化表单数据
+ * 初始化表单数据(数值字段转为 number,便于滑块/输入框正确回显)
*/
const initForm = () => {
- if (props.data) {
- for (const key in formData) {
- if (props.data[key] != null && props.data[key] != undefined) {
- ;(formData as any)[key] = props.data[key]
- }
+ if (!props.data) return
+ const numKeys = ['id', 'grid_number', 'real_ev', 'weight']
+ for (const key of Object.keys(formData)) {
+ if (!(key in props.data)) continue
+ const val = props.data[key]
+ if (val == null || val === undefined) continue
+ if (numKeys.includes(key)) {
+ const numVal = Number(val)
+ ;(formData as Record)[key] =
+ key === 'id' ? numVal || null : Number.isNaN(numVal) ? 0 : numVal
+ } else {
+ ;(formData as Record)[key] = val ?? ''
}
}
}
@@ -168,11 +197,18 @@
if (!formRef.value) return
try {
await formRef.value.validate()
+ const payload = { ...formData }
+ if (payload.tier !== 'BIGWIN') {
+ payload.weight = 0
+ } else {
+ const w = Number(payload.weight)
+ payload.weight = Number.isNaN(w) ? 0 : Math.max(0, Math.min(100, w))
+ }
if (props.dialogType === 'add') {
- await api.save(formData)
+ await api.save(payload)
ElMessage.success('新增成功')
} else {
- await api.update(formData)
+ await api.update(payload)
ElMessage.success('修改成功')
}
emit('success')
diff --git a/server/app/api/controller/GameController.php b/server/app/api/controller/GameController.php
index 072f097..75384cf 100644
--- a/server/app/api/controller/GameController.php
+++ b/server/app/api/controller/GameController.php
@@ -150,6 +150,7 @@ class GameController extends OpenController
'start_index' => 0,
'target_index' => 0,
'roll_array' => '[]',
+ 'roll_number' => 0,
'status' => PlayStartLogic::RECORD_STATUS_TIMEOUT,
]);
} catch (\Exception $inner) {
diff --git a/server/app/api/logic/PlayStartLogic.php b/server/app/api/logic/PlayStartLogic.php
index 011c7e1..a7749af 100644
--- a/server/app/api/logic/PlayStartLogic.php
+++ b/server/app/api/logic/PlayStartLogic.php
@@ -34,8 +34,10 @@ class PlayStartLogic
/** 开启对局最低余额 = |DiceRewardConfig 最小 real_ev + 100| */
private const MIN_COIN_EXTRA = 100;
- /** 豹子号中大奖额外平台币(可从 dice_config 等配置读取) */
+ /** 豹子号中大奖额外平台币(无 BIGWIN 配置时兜底) */
private const SUPER_WIN_BONUS = 500;
+ /** 可触发超级大奖的 grid_number(5=全1 10=全2 15=全3 20=全4 25=全5) */
+ private const SUPER_WIN_GRID_NUMBERS = [5, 10, 15, 20, 25];
/**
* 执行一局游戏
@@ -112,7 +114,30 @@ class PlayStartLogic
? (int) ($startRecord['s_end_index'] ?? 0)
: (int) ($startRecord['n_end_index'] ?? 0);
$rollNumber = (int) ($startRecord['grid_number'] ?? 0);
- $rollArray = $this->generateRollArrayFromSum($rollNumber);
+ $realEv = (float) ($chosen['real_ev'] ?? 0);
+ $rewardWinCoin = 100 + $realEv; // 摇色子中奖平台币 = 100 + DiceRewardConfig.real_ev
+
+ // 当抽到的 grid_number 为 5/10/15/20/25 时,从缓存查 tier=BIGWIN 同 grid_number 的配置,按 weight 决定是否生成豹子组合
+ $superWinCoin = 0;
+ $isWin = 0;
+ if (in_array($rollNumber, self::SUPER_WIN_GRID_NUMBERS, true)) {
+ $bigWinConfig = DiceRewardConfig::getCachedByTierAndGridNumber('BIGWIN', $rollNumber);
+ $weight = $bigWinConfig !== null
+ ? max(0.0, min(100.0, (float) ($bigWinConfig['weight'] ?? 0)))
+ : 100.0;
+ $roll = mt_rand(1, 10000) / 10000;
+ if ($roll <= $weight / 100) {
+ $rollArray = $this->getSuperWinRollArray($rollNumber);
+ $isWin = 1;
+ $superWinCoin = $bigWinConfig !== null
+ ? 100 + (float) ($bigWinConfig['real_ev'] ?? 0)
+ : self::SUPER_WIN_BONUS;
+ } else {
+ $rollArray = $this->generateNonSuperWinRollArrayWithSum($rollNumber);
+ }
+ } else {
+ $rollArray = $this->generateRollArrayFromSum($rollNumber);
+ }
Log::info(sprintf(
'摇取点数 roll_number=%d, 方向=%d, start_index=%d, target_index=%d',
@@ -121,17 +146,6 @@ class PlayStartLogic
$startIndex,
$targetIndex
));
- $realEv = (float) ($chosen['real_ev'] ?? 0);
- $rewardWinCoin = 100 + $realEv; // 摇色子中奖平台币 = 100 + DiceRewardConfig.real_ev
- $isSuperWin = DicePlayRecord::isSuperWin($rollArray);
- // 豹子中大奖时从缓存查 tier=BIGWIN 且 grid_number=roll_number 的奖励配置,取 real_ev 计算中大奖平台币
- $superWinCoin = 0;
- if ($isSuperWin) {
- $bigWinConfig = DiceRewardConfig::getCachedByTierAndGridNumber('BIGWIN', $rollNumber);
- $superWinCoin = $bigWinConfig !== null
- ? 100 + (float) ($bigWinConfig['real_ev'] ?? 0)
- : self::SUPER_WIN_BONUS;
- }
$winCoin = $superWinCoin + $rewardWinCoin; // 赢取平台币 = 中大奖 + 摇色子中奖
$record = null;
@@ -139,7 +153,6 @@ class PlayStartLogic
$rewardId = $chosenId;
$configName = (string) ($config->name ?? '');
$isTierT5 = (string) ($chosen['tier'] ?? '') === 'T5';
- $isWin = $isSuperWin ? 1 : 0;
try {
Db::transaction(function () use (
$playerId,
@@ -173,6 +186,7 @@ class PlayStartLogic
'start_index' => $startIndex,
'target_index' => $targetIndex,
'roll_array' => is_array($rollArray) ? json_encode($rollArray) : $rollArray,
+ 'roll_number' => is_array($rollArray) ? array_sum($rollArray) : 0,
'lottery_name' => $configName,
'status' => self::RECORD_STATUS_SUCCESS,
]);
@@ -239,6 +253,7 @@ class PlayStartLogic
'start_index' => $startIndex,
'target_index' => 0,
'roll_array' => '[]',
+ 'roll_number' => 0,
'status' => self::RECORD_STATUS_TIMEOUT,
]);
} catch (\Throwable $_) {
@@ -290,4 +305,51 @@ class PlayStartLogic
shuffle($arr);
return array_values($arr);
}
+
+ /**
+ * 豹子组合:grid_number 5->[1,1,1,1,1],10->[2,2,2,2,2],15->[3,3,3,3,3],20->[4,4,4,4,4],25->[5,5,5,5,5]
+ * @return int[]
+ */
+ private function getSuperWinRollArray(int $gridNumber): array
+ {
+ $n = (int) ($gridNumber / 5);
+ $n = max(1, min(5, $n));
+ return array_fill(0, 5, $n);
+ }
+
+ /**
+ * 生成总和为 $sum 且非豹子的 5 个色子(1-6);sum=5 时仅 [1,1,1,1,1] 可能,仍返回该组合
+ * @return int[]
+ */
+ private function generateNonSuperWinRollArrayWithSum(int $sum): array
+ {
+ $sum = max(5, min(30, $sum));
+ $super = $this->getSuperWinRollArray($sum);
+ if ($sum === 5) {
+ return $super;
+ }
+ $arr = $super;
+ $maxAttempts = 20;
+ for ($a = 0; $a < $maxAttempts; $a++) {
+ $idx = array_rand($arr);
+ $j = array_rand($arr);
+ if ($idx === $j) {
+ $j = ($j + 1) % 5;
+ }
+ $i = $idx;
+ if ($arr[$i] >= 2 && $arr[$j] <= 5) {
+ $arr[$i]--;
+ $arr[$j]++;
+ shuffle($arr);
+ return array_values($arr);
+ }
+ if ($arr[$i] <= 5 && $arr[$j] >= 2) {
+ $arr[$i]++;
+ $arr[$j]--;
+ shuffle($arr);
+ return array_values($arr);
+ }
+ }
+ return $this->generateRollArrayFromSum($sum);
+ }
}
diff --git a/server/app/dice/controller/play_record/DicePlayRecordController.php b/server/app/dice/controller/play_record/DicePlayRecordController.php
index abe2f83..bd17270 100644
--- a/server/app/dice/controller/play_record/DicePlayRecordController.php
+++ b/server/app/dice/controller/play_record/DicePlayRecordController.php
@@ -46,6 +46,8 @@ class DicePlayRecordController extends BaseController
['is_win', ''],
['win_coin_min', ''],
['win_coin_max', ''],
+ ['roll_number_min', ''],
+ ['roll_number_max', ''],
['reward_ui_text', ''],
['reward_tier', ''],
['direction', ''],
diff --git a/server/app/dice/logic/play_record/DicePlayRecordLogic.php b/server/app/dice/logic/play_record/DicePlayRecordLogic.php
index 86b7526..e99a548 100644
--- a/server/app/dice/logic/play_record/DicePlayRecordLogic.php
+++ b/server/app/dice/logic/play_record/DicePlayRecordLogic.php
@@ -43,16 +43,18 @@ class DicePlayRecordLogic extends BaseLogic
}
/**
- * 将 roll_array 从数组转为 JSON 字符串
+ * 将 roll_array 转为 JSON 字符串,并确保 roll_number 与摇取点数一致
*/
private function normalizeRollArray(array $data): array
{
- if (!array_key_exists('roll_array', $data)) {
- return $data;
- }
- $val = $data['roll_array'];
- if (is_array($val)) {
- $data['roll_array'] = json_encode($val, JSON_UNESCAPED_UNICODE);
+ if (array_key_exists('roll_array', $data)) {
+ $val = $data['roll_array'];
+ if (is_array($val)) {
+ $data['roll_array'] = json_encode($val, JSON_UNESCAPED_UNICODE);
+ if (!isset($data['roll_number'])) {
+ $data['roll_number'] = array_sum($val);
+ }
+ }
}
return $data;
}
diff --git a/server/app/dice/logic/reward_config/DiceRewardConfigLogic.php b/server/app/dice/logic/reward_config/DiceRewardConfigLogic.php
index 2640b8a..a9457dc 100644
--- a/server/app/dice/logic/reward_config/DiceRewardConfigLogic.php
+++ b/server/app/dice/logic/reward_config/DiceRewardConfigLogic.php
@@ -13,6 +13,7 @@ use app\dice\model\reward_config\DiceRewardConfig;
/**
* 奖励配置逻辑层
+ * weight 仅 tier=BIGWIN 时可设定,保存时非 BIGWIN 强制 weight=0
*/
class DiceRewardConfigLogic extends BaseLogic
{
@@ -24,4 +25,36 @@ class DiceRewardConfigLogic extends BaseLogic
$this->model = new DiceRewardConfig();
}
+ /**
+ * 新增前:非 BIGWIN 时强制 weight=0
+ */
+ public function add(array $data): mixed
+ {
+ $data = $this->normalizeWeightByTier($data);
+ return parent::add($data);
+ }
+
+ /**
+ * 修改前:非 BIGWIN 时强制 weight=0
+ */
+ public function edit($id, array $data): mixed
+ {
+ $data = $this->normalizeWeightByTier($data);
+ return parent::edit($id, $data);
+ }
+
+ /**
+ * 仅 tier=BIGWIN 时保留 weight(且限制 0-100),否则强制为 0
+ */
+ private function normalizeWeightByTier(array $data): array
+ {
+ $tier = isset($data['tier']) ? (string) $data['tier'] : '';
+ if ($tier !== 'BIGWIN') {
+ $data['weight'] = 0;
+ return $data;
+ }
+ $w = isset($data['weight']) ? (float) $data['weight'] : 0;
+ $data['weight'] = max(0, min(100, $w));
+ return $data;
+ }
}
diff --git a/server/app/dice/model/play_record/DicePlayRecord.php b/server/app/dice/model/play_record/DicePlayRecord.php
index aee8bf4..8171aba 100644
--- a/server/app/dice/model/play_record/DicePlayRecord.php
+++ b/server/app/dice/model/play_record/DicePlayRecord.php
@@ -31,6 +31,7 @@ use think\model\relation\BelongsTo;
* @property $start_index 起始索引
* @property $target_index 结束索引
* @property $roll_array 摇取点数,格式:[1,2,3,4,5](5个点数)
+ * @property $roll_number 摇取点数和(5个色子点数之和,5-30)
* @property $lottery_name 奖池名
* @property $status 状态:0=超时/失败 1=成功
* @property $create_time 创建时间
@@ -222,4 +223,20 @@ class DicePlayRecord extends BaseModel
$query->where('direction', '=', $value);
}
}
+
+ /** 摇取点数和下限 */
+ public function searchRollNumberMinAttr($query, $value)
+ {
+ if ($value !== '' && $value !== null) {
+ $query->where('roll_number', '>=', $value);
+ }
+ }
+
+ /** 摇取点数和上限 */
+ public function searchRollNumberMaxAttr($query, $value)
+ {
+ if ($value !== '' && $value !== null) {
+ $query->where('roll_number', '<=', $value);
+ }
+ }
}
diff --git a/server/app/dice/model/reward_config/DiceRewardConfig.php b/server/app/dice/model/reward_config/DiceRewardConfig.php
index a5517d7..2291ea1 100644
--- a/server/app/dice/model/reward_config/DiceRewardConfig.php
+++ b/server/app/dice/model/reward_config/DiceRewardConfig.php
@@ -20,6 +20,7 @@ use support\think\Cache;
* @property $ui_text 前端显示文本
* @property $real_ev 真实资金结算
* @property $tier 所属档位
+ * @property $weight 权重%(仅 tier=BIGWIN 时可设定,0-100)
* @property $s_end_index 顺时针结束索引
* @property $n_end_index 逆时针结束索引
* @property $remark 备注
@@ -80,7 +81,8 @@ class DiceRewardConfig extends BaseModel
}
/**
- * 重新从数据库加载并写入缓存(保存时调用),构建列表与索引
+ * 重新从数据库加载并写入缓存(DiceRewardConfig 新增/修改/删除后调用),构建列表与索引
+ * 实例化结果含完整行(含 weight),供 playStart 从缓存中查找 BIGWIN 的 weight 按概率抽奖
*/
public static function refreshCache(): void
{
@@ -148,10 +150,11 @@ class DiceRewardConfig extends BaseModel
}
/**
- * 从缓存按档位 + 色子点数取一条奖励配置(用于超级大奖 tier=BIGWIN + grid_number=roll_number)
+ * 从缓存实例按档位 + 色子点数取一条奖励配置(用于超级大奖 tier=BIGWIN + grid_number=roll_number)
+ * 返回行含 weight(0-100):playStart 据此概率抽奖,weight=100 表示摇到该 roll_number 时 100% 中超级大奖
* @param string $tier 档位,如 BIGWIN
- * @param int $gridNumber 色子点数(如摇出总和)
- * @return array|null 配置行或 null
+ * @param int $gridNumber 色子点数(摇出总和 roll_number)
+ * @return array|null 配置行(含 weight、real_ev 等)或 null
*/
public static function getCachedByTierAndGridNumber(string $tier, int $gridNumber): ?array
{
@@ -277,4 +280,20 @@ class DiceRewardConfig extends BaseModel
$query->where('tier', '=', $value);
}
}
+
+ /** 权重下限(仅 tier=BIGWIN 时有意义) */
+ public function searchWeightMinAttr($query, $value)
+ {
+ if ($value !== '' && $value !== null) {
+ $query->where('weight', '>=', $value);
+ }
+ }
+
+ /** 权重上限 */
+ public function searchWeightMaxAttr($query, $value)
+ {
+ if ($value !== '' && $value !== null) {
+ $query->where('weight', '<=', $value);
+ }
+ }
}
diff --git a/server/app/dice/validate/reward_config/DiceRewardConfigValidate.php b/server/app/dice/validate/reward_config/DiceRewardConfigValidate.php
index 4aadbc6..d615d76 100644
--- a/server/app/dice/validate/reward_config/DiceRewardConfigValidate.php
+++ b/server/app/dice/validate/reward_config/DiceRewardConfigValidate.php
@@ -10,45 +10,56 @@ use plugin\saiadmin\basic\BaseValidate;
/**
* 奖励配置验证器
+ * weight 仅当 tier=BIGWIN 时可设定,且严格限制 0-100(%)
*/
class DiceRewardConfigValidate extends BaseValidate
{
/**
* 定义验证规则
*/
- protected $rule = [
+ protected $rule = [
'grid_number' => 'require',
- 'ui_text' => 'require',
- 'real_ev' => 'require',
- 'tier' => 'require',
+ 'ui_text' => 'require',
+ 'real_ev' => 'require',
+ 'tier' => 'require',
+ 'weight' => 'checkWeight',
];
/**
* 定义错误信息
*/
- protected $message = [
+ protected $message = [
'grid_number' => '色子点数必须填写',
- 'ui_text' => '前端显示文本必须填写',
- 'real_ev' => '真实资金结算必须填写',
- 'tier' => '所属档位必须填写',
+ 'ui_text' => '前端显示文本必须填写',
+ 'real_ev' => '真实资金结算必须填写',
+ 'tier' => '所属档位必须填写',
+ 'weight' => '权重仅 tier=BIGWIN 时可设定,且必须为 0-100',
];
/**
* 定义场景
*/
protected $scene = [
- 'save' => [
- 'grid_number',
- 'ui_text',
- 'real_ev',
- 'tier',
- ],
- 'update' => [
- 'grid_number',
- 'ui_text',
- 'real_ev',
- 'tier',
- ],
+ 'save' => ['grid_number', 'ui_text', 'real_ev', 'tier', 'weight'],
+ 'update' => ['grid_number', 'ui_text', 'real_ev', 'tier', 'weight'],
];
+ /**
+ * weight:仅 tier=BIGWIN 时可设定,严格限制 0-100(%)
+ */
+ protected function checkWeight($value, $rule = '', $data = []): bool
+ {
+ $tier = isset($data['tier']) ? (string) $data['tier'] : '';
+ if ($tier !== 'BIGWIN') {
+ return true;
+ }
+ $num = is_numeric($value) ? (float) $value : null;
+ if ($num === null) {
+ return false;
+ }
+ if ($num < 0 || $num > 100) {
+ return false;
+ }
+ return true;
+ }
}