refactor(admin): 合并管理后台并移除 apps/agent

- 平台与代理共用 apps/admin,统一登录 manage/auth/login
- 按 userType 展示菜单,修复 token 循环跳转
- 删除独立 apps/agent 前端工程

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-02 17:50:58 +08:00
parent b5dca1bfb1
commit 31737286b9
34 changed files with 363 additions and 255 deletions

View File

@@ -0,0 +1,25 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import api from '../../api';
const bets = ref<unknown[]>([]);
onMounted(async () => {
const { data } = await api.get('/agent/bets');
bets.value = data.data.items;
});
</script>
<template>
<h2>下级注单</h2>
<el-table :data="bets">
<el-table-column prop="betNo" label="注单号" />
<el-table-column label="玩家">
<template #default="{ row }">
{{ (row as { user?: { username: string } }).user?.username }}
</template>
</el-table-column>
<el-table-column prop="stake" label="投注额" />
<el-table-column prop="status" label="状态" />
</el-table>
</template>

View File

@@ -0,0 +1,35 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import api from '../../api';
const summary = ref<Record<string, unknown>>({});
onMounted(async () => {
const { data } = await api.get('/agent/reports/summary');
summary.value = data.data;
});
</script>
<template>
<h2>代理概览</h2>
<el-row :gutter="16" style="margin-top: 16px">
<el-col :span="6">
<el-statistic
title="授信额度"
:value="Number((summary.profile as { creditLimit?: string })?.creditLimit) || 0"
/>
</el-col>
<el-col :span="6">
<el-statistic
title="已用额度"
:value="Number((summary.profile as { usedCredit?: string })?.usedCredit) || 0"
/>
</el-col>
<el-col :span="6">
<el-statistic title="直属玩家" :value="(summary.directPlayerCount as number) || 0" />
</el-col>
<el-col :span="6">
<el-statistic title="今日投注" :value="Number(summary.todayStake) || 0" :precision="2" />
</el-col>
</el-row>
</template>

View File

@@ -0,0 +1,68 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import api from '../../api';
import { ElMessage } from 'element-plus';
const players = ref<unknown[]>([]);
const form = ref({ username: '', password: 'Player@123' });
const depositForm = ref({ playerId: '', amount: 100, requestId: '' });
onMounted(load);
async function load() {
const { data } = await api.get('/agent/players');
players.value = data.data;
}
async function create() {
await api.post('/agent/players', form.value);
ElMessage.success('玩家已创建');
load();
}
async function deposit() {
depositForm.value.requestId = `dep-${Date.now()}`;
await api.post(`/agent/players/${depositForm.value.playerId}/deposit`, {
amount: depositForm.value.amount,
requestId: depositForm.value.requestId,
});
ElMessage.success('上分成功');
load();
}
async function withdraw(playerId: string, amount: number) {
await api.post(`/agent/players/${playerId}/withdraw`, {
amount,
requestId: `wd-${Date.now()}`,
});
ElMessage.success('下分成功');
load();
}
</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>
</template>

View File

@@ -0,0 +1,39 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import api from '../../api';
import { ElMessage } from 'element-plus';
const agents = ref<unknown[]>([]);
const form = ref({ username: '', password: 'Agent@123', creditLimit: 10000 });
onMounted(load);
async function load() {
const { data } = await api.get('/agent/agents');
agents.value = data.data;
}
async function create() {
await api.post('/agent/agents', form.value);
ElMessage.success('下级代理已创建');
load();
}
</script>
<template>
<h2>下级代理仅一级代理可见</h2>
<el-form inline style="margin-bottom: 16px">
<el-input v-model="form.username" placeholder="用户名" />
<el-input-number v-model="form.creditLimit" />
<el-button type="primary" @click="create">创建二级代理</el-button>
</el-form>
<el-table :data="agents">
<el-table-column label="用户名">
<template #default="{ row }">
{{ (row as { user?: { username: string } }).user?.username }}
</template>
</el-table-column>
<el-table-column prop="creditLimit" label="额度" />
<el-table-column prop="usedCredit" label="已用" />
</el-table>
</template>