feat: 开户备注、账单展示优化与后台代理管理增强

- 新增初始上分备注(日常上分/开户赠金/自定义)及前后台校验与展示

- 优化钱包流水类型与备注显示,区分管理员/代理/玩家上下分

- 修复登录后语言被后端覆盖的问题,登录时同步当前语言到服务端

- 后台代理/玩家表格操作栏重构,充值订单增加备注列

- 前台个人中心、充值、账单与验证码组件体验优化

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-11 17:23:58 +08:00
parent 10485ecfaf
commit 03e72ca9b2
46 changed files with 3721 additions and 1059 deletions

View File

@@ -4,6 +4,7 @@ import { RouterView, RouterLink, useRoute, useRouter } from 'vue-router';
import { useAuthStore } from '../stores/auth';
import { useAdminLocale } from '../composables/useAdminLocale';
import AdminLocaleSwitcher from '../components/AdminLocaleSwitcher.vue';
import AdminNavIcon from '../components/AdminNavIcon.vue';
import { resolveAdminBreadcrumb } from '../utils/admin-breadcrumb';
const route = useRoute();
@@ -15,24 +16,24 @@ const sidebarOpen = ref(false);
const isMobileNav = ref(false);
const adminMenus = computed(() => [
{ path: '/', label: t('nav.dashboard'), matchPrefix: true },
{ path: '/matches', label: t('nav.matches'), matchPrefix: true },
{ path: '/users', label: t('nav.agents_players') },
{ path: '/finance-logs', label: t('nav.finance_logs') },
{ path: '/deposit', label: t('nav.deposit_manage'), matchPrefix: true },
{ path: '/cashback', label: t('nav.cashback') },
{ path: '/bets', label: t('nav.bets') },
{ path: '/contents', label: t('nav.contents') },
{ path: '/media', label: t('nav.media') },
{ path: '/audit', label: t('nav.audit') },
{ path: '/smoke-tests', label: t('nav.smoke_tests') },
{ path: '/', label: t('nav.dashboard'), icon: 'dashboard', matchPrefix: true },
{ path: '/matches', label: t('nav.matches'), icon: 'matches', matchPrefix: true },
{ path: '/users', label: t('nav.agents_players'), icon: 'users' },
{ path: '/finance-logs', label: t('nav.finance_logs'), icon: 'finance' },
{ path: '/deposit', label: t('nav.deposit_manage'), icon: 'deposit', matchPrefix: true },
{ path: '/cashback', label: t('nav.cashback'), icon: 'cashback' },
{ path: '/bets', label: t('nav.bets'), icon: 'bets' },
{ path: '/contents', label: t('nav.contents'), icon: 'contents' },
{ path: '/media', label: t('nav.media'), icon: 'media' },
{ path: '/audit', label: t('nav.audit'), icon: 'audit' },
{ path: '/smoke-tests', label: t('nav.smoke_tests'), icon: 'smoke-tests' },
]);
const agentMenus = computed(() => [
{ path: '/', label: t('nav.dashboard') },
{ path: '/my-players', label: t('nav.agents_players') },
{ path: '/finance-logs', label: t('nav.finance_logs') },
{ path: '/my-bets', label: t('nav.myBets') },
{ path: '/', label: t('nav.dashboard'), icon: 'dashboard' },
{ path: '/my-players', label: t('nav.agents_players'), icon: 'users' },
{ path: '/finance-logs', label: t('nav.finance_logs'), icon: 'finance' },
{ path: '/my-bets', label: t('nav.myBets'), icon: 'bets' },
]);
const menus = computed(() => (auth.isAdmin.value ? adminMenus.value : agentMenus.value));
@@ -159,7 +160,8 @@ watch(() => route.path, () => {
}"
@click="onNavClick"
>
{{ m.label }}
<AdminNavIcon :name="m.icon" />
<span class="nav-label">{{ m.label }}</span>
</RouterLink>
</nav>
@@ -272,6 +274,7 @@ watch(() => route.path, () => {
.nav-item {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 10px;
border-radius: 6px;
color: #737373;
@@ -280,15 +283,29 @@ watch(() => route.path, () => {
transition: color 0.15s, background 0.15s;
letter-spacing: 0;
}
.nav-item :deep(.admin-nav-icon) {
opacity: 0.72;
transition: opacity 0.15s;
}
.nav-label {
min-width: 0;
line-height: 1.25;
}
.nav-item:hover {
background: rgba(255, 255, 255, 0.04);
color: #d4d4d4;
}
.nav-item:hover :deep(.admin-nav-icon) {
opacity: 0.92;
}
.nav-item.active {
background: rgba(255, 255, 255, 0.06);
color: #f5f5f5;
font-weight: 500;
}
.nav-item.active :deep(.admin-nav-icon) {
opacity: 1;
}
.sidebar-foot {
padding: 10px 10px;