feat: add finance logs page, banner upload, and admin withdraw fix

## 财务流水
- 新增 FinanceLogs.vue(/finance-logs):额度流水 + 上下分流水双 Tab,支持时间/代理/玩家/操作人筛选与分页
- 管理员与代理共用页面,API 按角色自动切换(/admin/* 或 /agent/*)
- 侧栏「财务流水」替代原「额度流水」;代理侧栏同步新增入口
- /agent-credit-transactions 重定向至 /finance-logs?tab=credit,旧链接仍可用
- 后端:新增 GET /admin/wallet/transfer-transactions;增强额度/上下分列表筛选
- 代理端:新增 GET /agent/credit-transactions;GET /agent/wallet-transactions 支持分页与筛选
- 修复:管理员下分改为 adminWithdrawFromPlayer(),下分后重算上级代理 usedCredit

## 内容管理 Banner
- Contents.vue:各语言 Banner 支持本地上传、媒体库选择、手动填 URL(≤5MB)
- vite 开发代理 /uploads;生产 nginx 反代 /uploads/ 至 API

## 玩家端 Banner
- BannerCarousel:外链无协议时自动补 https://
- defaultBanner:API 加载中不闪默认图,仅空列表时展示默认 Banner

## 其他
- AgentManager:查看额度流水链接改为 /finance-logs
- i18n:finance.*、nav.finance_logs、content.upload.*(中/英/马来)

未纳入本次提交:.pnpm-store/、release/ 部署包、uploads/banners/ 下测试上传图片

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-10 10:02:53 +08:00
parent df20444be9
commit 6124313369
17 changed files with 1233 additions and 25 deletions

View File

@@ -38,6 +38,7 @@ const zh: Record<string, string> = {
'nav.outrights': '优胜冠军',
'nav.bets': '注单管理',
'nav.credit_transactions': '额度流水',
'nav.finance_logs': '财务流水',
'nav.cashback': '返水管理',
'nav.contents': '公共管理',
'nav.audit': '操作日志',
@@ -219,6 +220,7 @@ const en: Record<string, string> = {
'nav.outrights': 'Outrights',
'nav.bets': 'Bets',
'nav.credit_transactions': 'Credit ledger',
'nav.finance_logs': 'Finance ledger',
'nav.cashback': 'Cashback',
'nav.contents': 'Public Content',
'nav.audit': 'Audit Log',
@@ -400,6 +402,7 @@ const ms: Record<string, string> = {
'nav.outrights': 'Juara',
'nav.bets': 'Pertaruhan',
'nav.credit_transactions': 'Lejar kredit',
'nav.finance_logs': 'Lejar kewangan',
'nav.cashback': 'Rebat',
'nav.contents': 'Kandungan awam',
'nav.audit': 'Log audit',

View File

@@ -147,6 +147,21 @@ export const adminPagesMs: Record<string, string> = {
'agent.credit_tx.filter_agent_id_ph': 'ID pengguna',
'agent.credit_tx.col.operator': 'Operator',
'agent.credit_tx.view_all': 'Lihat semua lejar kredit',
'finance.tab.credit': 'Lejar kredit',
'finance.tab.transfer': 'Lejar pemindahan',
'finance.filter.date_range': 'Julat tarikh',
'finance.filter.player_ph': 'Nama pengguna pemain',
'finance.filter.parent_agent_ph': 'Nama/ID ejen induk',
'finance.filter.operator_ph': 'Nama pengguna operator',
'finance.col.player': 'Pemain',
'finance.col.parent_agent': 'Ejen induk',
'finance.col.tx_id': 'ID transaksi',
'finance.col.balance_change': 'Perubahan baki',
'finance.col.balance_before': 'Baki sebelum',
'finance.col.balance_after': 'Baki selepas',
'finance.tx.deposit': 'Deposit',
'finance.tx.withdraw': 'Pengeluaran',
'finance.tx.request_id': 'ID permintaan',
'agent.col.no_records': 'Tiada rekod',
'agent.btn.confirm_adjust': 'Sahkan',
'agent.field.select_user': 'Pilih pengguna',
@@ -535,6 +550,16 @@ export const adminPagesMs: Record<string, string> = {
'content.field.body': 'Kandungan',
'content.field.announce_text': 'Teks ticker',
'content.field.image_url': 'URL imej',
'content.upload.upload_btn': 'Muat naik imej',
'content.upload.uploading': 'Memuat naik…',
'content.upload.success': 'Imej berjaya dimuat naik',
'content.upload.failed': 'Gagal memuat naik',
'content.upload.size_error': 'Imej mestilah di bawah 5 MB',
'content.upload.remove': 'Buang imej',
'content.upload.pick_media': 'Pilih dari pustaka',
'content.upload.pick_media_title': 'Pilih Imej Banner',
'content.upload.no_media': 'Tiada imej banner dalam pustaka — muat naik dahulu',
'content.upload.url_placeholder': 'Atau tampal URL imej',
'content.link.none': 'Tiada pautan',
'content.locale.zh-CN': 'Cina Ringkas',
'content.locale.en-US': 'English',

View File

@@ -150,6 +150,21 @@ export const adminPagesZh: Record<string, string> = {
'agent.credit_tx.filter_agent_id_ph': '用户 ID',
'agent.credit_tx.col.operator': '操作人',
'agent.credit_tx.view_all': '查看全部额度流水',
'finance.tab.credit': '额度流水',
'finance.tab.transfer': '上下分流水',
'finance.filter.date_range': '时间范围',
'finance.filter.player_ph': '玩家用户名',
'finance.filter.parent_agent_ph': '上级代理用户名或 ID',
'finance.filter.operator_ph': '操作人用户名',
'finance.col.player': '玩家',
'finance.col.parent_agent': '上级代理',
'finance.col.tx_id': '流水号',
'finance.col.balance_change': '余额变动',
'finance.col.balance_before': '变动前余额',
'finance.col.balance_after': '变动后余额',
'finance.tx.deposit': '上分',
'finance.tx.withdraw': '下分',
'finance.tx.request_id': '请求 ID',
'agent.col.no_records': '暂无记录',
'agent.btn.confirm_adjust': '确认调整',
'agent.field.select_user': '选择用户',
@@ -601,6 +616,16 @@ export const adminPagesZh: Record<string, string> = {
'content.field.body': '正文',
'content.field.announce_text': '滚动文案',
'content.field.image_url': '图片地址',
'content.upload.upload_btn': '上传图片',
'content.upload.uploading': '上传中…',
'content.upload.success': '图片上传成功',
'content.upload.failed': '图片上传失败',
'content.upload.size_error': '图片大小不能超过 5MB',
'content.upload.remove': '移除图片',
'content.upload.pick_media': '从媒体库选择',
'content.upload.pick_media_title': '选择 Banner 图片',
'content.upload.no_media': '媒体库中暂无 Banner 图片,请先上传',
'content.upload.url_placeholder': '或手动粘贴图片 URL',
'content.link.none': '无跳转',
'content.locale.zh-CN': '简体中文',
'content.locale.en-US': 'English',
@@ -931,6 +956,21 @@ export const adminPagesEn: Record<string, string> = {
'agent.credit_tx.filter_agent_id_ph': 'User ID',
'agent.credit_tx.col.operator': 'Operator',
'agent.credit_tx.view_all': 'View all credit ledger',
'finance.tab.credit': 'Credit ledger',
'finance.tab.transfer': 'Transfer ledger',
'finance.filter.date_range': 'Date range',
'finance.filter.player_ph': 'Player username',
'finance.filter.parent_agent_ph': 'Parent agent username or ID',
'finance.filter.operator_ph': 'Operator username',
'finance.col.player': 'Player',
'finance.col.parent_agent': 'Parent agent',
'finance.col.tx_id': 'Transaction ID',
'finance.col.balance_change': 'Balance change',
'finance.col.balance_before': 'Balance before',
'finance.col.balance_after': 'Balance after',
'finance.tx.deposit': 'Deposit',
'finance.tx.withdraw': 'Withdraw',
'finance.tx.request_id': 'Request ID',
'agent.col.no_records': 'No records',
'agent.btn.confirm_adjust': 'Confirm',
'agent.field.select_user': 'Select user',
@@ -1383,6 +1423,16 @@ export const adminPagesEn: Record<string, string> = {
'content.field.body': 'Body',
'content.field.announce_text': 'Marquee text',
'content.field.image_url': 'Image URL',
'content.upload.upload_btn': 'Upload Image',
'content.upload.uploading': 'Uploading…',
'content.upload.success': 'Image uploaded',
'content.upload.failed': 'Upload failed',
'content.upload.size_error': 'Image must be under 5 MB',
'content.upload.remove': 'Remove image',
'content.upload.pick_media': 'Pick from library',
'content.upload.pick_media_title': 'Select Banner Image',
'content.upload.no_media': 'No banner images in library — upload one first',
'content.upload.url_placeholder': 'Or paste image URL',
'content.link.none': 'No link',
'content.locale.zh-CN': 'Chinese (Simplified)',
'content.locale.en-US': 'English',