diff --git a/app/admin/controller/game/RewardConfig.php b/app/admin/controller/game/RewardConfig.php index 41974d4..acc70fc 100644 --- a/app/admin/controller/game/RewardConfig.php +++ b/app/admin/controller/game/RewardConfig.php @@ -7,6 +7,8 @@ namespace app\admin\controller\game; use Throwable; use app\common\controller\Backend; use app\common\library\GameRewardConfigTemplate; +use app\common\library\GameRewardTierBoardGenerator; +use app\common\library\GameRewardWeightSeeder; use app\common\model\GameRewardConfig; use app\common\validate\GameRewardConfig as GameRewardConfigValidate; use support\think\Db; @@ -117,6 +119,117 @@ class RewardConfig extends Backend return $this->success(__('Update successful')); } + /** + * 按条数与结算标准生成 26 格档位奖励并保存(保留当前 bigwin_form) + */ + public function generateTierBoard(WebmanRequest $request): Response + { + $response = $this->initializeBackend($request); + if ($response !== null) { + return $response; + } + + if ($request->method() !== 'POST') { + return $this->error(__('Parameter error')); + } + + $data = $request->post(); + if (!$data || !is_array($data)) { + return $this->error(__('Parameter %s can not be empty', [''])); + } + + [$channelId, $err] = $this->resolveTargetChannelId($request, true); + if ($err !== null) { + return $err; + } + + if (!$this->channelExists($channelId)) { + return $this->error(__('Record not found')); + } + + try { + $out = GameRewardTierBoardGenerator::generate($data); + } catch (Throwable $e) { + return $this->error($e->getMessage()); + } + + $tier = $out['tier_reward_form']; + $existing = GameRewardConfig::where('game_channel_id', $channelId)->find(); + if ($existing && is_string($existing->bigwin_form) && trim($existing->bigwin_form) !== '') { + $big = $existing->bigwin_form; + } else { + $defaults = GameRewardConfigTemplate::getDefaultJsonColumns(); + $big = $defaults['bigwin_form']; + } + + try { + $validate = new GameRewardConfigValidate(); + $validate->scene('channel_form')->check([ + 'tier_reward_form' => $tier, + 'bigwin_form' => $big, + ]); + } catch (Throwable $e) { + return $this->error($e->getMessage()); + } + + try { + if ($existing) { + $existing->save([ + 'tier_reward_form' => $tier, + 'bigwin_form' => $big, + ]); + } else { + $m = new GameRewardConfig(); + $m->save([ + 'game_channel_id' => $channelId, + 'tier_reward_form' => $tier, + 'bigwin_form' => $big, + ]); + } + } catch (Throwable $e) { + return $this->error($e->getMessage()); + } + + return $this->success(__('Update successful')); + } + + /** + * 根据当前档位奖励 JSON 生成 game_reward_weight(先清空该渠道再写入 52 条) + */ + public function generateRewardWeight(WebmanRequest $request): Response + { + $response = $this->initializeBackend($request); + if ($response !== null) { + return $response; + } + + if ($request->method() !== 'POST') { + return $this->error(__('Parameter error')); + } + + [$channelId, $err] = $this->resolveTargetChannelId($request, true); + if ($err !== null) { + return $err; + } + + if (!$this->channelExists($channelId)) { + return $this->error(__('Record not found')); + } + + $row = GameRewardConfig::where('game_channel_id', $channelId)->find(); + if (!$row || !is_string($row->tier_reward_form) || trim($row->tier_reward_form) === '') { + return $this->error('请先保存档位奖励配置'); + } + + try { + GameRewardWeightSeeder::syncFromTierRewardForm($channelId, $row->tier_reward_form); + } catch (Throwable $e) { + return $this->error($e->getMessage()); + } + + return $this->success(__('Update successful')); + } + /** * @return array{0: int, 1: Response|null} */ diff --git a/app/common/library/GameRewardTierBoardGenerator.php b/app/common/library/GameRewardTierBoardGenerator.php new file mode 100644 index 0000000..028b69f --- /dev/null +++ b/app/common/library/GameRewardTierBoardGenerator.php @@ -0,0 +1,273 @@ += 0 ? $x : 26 + $start - $d; + } + + /** + * 豹子点数:该次摇取顺、逆落点档位不能为 T4、T5 + * + * @param list $tier + */ + private static function leopardOk(array $tier): bool + { + foreach (self::LEOPARD as $d) { + foreach ([self::landingCw($d), self::landingCcw($d)] as $idx) { + $t = $tier[$idx]; + if ($t === 'T4' || $t === 'T5') { + return false; + } + } + } + + return true; + } + + /** + * @param array $params + * @return array{tier_reward_form: string} + */ + public static function generate(array $params): array + { + $t1Cw = self::intParam($params, 't1_fixed_cw'); + $t1Ccw = self::intParam($params, 't1_fixed_ccw'); + $t2MinCw = self::intParam($params, 't2_min_cw'); + $t2MinCcw = self::intParam($params, 't2_min_ccw'); + $t4Cw = self::intParam($params, 't4_fixed_cw'); + $t4Ccw = self::intParam($params, 't4_fixed_ccw'); + $t5Cw = self::intParam($params, 't5_fixed_cw'); + $t5Ccw = self::intParam($params, 't5_fixed_ccw'); + + $amt1 = self::numParam($params, 'amt_t1'); + $amt2 = self::numParam($params, 'amt_t2'); + $amt3 = self::numParam($params, 'amt_t3'); + $amt4 = self::numParam($params, 'amt_t4'); + + $bestTier = null; + $bestScore = INF; + + for ($attempt = 0; $attempt < 32; $attempt++) { + $tier = self::randomInitialTier($attempt); + $temp = 5.0; + for ($step = 0; $step < 8000; $step++) { + $score = self::score($tier, $t1Cw, $t1Ccw, $t2MinCw, $t2MinCcw, $t4Cw, $t4Ccw, $t5Cw, $t5Ccw); + if ($score < $bestScore) { + $bestScore = $score; + $bestTier = $tier; + } + $i = mt_rand(0, 25); + $j = mt_rand(0, 25); + if ($i === $j) { + continue; + } + $oldI = $tier[$i]; + $oldJ = $tier[$j]; + $tier[$i] = $oldJ; + $tier[$j] = $oldI; + if (!self::leopardOk($tier)) { + $tier[$i] = $oldI; + $tier[$j] = $oldJ; + continue; + } + $newScore = self::score($tier, $t1Cw, $t1Ccw, $t2MinCw, $t2MinCcw, $t4Cw, $t4Ccw, $t5Cw, $t5Ccw); + $delta = $newScore - $score; + $u = mt_rand() / max(1, mt_getrandmax()); + if ($delta < 0 || ($temp > 0.02 && exp(-$delta / $temp) > $u)) { + // keep + } else { + $tier[$i] = $oldI; + $tier[$j] = $oldJ; + } + $temp *= 0.999; + } + } + + if ($bestTier === null || $bestScore > 45) { + throw new \RuntimeException('无法在豹子与条数约束下收敛盘面,请调整条数后重试'); + } + + $json = self::buildJson($bestTier, $amt1, $amt2, $amt3, $amt4); + + return ['tier_reward_form' => $json]; + } + + /** @return list */ + private static function randomInitialTier(int $seedBias): array + { + mt_srand((int) (microtime(true) * 1000000) + $seedBias * 10007); + $tier = []; + for ($p = 0; $p < 26; $p++) { + $tier[$p] = ['T1', 'T2', 'T3'][mt_rand(0, 2)]; + } + if (!self::leopardOk($tier)) { + for ($p = 0; $p < 26; $p++) { + $tier[$p] = 'T3'; + } + } + + return $tier; + } + + /** + * @param list $tier + */ + private static function score( + array $tier, + int $t1Cw, + int $t1Ccw, + int $t2MinCw, + int $t2MinCcw, + int $t4Cw, + int $t4Ccw, + int $t5Cw, + int $t5Ccw + ): float { + if (!self::leopardOk($tier)) { + return 1e9; + } + $h = self::histogram($tier); + $s = 0.0; + $s += ($h['cw']['T1'] - $t1Cw) ** 2; + $s += ($h['ccw']['T1'] - $t1Ccw) ** 2; + $s += max(0, $t2MinCw - $h['cw']['T2']) ** 2 * 8; + $s += max(0, $t2MinCcw - $h['ccw']['T2']) ** 2 * 8; + $s += ($h['cw']['T4'] - $t4Cw) ** 2; + $s += ($h['ccw']['T4'] - $t4Ccw) ** 2; + $s += ($h['cw']['T5'] - $t5Cw) ** 2; + $s += ($h['ccw']['T5'] - $t5Ccw) ** 2; + + return $s; + } + + /** + * @param list $tier + * @return array{cw: array, ccw: array} + */ + private static function histogram(array $tier): array + { + $cw = ['T1' => 0, 'T2' => 0, 'T3' => 0, 'T4' => 0, 'T5' => 0]; + $ccw = ['T1' => 0, 'T2' => 0, 'T3' => 0, 'T4' => 0, 'T5' => 0]; + for ($d = 5; $d <= 30; $d++) { + $cw[$tier[self::landingCw($d)]]++; + $ccw[$tier[self::landingCcw($d)]]++; + } + + return ['cw' => $cw, 'ccw' => $ccw]; + } + + /** + * @param list $tier + */ + private static function remarkForTier(string $t, float $amt2): string + { + if ($t === 'T1') { + return '大奖'; + } + if ($t === 'T2') { + return $amt2 < 100 ? '完美回本' : '小赚'; + } + if ($t === 'T3') { + return '抽水'; + } + if ($t === 'T4') { + return '惩罚'; + } + if ($t === 'T5') { + return '再来一次'; + } + + return ''; + } + + private static function buildJson(array $tier, float $amt1, float $amt2, float $amt3, float $amt4): string + { + $rows = []; + for ($i = 0; $i < 26; $i++) { + $t = $tier[$i]; + if ($t === 'T5') { + $ui = '再来一次'; + $uiEn = 'Once again'; + $ev = '0'; + } else { + $a = match ($t) { + 'T1' => $amt1, + 'T2' => $amt2, + 'T3' => $amt3, + 'T4' => $amt4, + default => $amt3, + }; + $ui = self::fmtMoney($a); + $uiEn = self::fmtMoney($a); + $ev = self::fmtMoney($a); + } + $rows[] = [ + 'grid_number' => strval(5 + $i), + 'ui_text' => $ui, + 'ui_text_en' => $uiEn, + 'real_ev' => $ev, + 'tier' => $t, + 'remark' => self::remarkForTier($t, $amt2), + ]; + } + + return json_encode($rows, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR); + } + + private static function fmtMoney(float $v): string + { + if (abs($v - round($v)) < 0.000001) { + return strval((int) round($v)); + } + + return rtrim(rtrim(sprintf('%.4f', $v), '0'), '.'); + } + + private static function intParam(array $params, string $key): int + { + $v = $params[$key] ?? 0; + if (is_string($v) && trim($v) === '') { + return 0; + } + if (!is_numeric($v)) { + return 0; + } + + return intval(strval($v)); + } + + private static function numParam(array $params, string $key): float + { + $v = $params[$key] ?? 0; + if (is_string($v) && trim($v) === '') { + return 0.0; + } + if (!is_numeric($v)) { + return 0.0; + } + + return floatval(strval($v)); + } +} diff --git a/app/common/library/GameRewardWeightSeeder.php b/app/common/library/GameRewardWeightSeeder.php new file mode 100644 index 0000000..70ded28 --- /dev/null +++ b/app/common/library/GameRewardWeightSeeder.php @@ -0,0 +1,172 @@ + $row) { + if (!is_array($row)) { + throw new \RuntimeException('档位奖励表单第' . strval($idx + 1) . '条格式错误'); + } + $g = $row['grid_number'] ?? null; + if (!is_numeric($g)) { + throw new \RuntimeException('档位奖励表单第' . strval($idx + 1) . '条点数无效'); + } + $gi = intval(strval($g)); + if ($gi < 5 || $gi > 30) { + throw new \RuntimeException('档位奖励表单点数须在 5~30'); + } + $byGrid[$gi] = $row; + } + + $cells = []; + for ($i = 0; $i < 26; $i++) { + $g = 5 + $i; + if (!isset($byGrid[$g])) { + throw new \RuntimeException('档位奖励表单缺少点数 ' . strval($g)); + } + $cells[$i] = self::normalizeCell($byGrid[$g], $i + 1); + } + + self::assertLeopardOk($cells); + + $batch = []; + for ($d = 5; $d <= 30; $d++) { + $start = $d - 5; + $endCw = ($start + $d) % 26; + $x = $start - $d; + $endCcw = $x >= 0 ? $x : 26 + $start - $d; + $batch[] = self::buildInsertRow($gameChannelId, 0, $d, $start, $endCw, $cells[$endCw]); + $batch[] = self::buildInsertRow($gameChannelId, 1, $d, $start, $endCcw, $cells[$endCcw]); + } + + $now = time(); + foreach ($batch as $k => $_) { + $batch[$k]['create_time'] = $now; + $batch[$k]['update_time'] = $now; + } + + Db::startTrans(); + try { + Db::name('game_reward_weight')->where('game_channel_id', $gameChannelId)->delete(); + Db::name('game_reward_weight')->insertAll($batch); + Db::commit(); + } catch (Throwable $e) { + Db::rollback(); + $msg = $e->getMessage(); + if (str_contains($msg, 'game_reward_weight') || str_contains($msg, "doesn't exist")) { + throw new \RuntimeException('写入失败:请确认已创建数据表 game_reward_weight 并已执行迁移。' . $msg); + } + throw $e; + } + } + + /** + * @param list $cells + */ + private static function assertLeopardOk(array $cells): void + { + foreach (self::LEOPARD as $d) { + $start = $d - 5; + $endCw = ($start + $d) % 26; + $x = $start - $d; + $endCcw = $x >= 0 ? $x : 26 + $start - $d; + foreach ([$endCw, $endCcw] as $idx) { + $t = $cells[$idx]['tier']; + if ($t === 'T4' || $t === 'T5') { + throw new \RuntimeException( + '豹子点数 ' . strval($d) . ' 的落点不能为 T4/T5,请先在档位表中调整后再生成权重对照' + ); + } + } + } + } + + /** + * @param array $row + * @return array{ui_text: string, real_ev: float, tier: string, remark: string} + */ + private static function normalizeCell(array $row, int $rowNo): array + { + $ui = $row['ui_text'] ?? null; + $ev = $row['real_ev'] ?? null; + $tier = $row['tier'] ?? null; + if (!is_string($ui) || trim($ui) === '') { + throw new \RuntimeException('档位奖励表单第' . strval($rowNo) . '条显示文本不能为空'); + } + if ($ev === null || $ev === '' || !is_numeric($ev)) { + throw new \RuntimeException('档位奖励表单第' . strval($rowNo) . '条实际中奖无效'); + } + if (!is_string($tier) || !in_array($tier, ['T1', 'T2', 'T3', 'T4', 'T5'], true)) { + throw new \RuntimeException('档位奖励表单第' . strval($rowNo) . '条档位无效'); + } + $remark = $row['remark'] ?? ''; + $remarkStr = is_string($remark) ? $remark : ''; + + return [ + 'ui_text' => $ui, + 'real_ev' => floatval(strval($ev)), + 'tier' => $tier, + 'remark' => $remarkStr, + ]; + } + + /** + * @param array{ui_text: string, real_ev: float, tier: string, remark: string} $cell + * @return array + */ + private static function buildInsertRow( + int $gameChannelId, + int $direction, + int $gridNumber, + int $startIndex, + int $endIndex, + array $cell + ): array { + return [ + 'game_channel_id' => $gameChannelId, + 'direction' => $direction, + 'grid_number' => $gridNumber, + 'start_index' => $startIndex, + 'end_index' => $endIndex, + 'ui_text' => $cell['ui_text'], + 'real_ev' => $cell['real_ev'], + 'tier' => $cell['tier'], + 'type' => self::tierToType($cell['tier']), + 'remark' => $cell['remark'], + 'weight' => 1, + ]; + } + + private static function tierToType(string $tier): int + { + return match ($tier) { + 'T1' => 3, + 'T2' => 2, + 'T3' => -1, + 'T4' => -2, + 'T5' => 1, + }; + } +} diff --git a/web/src/lang/backend/en/game/rewardConfig.ts b/web/src/lang/backend/en/game/rewardConfig.ts index 168d66d..48cbf85 100644 --- a/web/src/lang/backend/en/game/rewardConfig.ts +++ b/web/src/lang/backend/en/game/rewardConfig.ts @@ -8,6 +8,8 @@ export default { update_time: 'update_time', grid_number: 'grid_number', ui_text: 'ui_text', + ui_text_en: 'ui_text (EN)', + remark: 'remark', real_ev: 'real_ev', tier: 'tier', tier_t1: 'T1', @@ -16,7 +18,8 @@ export default { tier_t4: 'T4', tier_t5: 'T5', tier_bigwin: 'BIGWIN', - tier_reward_form_help: 'Fixed 26 rows (5-30), no add/delete. Editable: ui_text, real_ev, tier.', + tier_reward_form_help: + 'Fixed 26 rows (5-30), no add/delete. Editable: ui_text, ui_text_en, real_ev, tier, remark.', bigwin_form_help: 'Fixed 6 rows (5,10,15,20,25,30), no add/delete. Editable: ui_text, real_ev.', 'quick Search Fields': 'id', } diff --git a/web/src/lang/backend/en/game/rewardConfigForm.ts b/web/src/lang/backend/en/game/rewardConfigForm.ts index c3a95ec..0674e8e 100644 --- a/web/src/lang/backend/en/game/rewardConfigForm.ts +++ b/web/src/lang/backend/en/game/rewardConfigForm.ts @@ -8,4 +8,39 @@ export default { super_scope_hint: 'Pick a channel below, then click Refresh to load.', btn_add: 'Save', btn_reset: 'Reset', + btn_gen_tier: 'Generate tier board', + btn_gen_weight: 'Generate reward weight table', + gen_tier_title: 'Generate reward index by rules', + gen_tier_rule: + '[Same logic as reward comparison]\n' + + '• 26 cells id 0–25; grid_number 5–30 unique.\n' + + '• Roll D: start_index = id where grid_number=D; CW end=(start+D)%26; CCW end=start−D, if <0 then +26.\n' + + '• Comparison rows use D as dice points; tier/settlement/copy from landing cell.\n\n' + + '[Leopard rolls]\n' + + 'For D in 5,10,15,20,25,30, CW/CCW landing tier cannot be T4/T5.\n\n' + + '[Settlement vs tier]\n' + + '<0→T4; 0–100→T3; 100–200→T2; >200→T1; T5 amount 0. Below you set per-tier amounts; T1–T4 zh/en display text = amount string; T5 fixed.\n\n' + + '[Inputs]\n' + + 'Counts: T1/T4/T5 fixed per direction; T2 minimum per direction.', + gen_tier_footer_hint: 'T2 is a lower bound; if generation fails, relax counts. You can still edit the table after.', + gen_tier_cancel: 'Cancel', + gen_tier_submit: 'Generate and save', + gen_t1_label: 'T1 grand prize', + gen_t1_fixed: 'Fixed count (CW/CCW)', + gen_t2_label: 'T2 small profit / break-even', + gen_t2_min: 'Minimum count', + gen_t3_label: 'T3 commission', + gen_t3_amt_only: 'Settlement amount', + gen_t4_label: 'T4 penalty', + gen_t4_fixed: 'Fixed count (CW/CCW)', + gen_t5_label: 'T5 try again', + gen_t5_fixed: 'Fixed count (CW/CCW)', + gen_settlement: 'Settlement amount', + gen_dir_cw: 'Clockwise', + gen_dir_ccw: 'Counter-clockwise', + gen_weight_confirm_title: 'Create reward comparison', + gen_weight_confirm_body: + 'Rules: start_index = id of the cell whose grid_number equals roll D; CW end_index=(start_index+D)%26; CCW end_index = start_index−D if ≥0 else 26+start_index−D. Existing rows for this channel in game_reward_weight will be deleted, then 52 rows created (D=5..30 × two directions). Tier, settlement, display text and remark come from the landing cell in the tier table. Continue?', + gen_weight_confirm_ok: 'Confirm', + gen_weight_need_channel: 'Select a channel and refresh before generating weights.', } diff --git a/web/src/lang/backend/zh-cn/game/rewardConfig.ts b/web/src/lang/backend/zh-cn/game/rewardConfig.ts index 39593ce..a8fed81 100644 --- a/web/src/lang/backend/zh-cn/game/rewardConfig.ts +++ b/web/src/lang/backend/zh-cn/game/rewardConfig.ts @@ -8,6 +8,8 @@ export default { update_time: '更新时间', grid_number: '色子点数', ui_text: '显示文本', + ui_text_en: '显示文本(en)', + remark: '备注', real_ev: '实际中奖', tier: '档位', tier_t1: 'T1', @@ -16,7 +18,8 @@ export default { tier_t4: 'T4', tier_t5: 'T5', tier_bigwin: 'BIGWIN', - tier_reward_form_help: '固定 26 条(点数 5-30),不可新增或删除,仅可修改显示文本、实际中奖、档位', + tier_reward_form_help: + '固定 26 条(点数 5-30),不可新增或删除;可修改显示文本、英文显示、实际中奖、档位与备注(生成器会预填英文与备注)', bigwin_form_help: '固定 6 条(点数 5、10、15、20、25、30),不可新增或删除,仅可修改显示文本、实际中奖', 'quick Search Fields': 'ID', } diff --git a/web/src/lang/backend/zh-cn/game/rewardConfigForm.ts b/web/src/lang/backend/zh-cn/game/rewardConfigForm.ts index 1f04760..970a7d3 100644 --- a/web/src/lang/backend/zh-cn/game/rewardConfigForm.ts +++ b/web/src/lang/backend/zh-cn/game/rewardConfigForm.ts @@ -8,4 +8,41 @@ export default { super_scope_hint: '选择「指定渠道」后请在下拉框中选择具体渠道并点击刷新加载。', btn_add: '新增', btn_reset: '重置', + btn_gen_tier: '生成游戏奖励配置', + btn_gen_weight: '生成游戏奖励权重配置', + gen_tier_title: '按规则生成奖励索引', + gen_tier_rule: + '【生成逻辑(与创建奖励对照一致)】\n' + + '• 盘面 26 格按 id 升序为位置 0~25;每条配置的 grid_number 为 5~30 且不重复。\n' + + '• 摇取点数 D(5~30):起点为「grid_number=D」所在格位的 id(start_index),顺时针落点 = (起点 + D) mod 26,逆时针落点 = 起点 − D(若小于 0 则 +26)。\n' + + '• 对照表每条记录的「色子点数」列为 D;档位、真实结算、显示文案取自落点格位对应 id 的配置。\n\n' + + '【豹子摇取点数】\n' + + '摇取点数为 5、10、15、20、25、30 时,其顺/逆时针落点档位不能为 T4、T5。\n\n' + + '【结算金额与档位】\n' + + '结算金额 < 0 → T4;0 < 结算金额 < 100 → T3;100 < 结算金额 < 200 → T2;200 < 结算金额 → T1;T5 结算金额=0。\n' + + '下方填写各档位统一结算金额标准;T1~T4 的中/英文显示文本将等于该金额字符串;T5 固定「再来一次」/「Once again」。\n\n' + + '【本弹窗输入】\n' + + '条数:T1/T4/T5 为顺时针与逆时针各自的固定条数;T2 为顺时针与逆时针各自「不少于」的条数。生成后仍可在主表中微调。', + gen_tier_footer_hint: + 'T1/T4/T5 为精确条数,T2 为下限;生成失败时请放宽条数或稍后再试。生成后可在上方表格中继续修改。', + gen_tier_cancel: '取消', + gen_tier_submit: '生成并保存', + gen_t1_label: 'T1 大奖', + gen_t1_fixed: '固定条数(顺/逆)', + gen_t2_label: 'T2 小赚/回本', + gen_t2_min: '最少条数', + gen_t3_label: 'T3 抽水', + gen_t3_amt_only: '结算金额', + gen_t4_label: 'T4 惩罚', + gen_t4_fixed: '固定条数(顺/逆)', + gen_t5_label: 'T5 再来一次', + gen_t5_fixed: '固定条数(顺/逆)', + gen_settlement: '结算金额', + gen_dir_cw: '顺时针', + gen_dir_ccw: '逆时针', + gen_weight_confirm_title: '创建奖励对照', + gen_weight_confirm_body: + '按规则创建奖励对照:起始索引 start_index 为奖励配置中 grid_number 与摇取点数 D 相同的那一格的 id;顺时针 end_index=(start_index+摇取点数)%26;逆时针 end_index=start_index−摇取点数,若≥0 则取该值,否则 26+start_index−摇取点数。将先清空该渠道 game_reward_weight 表中现有数据,再为 5~30 共 26 个点数、顺/逆时针各生成一条(共 52 条)。档位、真实结算、显示文案、备注取自落点格位在档位表中的配置。是否继续?', + gen_weight_confirm_ok: '确定创建', + gen_weight_need_channel: '请先选择具体渠道并刷新后再生成权重对照。', } diff --git a/web/src/views/backend/game/rewardConfig/index.vue b/web/src/views/backend/game/rewardConfig/index.vue index 17007c5..7152ead 100644 --- a/web/src/views/backend/game/rewardConfig/index.vue +++ b/web/src/views/backend/game/rewardConfig/index.vue @@ -27,8 +27,8 @@ + + + +
{{ t('game.rewardConfigForm.gen_tier_rule') }}
+ +
+
{{ t('game.rewardConfigForm.gen_t1_label') }}
+ + + + + + + + + +
+
+
{{ t('game.rewardConfigForm.gen_t2_label') }}
+ + + + + + + + + +
+
+
{{ t('game.rewardConfigForm.gen_t3_label') }}
+ + + +
+
+
{{ t('game.rewardConfigForm.gen_t4_label') }}
+ + + + + + + + + +
+
+
{{ t('game.rewardConfigForm.gen_t5_label') }}
+ + + + + + + + + +
+
+ +
+ +
+ + +