diff --git a/.gitignore b/.gitignore index 84576aa..007e23a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ node_modules/ dist/ +.pnpm-store/ +release/ .claude/ *.log .DS_Store diff --git a/apps/admin/src/App.vue b/apps/admin/src/App.vue index 9a78bba..625b410 100644 --- a/apps/admin/src/App.vue +++ b/apps/admin/src/App.vue @@ -659,8 +659,7 @@ body { border-color: #2a2a2a !important; } .user-edit-dialog .el-dialog__body, -.agent-edit-dialog .el-dialog__body, -.create-account-dialog .el-dialog__body { +.agent-edit-dialog .el-dialog__body { max-height: min(70vh, 640px); overflow-y: auto; } diff --git a/apps/admin/src/components/PlayerWalletLedgerDialog.vue b/apps/admin/src/components/PlayerWalletLedgerDialog.vue new file mode 100644 index 0000000..871bfb4 --- /dev/null +++ b/apps/admin/src/components/PlayerWalletLedgerDialog.vue @@ -0,0 +1,285 @@ + + + + + diff --git a/apps/admin/src/i18n/admin-messages.ts b/apps/admin/src/i18n/admin-messages.ts index f851ca0..1a5ae7b 100644 --- a/apps/admin/src/i18n/admin-messages.ts +++ b/apps/admin/src/i18n/admin-messages.ts @@ -47,7 +47,7 @@ const zh: Record = { 'nav.smoke_tests': '自动化测试', 'nav.media': '媒体库', 'nav.players': '直属玩家', - 'nav.subAgents': '下级代理', + 'nav.subAgents': '二级代理', 'nav.myBets': '注单查询', 'nav.open_menu': '打开菜单', 'nav.close_menu': '关闭菜单', @@ -174,7 +174,7 @@ const zh: Record = { 'agent_dash.liability_child': '下级代理占用', 'page.agent_players.title': '直属玩家', 'page.agent_players.desc': '管理你名下的直属玩家', - 'page.agent_sub.title': '下级代理', + 'page.agent_sub.title': '二级代理', 'page.agent_sub.desc': '管理二级代理账号与授信分配', 'page.agent_bets.title': '注单查询', 'page.agent_bets.desc': '下级玩家的全部投注记录', @@ -247,7 +247,7 @@ const en: Record = { 'nav.smoke_tests': 'Smoke tests', 'nav.media': 'Media Library', 'nav.players': 'My Players', - 'nav.subAgents': 'Sub-Agents', + 'nav.subAgents': 'Tier-2 agents', 'nav.myBets': 'Bet Search', 'nav.open_menu': 'Open menu', 'nav.close_menu': 'Close menu', @@ -374,7 +374,7 @@ const en: Record = { 'agent_dash.liability_child': 'Sub-agent exposure', 'page.agent_players.title': 'My players', 'page.agent_players.desc': 'Players under your account', - 'page.agent_sub.title': 'Sub-agents', + 'page.agent_sub.title': 'Tier-2 agents', 'page.agent_sub.desc': 'Manage tier-2 agents and credit allocation', 'page.agent_bets.title': 'Bet search', 'page.agent_bets.desc': 'All bets from downstream players', @@ -447,7 +447,7 @@ const ms: Record = { 'nav.smoke_tests': 'Ujian asap', 'nav.media': 'Perpustakaan Media', 'nav.players': 'Pemain saya', - 'nav.subAgents': 'Sub-ejen', + 'nav.subAgents': 'Ejen peringkat 2', 'nav.myBets': 'Carian pertaruhan', 'nav.open_menu': 'Buka menu', 'nav.close_menu': 'Tutup menu', @@ -574,7 +574,7 @@ const ms: Record = { 'agent_dash.liability_child': 'Pendedahan ejen bawahan', 'page.agent_players.title': 'Pemain saya', 'page.agent_players.desc': 'Pemain di bawah akaun anda', - 'page.agent_sub.title': 'Sub-ejen', + 'page.agent_sub.title': 'Ejen peringkat 2', 'page.agent_sub.desc': 'Urus ejen peringkat 2 dan peruntukan kredit', 'page.agent_bets.title': 'Carian pertaruhan', 'page.agent_bets.desc': 'Semua pertaruhan pemain hiliran', diff --git a/apps/admin/src/i18n/admin-pages-ms.ts b/apps/admin/src/i18n/admin-pages-ms.ts index b142bd3..7927bb3 100644 --- a/apps/admin/src/i18n/admin-pages-ms.ts +++ b/apps/admin/src/i18n/admin-pages-ms.ts @@ -100,13 +100,21 @@ export const adminPagesMs: Record = { 'user.field.account_type': 'Jenis akaun', 'user.type.player': 'Pemain', 'user.type.tier1_agent': 'Ejen peringkat 1', - 'user.type.sub_agent': 'Sub-ejen', + 'user.type.sub_agent': 'Ejen peringkat 2', 'user.hint.account_type': 'Ejen guna had kredit; pemain boleh di bawah ejen', 'agent.create_btn': '+ Ejen peringkat 1 baharu', 'agent.create_sub_btn': '+ Ejen peringkat 2 baharu', - 'agent.create_sub': 'Cipta sub-ejen', - 'agent.hint.sub_agent_parent': 'Ejen peringkat 2 mesti di bawah ejen peringkat 1', + 'agent.create_sub': 'Cipta ejen peringkat 2', + 'agent.create_child_btn': '+ Sub-ejen baharu', + 'agent.dialog.create_child_agent': 'Sub-ejen baharu', + 'agent.create_level_agent': 'Cipta ejen peringkat {level}', + 'agent.create_level_agent_btn': '+ Ejen peringkat {level} baharu', + 'agent.level_name': 'Ejen peringkat {level}', + 'agent.level_tab': 'Ejen peringkat {level}', + 'agent.dialog.create_level_agent': 'Ejen peringkat {level} baharu', + 'agent.hint.select_parent_for_level': 'Pilih ejen peringkat {level} sebagai induk', + 'agent.err.parent_level_mismatch': 'Peringkat induk tidak sah untuk cipta ejen peringkat {level}', 'agent.hint.creating_under_agent': 'Cipta akaun di bawah ejen ini', 'agent.filter.username_ph': 'Nama pengguna', 'agent_mgr.tab.players': 'Pemain', @@ -150,6 +158,37 @@ export const adminPagesMs: Record = { 'agent.credit_tx.view_all': 'Lihat semua lejar kredit', 'finance.tab.credit': 'Lejar kredit', 'finance.tab.transfer': 'Lejar pemindahan', + 'finance.tab.wallet': 'Lejar dompet', + 'finance.filter.type_category': 'Jenis transaksi', + 'finance.filter.type_category_all': 'Semua', + 'finance.filter.type_category_deposit': 'Pemindahan', + 'finance.filter.type_category_bet': 'Pertaruhan', + 'finance.filter.type_category_cashback': 'Rebat', + 'finance.col.frozen_before': 'Beku sebelum', + 'finance.col.frozen_after': 'Beku selepas', + 'finance.col.reference': 'Pertaruhan berkaitan', + 'finance.tx.adjust': 'Pelarasan baki', + 'finance.tx.bet_freeze': 'Beku pertaruhan', + 'finance.tx.bet_deduct': 'Potong pertaruhan', + 'finance.tx.bet_win': 'Bayaran pertaruhan', + 'finance.tx.bet_lose': 'Penyelesaian pertaruhan', + 'finance.tx.bet_push': 'Refund seri', + 'finance.tx.bet_refund': 'Refund pertaruhan', + 'finance.tx.bet_void': 'Pertaruhan batal', + 'finance.tx.cashback': 'Rebat', + 'finance.tx.resettle': 'Penyelesaian semula', + 'user.action.view_wallet_ledger': 'Lihat lejar dompet', + 'user.wallet_ledger_dialog_title': 'Lejar dompet — {name}', + 'agent.hierarchy.settings_title': 'Hierarki ejen', + 'agent.hierarchy.settings_hint': '0 bermaksud tanpa had. Ejen di had atas tidak boleh cipta sub-ejen.', + 'agent.hierarchy.max_level': 'Tahap ejen maksimum', + 'agent.hierarchy.default_sub_credit_ratio': 'Nisbah kredit sub-ejen lalai', + 'agent.hierarchy.create_credit_default_hint': 'Lalai {ratio}% ({amount}), tidak melebihi kredit induk; boleh diselaraskan', + 'agent.hierarchy.create_credit_quick_hint': 'Kredit induk tersedia {amount} — klik nisbah untuk isi', + 'agent.hierarchy.create_level_hint': 'Akan dicipta sebagai ejen peringkat {n}', + 'agent.field.parent_agent': 'Ejen induk', + 'agent.col.parent_chain': 'Rantaian induk', + 'role.agent_level': 'Ejen peringkat {n}', 'finance.filter.date_range': 'Julat tarikh', 'finance.filter.player_ph': 'Nama pengguna pemain', 'finance.filter.parent_agent_ph': 'Nama/ID ejen induk', diff --git a/apps/admin/src/i18n/admin-pages.ts b/apps/admin/src/i18n/admin-pages.ts index 5bb97bd..f74a883 100644 --- a/apps/admin/src/i18n/admin-pages.ts +++ b/apps/admin/src/i18n/admin-pages.ts @@ -106,13 +106,21 @@ export const adminPagesZh: Record = { 'agent.create_btn': '+ 新建一级代理', 'agent.create_sub_btn': '+ 新建二级代理', 'agent.create_sub': '创建二级代理', - 'agent.hint.sub_agent_parent': '二级代理必须挂靠在一级代理名下', + 'agent.create_child_btn': '+ 新建下级代理', + 'agent.dialog.create_child_agent': '新建下级代理', + 'agent.create_level_agent': '创建{level}级代理', + 'agent.create_level_agent_btn': '+ 新建{level}级代理', + 'agent.level_name': '{level}级代理', + 'agent.level_tab': '{level}级代理', + 'agent.dialog.create_level_agent': '新建{level}级代理', + 'agent.hint.select_parent_for_level': '请选择 {level} 级代理作为上级', + 'agent.err.parent_level_mismatch': '上级代理层级不正确,无法创建 {level} 级代理', 'agent.hint.creating_under_agent': '在此代理下创建账号', 'agent.filter.username_ph': '用户名', 'agent_mgr.tab.players': '玩家', 'agent_mgr.tab.agents': '代理', 'agent.col.level': '层级', - 'agent.col.credit': '授信 / 已用 / 可用', + 'agent.col.credit': '授信/已用/可用', 'agent.col.direct_players': '直属玩家', 'agent.direct_players_title': '直属玩家 · {name}', 'agent.platform_row_name': '平台', @@ -153,6 +161,38 @@ export const adminPagesZh: Record = { 'agent.credit_tx.view_all': '查看全部额度流水', 'finance.tab.credit': '额度流水', 'finance.tab.transfer': '上下分流水', + 'finance.tab.wallet': '钱包流水', + 'finance.filter.type_category': '流水类型', + 'finance.filter.type_category_all': '全部', + 'finance.filter.type_category_deposit': '上下分', + 'finance.filter.type_category_bet': '投注', + 'finance.filter.type_category_cashback': '返水', + 'finance.col.frozen_before': '变动前冻结', + 'finance.col.frozen_after': '变动后冻结', + 'finance.col.reference': '关联注单', + 'finance.tx.adjust': '余额调整', + 'finance.tx.bet_freeze': '投注冻结', + 'finance.tx.bet_deduct': '投注扣款', + 'finance.tx.bet_win': '投注派彩', + 'finance.tx.bet_lose': '投注结算', + 'finance.tx.bet_push': '走水返还', + 'finance.tx.bet_refund': '投注退款', + 'finance.tx.bet_void': '注单作废', + 'finance.tx.cashback': '返水', + 'finance.tx.resettle': '重结算调整', + 'user.action.view_wallet_ledger': '查看资金流水', + 'user.wallet_ledger_dialog_title': '{name} 的资金流水', + 'agent.hierarchy.settings_title': '代理层级设置', + 'agent.hierarchy.settings_hint': '0 表示不限制代理层级;达到上限的代理将无法创建下级。下级默认授信比例用于创建下级代理时的预填额度。', + 'agent.hierarchy.max_level': '最大代理层级', + 'agent.hierarchy.default_sub_credit_ratio': '下级默认授信比例', + 'agent.hierarchy.default_sub_credit_ratio_hint': '创建下级代理时,授信额度默认预填为上级可用授信 × 此比例', + 'agent.hierarchy.create_credit_default_hint': '默认 {ratio}%({amount}),不超过上级可用授信,可手动调整', + 'agent.hierarchy.create_credit_quick_hint': '上级可用授信 {amount},点击比例快速填入', + 'agent.hierarchy.create_level_hint': '将创建为 {n} 级代理', + 'agent.field.parent_agent': '上级代理', + 'agent.col.parent_chain': '上级链路', + 'role.agent_level': '{n}级代理', 'finance.filter.date_range': '时间范围', 'finance.filter.player_ph': '玩家用户名', 'finance.filter.parent_agent_ph': '上级代理用户名或 ID', @@ -176,17 +216,15 @@ export const adminPagesZh: Record = { 'agent.field.select_user': '选择用户', 'agent.ph.select_user': '搜索玩家用户名', 'agent.hint.select_user': '从已有玩家账号中选择,将其设为一级代理(不新建登录账号)', - 'agent.suspend.settings_title': '代理停用策略', - 'agent.suspend.settings_hint': 'MVP 默认仅停用代理操作权限,不自动冻结或禁止其直属玩家登录。', - 'agent.suspend.freeze_direct_players': '停用时允许级联冻结直属玩家', - 'agent.suspend.block_player_login': '上级代理停用时禁止直属玩家登录', - 'agent.suspend.cascade_disabled_hint': '未开启级联冻结,仅停用该代理操作权限,直属玩家不受影响。', 'agent.freeze.confirm_freeze_title': '确认停用代理', 'agent.freeze.confirm_freeze_body': '确定停用代理「{name}」?停用后该代理无法登录代理端。', 'agent.freeze.confirm_unfreeze_body': '确定恢复代理「{name}」为正常状态?', - 'agent.freeze.cascade_hint': '是否同时冻结该代理名下所有直属玩家账号?', - 'agent.freeze.cascade_label': '级联冻结直属玩家', + 'agent.freeze.opt_freeze_direct_players': '同时冻结直属玩家', + 'agent.freeze.opt_block_player_login': '禁止直属玩家登录', + 'agent.unfreeze.confirm_title': '确认恢复代理', + 'agent.unfreeze.opt_unfreeze_direct_players': '同时解冻直属玩家', 'agent.msg.cascade_freeze_done': '已停用代理并冻结其直属玩家', + 'agent.msg.cascade_unfreeze_done': '已恢复代理并解冻其直属玩家', 'agent.msg.freeze_done': '已{action}', 'match.create_btn': '+ 新增联赛', @@ -931,13 +969,21 @@ export const adminPagesEn: Record = { 'user.field.account_type': 'Account type', 'user.type.player': 'Player', 'user.type.tier1_agent': 'Tier-1 agent', - 'user.type.sub_agent': 'Sub-agent', + 'user.type.sub_agent': 'Tier-2 agent', 'user.hint.account_type': 'Agents use credit limits; players can belong to an agent and receive top-ups', 'agent.create_btn': '+ New tier-1 agent', 'agent.create_sub_btn': '+ New tier-2 agent', - 'agent.create_sub': 'Create sub-agent', - 'agent.hint.sub_agent_parent': 'Tier-2 agents must belong to a tier-1 agent', + 'agent.create_sub': 'Create tier-2 agent', + 'agent.create_child_btn': '+ New sub-agent', + 'agent.dialog.create_child_agent': 'New sub-agent', + 'agent.create_level_agent': 'Create L{level} agent', + 'agent.create_level_agent_btn': '+ New L{level} agent', + 'agent.level_name': 'Tier-{level} agent', + 'agent.level_tab': 'L{level} agents', + 'agent.dialog.create_level_agent': 'New L{level} agent', + 'agent.hint.select_parent_for_level': 'Select a level-{level} agent as parent', + 'agent.err.parent_level_mismatch': 'Invalid parent level for creating a level-{level} agent', 'agent.hint.creating_under_agent': 'Create account under this agent', 'agent.filter.username_ph': 'Username', 'agent_mgr.tab.players': 'Players', @@ -984,6 +1030,38 @@ export const adminPagesEn: Record = { 'agent.credit_tx.view_all': 'View all credit ledger', 'finance.tab.credit': 'Credit ledger', 'finance.tab.transfer': 'Transfer ledger', + 'finance.tab.wallet': 'Wallet ledger', + 'finance.filter.type_category': 'Transaction type', + 'finance.filter.type_category_all': 'All', + 'finance.filter.type_category_deposit': 'Transfers', + 'finance.filter.type_category_bet': 'Bets', + 'finance.filter.type_category_cashback': 'Cashback', + 'finance.col.frozen_before': 'Frozen before', + 'finance.col.frozen_after': 'Frozen after', + 'finance.col.reference': 'Related bet', + 'finance.tx.adjust': 'Balance adjustment', + 'finance.tx.bet_freeze': 'Bet freeze', + 'finance.tx.bet_deduct': 'Bet deduct', + 'finance.tx.bet_win': 'Bet payout', + 'finance.tx.bet_lose': 'Bet settlement', + 'finance.tx.bet_push': 'Push refund', + 'finance.tx.bet_refund': 'Bet refund', + 'finance.tx.bet_void': 'Bet void', + 'finance.tx.cashback': 'Cashback', + 'finance.tx.resettle': 'Resettlement', + 'user.action.view_wallet_ledger': 'View wallet ledger', + 'user.wallet_ledger_dialog_title': 'Wallet ledger — {name}', + 'agent.hierarchy.settings_title': 'Agent hierarchy', + 'agent.hierarchy.settings_hint': '0 means unlimited levels. Agents at the cap cannot create sub-agents. The default credit ratio pre-fills sub-agent credit limits.', + 'agent.hierarchy.max_level': 'Max agent level', + 'agent.hierarchy.default_sub_credit_ratio': 'Default sub-agent credit ratio', + 'agent.hierarchy.default_sub_credit_ratio_hint': 'When creating a sub-agent, pre-fill credit as parent available × this ratio', + 'agent.hierarchy.create_credit_default_hint': 'Default {ratio}% ({amount}), capped by parent available credit; adjustable', + 'agent.hierarchy.create_credit_quick_hint': 'Parent available {amount} — click a ratio to fill', + 'agent.hierarchy.create_level_hint': 'Will be created as level {n} agent', + 'agent.field.parent_agent': 'Parent agent', + 'agent.col.parent_chain': 'Parent chain', + 'role.agent_level': 'Level {n} agent', 'finance.filter.date_range': 'Date range', 'finance.filter.player_ph': 'Player username', 'finance.filter.parent_agent_ph': 'Parent agent username or ID', @@ -1007,17 +1085,15 @@ export const adminPagesEn: Record = { 'agent.field.select_user': 'Select user', 'agent.ph.select_user': 'Search player username', 'agent.hint.select_user': 'Pick an existing player account to promote to tier-1 agent (no new login)', - 'agent.suspend.settings_title': 'Agent suspension policy', - 'agent.suspend.settings_hint': 'MVP default: suspend agent operations only; do not auto-freeze or block direct players.', - 'agent.suspend.freeze_direct_players': 'Allow cascade freeze of direct players on suspend', - 'agent.suspend.block_player_login': 'Block direct player login when parent agent is suspended', - 'agent.suspend.cascade_disabled_hint': 'Cascade freeze is off; only the agent is suspended, direct players are unaffected.', 'agent.freeze.confirm_freeze_title': 'Confirm suspend agent', 'agent.freeze.confirm_freeze_body': 'Suspend agent "{name}"? They will not be able to sign in to the agent portal.', 'agent.freeze.confirm_unfreeze_body': 'Restore agent "{name}" to active status?', - 'agent.freeze.cascade_hint': 'Also freeze all direct player accounts under this agent?', - 'agent.freeze.cascade_label': 'Cascade freeze direct players', + 'agent.freeze.opt_freeze_direct_players': 'Also freeze direct players', + 'agent.freeze.opt_block_player_login': 'Block direct player login', + 'agent.unfreeze.confirm_title': 'Confirm restore agent', + 'agent.unfreeze.opt_unfreeze_direct_players': 'Also unfreeze direct players', 'agent.msg.cascade_freeze_done': 'Agent suspended and direct players frozen', + 'agent.msg.cascade_unfreeze_done': 'Agent restored and direct players unfrozen', 'agent.msg.freeze_done': '{action} completed', 'match.create_btn': '+ New league', diff --git a/apps/admin/src/layouts/ManageLayout.vue b/apps/admin/src/layouts/ManageLayout.vue index a58957c..bfda375 100644 --- a/apps/admin/src/layouts/ManageLayout.vue +++ b/apps/admin/src/layouts/ManageLayout.vue @@ -64,8 +64,10 @@ const topbarCrumbs = computed(() => resolveAdminBreadcrumb(route.path, t)); const roleLabel = computed(() => { if (auth.isAdmin.value) return t('role.admin'); - if (auth.isTier1Agent.value) return t('role.tier1_agent'); - if (auth.isTier2Agent.value) return t('role.tier2_agent'); + const level = auth.user.value?.agentLevel; + if (auth.isAgent.value && level != null && level > 0) { + return t('role.agent_level', { n: level }); + } return t('role.agent'); }); diff --git a/apps/admin/src/stores/auth.ts b/apps/admin/src/stores/auth.ts index 26f9e5f..0c4ce30 100644 --- a/apps/admin/src/stores/auth.ts +++ b/apps/admin/src/stores/auth.ts @@ -9,6 +9,8 @@ export interface StaffUser { locale?: string; role?: string; agentLevel?: number | null; + maxAgentLevel?: number | null; + canManageSubAgents?: boolean; } const TOKEN_KEY = 'manage_token'; @@ -127,6 +129,15 @@ export function useAuthStore() { const isAgent = computed(() => resolveUserType() === 'AGENT'); const isTier1Agent = computed(() => isAgent.value && user.value?.agentLevel === 1); const isTier2Agent = computed(() => isAgent.value && user.value?.agentLevel === 2); + const canManageSubAgents = computed(() => { + if (!isAgent.value) return false; + if (user.value?.canManageSubAgents != null) return user.value.canManageSubAgents; + const level = user.value?.agentLevel; + const max = user.value?.maxAgentLevel; + if (level == null || level < 1) return false; + if (max == null || max === 0) return true; + return level < max; + }); const portalLabel = computed(() => (isAdmin.value ? '平台后台' : '代理后台')); function setSession(newToken: string, newUser: StaffUser) { @@ -149,6 +160,7 @@ export function useAuthStore() { isAgent, isTier1Agent, isTier2Agent, + canManageSubAgents, portalLabel, setSession, logout, diff --git a/apps/admin/src/utils/agent-level-label.ts b/apps/admin/src/utils/agent-level-label.ts new file mode 100644 index 0000000..3607228 --- /dev/null +++ b/apps/admin/src/utils/agent-level-label.ts @@ -0,0 +1,20 @@ +const ZH_LEVEL_NUMERALS: Record = { + 1: '一', + 2: '二', + 3: '三', + 4: '四', + 5: '五', + 6: '六', + 7: '七', + 8: '八', + 9: '九', + 10: '十', +}; + +/** 中文界面用「一、二、三…」,其他语言用阿拉伯数字 */ +export function formatAgentLevelNumeral(level: number, locale: string): string { + if (locale.startsWith('zh') && ZH_LEVEL_NUMERALS[level]) { + return ZH_LEVEL_NUMERALS[level]; + } + return String(level); +} diff --git a/apps/admin/src/utils/session-hydrate.ts b/apps/admin/src/utils/session-hydrate.ts index c3894ab..913f23c 100644 --- a/apps/admin/src/utils/session-hydrate.ts +++ b/apps/admin/src/utils/session-hydrate.ts @@ -47,6 +47,8 @@ export async function hydrateStaffSession(): Promise { locale: raw.locale, role: raw.role, agentLevel: typeof raw.agentLevel === 'number' ? raw.agentLevel : null, + maxAgentLevel: typeof raw.maxAgentLevel === 'number' ? raw.maxAgentLevel : null, + canManageSubAgents: raw.canManageSubAgents === true, }); return true; } catch (e: unknown) { diff --git a/apps/admin/src/utils/walletTx.ts b/apps/admin/src/utils/walletTx.ts new file mode 100644 index 0000000..4a7d46e --- /dev/null +++ b/apps/admin/src/utils/walletTx.ts @@ -0,0 +1,23 @@ +export const TX_KEY_MAP: Record = { + MANUAL_DEPOSIT: 'finance.tx.deposit', + MANUAL_WITHDRAW: 'finance.tx.withdraw', + MANUAL_ADJUST: 'finance.tx.adjust', + BET_FREEZE: 'finance.tx.bet_freeze', + BET_DEDUCT: 'finance.tx.bet_deduct', + BET_SETTLE_WIN: 'finance.tx.bet_win', + BET_SETTLE_LOSE: 'finance.tx.bet_lose', + BET_SETTLE_PUSH: 'finance.tx.bet_push', + BET_WIN: 'finance.tx.bet_win', + BET_REFUND: 'finance.tx.bet_refund', + BET_VOID: 'finance.tx.bet_void', + BET_VOID_REFUND: 'finance.tx.bet_void', + CASHBACK: 'finance.tx.cashback', + CASHBACK_DEPOSIT: 'finance.tx.cashback', + RESETTLE_REVERSE: 'finance.tx.resettle', + DEPOSIT: 'finance.tx.deposit', + WITHDRAW: 'finance.tx.withdraw', +}; + +export function walletTxTypeKey(type: string): string { + return TX_KEY_MAP[type.toUpperCase()] ?? ''; +} diff --git a/apps/admin/src/views/AgentManager.vue b/apps/admin/src/views/AgentManager.vue index be60ecd..799b0b6 100644 --- a/apps/admin/src/views/AgentManager.vue +++ b/apps/admin/src/views/AgentManager.vue @@ -1,5 +1,5 @@