Files
pk10/App/Views/Admin/water_control.php
T
li 4a94fe36cf feat: 重构代码架构 + 新增报表/跟单/输赢统计功能
- 拆分 HomeController → TransactionController, ReportWebController, FollowPlanController
- 新增 Service 层: TransactionService, ReportService, FollowPlanService
- pk10.php JS 抽离为 4 个独立文件 (sound/race/bet/poll)
- 前台新增报表查询页面 (/report) + 跟单计划页面 (/follow-plan)
- 后台新增跟单计划管理 + 用户输赢明细统计
- 封盘状态显示倒计时 (x:xx)
- 音效仅在开奖弹窗打开时播放
- 路由按模块分组整理
- autoload 支持 App\Services 命名空间
2026-03-27 18:41:06 +08:00

130 lines
6.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div class="p-6">
<h2 class="text-2xl font-bold mb-2">🌊 放水控制 & 投注限额</h2>
<p class="text-gray-500 text-sm mb-6">放水 = 控制玩家胜率。百分比越低,平台赢得越多。设为50%表示公平对赌。</p>
<!-- 平台盈利率目标 -->
<div class="bg-white rounded-xl p-4 shadow mb-6">
<h3 class="font-bold mb-2">🎯 平台盈利率目标</h3>
<div style="display:flex;align-items:center;gap:15px;flex-wrap:wrap">
<span>目标盈利率:</span>
<input type="number" id="targetProfitRate" value="<?=htmlspecialchars($targetProfitRate ?? '15')?>"
min="0" max="100" step="1" class="w-24 border rounded px-2 py-1 text-sm text-center">
<span>%</span>
<button onclick="saveProfitRate()" class="px-4 py-1 bg-purple-500 text-white rounded hover:bg-purple-600 text-sm">保存</button>
<span style="color:#999;font-size:12px">说明:0=取最大利润(原逻辑),15=平台每期目标盈利15%</span>
</div>
</div>
<?php
// 投注类型中文映射
$betTypeLabels = [
// PK10
'rank' => '🏎️ 名次(猜第N名是几号车)',
'bs' => '🔢 大小(名次车号 ≥6大 ≤5小)',
'oe' => '🎯 单双(名次车号的奇偶)',
'dt' => '🐉 龙虎(前名次 vs 后名次比大小)',
'sum' => '➕ 冠亚和值(冠军+亚军车号之和)',
'sum_bs' => '📊 冠亚和大小(和值≥12大 ≤11小)',
// 骰子
'tai' => '🎲 大(总点数 ≥11',
'xiu' => '🎲 小(总点数 ≤10',
'chan' => '🎲 双(总点数为偶数)',
'le' => '🎲 单(总点数为奇数)',
'number' => '🔢 押点数(猜总和具体数字)',
'dice' => '🎯 单骰(猜某颗骰子的点数)',
'combo' => '💎 豹子(三颗相同)',
// Xóc Đĩa
'even' => '⚪ 偶数红',
'odd' => '🔴 奇数红',
'4red' => '🔴🔴🔴🔴 四红',
'4white' => '⚪⚪⚪⚪ 四白',
'big_small' => '🎲 大小',
'odd_even' => '🎲 单双',
];
function getBetLabel($type, $labels) {
return $labels[$type] ?? $type;
}
?>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- 放水配置 -->
<div class="bg-white rounded-xl p-6 shadow">
<h3 class="font-bold mb-2">胜率控制</h3>
<p class="text-gray-400 text-xs mb-4">数值含义:玩家赢的概率百分比。例如 40% = 玩家有40%概率赢,平台抽成约60%。</p>
<div class="space-y-3" id="waterList">
<?php foreach($configs??[] as $c): ?>
<div class="flex items-center gap-3 py-2 border-b">
<span class="flex-1 text-sm" title="<?=htmlspecialchars($c['bet_type'])?>"><?=getBetLabel($c['bet_type'], $betTypeLabels)?></span>
<input type="number" step="0.1" min="0" max="100" value="<?=$c['win_rate_pct']?>" class="w-20 border rounded px-2 py-1 text-sm text-center water-pct" data-type="<?=$c['bet_type']?>" data-game="<?=$c['game_id']?>">
<span class="text-xs text-gray-400">%</span>
<label class="flex items-center gap-1"><input type="checkbox" class="water-enabled" data-type="<?=$c['bet_type']?>" <?=$c['enabled']?'checked':''?>><span class="text-xs">启用</span></label>
</div>
<?php endforeach; ?>
<?php if(empty($configs)): ?>
<div class="text-gray-400 text-sm text-center py-4">暂无放水配置,请先在「游戏与赔率」中配置游戏赔率</div>
<?php endif; ?>
</div>
<button onclick="saveWater()" class="mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 text-sm">💾 保存放水配置</button>
</div>
<!-- 限额配置 -->
<div class="bg-white rounded-xl p-6 shadow">
<h3 class="font-bold mb-2">投注限额</h3>
<p class="text-gray-400 text-xs mb-4">控制每种玩法的单笔最小/最大金额,以及每期总投注上限。</p>
<div class="space-y-3" id="limitList">
<?php foreach($limits??[] as $l): ?>
<div class="flex items-center gap-2 py-2 border-b flex-wrap">
<span class="w-full text-sm mb-1 font-medium" title="<?=htmlspecialchars($l['bet_type'])?>"><?=getBetLabel($l['bet_type'], $betTypeLabels)?></span>
<div class="flex items-center gap-1">
<span class="text-xs text-gray-400">单笔最小:</span>
<input type="number" value="<?=$l['min_amount']?>" class="w-24 border rounded px-2 py-1 text-sm text-center limit-min" data-type="<?=$l['bet_type']?>" data-game="<?=$l['game_id']?>">
</div>
<div class="flex items-center gap-1">
<span class="text-xs text-gray-400">单笔最大:</span>
<input type="number" value="<?=$l['max_amount']?>" class="w-24 border rounded px-2 py-1 text-sm text-center limit-max" data-type="<?=$l['bet_type']?>">
</div>
<div class="flex items-center gap-1">
<span class="text-xs text-gray-400">每期上限:</span>
<input type="number" value="<?=$l['max_per_period']?>" class="w-24 border rounded px-2 py-1 text-sm text-center limit-period" data-type="<?=$l['bet_type']?>">
</div>
</div>
<?php endforeach; ?>
<?php if(empty($limits)): ?>
<div class="text-gray-400 text-sm text-center py-4">暂无限额配置</div>
<?php endif; ?>
</div>
<button onclick="saveLimits()" class="mt-4 px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600 text-sm">💾 保存限额</button>
</div>
</div>
</div>
<script>
async function saveProfitRate(){
const rate=parseFloat(document.getElementById('targetProfitRate').value);
if(isNaN(rate)||rate<0||rate>100){alert('请输入0-100之间的数值');return;}
const r=await fetch('/admin/water/profit-rate',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({target_profit_rate:rate})});
const d=await r.json();alert(d.status==='success'?'盈利率目标保存成功!':d.message);
}
async function saveWater(){
const items=[];
document.querySelectorAll('.water-pct').forEach(el=>{
items.push({game_id:el.dataset.game,bet_type:el.dataset.type,win_rate_pct:parseFloat(el.value),
enabled:document.querySelector('.water-enabled[data-type="'+el.dataset.type+'"]').checked?1:0});
});
const r=await fetch('/admin/water/update',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({items})});
const d=await r.json();alert(d.status==='success'?'保存成功!':d.message);
}
async function saveLimits(){
const items=[];
document.querySelectorAll('.limit-min').forEach(el=>{
const t=el.dataset.type;
items.push({game_id:el.dataset.game,bet_type:t,min_amount:parseFloat(el.value),
max_amount:parseFloat(document.querySelector('.limit-max[data-type="'+t+'"]').value),
max_per_period:parseFloat(document.querySelector('.limit-period[data-type="'+t+'"]').value)});
});
const r=await fetch('/admin/water/limits',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({items})});
const d=await r.json();alert(d.status==='success'?'保存成功!':d.message);
}
</script>