From 9d29ac1e6eeeda7633fc098bb5236bfeae55bae2 Mon Sep 17 00:00:00 2001 From: zheng020 Date: Tue, 2 Jun 2026 21:07:38 +0800 Subject: [PATCH] =?UTF-8?q?feat(dashboard):=20=E8=BF=BD=E5=8A=A0=20mock=20?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=B7=A5=E5=8E=82=20+=20dashboardApi=20?= =?UTF-8?q?=E5=91=BD=E5=90=8D=E7=A9=BA=E9=97=B4=20+=20=E6=89=93=E5=BC=80?= =?UTF-8?q?=20USE=5FMOCK=5FAPI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/utils/api.js | 27 +++++- frontend/utils/mock/dashboard.js | 151 +++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 frontend/utils/mock/dashboard.js diff --git a/frontend/utils/api.js b/frontend/utils/api.js index d40e1cd..f50258f 100644 --- a/frontend/utils/api.js +++ b/frontend/utils/api.js @@ -6,7 +6,7 @@ const PROD_BASE = 'http://101.132.250.62:8080' // 生产环境 const HEALTH_URL = DEV_BASE + '/health' // 是否使用模拟数据(开发调试时设为 true,后端API准备好后改为 false) -const USE_MOCK_API = false +const USE_MOCK_API = true // 环境检测状态:0=检测中, 1=开发环境, 2=生产环境 let envStatus = 0 @@ -896,3 +896,28 @@ export function getEarningsSummaryApi() { }) } +// ==================== 数据看板 ==================== +import { mockRouter } from './mock/dashboard' + +const DASHBOARD_PREFIX = '/api/v1/dashboard' + +// mock 触发器:当 USE_MOCK_API 为 true 时短路返回 mock 数据 +// 后端就绪后将 USE_MOCK_API 改为 false 即可 +async function dashboardRequest(endpoint, params = {}) { + if (USE_MOCK_API) { + const factory = mockRouter[`${DASHBOARD_PREFIX}${endpoint}`] + if (factory) return factory(params) + } + return request({ url: `${DASHBOARD_PREFIX}${endpoint}`, method: 'GET', data: params }) +} + +export const dashboardApi = { + getTodayOverview: (starId) => dashboardRequest('/today-overview', { star_id: starId }).then((r) => r.data), + get7DayIncomeCurve: (starId) => dashboardRequest('/income-curve', { star_id: starId }).then((r) => r.data), + getExhibitionSummary: (starId) => dashboardRequest('/exhibition-summary', { star_id: starId }).then((r) => r.data), + getLikeIncomeByLevel: (starId) => dashboardRequest('/like-income-by-level', { star_id: starId }).then((r) => r.data), + getTopAssets: (starId) => dashboardRequest('/top-assets', { star_id: starId }).then((r) => r.data), + getLevelDistribution: (starId) => dashboardRequest('/level-distribution', { star_id: starId }).then((r) => r.data), + getUpgradeProgress: (starId) => dashboardRequest('/upgrade-progress', { star_id: starId }).then((r) => r.data), +} + diff --git a/frontend/utils/mock/dashboard.js b/frontend/utils/mock/dashboard.js new file mode 100644 index 0000000..973ba1c --- /dev/null +++ b/frontend/utils/mock/dashboard.js @@ -0,0 +1,151 @@ +// 数据看板 mock 数据工厂 +// 后端就绪后,将 utils/api.js 顶部 USE_MOCK_API 改为 false 即可 + +const randomDelay = (min = 200, max = 600) => + new Promise((resolve) => setTimeout(resolve, Math.random() * (max - min) + min)) + +// 1. 今日概览 +export async function mockTodayOverview({ star_id }) { + await randomDelay() + return { + code: 200, + data: { + crystal_balance: 2713, + today_income: 213, + week_rank: 12, + }, + } +} + +// 2. 七日收益曲线 +export async function mock7DayIncomeCurve({ star_id }) { + await randomDelay() + const today = new Date() + const points = [] + const incomes = [180, 245, 198, 312, 276, 221, 189] // 最后一个是今天 + for (let i = 6; i >= 0; i--) { + const d = new Date(today) + d.setDate(d.getDate() - i) + const income = incomes[6 - i] + points.push({ + date: `${d.getFullYear()}.${String(d.getMonth() + 1).padStart(2, '0')}.${String(d.getDate()).padStart(2, '0')}`, + income, + is_today: i === 0, + is_peak: income === 312, + }) + } + return { + code: 200, + data: { + points, + total_income: incomes.reduce((a, b) => a + b, 0), + avg_income: Math.round(incomes.reduce((a, b) => a + b, 0) / 7), + }, + } +} + +// 3. 展出收益中心 +export async function mockExhibitionSummary({ star_id }) { + await randomDelay() + return { + code: 200, + data: { + exhibiting_count: 21, + starbook_count: 33, + total_duration: '712:13:56', + total_earnings: 39721, + top5: [ + { asset_id: 1, asset_name: '璀璨星河', asset_thumb: '', duration_7d: '144:13:56', earnings_7d: 2173, avg_earnings: 15 }, + { asset_id: 2, asset_name: '夏日微风', asset_thumb: '', duration_7d: '77:13:56', earnings_7d: 1332, avg_earnings: 15 }, + { asset_id: 3, asset_name: '夜色霓虹', asset_thumb: '', duration_7d: '64:15:37', earnings_7d: 1201, avg_earnings: 12 }, + { asset_id: 4, asset_name: '黎明序曲', asset_thumb: '', duration_7d: '51:22:12', earnings_7d: 783, avg_earnings: 12 }, + { asset_id: 5, asset_name: '深海回响', asset_thumb: '', duration_7d: '51:22:12', earnings_7d: 783, avg_earnings: 12 }, + ], + }, + } +} + +// 4. 点赞收益按等级 +export async function mockLikeIncomeByLevel({ star_id }) { + await randomDelay() + return { + code: 200, + data: { + total_like_count: 231, + total_income: 12719, + levels: [ + { level: 'UR', asset_count: 1, total_income: 723, thumb: '' }, + { level: 'SSR', asset_count: 2, total_income: 381, thumb: '' }, + { level: 'SR', asset_count: 5, total_income: 233, thumb: '' }, + { level: 'SR', asset_count: 4, total_income: 169, thumb: '' }, + { level: 'R', asset_count: 6, total_income: 57, thumb: '' }, + ], + }, + } +} + +// 5. 藏品 TOP5 +export async function mockTopAssets({ star_id }) { + await randomDelay() + return { + code: 200, + data: { + items: [ + { asset_id: 1, asset_name: '璀璨星河', asset_thumb: '', total_earnings: 8420, rank: 1 }, + { asset_id: 2, asset_name: '夏日微风', asset_thumb: '', total_earnings: 6230, rank: 2 }, + { asset_id: 3, asset_name: '夜色霓虹', asset_thumb: '', total_earnings: 5180, rank: 3 }, + { asset_id: 4, asset_name: '黎明序曲', asset_thumb: '', total_earnings: 4320, rank: 4 }, + { asset_id: 5, asset_name: '深海回响', asset_thumb: '', total_earnings: 3980, rank: 5 }, + ], + }, + } +} + +// 6. 藏品等级分布 +export async function mockLevelDistribution({ star_id }) { + await randomDelay() + const total = 33 + return { + code: 200, + data: { + items: [ + { level: 'UR', count: 1, total }, + { level: 'SSR', count: 2, total }, + { level: 'SR', count: 5, total }, + { level: 'R', count: 6, total }, + { level: 'N', count: 0, total }, + ], + }, + } +} + +// 7. 升级进度 +export async function mockUpgradeProgress({ star_id }) { + await randomDelay() + return { + code: 200, + data: { + upcoming: [ + { asset_id: 1, asset_name: '璀璨星河', asset_thumb: '', like_progress: 73, duration_progress: 92 }, + { asset_id: 2, asset_name: '夏日微风', asset_thumb: '', like_progress: 75, duration_progress: 96 }, + { asset_id: 3, asset_name: '夜色霓虹', asset_thumb: '', like_progress: 97, duration_progress: 71 }, + ], + recent: [ + { asset_id: 4, asset_name: '黎明序曲', asset_thumb: '', new_level: 'SSR', upgrade_time: Date.now() - 3600000 }, + { asset_id: 5, asset_name: '深海回响', asset_thumb: '', new_level: 'SR', upgrade_time: Date.now() - 86400000 }, + { asset_id: 6, asset_name: '晨曦微光', asset_thumb: '', new_level: 'SR', upgrade_time: Date.now() - 172800000 }, + ], + }, + } +} + +// 路由表:endpoints 字符串 → mock 工厂 +export const mockRouter = { + '/api/v1/dashboard/today-overview': mockTodayOverview, + '/api/v1/dashboard/income-curve': mock7DayIncomeCurve, + '/api/v1/dashboard/exhibition-summary': mockExhibitionSummary, + '/api/v1/dashboard/like-income-by-level': mockLikeIncomeByLevel, + '/api/v1/dashboard/top-assets': mockTopAssets, + '/api/v1/dashboard/level-distribution': mockLevelDistribution, + '/api/v1/dashboard/upgrade-progress': mockUpgradeProgress, +}