From 199a54bc12ada6c58c7a0f0937d14dcafbcf1577 Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Mon, 27 Oct 2025 15:10:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=BA"=E8=82=A1=E7=A5=A8=E8=A1=8C?= =?UTF-8?q?=E6=83=85"=E5=92=8C"=E8=B4=A2=E5=8A=A1=E5=85=A8=E6=99=AF"?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E9=A1=B5=E6=B7=BB=E5=8A=A0=20Mock=20?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题: - 点击"股票行情"标签页:MarketDataView 组件需要市场数据接口 - 点击"财务全景"标签页:FinancialPanorama 组件需要财务数据接口 - 这些接口都没有 mock 数据,导致页面显示空白 需要添加的接口: 股票行情 (MarketDataView) - 7个接口 1. /api/market/trade/:stockCode - 成交数据 2. /api/market/funding/:stockCode - 资金流向 3. /api/market/bigdeal/:stockCode - 大单统计 4. /api/market/unusual/:stockCode - 异动分析 5. /api/market/pledge/:stockCode - 股权质押 6. /api/market/summary/:stockCode - 市场摘要 7. /api/market/rise-analysis/:stockCode - 涨停分析 8. /api/stock/:stockCode/latest-minute - 最新分时数据 财务全景 (FinancialPanorama) - 9个接口 1. /api/financial/stock-info/:stockCode - 股票基本信息 2. /api/financial/balance-sheet/:stockCode - 资产负债表 3. /api/financial/income-statement/:stockCode - 利润表 4. /api/financial/cashflow/:stockCode - 现金流量表 5. /api/financial/financial-metrics/:stockCode - 财务指标 6. /api/financial/main-business/:stockCode - 主营业务 7. /api/financial/forecast/:stockCode - 业绩预告 8. /api/financial/industry-rank/:stockCode - 行业排名 9. /api/financial/comparison/:stockCode - 期间对比 实施步骤: 1. 创建 src/mocks/data/market.js - 市场数据 2. 创建 src/mocks/data/financial.js - 财务数据 3. 创建 src/mocks/handlers/market.js - 市场接口handlers 4. 创建 src/mocks/handlers/financial.js - 财务接口handlers 5. 更新 src/mocks/handlers/index.js - 注册新handlers 数据内容: - 为平安银行 (000001) 提供完整真实数据 - 其他股票代码生成合理的模拟数据 --- src/mocks/data/financial.js | 139 +++++++++++++++++++++++++++++++ src/mocks/data/market.js | 141 ++++++++++++++++++++++++++++++++ src/mocks/handlers/financial.js | 121 +++++++++++++++++++++++++++ src/mocks/handlers/index.js | 4 + src/mocks/handlers/market.js | 74 +++++++++++++++++ 5 files changed, 479 insertions(+) create mode 100644 src/mocks/data/financial.js create mode 100644 src/mocks/data/market.js create mode 100644 src/mocks/handlers/financial.js create mode 100644 src/mocks/handlers/market.js diff --git a/src/mocks/data/financial.js b/src/mocks/data/financial.js new file mode 100644 index 00000000..c7128610 --- /dev/null +++ b/src/mocks/data/financial.js @@ -0,0 +1,139 @@ +// src/mocks/data/financial.js +// 财务数据相关的 Mock 数据 + +// 生成财务数据 +export const generateFinancialData = (stockCode) => { + const periods = ['2024-09-30', '2024-06-30', '2024-03-31', '2023-12-31']; + + return { + stockCode, + + // 股票基本信息 + stockInfo: { + code: stockCode, + name: stockCode === '000001' ? '平安银行' : '示例公司', + industry: stockCode === '000001' ? '银行' : '制造业', + list_date: '1991-04-03', + market: 'SZ' + }, + + // 资产负债表 + balanceSheet: periods.map((period, i) => ({ + period, + total_assets: 5024560 - i * 50000, // 百万元 + total_liabilities: 4698880 - i * 48000, + shareholders_equity: 325680 - i * 2000, + current_assets: 2512300 - i * 25000, + non_current_assets: 2512260 - i * 25000, + current_liabilities: 3456780 - i * 35000, + non_current_liabilities: 1242100 - i * 13000 + })), + + // 利润表 + incomeStatement: periods.map((period, i) => ({ + period, + revenue: 162350 - i * 4000, // 百万元 + operating_cost: 45620 - i * 1200, + gross_profit: 116730 - i * 2800, + operating_profit: 68450 - i * 1500, + net_profit: 52860 - i * 1200, + eps: 2.72 - i * 0.06 + })), + + // 现金流量表 + cashflow: periods.map((period, i) => ({ + period, + operating_cashflow: 125600 - i * 3000, // 百万元 + investing_cashflow: -45300 - i * 1000, + financing_cashflow: -38200 + i * 500, + net_cashflow: 42100 - i * 1500, + cash_ending: 456780 - i * 10000 + })), + + // 财务指标 + financialMetrics: periods.map((period, i) => ({ + period, + roe: 16.23 - i * 0.3, // % + roa: 1.05 - i * 0.02, + gross_margin: 71.92 - i * 0.5, + net_margin: 32.56 - i * 0.3, + current_ratio: 0.73 + i * 0.01, + quick_ratio: 0.71 + i * 0.01, + debt_ratio: 93.52 + i * 0.05, + asset_turnover: 0.41 - i * 0.01, + inventory_turnover: 0, // 银行无库存 + receivable_turnover: 0 // 银行特殊 + })), + + // 主营业务 + mainBusiness: { + by_product: [ + { name: '对公业务', revenue: 68540, ratio: 42.2, yoy_growth: 6.8 }, + { name: '零售业务', revenue: 81320, ratio: 50.1, yoy_growth: 11.2 }, + { name: '金融市场业务', revenue: 12490, ratio: 7.7, yoy_growth: 3.5 } + ], + by_region: [ + { name: '华南地区', revenue: 56800, ratio: 35.0, yoy_growth: 9.2 }, + { name: '华东地区', revenue: 48705, ratio: 30.0, yoy_growth: 8.5 }, + { name: '华北地区', revenue: 32470, ratio: 20.0, yoy_growth: 7.8 }, + { name: '其他地区', revenue: 24375, ratio: 15.0, yoy_growth: 6.5 } + ] + }, + + // 业绩预告 + forecast: { + period: '2024', + forecast_net_profit_min: 580000, // 百万元 + forecast_net_profit_max: 620000, + yoy_growth_min: 10.0, // % + yoy_growth_max: 17.0, + forecast_type: '预增', + reason: '受益于零售业务快速增长及资产质量改善,预计全年业绩保持稳定增长', + publish_date: '2024-10-15' + }, + + // 行业排名 + industryRank: { + industry: '银行', + total_companies: 42, + rankings: [ + { metric: '总资产', rank: 8, value: 5024560, percentile: 19 }, + { metric: '营业收入', rank: 9, value: 162350, percentile: 21 }, + { metric: '净利润', rank: 8, value: 52860, percentile: 19 }, + { metric: 'ROE', rank: 12, value: 16.23, percentile: 29 }, + { metric: '不良贷款率', rank: 18, value: 1.02, percentile: 43 } + ] + }, + + // 期间对比 + periodComparison: { + periods: ['Q3-2024', 'Q2-2024', 'Q1-2024', 'Q4-2023'], + metrics: [ + { + name: '营业收入', + unit: '百万元', + values: [41500, 40800, 40200, 40850], + yoy: [8.2, 7.8, 8.5, 9.2] + }, + { + name: '净利润', + unit: '百万元', + values: [13420, 13180, 13050, 13210], + yoy: [12.5, 11.2, 10.8, 12.3] + }, + { + name: 'ROE', + unit: '%', + values: [16.23, 15.98, 15.75, 16.02], + yoy: [1.2, 0.8, 0.5, 1.0] + }, + { + name: 'EPS', + unit: '元', + values: [0.69, 0.68, 0.67, 0.68], + yoy: [12.3, 11.5, 10.5, 12.0] + } + ] + } + }; +}; diff --git a/src/mocks/data/market.js b/src/mocks/data/market.js new file mode 100644 index 00000000..94b46de3 --- /dev/null +++ b/src/mocks/data/market.js @@ -0,0 +1,141 @@ +// src/mocks/data/market.js +// 市场行情相关的 Mock 数据 + +// 生成市场数据 +export const generateMarketData = (stockCode) => { + const basePrice = 13.50; // 基准价格(平安银行约13.5元) + + return { + stockCode, + + // 成交数据 + tradeData: { + success: true, + data: Array(30).fill(null).map((_, i) => ({ + date: new Date(Date.now() - (29 - i) * 24 * 60 * 60 * 1000).toISOString().split('T')[0], + volume: Math.floor(Math.random() * 500000000) + 100000000, // 1-6亿股 + amount: Math.floor(Math.random() * 7000000000) + 1300000000, // 13-80亿元 + turnover_rate: (Math.random() * 2 + 0.5).toFixed(2), // 0.5-2.5% + change_pct: (Math.random() * 6 - 3).toFixed(2) // -3% to +3% + })) + }, + + // 资金流向 + fundingData: { + success: true, + data: { + main_inflow: 125600000, // 主力净流入(元) + retail_inflow: -45300000, // 散户净流入 + large_inflow: 89200000, // 大单净流入 + medium_inflow: 23400000, // 中单净流入 + small_outflow: -68600000, // 小单净流出 + trend: Array(30).fill(null).map((_, i) => ({ + date: new Date(Date.now() - (29 - i) * 24 * 60 * 60 * 1000).toISOString().split('T')[0], + main_inflow: Math.floor(Math.random() * 200000000) - 100000000 + })) + } + }, + + // 大单统计 + bigDealData: { + success: true, + data: { + today: { + buy_large: 234500000, + sell_large: 189600000, + net_large: 44900000, + buy_count: 1256, + sell_count: 1089 + }, + history: Array(30).fill(null).map((_, i) => ({ + date: new Date(Date.now() - (29 - i) * 24 * 60 * 60 * 1000).toISOString().split('T')[0], + net_large: Math.floor(Math.random() * 200000000) - 100000000 + })) + } + }, + + // 异动分析 + unusualData: { + success: true, + data: { + events: [ + { time: '14:35:22', type: '快速拉升', change: '+2.3%', description: '5分钟内上涨2.3%' }, + { time: '11:28:45', type: '大单买入', amount: '5680万', description: '单笔大单买入' }, + { time: '10:15:30', type: '量比异动', ratio: '3.2', description: '量比达到3.2倍' } + ], + volume_ratio: 1.85, // 量比 + turnover_rate: 1.23, // 换手率 + amplitude: 3.45 // 振幅% + } + }, + + // 股权质押 + pledgeData: { + success: true, + data: { + total_pledged: 25.6, // 质押比例% + major_shareholders: [ + { name: '中国平安保险集团', pledged_shares: 0, total_shares: 10168542300, pledge_ratio: 0 }, + { name: '深圳市投资控股', pledged_shares: 50000000, total_shares: 382456100, pledge_ratio: 13.08 } + ], + update_date: '2024-09-30' + } + }, + + // 市场摘要 + summaryData: { + success: true, + data: { + current_price: basePrice, + change: 0.25, + change_pct: 1.89, + open: 13.35, + high: 13.68, + low: 13.28, + volume: 345678900, + amount: 4678900000, + turnover_rate: 1.78, + pe_ratio: 4.96, + pb_ratio: 0.72, + total_market_cap: 262300000000, + circulating_market_cap: 262300000000 + } + }, + + // 涨停分析 + riseAnalysisData: { + success: true, + data: { + is_limit_up: false, + limit_up_price: basePrice * 1.10, + current_price: basePrice, + distance_to_limit: 8.92, // % + consecutive_days: 0, + reason: '', + concept_tags: ['银行', '深圳国资', 'MSCI', '沪深300'] + } + }, + + // 最新分时数据 + latestMinuteData: { + success: true, + data: Array(240).fill(null).map((_, i) => { + const minute = 9 * 60 + 30 + i; // 从9:30开始 + const hour = Math.floor(minute / 60); + const min = minute % 60; + const time = `${hour.toString().padStart(2, '0')}:${min.toString().padStart(2, '0')}`; + const randomChange = (Math.random() - 0.5) * 0.1; + return { + time, + price: (basePrice + randomChange).toFixed(2), + volume: Math.floor(Math.random() * 2000000) + 500000, + avg_price: (basePrice + randomChange * 0.8).toFixed(2) + }; + }), + code: stockCode, + name: stockCode === '000001' ? '平安银行' : '示例股票', + trade_date: new Date().toISOString().split('T')[0], + type: 'minute' + } + }; +}; diff --git a/src/mocks/handlers/financial.js b/src/mocks/handlers/financial.js new file mode 100644 index 00000000..2d2a28f8 --- /dev/null +++ b/src/mocks/handlers/financial.js @@ -0,0 +1,121 @@ +// src/mocks/handlers/financial.js +// 财务数据相关的 Mock Handlers + +import { http, HttpResponse } from 'msw'; +import { generateFinancialData } from '../data/financial'; + +// 模拟延迟 +const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); + +export const financialHandlers = [ + // 1. 股票基本信息 + http.get('/api/financial/stock-info/:stockCode', async ({ params }) => { + await delay(150); + const { stockCode } = params; + const data = generateFinancialData(stockCode); + return HttpResponse.json({ + success: true, + data: data.stockInfo + }); + }), + + // 2. 资产负债表 + http.get('/api/financial/balance-sheet/:stockCode', async ({ params, request }) => { + await delay(250); + const { stockCode } = params; + const url = new URL(request.url); + const limit = parseInt(url.searchParams.get('limit') || '4', 10); + + const data = generateFinancialData(stockCode); + return HttpResponse.json({ + success: true, + data: data.balanceSheet.slice(0, limit) + }); + }), + + // 3. 利润表 + http.get('/api/financial/income-statement/:stockCode', async ({ params, request }) => { + await delay(250); + const { stockCode } = params; + const url = new URL(request.url); + const limit = parseInt(url.searchParams.get('limit') || '4', 10); + + const data = generateFinancialData(stockCode); + return HttpResponse.json({ + success: true, + data: data.incomeStatement.slice(0, limit) + }); + }), + + // 4. 现金流量表 + http.get('/api/financial/cashflow/:stockCode', async ({ params, request }) => { + await delay(250); + const { stockCode } = params; + const url = new URL(request.url); + const limit = parseInt(url.searchParams.get('limit') || '4', 10); + + const data = generateFinancialData(stockCode); + return HttpResponse.json({ + success: true, + data: data.cashflow.slice(0, limit) + }); + }), + + // 5. 财务指标 + http.get('/api/financial/financial-metrics/:stockCode', async ({ params, request }) => { + await delay(250); + const { stockCode } = params; + const url = new URL(request.url); + const limit = parseInt(url.searchParams.get('limit') || '4', 10); + + const data = generateFinancialData(stockCode); + return HttpResponse.json({ + success: true, + data: data.financialMetrics.slice(0, limit) + }); + }), + + // 6. 主营业务 + http.get('/api/financial/main-business/:stockCode', async ({ params }) => { + await delay(200); + const { stockCode } = params; + const data = generateFinancialData(stockCode); + return HttpResponse.json({ + success: true, + data: data.mainBusiness + }); + }), + + // 7. 业绩预告 + http.get('/api/financial/forecast/:stockCode', async ({ params }) => { + await delay(200); + const { stockCode } = params; + const data = generateFinancialData(stockCode); + return HttpResponse.json({ + success: true, + data: data.forecast + }); + }), + + // 8. 行业排名 + http.get('/api/financial/industry-rank/:stockCode', async ({ params }) => { + await delay(250); + const { stockCode } = params; + const data = generateFinancialData(stockCode); + return HttpResponse.json({ + success: true, + data: data.industryRank + }); + }), + + // 9. 期间对比 + http.get('/api/financial/comparison/:stockCode', async ({ params }) => { + await delay(250); + const { stockCode } = params; + const data = generateFinancialData(stockCode); + return HttpResponse.json({ + success: true, + data: data.periodComparison + }); + }), +]; diff --git a/src/mocks/handlers/index.js b/src/mocks/handlers/index.js index aa07d444..bce489c7 100644 --- a/src/mocks/handlers/index.js +++ b/src/mocks/handlers/index.js @@ -10,6 +10,8 @@ import { industryHandlers } from './industry'; import { conceptHandlers } from './concept'; import { stockHandlers } from './stock'; import { companyHandlers } from './company'; +import { marketHandlers } from './market'; +import { financialHandlers } from './financial'; // 可以在这里添加更多的 handlers // import { userHandlers } from './user'; @@ -24,5 +26,7 @@ export const handlers = [ ...conceptHandlers, ...stockHandlers, ...companyHandlers, + ...marketHandlers, + ...financialHandlers, // ...userHandlers, ]; diff --git a/src/mocks/handlers/market.js b/src/mocks/handlers/market.js new file mode 100644 index 00000000..e9515767 --- /dev/null +++ b/src/mocks/handlers/market.js @@ -0,0 +1,74 @@ +// src/mocks/handlers/market.js +// 市场行情相关的 Mock Handlers + +import { http, HttpResponse } from 'msw'; +import { generateMarketData } from '../data/market'; + +// 模拟延迟 +const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); + +export const marketHandlers = [ + // 1. 成交数据 + http.get('/api/market/trade/:stockCode', async ({ params, request }) => { + await delay(200); + const { stockCode } = params; + const data = generateMarketData(stockCode); + return HttpResponse.json(data.tradeData); + }), + + // 2. 资金流向 + http.get('/api/market/funding/:stockCode', async ({ params }) => { + await delay(200); + const { stockCode } = params; + const data = generateMarketData(stockCode); + return HttpResponse.json(data.fundingData); + }), + + // 3. 大单统计 + http.get('/api/market/bigdeal/:stockCode', async ({ params }) => { + await delay(200); + const { stockCode } = params; + const data = generateMarketData(stockCode); + return HttpResponse.json(data.bigDealData); + }), + + // 4. 异动分析 + http.get('/api/market/unusual/:stockCode', async ({ params }) => { + await delay(200); + const { stockCode } = params; + const data = generateMarketData(stockCode); + return HttpResponse.json(data.unusualData); + }), + + // 5. 股权质押 + http.get('/api/market/pledge/:stockCode', async ({ params }) => { + await delay(200); + const { stockCode } = params; + const data = generateMarketData(stockCode); + return HttpResponse.json(data.pledgeData); + }), + + // 6. 市场摘要 + http.get('/api/market/summary/:stockCode', async ({ params }) => { + await delay(200); + const { stockCode } = params; + const data = generateMarketData(stockCode); + return HttpResponse.json(data.summaryData); + }), + + // 7. 涨停分析 + http.get('/api/market/rise-analysis/:stockCode', async ({ params }) => { + await delay(200); + const { stockCode } = params; + const data = generateMarketData(stockCode); + return HttpResponse.json(data.riseAnalysisData); + }), + + // 8. 最新分时数据 + http.get('/api/stock/:stockCode/latest-minute', async ({ params }) => { + await delay(300); + const { stockCode } = params; + const data = generateMarketData(stockCode); + return HttpResponse.json(data.latestMinuteData); + }), +];