- 拆分 HomeController → TransactionController, ReportWebController, FollowPlanController - 新增 Service 层: TransactionService, ReportService, FollowPlanService - pk10.php JS 抽离为 4 个独立文件 (sound/race/bet/poll) - 前台新增报表查询页面 (/report) + 跟单计划页面 (/follow-plan) - 后台新增跟单计划管理 + 用户输赢明细统计 - 封盘状态显示倒计时 (x:xx) - 音效仅在开奖弹窗打开时播放 - 路由按模块分组整理 - autoload 支持 App\Services 命名空间
153 lines
8.7 KiB
PHP
153 lines
8.7 KiB
PHP
<h1 class="text-2xl font-bold text-gray-800 mb-6 flex items-center">
|
|
<i class="fas fa-clipboard-list text-primary mr-3"></i>
|
|
跟单计划管理
|
|
</h1>
|
|
|
|
<!-- 新建按钮 -->
|
|
<div class="mb-4">
|
|
<button onclick="showAddForm()" class="px-5 py-2 bg-primary text-white rounded-lg text-sm hover:opacity-90 transition">
|
|
<i class="fas fa-plus mr-1"></i> 新建计划
|
|
</button>
|
|
</div>
|
|
|
|
<!-- 计划列表 -->
|
|
<div class="bg-white rounded-xl shadow-md p-6 mb-6">
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full bg-white rounded-xl overflow-hidden">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">ID</th>
|
|
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">计划名称</th>
|
|
<th class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase">类型</th>
|
|
<th class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase">名次</th>
|
|
<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase">建议金额</th>
|
|
<th class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase">总期数</th>
|
|
<th class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase">胜率</th>
|
|
<th class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase">跟单人数</th>
|
|
<th class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase">状态</th>
|
|
<th class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase">操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-gray-200">
|
|
<?php if (!empty($plans)): ?>
|
|
<?php foreach ($plans as $p): ?>
|
|
<tr class="hover:bg-gray-50 transition-colors">
|
|
<td class="px-4 py-3 text-sm text-gray-500"><?= $p['id'] ?></td>
|
|
<td class="px-4 py-3 text-sm font-medium text-gray-900"><?= htmlspecialchars($p['name']) ?></td>
|
|
<td class="px-4 py-3 text-sm text-center">
|
|
<span class="inline-flex items-center px-2 py-1 rounded-full text-xs bg-primary/10 text-primary">
|
|
<?= ['bs'=>'大小','oe'=>'单双','dt'=>'龙虎','sum_bs'=>'冠亚大小'][$p['plan_type']] ?? $p['plan_type'] ?>
|
|
</span>
|
|
</td>
|
|
<td class="px-4 py-3 text-sm text-center"><?= $p['target_rank'] ?></td>
|
|
<td class="px-4 py-3 text-sm text-right"><?= number_format($p['bet_amount'], 2) ?></td>
|
|
<td class="px-4 py-3 text-sm text-center"><?= $p['total_records'] ?></td>
|
|
<td class="px-4 py-3 text-sm text-center">
|
|
<span class="inline-flex items-center px-2 py-1 rounded-full text-xs <?= $p['win_rate'] >= 50 ? 'bg-success/10 text-success' : 'bg-danger/10 text-danger' ?>">
|
|
<?= $p['win_rate'] ?>%
|
|
</span>
|
|
</td>
|
|
<td class="px-4 py-3 text-sm text-center font-semibold"><?= $p['follower_count'] ?></td>
|
|
<td class="px-4 py-3 text-sm text-center">
|
|
<span class="inline-flex items-center px-2 py-1 rounded-full text-xs cursor-pointer <?= $p['status'] ? 'bg-success/10 text-success' : 'bg-gray-200 text-gray-500' ?>"
|
|
onclick="togglePlan(<?= $p['id'] ?>)">
|
|
<?= $p['status'] ? '启用' : '禁用' ?>
|
|
</span>
|
|
</td>
|
|
<td class="px-4 py-3 text-sm text-center">
|
|
<button onclick='editPlan(<?= json_encode($p) ?>)' class="text-primary hover:underline text-xs mr-2">编辑</button>
|
|
<button onclick="deletePlan(<?= $p['id'] ?>)" class="text-danger hover:underline text-xs">删除</button>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php else: ?>
|
|
<tr>
|
|
<td colspan="10" class="px-6 py-12 text-center">
|
|
<div class="flex flex-col items-center">
|
|
<i class="fas fa-clipboard-list text-gray-300 text-5xl mb-4"></i>
|
|
<h3 class="text-lg font-medium text-gray-900">暂无跟单计划</h3>
|
|
<p class="mt-1 text-gray-500 text-sm">点击上方按钮新建跟单计划</p>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/Static/js/admin.js"></script>
|
|
<script>
|
|
var planTypes = {bs:'大小', oe:'单双', dt:'龙虎', sum_bs:'冠亚大小'};
|
|
|
|
function showAddForm(data) {
|
|
var isEdit = data && data.id;
|
|
var html = '<div style="padding:20px">' +
|
|
'<div style="margin-bottom:12px"><label style="display:block;margin-bottom:4px;font-size:13px;color:#666">计划名称</label>' +
|
|
'<input type="text" id="fp_name" value="' + (data ? data.name : '') + '" class="layui-input" style="width:100%"></div>' +
|
|
'<div style="display:flex;gap:12px;margin-bottom:12px">' +
|
|
'<div style="flex:1"><label style="display:block;margin-bottom:4px;font-size:13px;color:#666">类型</label>' +
|
|
'<select id="fp_type" class="layui-input">' +
|
|
'<option value="bs"' + (data && data.plan_type === 'bs' ? ' selected' : '') + '>大小</option>' +
|
|
'<option value="oe"' + (data && data.plan_type === 'oe' ? ' selected' : '') + '>单双</option>' +
|
|
'<option value="dt"' + (data && data.plan_type === 'dt' ? ' selected' : '') + '>龙虎</option>' +
|
|
'<option value="sum_bs"' + (data && data.plan_type === 'sum_bs' ? ' selected' : '') + '>冠亚大小</option>' +
|
|
'</select></div>' +
|
|
'<div style="flex:1"><label style="display:block;margin-bottom:4px;font-size:13px;color:#666">目标名次</label>' +
|
|
'<input type="number" id="fp_rank" min="1" max="10" value="' + (data ? data.target_rank : 1) + '" class="layui-input"></div>' +
|
|
'</div>' +
|
|
'<div style="margin-bottom:12px"><label style="display:block;margin-bottom:4px;font-size:13px;color:#666">建议投注金额</label>' +
|
|
'<input type="number" id="fp_amount" value="' + (data ? data.bet_amount : 100) + '" class="layui-input"></div>' +
|
|
'</div>';
|
|
|
|
layui.use('layer', function() {
|
|
layui.layer.open({
|
|
type: 1, title: isEdit ? '编辑计划' : '新建计划',
|
|
area: ['420px', '360px'], content: html,
|
|
btn: ['保存', '取消'],
|
|
yes: function(index) {
|
|
var postData = {
|
|
name: document.getElementById('fp_name').value,
|
|
plan_type: document.getElementById('fp_type').value,
|
|
target_rank: document.getElementById('fp_rank').value,
|
|
bet_amount: document.getElementById('fp_amount').value,
|
|
game_id: 1, status: 1
|
|
};
|
|
if (isEdit) postData.id = data.id;
|
|
fetch('/admin/follow-plans/save', {
|
|
method: 'POST', headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify(postData)
|
|
}).then(function(r) { return r.json(); }).then(function(d) {
|
|
if (d.success) { layui.layer.close(index); location.reload(); }
|
|
else { layui.layer.msg(d.message || '保存失败'); }
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function editPlan(plan) { showAddForm(plan); }
|
|
|
|
function togglePlan(id) {
|
|
fetch('/admin/follow-plans/toggle', {
|
|
method: 'POST', headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({id: id})
|
|
}).then(function(r) { return r.json(); }).then(function(d) {
|
|
if (d.success) location.reload();
|
|
});
|
|
}
|
|
|
|
function deletePlan(id) {
|
|
layui.use('layer', function() {
|
|
layui.layer.confirm('确定删除此计划?所有相关记录将被清除。', function(index) {
|
|
fetch('/admin/follow-plans/delete', {
|
|
method: 'POST', headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({id: id})
|
|
}).then(function(r) { return r.json(); }).then(function(d) {
|
|
if (d.success) { layui.layer.close(index); location.reload(); }
|
|
});
|
|
});
|
|
});
|
|
}
|
|
</script>
|