feat(admin): 上线报表中心页面并接入九类报表查询导出

新增报表控制台、汇总 API 客户端与中英尼文案,九类报表均可筛选预览并导出 CSV/Excel。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-22 10:08:43 +08:00
parent e8a5507411
commit b2b934e25e
24 changed files with 2029 additions and 8 deletions

View File

@@ -17,6 +17,7 @@ import enSettlement from "@/i18n/locales/en/settlement.json";
import enPlayers from "@/i18n/locales/en/players.json";
import enTickets from "@/i18n/locales/en/tickets.json";
import enReconcile from "@/i18n/locales/en/reconcile.json";
import enReports from "@/i18n/locales/en/reports.json";
import enWallet from "@/i18n/locales/en/wallet.json";
import neAudit from "@/i18n/locales/ne/audit.json";
import neAdminUsers from "@/i18n/locales/ne/adminUsers.json";
@@ -31,6 +32,7 @@ import neSettlement from "@/i18n/locales/ne/settlement.json";
import nePlayers from "@/i18n/locales/ne/players.json";
import neTickets from "@/i18n/locales/ne/tickets.json";
import neReconcile from "@/i18n/locales/ne/reconcile.json";
import neReports from "@/i18n/locales/ne/reports.json";
import neWallet from "@/i18n/locales/ne/wallet.json";
import zhAudit from "@/i18n/locales/zh/audit.json";
import zhAdminUsers from "@/i18n/locales/zh/adminUsers.json";
@@ -45,13 +47,14 @@ import zhSettlement from "@/i18n/locales/zh/settlement.json";
import zhPlayers from "@/i18n/locales/zh/players.json";
import zhTickets from "@/i18n/locales/zh/tickets.json";
import zhReconcile from "@/i18n/locales/zh/reconcile.json";
import zhReports from "@/i18n/locales/zh/reports.json";
import zhWallet from "@/i18n/locales/zh/wallet.json";
export const ADMIN_SUPPORTED_LANGUAGES = ["en", "ne", "zh"] as const;
export type AdminLanguage = (typeof ADMIN_SUPPORTED_LANGUAGES)[number];
export const ADMIN_DEFAULT_LANGUAGE: AdminLanguage = "zh";
const namespaces = ["common", "auth", "dashboard", "audit", "draws", "settlement", "risk", "jackpot", "players", "tickets", "reconcile", "wallet", "adminUsers", "config"] as const;
const namespaces = ["common", "auth", "dashboard", "audit", "draws", "settlement", "risk", "jackpot", "players", "tickets", "reconcile", "reports", "wallet", "adminUsers", "config"] as const;
const resources = {
en: {
@@ -65,6 +68,7 @@ const resources = {
players: enPlayers,
tickets: enTickets,
reconcile: enReconcile,
reports: enReports,
risk: enRisk,
audit: enAudit,
settlement: enSettlement,
@@ -81,6 +85,7 @@ const resources = {
players: nePlayers,
tickets: neTickets,
reconcile: neReconcile,
reports: neReports,
risk: neRisk,
audit: neAudit,
settlement: neSettlement,
@@ -97,6 +102,7 @@ const resources = {
players: zhPlayers,
tickets: zhTickets,
reconcile: zhReconcile,
reports: zhReports,
risk: zhRisk,
audit: zhAudit,
settlement: zhSettlement,

View File

@@ -3,6 +3,7 @@
"moduleCode": "Module code",
"actionCode": "Action code",
"operatorType": "Operator type",
"operatorIdPlaceholder": "Enter operator ID",
"exactMatch": "Exact match",
"operatorTypePlaceholder": "For example admin / system",
"operator": "Operator",

View File

@@ -94,6 +94,7 @@
"players": "Players",
"currencies": "Currencies",
"wallet": "Wallet",
"reports": "Reports",
"draws": "Draws",
"rules_plays": "Play rules",
"rules_odds": "Odds & rebate",

View File

@@ -0,0 +1,172 @@
{
"title": "Reports",
"subtitle": "Centralized operational, finance, risk, and audit reports with unified export filters.",
"exportPanel": "Export setup",
"chooseReport": "Choose a report to export",
"libraryTitle": "Report types",
"exportConfig": "Export filters",
"recentTasks": "Recent export tasks",
"taskEmpty": "No export tasks yet",
"dimension": "Dimension",
"exportPending": "{{report}} {{format}} export API is not connected yet",
"exportSuccess": "Exported {{report}} ({{format}})",
"exportFailed": "Export failed",
"exportHint": "Once export APIs are connected, the current filters will generate the selected file format.",
"validation": {
"drawNoRequired": "Please enter a draw number",
"drawNoNumberRequired": "Please enter both draw number and number"
},
"formats": {
"csv": "CSV",
"excel": "Excel"
},
"empty": "No matching reports",
"connected": "Connected",
"pending": "Pending",
"backendPending": "Backend API not connected yet",
"filterPanel": "Filters",
"queryHint": "Set filters and run a query to preview and export.",
"query": "Query",
"querying": "Querying…",
"reset": "Reset",
"loadFailed": "Failed to load",
"yes": "Yes",
"no": "No",
"filterAll": "All plays",
"searchPicker": {
"open": "Open picker",
"select": "Pick",
"keyword": "Search keyword"
},
"preview": {
"title": "Preview",
"subtitle": "Results appear below. Export as CSV or Excel.",
"empty": "No data. Adjust filters and try again.",
"exportableRows": "rows exportable",
"columns": {
"primary": "Primary",
"secondary": "Secondary",
"metricA": "Metric A",
"metricB": "Metric B",
"metricC": "Metric C",
"status": "Status",
"extra": "Extra",
"time": "Time"
},
"stats": {
"records": "Records",
"currentPage": "This page",
"drawNo": "Draw no.",
"currency": "Currency",
"exportRows": "Export rows",
"bet": "Bets",
"payout": "Payout",
"houseGross": "House P&L",
"orders": "Orders",
"locked": "Locked",
"remaining": "Remaining",
"usage": "Usage",
"logs": "Logs",
"modules": "Modules",
"operators": "Operators",
"players": "Players",
"transferIn": "Transfer in",
"transferOut": "Transfer out",
"rebate": "Total rebate"
}
},
"stats": {
"total": "Total reports",
"current": "Current list",
"formats": "Export formats"
},
"table": {
"report": "Report",
"category": "Category",
"dimension": "Dimension",
"description": "Description",
"formats": "Formats",
"actions": "Actions",
"status": "Status",
"createdAt": "Created at"
},
"categories": {
"all": "All",
"profit": "Profit",
"wallet": "Funds",
"risk": "Risk",
"audit": "Audit"
},
"filters": {
"draw": "Draw",
"date": "Date",
"player_period": "Player + period",
"draw_number": "Draw + number",
"play": "Play",
"play_period": "Play + period",
"operator_period": "Operator + period"
},
"scopes": {
"drawNo": "Draw",
"date": "Date",
"playerPeriod": "Player + period",
"drawNumber": "Draw + number",
"play": "Play",
"playPeriod": "Play + period",
"operatorPeriod": "Operator + period"
},
"fields": {
"drawNo": "Draw no.",
"number": "Number",
"period": "Period",
"player": "Player",
"play": "Play",
"operator": "Operator"
},
"placeholders": {
"drawNo": "e.g. 20260522-001",
"number": "Enter number",
"keyword": "Search report name / description",
"player": "Player ID / name / phone",
"play": "Play name or code",
"operator": "Admin account or name"
},
"items": {
"draw_profit": {
"title": "Draw bets / payout / P&L",
"summary": "Review bet amount, payout, platform P&L, and settlement state by draw."
},
"daily_profit": {
"title": "Daily P&L summary",
"summary": "Summarize bets, payouts, refunds, P&L, and net amount by date."
},
"player_win_loss": {
"title": "Player win/loss report",
"summary": "Track player win/loss over a selected period for finance and support review."
},
"player_transfer": {
"title": "Player transfer report",
"summary": "Review player transfers in, transfers out, reversals, and exception handling."
},
"hot_number_risk": {
"title": "Hot number risk report",
"summary": "Inspect betting heat, risk occupancy, and cap proximity by draw and number."
},
"play_dimension": {
"title": "Play dimension report",
"summary": "Break down betting volume, payout, rebate, and P&L structure by play."
},
"sold_out_number": {
"title": "Sold-out number report",
"summary": "Review sold-out numbers, sold-out time, and risk lock state by draw."
},
"rebate_commission": {
"title": "Commission / rebate report",
"summary": "Summarize commission, rebate, and matched rules by play and period."
},
"admin_audit": {
"title": "Admin operation audit report",
"summary": "Export key admin operation traces by operator and period."
}
}
}

View File

@@ -3,6 +3,7 @@
"moduleCode": "मोड्युल कोड",
"actionCode": "कार्य कोड",
"operatorType": "अपरेटर प्रकार",
"operatorIdPlaceholder": "अपरेटर ID प्रविष्ट गर्नुहोस्",
"exactMatch": "ठ्याक्कै मिलान",
"operatorTypePlaceholder": "जस्तै admin / system",
"operator": "अपरेटर",

View File

@@ -94,6 +94,7 @@
"players": "खेलाडी सूची",
"currencies": "मुद्रा व्यवस्थापन",
"wallet": "वालेट",
"reports": "रिपोर्ट",
"draws": "ड्रअहरू",
"rules_plays": "खेल नियम",
"rules_odds": "बाधा र रिबेट",

View File

@@ -0,0 +1,172 @@
{
"title": "रिपोर्ट",
"subtitle": "सञ्चालन, वित्त, जोखिम र अडिट रिपोर्टहरू एउटै ठाउँबाट फिल्टर गरी निर्यात गर्नुहोस्।",
"exportPanel": "निर्यात सेटअप",
"chooseReport": "निर्यात गर्ने रिपोर्ट छान्नुहोस्",
"libraryTitle": "रिपोर्ट प्रकार",
"exportConfig": "निर्यात फिल्टर",
"recentTasks": "हालका निर्यात कार्यहरू",
"taskEmpty": "निर्यात कार्य छैन",
"dimension": "आयाम",
"exportPending": "{{report}} {{format}} निर्यात API अझै जोडिएको छैन",
"exportSuccess": "{{report}} ({{format}}) निर्यात भयो",
"exportFailed": "निर्यात असफल भयो",
"exportHint": "निर्यात API जोडिएपछि हालका फिल्टरअनुसार छानिएको फाइल ढाँचा बनाइनेछ।",
"validation": {
"drawNoRequired": "कृपया ड्र नं. प्रविष्ट गर्नुहोस्",
"drawNoNumberRequired": "कृपया ड्र नं. र नम्बर दुवै प्रविष्ट गर्नुहोस्"
},
"formats": {
"csv": "CSV",
"excel": "Excel"
},
"empty": "मिल्ने रिपोर्ट छैन",
"connected": "जोडिएको",
"pending": "बाँकी",
"backendPending": "ब्याकएन्ड API जोडिन बाँकी",
"filterPanel": "फिल्टर",
"queryHint": "फिल्टर सेट गरी क्वेरी चलाउनुहोस्।",
"query": "क्वेरी",
"querying": "क्वेरी हुँदै…",
"reset": "रिसेट",
"loadFailed": "लोड असफल",
"yes": "हो",
"no": "होइन",
"filterAll": "सबै प्ले",
"searchPicker": {
"open": "छनोट खोल्नुहोस्",
"select": "छान्नुहोस्",
"keyword": "खोज शब्द"
},
"preview": {
"title": "पूर्वावलोकन",
"subtitle": "तल तालिकामा नतिजा देखिन्छ।",
"empty": "डाटा छैन।",
"exportableRows": "पङ्क्ति निर्यात योग्य",
"columns": {
"primary": "मुख्य",
"secondary": "दोस्रो",
"metricA": "मेट्रिक A",
"metricB": "मेट्रिक B",
"metricC": "मेट्रिक C",
"status": "स्थिति",
"extra": "अतिरिक्त",
"time": "समय"
},
"stats": {
"records": "रेकर्ड",
"currentPage": "यो पृष्ठ",
"drawNo": "ड्र नं.",
"currency": "मुद्रा",
"exportRows": "निर्यात पङ्क्ति",
"bet": "बेट",
"payout": "भुक्तानी",
"houseGross": "हाउस P&L",
"orders": "अर्डर",
"locked": "लक",
"remaining": "बाँकी",
"usage": "उपयोग",
"logs": "लग",
"modules": "मोड्युल",
"operators": "अपरेटर",
"players": "खेलाडी",
"transferIn": "भित्र",
"transferOut": "बाहिर",
"rebate": "रिबेट"
}
},
"stats": {
"total": "कुल रिपोर्ट",
"current": "हालको सूची",
"formats": "निर्यात ढाँचा"
},
"table": {
"report": "रिपोर्ट",
"category": "वर्ग",
"dimension": "आयाम",
"description": "विवरण",
"formats": "ढाँचा",
"actions": "कार्य",
"status": "स्थिति",
"createdAt": "सिर्जना समय"
},
"categories": {
"all": "सबै",
"profit": "नाफा/घाटा",
"wallet": "कोष",
"risk": "जोखिम",
"audit": "अडिट"
},
"filters": {
"draw": "ड्र",
"date": "मिति",
"player_period": "खेलाडी + अवधि",
"draw_number": "ड्र + नम्बर",
"play": "खेल",
"play_period": "खेल + अवधि",
"operator_period": "अपरेटर + अवधि"
},
"scopes": {
"drawNo": "ड्र",
"date": "मिति",
"playerPeriod": "खेलाडी + अवधि",
"drawNumber": "ड्र + नम्बर",
"play": "खेल",
"playPeriod": "खेल + अवधि",
"operatorPeriod": "अपरेटर + अवधि"
},
"fields": {
"drawNo": "ड्र नं.",
"number": "नम्बर",
"period": "अवधि",
"player": "खेलाडी",
"play": "खेल",
"operator": "अपरेटर"
},
"placeholders": {
"drawNo": "जस्तै 20260522-001",
"number": "नम्बर लेख्नुहोस्",
"keyword": "रिपोर्ट नाम / विवरण खोज्नुहोस्",
"player": "खेलाडी ID / नाम / फोन",
"play": "खेल नाम वा कोड",
"operator": "एडमिन खाता वा नाम"
},
"items": {
"draw_profit": {
"title": "ड्र बेट / पेआउट / P&L",
"summary": "ड्र अनुसार बेट रकम, पेआउट, प्लेटफर्म P&L र सेटलमेन्ट स्थिति हेर्नुहोस्।"
},
"daily_profit": {
"title": "दैनिक P&L सारांश",
"summary": "मिति अनुसार बेट, पेआउट, रिफन्ड, P&L र नेट रकम सारांश गर्नुहोस्।"
},
"player_win_loss": {
"title": "खेलाडी जित/हार रिपोर्ट",
"summary": "चयन गरिएको अवधिमा खेलाडीको जित/हार वित्त र सपोर्टका लागि हेर्नुहोस्।"
},
"player_transfer": {
"title": "खेलाडी ट्रान्सफर रिपोर्ट",
"summary": "खेलाडी ट्रान्सफर इन, आउट, रिभर्सल र अपवाद रेकर्ड हेर्नुहोस्।"
},
"hot_number_risk": {
"title": "हट नम्बर जोखिम रिपोर्ट",
"summary": "ड्र र नम्बर अनुसार बेटिङ हिट, जोखिम प्रयोग र क्याप नजिकिएको अवस्था हेर्नुहोस्।"
},
"play_dimension": {
"title": "खेल आयाम रिपोर्ट",
"summary": "खेल अनुसार बेट भोल्युम, पेआउट, रिबेट र P&L संरचना छुट्याउनुहोस्।"
},
"sold_out_number": {
"title": "सोल्ड-आउट नम्बर रिपोर्ट",
"summary": "ड्र अनुसार सोल्ड-आउट नम्बर, समय र जोखिम लक अवस्था हेर्नुहोस्।"
},
"rebate_commission": {
"title": "कमिसन / रिबेट रिपोर्ट",
"summary": "खेल र अवधिअनुसार कमिसन, रिबेट र मिलेको नियम सारांश गर्नुहोस्।"
},
"admin_audit": {
"title": "एडमिन अपरेशन अडिट रिपोर्ट",
"summary": "अपरेटर र अवधिअनुसार मुख्य एडमिन अपरेशन ट्रेस निर्यात गर्नुहोस्।"
}
}
}

View File

@@ -3,6 +3,7 @@
"moduleCode": "模块",
"actionCode": "动作",
"operatorType": "操作者类型",
"operatorIdPlaceholder": "请输入操作人 ID",
"exactMatch": "请输入完整名称",
"operatorTypePlaceholder": "如管理员、系统",
"operator": "操作者",

View File

@@ -94,6 +94,7 @@
"players": "玩家列表",
"currencies": "币种管理",
"wallet": "钱包流水",
"reports": "报表中心",
"draws": "期号列表",
"rules_plays": "投注规则",
"rules_odds": "赔率与回水",

View File

@@ -0,0 +1,172 @@
{
"title": "报表中心",
"subtitle": "集中查看运营、资金、风控与审计报表,统一按维度筛选后导出。",
"exportPanel": "导出设置",
"chooseReport": "选择要导出的报表",
"libraryTitle": "报表类型",
"exportConfig": "导出条件",
"recentTasks": "最近导出任务",
"taskEmpty": "暂无导出任务",
"dimension": "维度",
"exportPending": "{{report}} 的 {{format}} 导出接口待接入",
"exportSuccess": "已导出 {{report}}{{format}}",
"exportFailed": "导出失败",
"exportHint": "接入导出接口后,会按当前条件生成对应格式的文件。",
"validation": {
"drawNoRequired": "请输入期号",
"drawNoNumberRequired": "请输入期号和号码"
},
"formats": {
"csv": "CSV",
"excel": "Excel"
},
"empty": "没有匹配的报表",
"connected": "已接入",
"pending": "待接入",
"backendPending": "后端接口待接入",
"filterPanel": "筛选条件",
"queryHint": "设置筛选条件后点击查询,可预览并导出。",
"query": "查询",
"querying": "查询中…",
"reset": "重置",
"loadFailed": "加载失败",
"yes": "是",
"no": "否",
"filterAll": "全部玩法",
"searchPicker": {
"open": "打开选择器",
"select": "选择",
"keyword": "输入关键词搜索"
},
"preview": {
"title": "数据预览",
"subtitle": "查询结果将显示在下方表格,可导出 CSV 或 Excel。",
"empty": "暂无数据,请调整筛选条件后重试。",
"exportableRows": "行可导出",
"columns": {
"primary": "主字段",
"secondary": "次字段",
"metricA": "指标 A",
"metricB": "指标 B",
"metricC": "指标 C",
"status": "状态",
"extra": "附加",
"time": "时间"
},
"stats": {
"records": "记录数",
"currentPage": "当前页",
"drawNo": "期号",
"currency": "币种",
"exportRows": "导出行数",
"bet": "下注",
"payout": "派彩",
"houseGross": "平台盈亏",
"orders": "订单数",
"locked": "已占用",
"remaining": "剩余额度",
"usage": "使用率",
"logs": "日志数",
"modules": "模块数",
"operators": "操作人数",
"players": "玩家数",
"transferIn": "转入笔数",
"transferOut": "转出笔数",
"rebate": "回水合计"
}
},
"stats": {
"total": "全部报表",
"current": "当前列表",
"formats": "导出格式"
},
"table": {
"report": "报表名称",
"category": "分类",
"dimension": "统计维度",
"description": "说明",
"formats": "格式",
"actions": "操作",
"status": "状态",
"createdAt": "创建时间"
},
"categories": {
"all": "全部",
"profit": "盈亏",
"wallet": "资金",
"risk": "风控",
"audit": "审计"
},
"filters": {
"draw": "期号",
"date": "日期",
"player_period": "玩家 + 时间段",
"draw_number": "期号 + 号码",
"play": "玩法",
"play_period": "玩法 + 时间段",
"operator_period": "操作人 + 时间段"
},
"scopes": {
"drawNo": "期号",
"date": "日期",
"playerPeriod": "玩家 + 时间段",
"drawNumber": "期号 + 号码",
"play": "玩法",
"playPeriod": "玩法 + 时间段",
"operatorPeriod": "操作人 + 时间段"
},
"fields": {
"drawNo": "期号",
"number": "号码",
"period": "时间段",
"player": "玩家",
"play": "玩法",
"operator": "操作人"
},
"placeholders": {
"drawNo": "例如 20260522-001",
"number": "输入号码",
"keyword": "搜索报表名称 / 说明",
"player": "玩家 ID / 昵称 / 手机",
"play": "玩法名称或编码",
"operator": "管理员账号或昵称"
},
"items": {
"draw_profit": {
"title": "每期下注/派彩/盈亏",
"summary": "按期号核对下注额、派彩金额、平台盈亏与结算状态。"
},
"daily_profit": {
"title": "每日盈亏汇总",
"summary": "按自然日汇总投注、派奖、退款、盈亏和净额。"
},
"player_win_loss": {
"title": "玩家输赢报表",
"summary": "按玩家和时间段追踪输赢表现,适合客服与财务复核。"
},
"player_transfer": {
"title": "玩家转入转出报表",
"summary": "集中查看玩家转入、转出、冲正和异常处理记录。"
},
"hot_number_risk": {
"title": "热门号码风险报表",
"summary": "按期号与号码查看投注热度、风险占用和封顶接近度。"
},
"play_dimension": {
"title": "玩法维度报表",
"summary": "按玩法拆分投注量、派彩、回水和盈亏结构。"
},
"sold_out_number": {
"title": "售罄号码报表",
"summary": "查看单期已售罄号码、售罄时间和风险封锁情况。"
},
"rebate_commission": {
"title": "佣金/回水报表",
"summary": "按玩法与时间段汇总佣金、回水与配置命中情况。"
},
"admin_audit": {
"title": "后台操作审计报表",
"summary": "按操作人和时间段导出关键后台操作留痕。"
}
}
}