From 933932b86d39b4afdd01958c527d7c15ce93765e Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Fri, 31 Oct 2025 20:11:50 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E6=B7=BB=E5=8A=A0mock=E6=95=B0?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mocks/data/events.js | 120 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 111 insertions(+), 9 deletions(-) diff --git a/src/mocks/data/events.js b/src/mocks/data/events.js index dd640f73..959f3d0d 100644 --- a/src/mocks/data/events.js +++ b/src/mocks/data/events.js @@ -609,7 +609,7 @@ function generateEventDescription(industry, importance, seed) { return impacts[importance] + details[seed % details.length]; } -// 生成关键词 +// 生成关键词(对象数组格式,包含完整信息) function generateKeywords(industry, seed) { const commonKeywords = ['政策', '利好', '业绩', '涨停', '龙头', '突破', '合作', '投资']; const industryKeywords = { @@ -620,12 +620,93 @@ function generateKeywords(industry, seed) { '消费': ['白酒', '食品', '家电', '零售', '免税'], }; - const keywords = [ + // 概念描述模板 + const descriptionTemplates = { + '政策': '政策性利好消息对相关行业和板块产生积极影响,带动市场情绪和资金流向。', + '利好': '市场积极因素推动相关板块上涨,投资者情绪乐观,资金持续流入。', + '业绩': '公司业绩超预期增长,盈利能力提升,市场给予更高估值预期。', + '涨停': '强势涨停板显示市场热度,短期资金追捧,板块效应明显。', + '龙头': '行业龙头企业具备竞争优势,市场地位稳固,带动板块走势。', + '突破': '技术面或基本面出现重大突破,打开上涨空间,吸引资金关注。', + '合作': '战略合作为公司带来新的增长点,业务协同效应显著。', + '投资': '重大投资项目落地,长期发展空间广阔,市场预期良好。', + '芯片': '国产芯片替代加速,自主可控需求强烈,政策和资金支持力度大。', + '晶圆': '晶圆产能紧张,供需关系改善,相关企业盈利能力提升。', + '封测': '封测环节景气度上行,订单饱满,产能利用率提高。', + 'AI芯片': '人工智能快速发展带动AI芯片需求爆发,市场空间巨大。', + '国产替代': '国产替代进程加速,政策扶持力度大,进口依赖度降低。', + '电池': '新能源汽车渗透率提升,动力电池需求旺盛,技术迭代加快。', + '光伏': '光伏装机量快速增长,成本持续下降,行业景气度维持高位。', + '储能': '储能市场爆发式增长,政策支持力度大,应用场景不断拓展。', + '新能源车': '新能源汽车销量高增长,渗透率持续提升,产业链受益明显。', + '锂电': '锂电池技术进步,成本优势扩大,下游应用领域持续扩张。', + '大模型': '大语言模型技术突破,商业化进程加速,应用场景广阔。', + 'AI应用': '人工智能应用落地加速,垂直领域渗透率提升,市场空间巨大。', + '算力': '算力需求持续增长,数据中心建设加速,相关产业链受益。', + '数据': '数据要素市场化改革推进,数据价值释放,相关企业盈利模式清晰。', + '机器学习': '机器学习技术成熟,应用场景丰富,商业价值逐步显现。', + '创新药': '创新药研发管线丰富,商业化进程顺利,市场给予高估值。', + 'CRO': 'CRO行业高景气,订单充足,盈利能力稳定增长。', + '医疗器械': '医疗器械国产化率提升,技术创新加快,市场份额扩大。', + '生物制药': '生物制药技术突破,产品管线丰富,商业化前景广阔。', + '仿制药': '仿制药集采常态化,质量优势企业市场份额提升。', + '白酒': '白酒消费升级,高端产品量价齐升,龙头企业护城河深厚。', + '食品': '食品饮料需求稳定,品牌力强的企业市场份额持续提升。', + '家电': '家电消费需求回暖,智能化升级带动产品结构优化。', + '零售': '零售行业数字化转型,线上线下融合,运营效率提升。', + '免税': '免税政策优化,消费回流加速,行业景气度上行。' + }; + + const keywordNames = [ ...commonKeywords.slice(seed % 3, seed % 3 + 3), ...(industryKeywords[industry] || []).slice(0, 2) - ]; + ].slice(0, 5); - return keywords.slice(0, 5); + const matchTypes = ['hybrid_knn', 'keyword', 'semantic']; + + // 生成历史触发时间(3-5个历史日期) + const generateHappenedTimes = (baseSeed) => { + const times = []; + const count = 3 + (baseSeed % 3); // 3-5个时间点 + for (let i = 0; i < count; i++) { + const daysAgo = 30 + (baseSeed * 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(); // 降序排列 + }; + + // 生成核心相关股票(4-6只) + const generateRelatedStocks = (conceptName, baseSeed) => { + const stockCount = 4 + (baseSeed % 3); // 4-6只股票 + const selectedStocks = []; + + for (let i = 0; i < stockCount && i < stockPool.length; i++) { + const stockIndex = (baseSeed + i * 7) % stockPool.length; + const stock = stockPool[stockIndex]; + selectedStocks.push({ + stock_name: stock.stock_name, + stock_code: stock.stock_code, + reason: relationDescTemplates[(baseSeed + i) % relationDescTemplates.length], + change_pct: (Math.random() * 15 - 5).toFixed(2) // -5% ~ +10% + }); + } + + return selectedStocks; + }; + + // 将字符串数组转换为对象数组,包含完整字段 + return keywordNames.map((name, index) => ({ + name: name, + stock_count: 10 + Math.floor((seed + index) % 30), // 10-39个相关股票 + relevance: 70 + Math.floor((seed * 7 + index * 11) % 30), // 70-99的相关度 + description: descriptionTemplates[name] || `${name}相关概念,市场关注度较高,具有一定的投资价值。`, + avg_change_pct: (Math.random() * 15 - 5).toFixed(2), // -5% ~ +10% 的涨跌幅 + match_type: matchTypes[(seed + index) % 3], // 随机匹配类型 + happened_times: generateHappenedTimes(seed + index), // 历史触发时间 + stocks: generateRelatedStocks(name, seed + index) // 核心相关股票 + })); } /** @@ -670,22 +751,42 @@ export function generateMockEvents(params = {}) { const relatedStockCount = 2 + (i % 4); // 2-5个股票 const relatedStocks = []; const industryStocks = stockPool.filter(s => s.industry === industry); + const addedStockCodes = new Set(); // 用于去重 // 优先选择同行业股票 if (industryStocks.length > 0) { for (let j = 0; j < Math.min(relatedStockCount, industryStocks.length); j++) { - relatedStocks.push(industryStocks[j % industryStocks.length].stock_code); + const stock = industryStocks[j % industryStocks.length]; + if (!addedStockCodes.has(stock.stock_code)) { + relatedStocks.push({ + stock_name: stock.stock_name, + stock_code: stock.stock_code, + relation_desc: relationDescTemplates[(i + j) % relationDescTemplates.length] + }); + addedStockCodes.add(stock.stock_code); + } } } // 如果同行业股票不够,从整个 stockPool 中补充 - while (relatedStocks.length < relatedStockCount && relatedStocks.length < stockPool.length) { - const randomStock = stockPool[relatedStocks.length % stockPool.length]; - if (!relatedStocks.includes(randomStock.stock_code)) { - relatedStocks.push(randomStock.stock_code); + let poolIndex = 0; + while (relatedStocks.length < relatedStockCount && poolIndex < stockPool.length) { + const randomStock = stockPool[poolIndex % stockPool.length]; + if (!addedStockCodes.has(randomStock.stock_code)) { + relatedStocks.push({ + stock_name: randomStock.stock_name, + stock_code: randomStock.stock_code, + relation_desc: relationDescTemplates[(i + poolIndex) % relationDescTemplates.length] + }); + addedStockCodes.add(randomStock.stock_code); } + poolIndex++; } + // 计算交易日期(模拟下一交易日,这里简单地加1天) + const tradingDate = new Date(createdAt); + tradingDate.setDate(tradingDate.getDate() + 1); + allEvents.push({ id: i + 1, title: generateEventTitle(industry, i), @@ -696,6 +797,7 @@ export function generateMockEvents(params = {}) { status: 'published', created_at: createdAt.toISOString(), updated_at: createdAt.toISOString(), + trading_date: tradingDate.toISOString().split('T')[0], // YYYY-MM-DD 格式 hot_score: hotScore, view_count: Math.floor(Math.random() * 10000), related_avg_chg: parseFloat(relatedAvgChg),