diff --git a/saiadmin-artd/src/locales/langs/en/dice/lottery_pool_config.json b/saiadmin-artd/src/locales/langs/en/dice/lottery_pool_config.json index 60da1c4..ee760be 100644 --- a/saiadmin-artd/src/locales/langs/en/dice/lottery_pool_config.json +++ b/saiadmin-artd/src/locales/langs/en/dice/lottery_pool_config.json @@ -18,7 +18,6 @@ "t5Weight": "T5 Pool Weight (%)", "weightsSumHint": "Total pool weights: ", "weightsSumUnit": "% / 100% (must equal 100%)", - "weightsSumUnitCurrent": "% / 100%", "currentPoolTitle": "Current Lottery Pool", "loading": "Loading...", "poolName": "Pool Name", diff --git a/saiadmin-artd/src/locales/langs/zh/dice/lottery_pool_config.json b/saiadmin-artd/src/locales/langs/zh/dice/lottery_pool_config.json index f7bffc1..a0e1051 100644 --- a/saiadmin-artd/src/locales/langs/zh/dice/lottery_pool_config.json +++ b/saiadmin-artd/src/locales/langs/zh/dice/lottery_pool_config.json @@ -18,7 +18,6 @@ "t5Weight": "T5池权重(%)", "weightsSumHint": "五个池权重总和:", "weightsSumUnit": "% / 100%(必须为100%)", - "weightsSumUnitCurrent": "% / 100%(须为100%)", "currentPoolTitle": "当前彩金池", "loading": "加载中...", "poolName": "池子名称", diff --git a/saiadmin-artd/src/views/plugin/dice/api/lottery_pool_config/index.ts b/saiadmin-artd/src/views/plugin/dice/api/lottery_pool_config/index.ts index 43e77bf..61ff4ab 100644 --- a/saiadmin-artd/src/views/plugin/dice/api/lottery_pool_config/index.ts +++ b/saiadmin-artd/src/views/plugin/dice/api/lottery_pool_config/index.ts @@ -104,6 +104,7 @@ export default { id: number name: string safety_line: number + kill_enabled: number t1_weight: number t2_weight: number t3_weight: number @@ -118,14 +119,7 @@ export default { /** * 更新当前彩金池:仅 safety_line、t1_weight~t5_weight,不可改 profit_amount */ - updateCurrentPool(params: { - safety_line?: number - t1_weight?: number - t2_weight?: number - t3_weight?: number - t4_weight?: number - t5_weight?: number - }) { + updateCurrentPool(params: { safety_line?: number; kill_enabled?: number }) { return request.post({ url: '/core/dice/lottery_pool_config/DiceLotteryPoolConfig/updateCurrentPool', data: params diff --git a/saiadmin-artd/src/views/plugin/dice/lottery_pool_config/index/modules/current-pool-dialog.vue b/saiadmin-artd/src/views/plugin/dice/lottery_pool_config/index/modules/current-pool-dialog.vue index d16c152..242a43a 100644 --- a/saiadmin-artd/src/views/plugin/dice/lottery_pool_config/index/modules/current-pool-dialog.vue +++ b/saiadmin-artd/src/views/plugin/dice/lottery_pool_config/index/modules/current-pool-dialog.vue @@ -42,6 +42,9 @@ style="width: 100%" /> + + +
T1: {{ pool.t1_weight }}% / T2: {{ pool.t2_weight }}% / T3: {{ pool.t3_weight }}% / T4: {{ pool.t4_weight }}% / T5: {{ pool.t5_weight }}% @@ -49,10 +52,7 @@
- {{ $t('page.form.weightsSumHint') }}{{ - weightsSum - }}{{ $t('page.form.weightsSumUnitCurrent') }} {{ $t('page.form.killWeightNote') }} + {{ $t('page.form.killWeightNote') }}
@@ -81,6 +81,7 @@ id: number name: string safety_line: number + kill_enabled: number t1_weight: number t2_weight: number t3_weight: number @@ -104,7 +105,8 @@ const formRef = ref() const formData = reactive({ - safety_line: 0 + safety_line: 0, + kill_enabled: 1 }) const rules = computed(() => ({ @@ -143,6 +145,7 @@ if (data && typeof data === 'object') { pool.value = data formData.safety_line = data.safety_line ?? 0 + formData.kill_enabled = (data.kill_enabled ?? 1) === 1 ? 1 : 0 } } catch (e: any) { ElMessage.error(e?.message ?? t('page.form.msgGetPoolFailed')) @@ -180,7 +183,8 @@ await formRef.value?.validate?.() saving.value = true await api.updateCurrentPool({ - safety_line: formData.safety_line + safety_line: formData.safety_line, + kill_enabled: formData.kill_enabled }) ElMessage.success(t('page.form.msgSaveSuccess')) await loadPool() diff --git a/server/app/api/logic/PlayStartLogic.php b/server/app/api/logic/PlayStartLogic.php index edce568..2ff4037 100644 --- a/server/app/api/logic/PlayStartLogic.php +++ b/server/app/api/logic/PlayStartLogic.php @@ -75,10 +75,6 @@ class PlayStartLogic if (!$configType0) { throw new ApiException('奖池配置不存在(需 type=0)'); } - // 杀分时使用 type=1 配置的权重;未杀分时付费用 type=0、免费用 type=1(无 type=1 时回退 type=0) - $configForWeights = $ticketType === self::LOTTERY_TYPE_PAID - ? $configType0 - : ($configType1 ?? $configType0); // 玩家累计盈利:仅统计 lottery_config_id=type=0 的成功对局(中奖金额-100*局数) $playerQuery = DicePlayRecord::where('player_id', $playerId) @@ -88,13 +84,11 @@ class PlayStartLogic $playerPlayCount = (int) $playerQuery->count(); $playerProfitTotal = $playerWinSum - 100.0 * $playerPlayCount; $safetyLine = (int) ($configType0->safety_line ?? 0); - // 玩家累计盈利>=安全线时杀分:用 type=1 的 T*_weight,并记录 lottery_config_id=type=1 的 id;否则用玩家权重,记录对应配置 id - $usePoolWeights = $playerProfitTotal >= $safetyLine && $configType1 !== null; - if ($usePoolWeights) { - $config = $configType1; - } else { - $config = $configForWeights; - } + $killEnabled = ((int) ($configType0->kill_enabled ?? 1)) === 1; + // 玩家累计盈利>=安全线时杀分:无论付费/免费,都用 type=1 的 T*_weight;未达到时一律按玩家权重 + // 记录 lottery_config_id:杀分记 type=1;未杀分统一记当前池 type=0 + $usePoolWeights = $killEnabled && $playerProfitTotal >= $safetyLine && $configType1 !== null; + $config = $usePoolWeights ? $configType1 : $configType0; // 按档位 T1-T5 抽取后,从 DiceReward 表按当前方向取该档位数据,再按 weight 抽取一条得到 grid_number $rewardInstance = DiceReward::getCachedInstance(); diff --git a/server/app/dice/logic/lottery_pool_config/DiceLotteryPoolConfigLogic.php b/server/app/dice/logic/lottery_pool_config/DiceLotteryPoolConfigLogic.php index 3910d74..6bdd3c1 100644 --- a/server/app/dice/logic/lottery_pool_config/DiceLotteryPoolConfigLogic.php +++ b/server/app/dice/logic/lottery_pool_config/DiceLotteryPoolConfigLogic.php @@ -34,7 +34,7 @@ class DiceLotteryPoolConfigLogic extends BaseLogic * 获取当前彩金池(type=0)+ 杀分权重为 type=1 的只读展示 * profit_amount 每次从 DB 实时读取;t1_weight~t5_weight 来自 type=1(杀分权重,不可在弹窗内修改) * - * @return array{id:int,name:string,safety_line:int,t1_weight:int,...,t5_weight:int,profit_amount:float} + * @return array{id:int,name:string,safety_line:int,kill_enabled:int,t1_weight:int,...,t5_weight:int,profit_amount:float} */ public function getCurrentPool(): array { @@ -49,6 +49,7 @@ class DiceLotteryPoolConfigLogic extends BaseLogic 'id' => (int) $row0['id'], 'name' => (string) ($row0['name'] ?? ''), 'safety_line' => (int) ($row0['safety_line'] ?? 0), + 'kill_enabled' => (int) ($row0['kill_enabled'] ?? 1), 'profit_amount' => $profitAmount, ]; $row1 = $configType1 ? $configType1->toArray() : []; @@ -61,19 +62,28 @@ class DiceLotteryPoolConfigLogic extends BaseLogic } /** - * 更新当前彩金池:仅允许修改 type=0 的 safety_line(杀分权重来自 type=1,不可在此接口修改) + * 更新当前彩金池:仅允许修改 type=0 的 safety_line、kill_enabled(杀分权重来自 type=1,不可在此接口修改) * - * @param array{safety_line?:int} $data + * @param array{safety_line?:int,kill_enabled?:int} $data */ public function updateCurrentPool(array $data): void { $pool = $this->getCurrentPool(); $id = (int) $pool['id']; - if (!array_key_exists('safety_line', $data)) { + if (!array_key_exists('safety_line', $data) && !array_key_exists('kill_enabled', $data)) { return; } - $safetyLine = (int) $data['safety_line']; - DiceLotteryPoolConfig::where('id', $id)->update(['safety_line' => $safetyLine]); + $update = []; + if (array_key_exists('safety_line', $data)) { + $update['safety_line'] = (int) $data['safety_line']; + } + if (array_key_exists('kill_enabled', $data)) { + $update['kill_enabled'] = ((int) $data['kill_enabled']) === 1 ? 1 : 0; + } + if ($update === []) { + return; + } + DiceLotteryPoolConfig::where('id', $id)->update($update); } /** diff --git a/server/app/dice/model/lottery_pool_config/DiceLotteryPoolConfig.php b/server/app/dice/model/lottery_pool_config/DiceLotteryPoolConfig.php index ac8a77d..a6240c4 100644 --- a/server/app/dice/model/lottery_pool_config/DiceLotteryPoolConfig.php +++ b/server/app/dice/model/lottery_pool_config/DiceLotteryPoolConfig.php @@ -11,13 +11,14 @@ use plugin\saiadmin\basic\think\BaseModel; /** * 色子奖池配置模型 * - * dice_lottery_config 色子奖池配置 + * dice_lottery_pool_config 色子奖池配置 * * @property $id ID * @property $name 名称 * @property $remark 备注 * @property $type 奖池类型 * @property $safety_line 安全线 + * @property $kill_enabled 是否启用杀分:0=关闭 1=开启 * @property $create_time 创建时间 * @property $update_time 修改时间 * @property $t1_weight T1池权重 @@ -39,7 +40,7 @@ class DiceLotteryPoolConfig extends BaseModel * 数据库表名称 * @var string */ - protected $table = 'dice_lottery_config'; + protected $table = 'dice_lottery_pool_config'; /** * 名称 搜索 diff --git a/server/docs/PERFORMANCE_AND_QPS_ANALYSIS.md b/server/docs/PERFORMANCE_AND_QPS_ANALYSIS.md index bce6248..527820d 100644 --- a/server/docs/PERFORMANCE_AND_QPS_ANALYSIS.md +++ b/server/docs/PERFORMANCE_AND_QPS_ANALYSIS.md @@ -115,7 +115,7 @@ Goal: hot paths should hit Redis most of the time, and DB should primarily be fo - In `playStart`, ensure player is loaded once and reused (do not call `DicePlayer::find` multiple times per request). 3. EV update strategy: - - Repeated `UPDATE dice_lottery_config SET ev = ev - ?` on a hot row causes lock contention. + - Repeated `UPDATE dice_lottery_pool_config SET ev = ev - ?` on a hot row causes lock contention. - Better: - Accumulate EV deltas in Redis (per pool or per shard). - Periodic cron job to aggregate Redis deltas back into MySQL in batches. diff --git a/server/docs/PERFORMANCE_AND_QPS_ANALYSIS_CN.md b/server/docs/PERFORMANCE_AND_QPS_ANALYSIS_CN.md index 6fd8d7a..91073a7 100644 --- a/server/docs/PERFORMANCE_AND_QPS_ANALYSIS_CN.md +++ b/server/docs/PERFORMANCE_AND_QPS_ANALYSIS_CN.md @@ -113,7 +113,7 @@ - 在 `playStart` 中,玩家信息应只查询一次:`$player = DicePlayer::find($playerId)`,后续逻辑统一使用 `$player`,避免重复 `find`。 3. **EV 更新策略** - - 频繁在在线请求中执行 `UPDATE dice_lottery_config SET ev = ev - ?`,会造成该行热点锁竞争; + - 频繁在在线请求中执行 `UPDATE dice_lottery_pool_config SET ev = ev - ?`,会造成该行热点锁竞争; - 建议: - 在线请求仅将 EV 变动累加到 Redis 计数器; - 通过定时任务批量同步 Redis 中的统计数据回 MySQL。