feat(admin): 管理端列表分页、控制台图表与赛事导入

- 玩家/代理/赛事/注单/审计列表分页,默认每页 10 条,无页面滚动条布局

- ECharts 控制台概览、注单管理中文化与列宽优化

- zhibo 赛事字段迁移与导入,玩家编辑可改所属代理

- 管理端 API 分页与 dashboard 统计接口

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-03 13:49:31 +08:00
parent 2c356b2048
commit 80adc0e928
45 changed files with 6564 additions and 499 deletions

View File

@@ -2,6 +2,7 @@
import { ref, onMounted } from 'vue';
import api from '../../api';
import { ElMessage } from 'element-plus';
import { formatAmount, formatAmountFull } from '../../utils/format-amount';
const players = ref<unknown[]>([]);
const form = ref({ username: '', password: 'Player@123' });
@@ -41,28 +42,97 @@ async function withdraw(playerId: string, amount: number) {
</script>
<template>
<h2>直属玩家</h2>
<el-form inline style="margin-bottom: 16px">
<el-input v-model="form.username" placeholder="用户名" />
<el-button type="primary" @click="create">创建玩家</el-button>
</el-form>
<el-form inline style="margin-bottom: 16px">
<el-input v-model="depositForm.playerId" placeholder="玩家ID" style="width: 100px" />
<el-input-number v-model="depositForm.amount" :min="1" />
<el-button type="success" @click="deposit">上分</el-button>
</el-form>
<el-table :data="players">
<el-table-column prop="id" label="ID" />
<el-table-column prop="username" label="用户名" />
<el-table-column label="余额">
<template #default="{ row }">
{{ (row as { wallet?: { availableBalance: string } }).wallet?.availableBalance }}
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="{ row }">
<el-button size="small" @click="withdraw((row as { id: string }).id, 50)">下分50</el-button>
</template>
</el-table-column>
</el-table>
<div class="admin-list-page">
<div class="page-header">
<h2 class="page-title">直属玩家</h2>
<span class="page-desc">管理你名下的直属玩家</span>
</div>
<el-card class="tool-card" shadow="never">
<div class="tool-row">
<div class="tool-section">
<div class="tool-section-title">创建玩家</div>
<el-form inline>
<el-form-item label="用户名">
<el-input v-model="form.username" placeholder="输入用户名" style="width: 150px" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="create">+ 创建玩家</el-button>
</el-form-item>
</el-form>
</div>
<div class="tool-divider" />
<div class="tool-section">
<div class="tool-section-title">上分操作</div>
<el-form inline>
<el-form-item label="玩家ID">
<el-input v-model="depositForm.playerId" placeholder="玩家ID" style="width: 110px" />
</el-form-item>
<el-form-item label="金额">
<el-input-number v-model="depositForm.amount" :min="1" style="width: 130px" />
</el-form-item>
<el-form-item>
<el-button type="success" @click="deposit">上分</el-button>
</el-form-item>
</el-form>
</div>
</div>
</el-card>
<el-card class="data-card" shadow="never">
<div class="table-wrap">
<el-table :data="players" stripe>
<el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="username" label="用户名" min-width="120" />
<el-table-column label="可用余额" min-width="100" align="right">
<template #default="{ row }">
<template v-if="(row as { wallet?: { availableBalance: string } }).wallet?.availableBalance != null">
<el-tooltip
:content="formatAmountFull((row as { wallet: { availableBalance: string } }).wallet.availableBalance)"
placement="top"
>
<span>{{ formatAmount((row as { wallet: { availableBalance: string } }).wallet.availableBalance) }}</span>
</el-tooltip>
</template>
<span v-else></span>
</template>
</el-table-column>
<el-table-column label="操作" width="120" align="center">
<template #default="{ row }">
<el-button size="small" type="warning" plain @click="withdraw((row as { id: string }).id, 50)">下分 50</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-card>
</div>
</template>
<style scoped>
.page-header { display: flex; align-items: baseline; gap: 12px; margin-bottom: 20px; }
.page-title { font-size: 20px; font-weight: 700; color: #e0e0e0; }
.page-desc { font-size: 13px; color: #3a3a3a; }
.tool-card { margin-bottom: 16px; border-radius: 12px; }
.data-card { border-radius: 12px; }
.tool-row {
display: flex;
gap: 0;
align-items: flex-start;
}
.tool-section { flex: 1; padding-right: 24px; }
.tool-section-title {
font-size: 13px;
font-weight: 600;
color: #666;
margin-bottom: 12px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.tool-divider {
width: 1px;
background: #eee;
align-self: stretch;
margin: 0 24px 0 0;
}
</style>