526 lines
23 KiB
JavaScript
526 lines
23 KiB
JavaScript
// src/mocks/handlers/concept.js
|
||
// 概念相关的 Mock Handlers
|
||
|
||
import { http, HttpResponse } from 'msw';
|
||
|
||
// 模拟延迟
|
||
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
||
|
||
// 生成历史触发时间(3-5个历史日期)
|
||
const generateHappenedTimes = (seed) => {
|
||
const times = [];
|
||
const count = 3 + (seed % 3); // 3-5个时间点
|
||
for (let i = 0; i < count; i++) {
|
||
const daysAgo = 30 + (seed * 7 + i * 11) % 330; // 30-360天前
|
||
const date = new Date();
|
||
date.setDate(date.getDate() - daysAgo);
|
||
times.push(date.toISOString().split('T')[0]);
|
||
}
|
||
return times.sort().reverse(); // 降序排列
|
||
};
|
||
|
||
// 生成核心相关股票
|
||
const generateStocksForConcept = (seed, count = 4) => {
|
||
const stockPool = [
|
||
{ name: '贵州茅台', code: '600519' },
|
||
{ name: '宁德时代', code: '300750' },
|
||
{ name: '中国平安', code: '601318' },
|
||
{ name: '比亚迪', code: '002594' },
|
||
{ name: '隆基绿能', code: '601012' },
|
||
{ name: '阳光电源', code: '300274' },
|
||
{ name: '三一重工', code: '600031' },
|
||
{ name: '中芯国际', code: '688981' },
|
||
{ name: '京东方A', code: '000725' },
|
||
{ name: '立讯精密', code: '002475' }
|
||
];
|
||
|
||
const stocks = [];
|
||
for (let i = 0; i < count; i++) {
|
||
const stockIndex = (seed + i * 7) % stockPool.length;
|
||
const stock = stockPool[stockIndex];
|
||
stocks.push({
|
||
stock_name: stock.name,
|
||
stock_code: stock.code,
|
||
reason: `作为行业龙头企业,${stock.name}在该领域具有核心竞争优势,市场份额领先,技术实力雄厚。`,
|
||
change_pct: parseFloat((Math.random() * 15 - 5).toFixed(2)) // -5% ~ +10%
|
||
});
|
||
}
|
||
return stocks;
|
||
};
|
||
|
||
// 生成热门概念数据
|
||
export const generatePopularConcepts = (size = 20) => {
|
||
const concepts = [
|
||
'人工智能', '新能源汽车', '半导体', '光伏', '锂电池',
|
||
'储能', '氢能源', '风电', '特高压', '工业母机',
|
||
'军工', '航空航天', '卫星导航', '量子科技', '数字货币',
|
||
'云计算', '大数据', '物联网', '5G', '6G',
|
||
'元宇宙', '虚拟现实', 'AIGC', 'ChatGPT', '算力',
|
||
'芯片设计', '芯片制造', '半导体设备', '半导体材料', 'EDA',
|
||
'新能源', '风光储', '充电桩', '智能电网', '特斯拉',
|
||
'比亚迪', '宁德时代', '华为', '苹果产业链', '鸿蒙',
|
||
'国产软件', '信创', '网络安全', '数据安全', '量子通信',
|
||
'医疗器械', '创新药', '医美', 'CXO', '生物医药',
|
||
'疫苗', '中药', '医疗信息化', '智慧医疗', '基因测序'
|
||
];
|
||
|
||
const conceptDescriptions = {
|
||
'人工智能': '人工智能是"技术突破+政策扶持"双轮驱动的硬科技主题。随着大模型技术的突破,AI应用场景不断拓展,预计将催化算力、数据、应用三大产业链。',
|
||
'新能源汽车': '新能源汽车行业景气度持续向好,渗透率不断提升。政策支持力度大,产业链上下游企业均受益明显。',
|
||
'半导体': '国产半导体替代加速,自主可控需求强烈。政策和资金支持力度大,行业迎来黄金发展期。',
|
||
'光伏': '光伏装机量快速增长,成本持续下降,行业景气度维持高位。双碳目标下,光伏行业前景广阔。',
|
||
'锂电池': '锂电池技术进步,成本优势扩大,下游应用领域持续扩张。新能源汽车和储能需求旺盛。',
|
||
'储能': '储能市场爆发式增长,政策支持力度大,应用场景不断拓展。未来市场空间巨大。',
|
||
'默认': '该概念市场关注度较高,具有一定的投资价值。相关企业技术实力雄厚,市场前景广阔。'
|
||
};
|
||
|
||
const matchTypes = ['hybrid_knn', 'keyword', 'semantic'];
|
||
|
||
const results = [];
|
||
for (let i = 0; i < Math.min(size, concepts.length); i++) {
|
||
const changePct = (Math.random() * 12 - 2).toFixed(2); // -2% 到 +10%
|
||
const stockCount = Math.floor(Math.random() * 50) + 10; // 10-60 只股票
|
||
const score = parseFloat((Math.random() * 5 + 3).toFixed(2)); // 3-8 分数范围
|
||
|
||
results.push({
|
||
concept: concepts[i],
|
||
concept_id: `CONCEPT_${1000 + i}`,
|
||
stock_count: stockCount,
|
||
score: score, // 相关度分数
|
||
match_type: matchTypes[i % 3], // 匹配类型
|
||
description: conceptDescriptions[concepts[i]] || conceptDescriptions['默认'],
|
||
price_info: {
|
||
avg_change_pct: parseFloat(changePct),
|
||
avg_price: parseFloat((Math.random() * 100 + 10).toFixed(2)),
|
||
total_market_cap: parseFloat((Math.random() * 1000 + 100).toFixed(2))
|
||
},
|
||
happened_times: generateHappenedTimes(i), // 历史触发时间
|
||
stocks: generateStocksForConcept(i, 4), // 核心相关股票
|
||
hot_score: Math.floor(Math.random() * 100)
|
||
});
|
||
}
|
||
|
||
// 按涨跌幅降序排序
|
||
results.sort((a, b) => b.price_info.avg_change_pct - a.price_info.avg_change_pct);
|
||
|
||
return results;
|
||
};
|
||
|
||
// 生成完整的概念统计数据(用于 ConceptStatsPanel)
|
||
const generateConceptStats = () => {
|
||
// 热门概念(涨幅最大的前5)
|
||
const hot_concepts = [
|
||
{ name: '小米大模型', change_pct: 18.76, stock_count: 12, news_count: 35 },
|
||
{ name: '人工智能', change_pct: 15.67, stock_count: 45, news_count: 23 },
|
||
{ name: '新能源汽车', change_pct: 12.34, stock_count: 38, news_count: 18 },
|
||
{ name: '芯片概念', change_pct: 9.87, stock_count: 52, news_count: 31 },
|
||
{ name: '5G通信', change_pct: 8.45, stock_count: 29, news_count: 15 },
|
||
];
|
||
|
||
// 冷门概念(跌幅最大的前5)
|
||
const cold_concepts = [
|
||
{ name: '房地产', change_pct: -8.76, stock_count: 33, news_count: 12 },
|
||
{ name: '煤炭开采', change_pct: -6.54, stock_count: 25, news_count: 8 },
|
||
{ name: '传统零售', change_pct: -5.43, stock_count: 19, news_count: 6 },
|
||
{ name: '钢铁冶炼', change_pct: -4.21, stock_count: 28, news_count: 9 },
|
||
{ name: '纺织服装', change_pct: -3.98, stock_count: 15, news_count: 4 },
|
||
];
|
||
|
||
// 活跃概念(新闻+研报最多的前5)
|
||
const active_concepts = [
|
||
{ name: '人工智能', news_count: 89, report_count: 15, total_mentions: 104 },
|
||
{ name: '芯片概念', news_count: 76, report_count: 12, total_mentions: 88 },
|
||
{ name: '新能源汽车', news_count: 65, report_count: 18, total_mentions: 83 },
|
||
{ name: '生物医药', news_count: 54, report_count: 9, total_mentions: 63 },
|
||
{ name: '量子科技', news_count: 41, report_count: 7, total_mentions: 48 },
|
||
];
|
||
|
||
// 波动最大的概念(前5)
|
||
const volatile_concepts = [
|
||
{ name: '区块链', volatility: 23.45, avg_change: 3.21, max_change: 12.34 },
|
||
{ name: '元宇宙', volatility: 21.87, avg_change: 2.98, max_change: 11.76 },
|
||
{ name: '虚拟现实', volatility: 19.65, avg_change: -1.23, max_change: 9.87 },
|
||
{ name: '游戏概念', volatility: 18.32, avg_change: 4.56, max_change: 10.45 },
|
||
{ name: '在线教育', volatility: 17.89, avg_change: -2.11, max_change: 8.76 },
|
||
];
|
||
|
||
// 动量概念(连续上涨的前5)
|
||
const momentum_concepts = [
|
||
{ name: '数字经济', consecutive_days: 5, total_change: 18.76, avg_daily: 3.75 },
|
||
{ name: '云计算', consecutive_days: 4, total_change: 14.32, avg_daily: 3.58 },
|
||
{ name: '物联网', consecutive_days: 4, total_change: 12.89, avg_daily: 3.22 },
|
||
{ name: '大数据', consecutive_days: 3, total_change: 11.45, avg_daily: 3.82 },
|
||
{ name: '工业互联网', consecutive_days: 3, total_change: 9.87, avg_daily: 3.29 },
|
||
];
|
||
|
||
return {
|
||
hot_concepts,
|
||
cold_concepts,
|
||
active_concepts,
|
||
volatile_concepts,
|
||
momentum_concepts
|
||
};
|
||
};
|
||
|
||
// 概念相关的 Handlers
|
||
export const conceptHandlers = [
|
||
// 搜索概念(热门概念)
|
||
http.post('/concept-api/search', async ({ request }) => {
|
||
await delay(300);
|
||
|
||
try {
|
||
const body = await request.json();
|
||
const { query = '', size = 20, page = 1, sort_by = 'change_pct' } = body;
|
||
|
||
console.log('[Mock Concept] 搜索概念:', { query, size, page, sort_by });
|
||
|
||
// 生成数据(不过滤,模拟真实 API 的语义搜索返回热门概念)
|
||
let results = generatePopularConcepts(size);
|
||
console.log('[Mock Concept] 生成概念数量:', results.length);
|
||
|
||
// Mock 环境下不做过滤,直接返回热门概念
|
||
// 真实环境会根据 query 进行语义搜索
|
||
|
||
// 根据排序字段排序
|
||
if (sort_by === 'change_pct') {
|
||
results.sort((a, b) => b.price_info.avg_change_pct - a.price_info.avg_change_pct);
|
||
} else if (sort_by === 'stock_count') {
|
||
results.sort((a, b) => b.stock_count - a.stock_count);
|
||
} else if (sort_by === 'hot_score') {
|
||
results.sort((a, b) => b.hot_score - a.hot_score);
|
||
}
|
||
|
||
return HttpResponse.json({
|
||
results,
|
||
total: results.length,
|
||
page,
|
||
size,
|
||
message: '搜索成功'
|
||
});
|
||
} catch (error) {
|
||
console.error('[Mock Concept] 搜索概念失败:', error);
|
||
return HttpResponse.json(
|
||
{
|
||
results: [],
|
||
total: 0,
|
||
error: '搜索失败'
|
||
},
|
||
{ status: 500 }
|
||
);
|
||
}
|
||
}),
|
||
|
||
// 获取单个概念详情
|
||
http.get('/concept-api/concepts/:conceptId', async ({ params }) => {
|
||
await delay(300);
|
||
|
||
const { conceptId } = params;
|
||
console.log('[Mock Concept] 获取概念详情:', conceptId);
|
||
|
||
const concepts = generatePopularConcepts(50);
|
||
const concept = concepts.find(c => c.concept_id === conceptId || c.concept === conceptId);
|
||
|
||
if (concept) {
|
||
return HttpResponse.json({
|
||
...concept,
|
||
related_stocks: [
|
||
{ stock_code: '600519', stock_name: '贵州茅台', change_pct: 2.34 },
|
||
{ stock_code: '000858', stock_name: '五粮液', change_pct: 1.89 },
|
||
{ stock_code: '000568', stock_name: '泸州老窖', change_pct: 3.12 }
|
||
],
|
||
news: [
|
||
{ title: `${concept.concept}板块异动`, date: '2024-10-24', source: '财经新闻' }
|
||
]
|
||
});
|
||
} else {
|
||
return HttpResponse.json(
|
||
{ error: '概念不存在' },
|
||
{ status: 404 }
|
||
);
|
||
}
|
||
}),
|
||
|
||
// 获取概念相关股票
|
||
http.get('/concept-api/concepts/:conceptId/stocks', async ({ params, request }) => {
|
||
await delay(300);
|
||
|
||
const { conceptId } = params;
|
||
const url = new URL(request.url);
|
||
const limit = parseInt(url.searchParams.get('limit') || '20');
|
||
|
||
console.log('[Mock Concept] 获取概念相关股票:', { conceptId, limit });
|
||
|
||
// 生成模拟股票数据
|
||
const stocks = [];
|
||
for (let i = 0; i < limit; i++) {
|
||
stocks.push({
|
||
stock_code: `${600000 + i}`,
|
||
stock_name: `股票${i + 1}`,
|
||
change_pct: (Math.random() * 10 - 2).toFixed(2),
|
||
price: (Math.random() * 100 + 10).toFixed(2),
|
||
market_cap: (Math.random() * 1000 + 100).toFixed(2)
|
||
});
|
||
}
|
||
|
||
return HttpResponse.json({
|
||
stocks,
|
||
total: stocks.length,
|
||
concept_id: conceptId
|
||
});
|
||
}),
|
||
|
||
// 获取最新交易日期
|
||
http.get('http://111.198.58.126:16801/price/latest', async () => {
|
||
await delay(200);
|
||
|
||
const today = new Date();
|
||
const dateStr = today.toISOString().split('T')[0].replace(/-/g, '');
|
||
|
||
console.log('[Mock Concept] 获取最新交易日期:', dateStr);
|
||
|
||
return HttpResponse.json({
|
||
latest_date: dateStr,
|
||
timestamp: today.toISOString()
|
||
});
|
||
}),
|
||
|
||
// 搜索概念(硬编码 URL)
|
||
http.post('http://111.198.58.126:16801/search', async ({ request }) => {
|
||
await delay(300);
|
||
|
||
try {
|
||
const body = await request.json();
|
||
const { query = '', size = 20, page = 1, sort_by = 'change_pct' } = body;
|
||
|
||
console.log('[Mock Concept] 搜索概念 (硬编码URL):', { query, size, page, sort_by });
|
||
|
||
let results = generatePopularConcepts(size);
|
||
|
||
if (query) {
|
||
results = results.filter(item =>
|
||
item.concept.toLowerCase().includes(query.toLowerCase())
|
||
);
|
||
}
|
||
|
||
if (sort_by === 'change_pct') {
|
||
results.sort((a, b) => b.price_info.avg_change_pct - a.price_info.avg_change_pct);
|
||
} else if (sort_by === 'stock_count') {
|
||
results.sort((a, b) => b.stock_count - a.stock_count);
|
||
} else if (sort_by === 'hot_score') {
|
||
results.sort((a, b) => b.hot_score - a.hot_score);
|
||
}
|
||
|
||
return HttpResponse.json({
|
||
results,
|
||
total: results.length,
|
||
page,
|
||
size,
|
||
message: '搜索成功'
|
||
});
|
||
} catch (error) {
|
||
console.error('[Mock Concept] 搜索失败:', error);
|
||
return HttpResponse.json(
|
||
{ results: [], total: 0, error: '搜索失败' },
|
||
{ status: 500 }
|
||
);
|
||
}
|
||
}),
|
||
|
||
// 获取统计数据(直接访问外部 API)
|
||
http.get('http://111.198.58.126:16801/statistics', async ({ request }) => {
|
||
await delay(300);
|
||
|
||
const url = new URL(request.url);
|
||
const minStockCount = parseInt(url.searchParams.get('min_stock_count') || '3');
|
||
const days = parseInt(url.searchParams.get('days') || '7');
|
||
const startDate = url.searchParams.get('start_date');
|
||
const endDate = url.searchParams.get('end_date');
|
||
|
||
console.log('[Mock Concept] 获取统计数据 (直接API):', { minStockCount, days, startDate, endDate });
|
||
|
||
// 生成完整的统计数据
|
||
const statsData = generateConceptStats();
|
||
|
||
return HttpResponse.json({
|
||
success: true,
|
||
data: statsData,
|
||
note: 'Mock 数据',
|
||
params: {
|
||
min_stock_count: minStockCount,
|
||
days: days,
|
||
start_date: startDate,
|
||
end_date: endDate
|
||
},
|
||
updated_at: new Date().toISOString()
|
||
});
|
||
}),
|
||
|
||
// 获取统计数据(通过 nginx 代理)
|
||
http.get('/concept-api/statistics', async ({ request }) => {
|
||
await delay(300);
|
||
|
||
const url = new URL(request.url);
|
||
const minStockCount = parseInt(url.searchParams.get('min_stock_count') || '3');
|
||
const days = parseInt(url.searchParams.get('days') || '7');
|
||
const startDate = url.searchParams.get('start_date');
|
||
const endDate = url.searchParams.get('end_date');
|
||
|
||
console.log('[Mock Concept] 获取统计数据 (nginx代理):', { minStockCount, days, startDate, endDate });
|
||
|
||
// 生成完整的统计数据
|
||
const statsData = generateConceptStats();
|
||
|
||
return HttpResponse.json({
|
||
success: true,
|
||
data: statsData,
|
||
note: 'Mock 数据(通过 nginx 代理)',
|
||
params: {
|
||
min_stock_count: minStockCount,
|
||
days: days,
|
||
start_date: startDate,
|
||
end_date: endDate
|
||
},
|
||
updated_at: new Date().toISOString()
|
||
});
|
||
}),
|
||
|
||
// 获取概念价格时间序列
|
||
http.get('http://111.198.58.126:16801/concept/:conceptId/price-timeseries', async ({ params, request }) => {
|
||
await delay(300);
|
||
|
||
const { conceptId } = params;
|
||
const url = new URL(request.url);
|
||
const startDate = url.searchParams.get('start_date');
|
||
const endDate = url.searchParams.get('end_date');
|
||
|
||
console.log('[Mock Concept] 获取价格时间序列:', { conceptId, startDate, endDate });
|
||
|
||
// 生成时间序列数据
|
||
const timeseries = [];
|
||
const start = new Date(startDate || '2024-01-01');
|
||
const end = new Date(endDate || new Date());
|
||
const daysDiff = Math.ceil((end - start) / (1000 * 60 * 60 * 24));
|
||
|
||
for (let i = 0; i <= daysDiff; i++) {
|
||
const date = new Date(start);
|
||
date.setDate(date.getDate() + i);
|
||
|
||
// 跳过周末
|
||
if (date.getDay() !== 0 && date.getDay() !== 6) {
|
||
timeseries.push({
|
||
trade_date: date.toISOString().split('T')[0], // 改为 trade_date
|
||
avg_change_pct: parseFloat((Math.random() * 8 - 2).toFixed(2)), // 转为数值
|
||
stock_count: Math.floor(Math.random() * 30) + 10,
|
||
volume: Math.floor(Math.random() * 1000000000)
|
||
});
|
||
}
|
||
}
|
||
|
||
return HttpResponse.json({
|
||
concept_id: conceptId,
|
||
timeseries: timeseries,
|
||
start_date: startDate,
|
||
end_date: endDate
|
||
});
|
||
}),
|
||
|
||
// 获取概念相关新闻 (search_china_news)
|
||
http.get('http://111.198.58.126:21891/search_china_news', async ({ request }) => {
|
||
await delay(300);
|
||
|
||
const url = new URL(request.url);
|
||
const query = url.searchParams.get('query');
|
||
const exactMatch = url.searchParams.get('exact_match');
|
||
const startDate = url.searchParams.get('start_date');
|
||
const endDate = url.searchParams.get('end_date');
|
||
const topK = parseInt(url.searchParams.get('top_k') || '100');
|
||
|
||
console.log('[Mock Concept] 搜索中国新闻:', { query, exactMatch, startDate, endDate, topK });
|
||
|
||
// 生成新闻数据
|
||
const news = [];
|
||
const newsCount = Math.min(topK, Math.floor(Math.random() * 15) + 5); // 5-20 条新闻
|
||
|
||
for (let i = 0; i < newsCount; i++) {
|
||
const daysAgo = Math.floor(Math.random() * 100); // 0-100 天前
|
||
const date = new Date();
|
||
date.setDate(date.getDate() - daysAgo);
|
||
|
||
const hour = Math.floor(Math.random() * 24);
|
||
const minute = Math.floor(Math.random() * 60);
|
||
const publishedTime = `${date.toISOString().split('T')[0]} ${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:00`;
|
||
|
||
news.push({
|
||
id: `news_${i}`,
|
||
title: `${query || '概念'}板块动态:${['利好政策发布', '行业景气度提升', '龙头企业业绩超预期', '技术突破进展', '市场需求旺盛'][i % 5]}`,
|
||
detail: `${query || '概念'}相关新闻详细内容。近期${query || '概念'}板块表现活跃,市场关注度持续上升。多家券商研报指出,${query || '概念'}行业前景广阔,建议重点关注龙头企业投资机会。`,
|
||
description: `${query || '概念'}板块最新动态摘要...`,
|
||
source: ['新浪财经', '东方财富网', '财联社', '证券时报', '中国证券报', '上海证券报'][Math.floor(Math.random() * 6)],
|
||
published_time: publishedTime,
|
||
url: `https://finance.sina.com.cn/stock/news/${date.getFullYear()}${String(date.getMonth() + 1).padStart(2, '0')}${String(date.getDate()).padStart(2, '0')}/news_${i}.html`
|
||
});
|
||
}
|
||
|
||
// 按时间降序排序
|
||
news.sort((a, b) => new Date(b.published_time) - new Date(a.published_time));
|
||
|
||
// 返回数组(不是对象)
|
||
return HttpResponse.json(news);
|
||
}),
|
||
|
||
// 获取概念相关研报 (search)
|
||
http.get('http://111.198.58.126:8811/search', async ({ request }) => {
|
||
await delay(300);
|
||
|
||
const url = new URL(request.url);
|
||
const query = url.searchParams.get('query');
|
||
const mode = url.searchParams.get('mode');
|
||
const exactMatch = url.searchParams.get('exact_match');
|
||
const size = parseInt(url.searchParams.get('size') || '30');
|
||
const startDate = url.searchParams.get('start_date');
|
||
|
||
console.log('[Mock Concept] 搜索研报:', { query, mode, exactMatch, size, startDate });
|
||
|
||
// 生成研报数据
|
||
const reports = [];
|
||
const reportCount = Math.min(size, Math.floor(Math.random() * 10) + 3); // 3-12 份研报
|
||
|
||
const publishers = ['中信证券', '国泰君安', '华泰证券', '招商证券', '海通证券', '广发证券', '申万宏源', '兴业证券'];
|
||
const authors = ['张明', '李华', '王强', '刘洋', '陈杰', '赵敏'];
|
||
const ratings = ['买入', '增持', '中性', '减持', '强烈推荐'];
|
||
const securityNames = ['行业研究', '公司研究', '策略研究', '宏观研究', '固收研究'];
|
||
|
||
for (let i = 0; i < reportCount; i++) {
|
||
const daysAgo = Math.floor(Math.random() * 100); // 0-100 天前
|
||
const date = new Date();
|
||
date.setDate(date.getDate() - daysAgo);
|
||
|
||
const declareDate = `${date.toISOString().split('T')[0]} ${String(Math.floor(Math.random() * 24)).padStart(2, '0')}:${String(Math.floor(Math.random() * 60)).padStart(2, '0')}:00`;
|
||
|
||
reports.push({
|
||
id: `report_${i}`,
|
||
report_title: `${query || '概念'}行业${['深度研究报告', '投资策略分析', '行业景气度跟踪', '估值分析报告', '竞争格局研究'][i % 5]}`,
|
||
content: `${query || '概念'}行业研究报告内容摘要。\n\n核心观点:\n1. ${query || '概念'}行业景气度持续向好,市场规模预计将保持高速增长。\n2. 龙头企业凭借技术优势和规模效应,市场份额有望进一步提升。\n3. 政策支持力度加大,为行业发展提供有力保障。\n\n投资建议:建议重点关注行业龙头企业,给予"${ratings[Math.floor(Math.random() * ratings.length)]}"评级。`,
|
||
abstract: `本报告深入分析了${query || '概念'}行业的发展趋势、竞争格局和投资机会,认为行业具备良好的成长性...`,
|
||
publisher: publishers[Math.floor(Math.random() * publishers.length)],
|
||
author: authors[Math.floor(Math.random() * authors.length)],
|
||
declare_date: declareDate,
|
||
rating: ratings[Math.floor(Math.random() * ratings.length)],
|
||
security_name: securityNames[Math.floor(Math.random() * securityNames.length)],
|
||
content_url: `https://pdf.dfcfw.com/pdf/H3_${1000000 + i}_1_${date.getFullYear()}${String(date.getMonth() + 1).padStart(2, '0')}${String(date.getDate()).padStart(2, '0')}.pdf`
|
||
});
|
||
}
|
||
|
||
// 按时间降序排序
|
||
reports.sort((a, b) => new Date(b.declare_date) - new Date(a.declare_date));
|
||
|
||
// 返回符合组件期望的格式
|
||
return HttpResponse.json({
|
||
results: reports,
|
||
total: reports.length,
|
||
query: query,
|
||
mode: mode
|
||
});
|
||
})
|
||
];
|