feat: 添加mock数据
This commit is contained in:
@@ -27,52 +27,65 @@ const CitationMark = ({ citationId, citation }) => {
|
|||||||
|
|
||||||
// 引用卡片内容
|
// 引用卡片内容
|
||||||
const citationContent = (
|
const citationContent = (
|
||||||
<div style={{ maxWidth: 350, padding: '8px 4px' }}>
|
<div style={{ maxWidth: 320, padding: '8px 10px' }}>
|
||||||
{/* 作者 */}
|
{/* 报告标题 - 顶部突出显示 */}
|
||||||
<Space align="start" style={{ marginBottom: 8 }}>
|
<div style={{ marginBottom: 8 }}>
|
||||||
<UserOutlined style={{ color: '#1890ff', marginTop: 4 }} />
|
<Text
|
||||||
<div>
|
strong
|
||||||
<Text type="secondary" style={{ fontSize: 12 }}>作者</Text>
|
style={{
|
||||||
<br />
|
fontSize: 14,
|
||||||
<Text strong style={{ fontSize: 13 }}>{citation.author}</Text>
|
fontWeight: 600,
|
||||||
|
color: '#262626',
|
||||||
|
display: 'block',
|
||||||
|
lineHeight: 1.3
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{citation.report_title}
|
||||||
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* 作者和日期 - 左右分布 */}
|
||||||
|
<div style={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginBottom: 8,
|
||||||
|
paddingBottom: 8,
|
||||||
|
borderBottom: '1px solid #f0f0f0'
|
||||||
|
}}>
|
||||||
|
{/* 左侧:作者 */}
|
||||||
|
<Space size={4}>
|
||||||
|
<UserOutlined style={{ color: '#1890ff', fontSize: 12 }} />
|
||||||
|
<Text style={{ fontSize: 12, color: '#595959' }}>
|
||||||
|
{citation.author}
|
||||||
|
</Text>
|
||||||
</Space>
|
</Space>
|
||||||
|
|
||||||
<Divider style={{ margin: '8px 0' }} />
|
{/* 右侧:发布日期(重点标注) */}
|
||||||
|
<Space size={4}>
|
||||||
{/* 报告标题 */}
|
<CalendarOutlined style={{ color: '#fa8c16', fontSize: 12 }} />
|
||||||
<Space align="start" style={{ marginBottom: 8 }}>
|
<Text
|
||||||
<FileTextOutlined style={{ color: '#52c41a', marginTop: 4 }} />
|
strong
|
||||||
<div>
|
style={{
|
||||||
<Text type="secondary" style={{ fontSize: 12 }}>报告标题</Text>
|
fontSize: 12,
|
||||||
<br />
|
fontWeight: 600,
|
||||||
<Text strong style={{ fontSize: 13 }}>{citation.report_title}</Text>
|
color: '#fa8c16'
|
||||||
</div>
|
}}
|
||||||
|
>
|
||||||
|
{citation.declare_date}
|
||||||
|
</Text>
|
||||||
</Space>
|
</Space>
|
||||||
|
|
||||||
<Divider style={{ margin: '8px 0' }} />
|
|
||||||
|
|
||||||
{/* 发布日期 */}
|
|
||||||
<Space align="start" style={{ marginBottom: 8 }}>
|
|
||||||
<CalendarOutlined style={{ color: '#faad14', marginTop: 4 }} />
|
|
||||||
<div>
|
|
||||||
<Text type="secondary" style={{ fontSize: 12 }}>发布日期</Text>
|
|
||||||
<br />
|
|
||||||
<Text style={{ fontSize: 13 }}>{citation.declare_date}</Text>
|
|
||||||
</div>
|
</div>
|
||||||
</Space>
|
|
||||||
|
|
||||||
<Divider style={{ margin: '8px 0' }} />
|
|
||||||
|
|
||||||
{/* 摘要片段 */}
|
{/* 摘要片段 */}
|
||||||
<div>
|
<div>
|
||||||
<Text type="secondary" style={{ fontSize: 12, display: 'block', marginBottom: 4 }}>
|
<Text type="secondary" style={{ fontSize: 11, display: 'block', marginBottom: 4 }}>
|
||||||
摘要片段
|
摘要片段
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
fontSize: 13,
|
fontSize: 12,
|
||||||
lineHeight: 1.6,
|
lineHeight: 1.5,
|
||||||
display: 'block',
|
display: 'block',
|
||||||
color: '#595959'
|
color: '#595959'
|
||||||
}}
|
}}
|
||||||
@@ -100,7 +113,7 @@ const CitationMark = ({ citationId, citation }) => {
|
|||||||
title={`引用来源 [${citationId}]`}
|
title={`引用来源 [${citationId}]`}
|
||||||
trigger={triggerType}
|
trigger={triggerType}
|
||||||
placement="top"
|
placement="top"
|
||||||
overlayInnerStyle={{ maxWidth: 380 }}
|
overlayInnerStyle={{ maxWidth: 340, padding: '8px' }}
|
||||||
open={popoverVisible}
|
open={popoverVisible}
|
||||||
onOpenChange={setPopoverVisible}
|
onOpenChange={setPopoverVisible}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -528,7 +528,7 @@ const StockChartAntdModal = ({
|
|||||||
{stock?.relation_desc?.data ? (
|
{stock?.relation_desc?.data ? (
|
||||||
// 使用引用组件(带研报来源)
|
// 使用引用组件(带研报来源)
|
||||||
<CitedContent
|
<CitedContent
|
||||||
data={stock.relation_desc.data}
|
data={stock.relation_desc}
|
||||||
title="关联描述"
|
title="关联描述"
|
||||||
showAIBadge={true}
|
showAIBadge={true}
|
||||||
containerStyle={{ marginTop: 16 }}
|
containerStyle={{ marginTop: 16 }}
|
||||||
|
|||||||
@@ -49,6 +49,12 @@ const relationDescTemplates = [
|
|||||||
'与行业巨头建立战略合作,订单保障充足。大客户资源优势明显,业务增长确定性强。',
|
'与行业巨头建立战略合作,订单保障充足。大客户资源优势明显,业务增长确定性强。',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// 模拟作者列表
|
||||||
|
const authorPool = [
|
||||||
|
"张明", "李华", "王芳", "陈强", "赵磊", "孙杰", "周磊", "吴洋",
|
||||||
|
"刘畅", "林芳", "郑华", "钱敏", "张敏", "赵强", "张华", "李明"
|
||||||
|
];
|
||||||
|
|
||||||
// 生成随机关联股票数据
|
// 生成随机关联股票数据
|
||||||
export function generateRelatedStocks(eventId, count = 5) {
|
export function generateRelatedStocks(eventId, count = 5) {
|
||||||
// 使用事件ID作为随机种子,确保相同事件ID返回相同的股票列表
|
// 使用事件ID作为随机种子,确保相同事件ID返回相同的股票列表
|
||||||
@@ -60,11 +66,49 @@ export function generateRelatedStocks(eventId, count = 5) {
|
|||||||
const index = (seed * 17 + i * 13) % stockPool.length;
|
const index = (seed * 17 + i * 13) % stockPool.length;
|
||||||
const stock = stockPool[index];
|
const stock = stockPool[index];
|
||||||
const descIndex = (seed * 7 + i * 11) % relationDescTemplates.length;
|
const descIndex = (seed * 7 + i * 11) % relationDescTemplates.length;
|
||||||
|
const authorIndex1 = (seed * 3 + i * 5) % authorPool.length;
|
||||||
|
const authorIndex2 = (seed * 5 + i * 7) % authorPool.length;
|
||||||
|
|
||||||
|
// 获取模板文本
|
||||||
|
const templateText = relationDescTemplates[descIndex];
|
||||||
|
|
||||||
|
// 将模板文本分成两部分作为query_part
|
||||||
|
const sentences = templateText.split('。');
|
||||||
|
const queryPart1 = sentences[0] || templateText.substring(0, 30);
|
||||||
|
const queryPart2 = sentences[1] || templateText.substring(30, 60);
|
||||||
|
|
||||||
|
// 生成随机日期(基于seed)
|
||||||
|
const baseDate = new Date('2025-08-01');
|
||||||
|
const daysOffset1 = (seed * i * 3) % 30;
|
||||||
|
const daysOffset2 = (seed * i * 5) % 30;
|
||||||
|
const date1 = new Date(baseDate);
|
||||||
|
date1.setDate(date1.getDate() + daysOffset1);
|
||||||
|
const date2 = new Date(baseDate);
|
||||||
|
date2.setDate(date2.getDate() + daysOffset2);
|
||||||
|
|
||||||
selectedStocks.push({
|
selectedStocks.push({
|
||||||
stock_code: stock.stock_code,
|
stock_code: stock.stock_code,
|
||||||
stock_name: stock.stock_name,
|
stock_name: stock.stock_name,
|
||||||
relation_desc: relationDescTemplates[descIndex],
|
relation_desc: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
author: authorPool[authorIndex1],
|
||||||
|
sentences: sentences[0] + '。' + (sentences[1] || ''),
|
||||||
|
query_part: queryPart1,
|
||||||
|
match_score: i < 2 ? "优" : "良",
|
||||||
|
declare_date: date1.toISOString(),
|
||||||
|
report_title: `${stock.stock_name}:行业分析与投资价值研究-深度报告`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
author: authorPool[authorIndex2],
|
||||||
|
sentences: sentences.slice(2).join('。') || templateText,
|
||||||
|
query_part: queryPart2 || '政策催化,市场关注度提升',
|
||||||
|
match_score: i < 3 ? "优" : "良",
|
||||||
|
declare_date: date2.toISOString(),
|
||||||
|
report_title: `${stock.industry}行业:事件驱动下的投资机会分析`
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
industry: stock.industry,
|
industry: stock.industry,
|
||||||
// 可选字段 - 用于前端显示更多信息
|
// 可选字段 - 用于前端显示更多信息
|
||||||
relevance_score: Math.max(60, 100 - i * 8), // 相关性评分,递减
|
relevance_score: Math.max(60, 100 - i * 8), // 相关性评分,递减
|
||||||
@@ -83,7 +127,26 @@ export const mockEventStocks = {
|
|||||||
{
|
{
|
||||||
stock_code: '600519.SH',
|
stock_code: '600519.SH',
|
||||||
stock_name: '贵州茅台',
|
stock_name: '贵州茅台',
|
||||||
relation_desc: '白酒行业绝对龙头,高端消费代表性标的。消费刺激政策将直接提振高端白酒需求,公司品牌溢价能力强,提价预期明确。2024年产能持续释放,叠加渠道库存处于低位,业绩增长确定性高。机构持仓集中度高,资金关注度极高。',
|
relation_desc: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
author: "张明",
|
||||||
|
sentences: "贵州茅台作为白酒行业绝对龙头,品牌溢价能力强,提价预期明确。2024年产能持续释放,叠加渠道库存处于低位,业绩增长确定性高。",
|
||||||
|
query_part: "白酒行业绝对龙头,高端消费代表性标的",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-03-15T00:00:00",
|
||||||
|
report_title: "贵州茅台:高端白酒龙头,消费复苏核心受益标的-深度报告"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
author: "李华",
|
||||||
|
sentences: "消费刺激政策将直接提振高端白酒需求,茅台作为高端消费代表性品牌,需求弹性大,定价权强。机构持仓集中度高,资金关注度极高。",
|
||||||
|
query_part: "消费刺激政策直接受益,品牌溢价能力行业领先",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-03-20T00:00:00",
|
||||||
|
report_title: "白酒行业:消费政策催化,高端白酒迎来配置良机"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
industry: '白酒',
|
industry: '白酒',
|
||||||
relevance_score: 95,
|
relevance_score: 95,
|
||||||
impact_level: 'high',
|
impact_level: 'high',
|
||||||
@@ -91,7 +154,26 @@ export const mockEventStocks = {
|
|||||||
{
|
{
|
||||||
stock_code: '000858.SZ',
|
stock_code: '000858.SZ',
|
||||||
stock_name: '五粮液',
|
stock_name: '五粮液',
|
||||||
relation_desc: '白酒行业第二梯队领军企业,产品矩阵完善。消费复苏背景下,公司中高端产品结构优化进程加快,次高端市场份额稳步提升。管理层改革成效显著,渠道改革红利持续释放。估值修复空间较大,股价弹性优于行业平均。',
|
relation_desc: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
author: "王芳",
|
||||||
|
sentences: "五粮液作为白酒行业第二梯队领军企业,产品矩阵完善,中高端产品结构优化进程加快。管理层改革成效显著,渠道改革红利持续释放。",
|
||||||
|
query_part: "白酒行业第二梯队领军企业,产品矩阵完善",
|
||||||
|
match_score: "良",
|
||||||
|
declare_date: "2025-03-18T00:00:00",
|
||||||
|
report_title: "五粮液:改革红利释放,次高端市场份额稳步提升"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
author: "陈强",
|
||||||
|
sentences: "消费复苏背景下,五粮液次高端市场份额稳步提升。估值修复空间较大,股价弹性优于行业平均水平。",
|
||||||
|
query_part: "消费复苏受益明显,估值修复空间大",
|
||||||
|
match_score: "良",
|
||||||
|
declare_date: "2025-03-22T00:00:00",
|
||||||
|
report_title: "白酒行业复盘:次高端品牌估值修复进行时"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
industry: '白酒',
|
industry: '白酒',
|
||||||
relevance_score: 90,
|
relevance_score: 90,
|
||||||
impact_level: 'high',
|
impact_level: 'high',
|
||||||
@@ -119,7 +201,26 @@ export const mockEventStocks = {
|
|||||||
{
|
{
|
||||||
stock_code: '002415.SZ',
|
stock_code: '002415.SZ',
|
||||||
stock_name: '海康威视',
|
stock_name: '海康威视',
|
||||||
relation_desc: 'AI+安防龙头企业,智能视觉技术全球领先。人工智能政策支持下,公司AI芯片、算法、云平台业务增长迅速。智慧城市、智能交通等政府项目订单充足,海外市场拓展提速。研发投入占比保持10%以上,技术护城河持续加深。',
|
relation_desc: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
author: "赵敏",
|
||||||
|
sentences: "海康威视作为AI+安防龙头企业,智能视觉技术全球领先。公司AI芯片、算法、云平台业务增长迅速,研发投入占比保持10%以上。",
|
||||||
|
query_part: "AI+安防龙头企业,智能视觉技术全球领先",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-04-10T00:00:00",
|
||||||
|
report_title: "海康威视:AI赋能安防,技术护城河持续加深-深度报告"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
author: "孙杰",
|
||||||
|
sentences: "人工智能政策支持下,智慧城市、智能交通等政府项目订单充足。海外市场拓展提速,国际化战略成效显著。",
|
||||||
|
query_part: "人工智能政策支持,政府项目订单充足",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-04-12T00:00:00",
|
||||||
|
report_title: "AI产业链深度:政策催化下的投资机遇分析"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
industry: '安防',
|
industry: '安防',
|
||||||
relevance_score: 92,
|
relevance_score: 92,
|
||||||
impact_level: 'high',
|
impact_level: 'high',
|
||||||
@@ -127,7 +228,34 @@ export const mockEventStocks = {
|
|||||||
{
|
{
|
||||||
stock_code: '000063.SZ',
|
stock_code: '000063.SZ',
|
||||||
stock_name: '中兴通讯',
|
stock_name: '中兴通讯',
|
||||||
relation_desc: '5G通信设备商,算力网络建设核心受益者。AI大模型训练和推理需要海量算力支撑,公司服务器、交换机等产品需求激增。运营商资本开支回暖,5G-A、算力网络投资加速。国产替代进程加快,市场份额持续提升。',
|
relation_desc: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
author: "周磊",
|
||||||
|
sentences: "中兴通讯作为5G通信设备商,是算力网络建设核心受益者。AI大模型训练和推理需要海量算力支撑,公司服务器、交换机等产品需求激增。",
|
||||||
|
query_part: "5G通信设备商,算力网络建设核心受益者",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-04-08T00:00:00",
|
||||||
|
report_title: "中兴通讯:算力基础设施建设加速,订单饱满-点评报告"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
author: "吴洋",
|
||||||
|
sentences: "运营商资本开支回暖,5G-A、算力网络投资加速。国产替代进程加快,中兴通讯市场份额持续提升,盈利能力改善明显。",
|
||||||
|
query_part: "国产替代加速,市场份额持续提升",
|
||||||
|
match_score: "良",
|
||||||
|
declare_date: "2025-04-15T00:00:00",
|
||||||
|
report_title: "通信设备行业:运营商资本开支拐点已现"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
author: "刘畅",
|
||||||
|
sentences: "AI产业链中,算力基础设施投资是重中之重。中兴通讯在数据中心交换机、服务器等领域布局完善,技术实力强劲。",
|
||||||
|
query_part: "AI算力基础设施投资核心标的",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-04-18T00:00:00",
|
||||||
|
report_title: "AI算力产业链投资机会深度解析"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
industry: '通信设备',
|
industry: '通信设备',
|
||||||
relevance_score: 88,
|
relevance_score: 88,
|
||||||
impact_level: 'high',
|
impact_level: 'high',
|
||||||
@@ -155,7 +283,26 @@ export const mockEventStocks = {
|
|||||||
{
|
{
|
||||||
stock_code: '300750.SZ',
|
stock_code: '300750.SZ',
|
||||||
stock_name: '宁德时代',
|
stock_name: '宁德时代',
|
||||||
relation_desc: '动力电池绝对龙头,全球市占率超35%。新能源汽车渗透率提升,带动电池需求持续高增长。公司技术路线全覆盖(三元、磷酸铁锂、钠电池),客户资源优质(特斯拉、比亚迪等)。储能业务高速增长,打开第二增长曲线。盈利能力行业最强。',
|
relation_desc: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
author: "张华",
|
||||||
|
sentences: "宁德时代作为全球动力电池绝对龙头,市占率超35%,技术路线覆盖三元、磷酸铁锂、钠电池等全品类。客户资源优质,特斯拉、比亚迪等头部车企深度绑定。",
|
||||||
|
query_part: "动力电池绝对龙头,全球市占率超35%",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-05-10T00:00:00",
|
||||||
|
report_title: "宁德时代:全球动力电池龙头,新能源汽车核心受益标的"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
author: "李明",
|
||||||
|
sentences: "新能源汽车补贴延续政策出台,将直接刺激终端需求,宁德时代作为产业链核心环节,电池出货量有望大幅提升。储能业务高速增长,打开第二增长曲线。",
|
||||||
|
query_part: "补贴政策核心受益,储能业务打开第二曲线",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-05-12T00:00:00",
|
||||||
|
report_title: "新能源汽车产业链:补贴延续下的投资机遇"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
industry: '新能源',
|
industry: '新能源',
|
||||||
relevance_score: 98,
|
relevance_score: 98,
|
||||||
impact_level: 'high',
|
impact_level: 'high',
|
||||||
@@ -163,7 +310,26 @@ export const mockEventStocks = {
|
|||||||
{
|
{
|
||||||
stock_code: '002594.SZ',
|
stock_code: '002594.SZ',
|
||||||
stock_name: 'BYD比亚迪',
|
stock_name: 'BYD比亚迪',
|
||||||
relation_desc: '新能源汽车销量冠军,产业链垂直整合优势显著。月销量持续突破30万辆,市占率稳步提升。王朝、海洋、腾势三大品牌矩阵完善,覆盖10-50万价格带。电池、电机、电控自主可控,成本优势明显。出海战略推进顺利,欧洲、东南亚市场表现亮眼。',
|
relation_desc: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
author: "王芳",
|
||||||
|
sentences: "比亚迪月销量持续突破30万辆,市占率稳步提升。王朝、海洋、腾势三大品牌矩阵完善,价格带覆盖10-50万元,产品竞争力强。",
|
||||||
|
query_part: "新能源汽车销量冠军,月销超30万辆",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-05-08T00:00:00",
|
||||||
|
report_title: "比亚迪:新能源汽车销量王者,产业链垂直整合优势显著"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
author: "陈强",
|
||||||
|
sentences: "电池、电机、电控自主可控,成本优势明显。出海战略推进顺利,欧洲、东南亚市场表现亮眼,国际化进程加速。",
|
||||||
|
query_part: "垂直整合成本优势,出海战略成效显著",
|
||||||
|
match_score: "良",
|
||||||
|
declare_date: "2025-05-15T00:00:00",
|
||||||
|
report_title: "比亚迪国际化战略深度解析"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
industry: '新能源汽车',
|
industry: '新能源汽车',
|
||||||
relevance_score: 95,
|
relevance_score: 95,
|
||||||
impact_level: 'high',
|
impact_level: 'high',
|
||||||
@@ -171,15 +337,53 @@ export const mockEventStocks = {
|
|||||||
{
|
{
|
||||||
stock_code: '601012.SH',
|
stock_code: '601012.SH',
|
||||||
stock_name: '隆基绿能',
|
stock_name: '隆基绿能',
|
||||||
relation_desc: '光伏组件龙头,单晶硅片市占率第一。绿色能源发展战略下,光伏装机需求旺盛。公司BC电池技术领先,产品溢价能力强。一体化产能布局完善,垂直整合降本增效。海外收入占比超50%,全球化布局分散风险。',
|
relation_desc: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
author: "赵磊",
|
||||||
|
sentences: "隆基绿能作为光伏组件龙头,单晶硅片市占率第一。BC电池技术领先,产品溢价能力强,一体化产能布局完善。",
|
||||||
|
query_part: "光伏组件龙头,BC电池技术领先",
|
||||||
|
match_score: "良",
|
||||||
|
declare_date: "2025-05-05T00:00:00",
|
||||||
|
report_title: "隆基绿能:光伏技术引领者,一体化优势突出"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
author: "孙杰",
|
||||||
|
sentences: "新能源汽车补贴延续,带动绿色能源需求增长。隆基海外收入占比超50%,全球化布局分散风险,盈利稳定性强。",
|
||||||
|
query_part: "绿色能源需求增长,全球化布局优势",
|
||||||
|
match_score: "良",
|
||||||
|
declare_date: "2025-05-18T00:00:00",
|
||||||
|
report_title: "光伏行业:新能源政策催化下的配置机会"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
industry: '光伏',
|
industry: '光伏',
|
||||||
relevance_score: 85,
|
relevance_score: 85,
|
||||||
impact_level: 'medium',
|
impact_level: 'medium',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
stock_code: '002594.SZ',
|
stock_code: '688187.SH',
|
||||||
stock_name: '天齐锂业',
|
stock_name: '天齐锂业',
|
||||||
relation_desc: '锂资源龙头,拥有优质锂矿资源。新能源汽车、储能需求增长带动锂盐价格中枢上移。公司锂资源自给率高,成本优势显著。澳洲、智利矿山产能稳定,国内锂盐产能持续扩张。锂价回暖周期开启,业绩弹性巨大。',
|
relation_desc: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
author: "刘畅",
|
||||||
|
sentences: "天齐锂业拥有优质锂矿资源,锂资源自给率高,成本优势显著。澳洲、智利矿山产能稳定,国内锂盐产能持续扩张。",
|
||||||
|
query_part: "锂资源龙头,优质矿山资源储备充足",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-05-20T00:00:00",
|
||||||
|
report_title: "天齐锂业:锂资源龙头,成本优势突出"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
author: "吴洋",
|
||||||
|
sentences: "新能源汽车、储能需求增长带动锂盐价格中枢上移。锂价回暖周期开启,天齐锂业业绩弹性巨大,是锂价上行核心受益标的。",
|
||||||
|
query_part: "锂价回暖周期受益,业绩弹性大",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-05-22T00:00:00",
|
||||||
|
report_title: "锂行业:供需格局改善,价格拐点已现"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
industry: '有色金属',
|
industry: '有色金属',
|
||||||
relevance_score: 82,
|
relevance_score: 82,
|
||||||
impact_level: 'high',
|
impact_level: 'high',
|
||||||
@@ -191,7 +395,26 @@ export const mockEventStocks = {
|
|||||||
{
|
{
|
||||||
stock_code: '600276.SH',
|
stock_code: '600276.SH',
|
||||||
stock_name: '恒瑞医药',
|
stock_name: '恒瑞医药',
|
||||||
relation_desc: '创新药龙头,研发管线最丰富。创新药政策支持下,公司多款重磅产品进入收获期。PD-1、PARP抑制剂等创新药放量迅速,海外授权合作频繁。研发投入占比超20%,管线覆盖肿瘤、麻醉、造影等多领域。集采影响逐步消化,业绩拐点显现。',
|
relation_desc: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
author: "周磊",
|
||||||
|
sentences: "恒瑞医药作为创新药龙头,研发管线最丰富,涵盖肿瘤、麻醉、造影等多领域。PD-1、PARP抑制剂等重磅产品进入收获期,放量迅速。",
|
||||||
|
query_part: "创新药龙头,研发管线最丰富",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-06-10T00:00:00",
|
||||||
|
report_title: "恒瑞医药:创新药进入收获期,业绩拐点显现"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
author: "钱敏",
|
||||||
|
sentences: "创新药政策支持力度加大,集采影响逐步消化。恒瑞研发投入占比超20%,海外授权合作频繁,国际化进程加速。",
|
||||||
|
query_part: "政策支持加码,国际化进程加速",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-06-12T00:00:00",
|
||||||
|
report_title: "医药创新政策解读:龙头企业核心受益"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
industry: '医药',
|
industry: '医药',
|
||||||
relevance_score: 93,
|
relevance_score: 93,
|
||||||
impact_level: 'high',
|
impact_level: 'high',
|
||||||
@@ -199,7 +422,26 @@ export const mockEventStocks = {
|
|||||||
{
|
{
|
||||||
stock_code: '603259.SH',
|
stock_code: '603259.SH',
|
||||||
stock_name: '药明康德',
|
stock_name: '药明康德',
|
||||||
relation_desc: 'CRO/CDMO龙头,全球制药产业链核心服务商。创新药研发投入增加,外包渗透率提升,公司订单饱满。客户覆盖全球TOP20药企,粘性强。一体化平台优势明显,从研发到商业化全流程服务。海外收入占比高,人民币贬值受益。',
|
relation_desc: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
author: "孙杰",
|
||||||
|
sentences: "药明康德作为CRO/CDMO龙头,全球制药产业链核心服务商。客户覆盖全球TOP20药企,粘性强,订单饱满。一体化平台优势明显。",
|
||||||
|
query_part: "CRO/CDMO龙头,全球制药核心服务商",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-06-08T00:00:00",
|
||||||
|
report_title: "药明康德:CRO龙头地位稳固,订单饱满"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
author: "林芳",
|
||||||
|
sentences: "创新药研发投入增加,外包渗透率提升。药明从研发到商业化全流程服务能力强,海外收入占比高,人民币贬值受益。",
|
||||||
|
query_part: "外包渗透率提升,全流程服务优势",
|
||||||
|
match_score: "良",
|
||||||
|
declare_date: "2025-06-15T00:00:00",
|
||||||
|
report_title: "CRO行业:创新药外包需求持续增长"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
industry: '医药研发',
|
industry: '医药研发',
|
||||||
relevance_score: 90,
|
relevance_score: 90,
|
||||||
impact_level: 'high',
|
impact_level: 'high',
|
||||||
@@ -207,7 +449,26 @@ export const mockEventStocks = {
|
|||||||
{
|
{
|
||||||
stock_code: '300760.SZ',
|
stock_code: '300760.SZ',
|
||||||
stock_name: '迈瑞医疗',
|
stock_name: '迈瑞医疗',
|
||||||
relation_desc: '医疗器械龙头,产品线覆盖生命信息与支持、体外诊断、医学影像三大领域。高端医疗设备国产替代加速,公司市占率持续提升。海外市场突破进展顺利,进入更多顶级医院。研发能力强,新品推出节奏加快。盈利能力稳定,现金流充沛。',
|
relation_desc: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
author: "赵强",
|
||||||
|
sentences: "迈瑞医疗产品线覆盖生命信息与支持、体外诊断、医学影像三大领域。高端医疗设备国产替代加速,市占率持续提升。",
|
||||||
|
query_part: "医疗器械龙头,国产替代加速",
|
||||||
|
match_score: "良",
|
||||||
|
declare_date: "2025-06-05T00:00:00",
|
||||||
|
report_title: "迈瑞医疗:医疗器械龙头,国产化进程提速"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
author: "吴洋",
|
||||||
|
sentences: "海外市场突破进展顺利,进入更多顶级医院。研发能力强,新品推出节奏加快,盈利能力稳定,现金流充沛。",
|
||||||
|
query_part: "海外突破顺利,研发能力强劲",
|
||||||
|
match_score: "良",
|
||||||
|
declare_date: "2025-06-18T00:00:00",
|
||||||
|
report_title: "医疗器械行业:国产品牌全球化加速"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
industry: '医疗器械',
|
industry: '医疗器械',
|
||||||
relevance_score: 87,
|
relevance_score: 87,
|
||||||
impact_level: 'medium',
|
impact_level: 'medium',
|
||||||
@@ -219,7 +480,26 @@ export const mockEventStocks = {
|
|||||||
{
|
{
|
||||||
stock_code: '300059.SZ',
|
stock_code: '300059.SZ',
|
||||||
stock_name: '东方财富',
|
stock_name: '东方财富',
|
||||||
relation_desc: '互联网金融龙头,流量优势显著。数字经济发展推动线上理财渗透率提升,公司APP月活超亿。券商、基金代销、数据服务多业务协同。市场交易活跃度提升,佣金收入和利息收入双增长。低成本负债优势明显,ROE水平行业领先。',
|
relation_desc: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
author: "郑华",
|
||||||
|
sentences: "东方财富作为互联网金融龙头,流量优势显著,APP月活超亿。券商、基金代销、数据服务多业务协同,形成完整生态闭环。",
|
||||||
|
query_part: "互联网金融龙头,流量优势显著",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-07-10T00:00:00",
|
||||||
|
report_title: "东方财富:互联网金融龙头,生态优势突出"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
author: "刘明",
|
||||||
|
sentences: "数字经济发展推动线上理财渗透率提升。市场交易活跃度提升,佣金收入和利息收入双增长,低成本负债优势明显,ROE水平行业领先。",
|
||||||
|
query_part: "数字经济受益,线上理财渗透率提升",
|
||||||
|
match_score: "优",
|
||||||
|
declare_date: "2025-07-12T00:00:00",
|
||||||
|
report_title: "数字经济政策解读:互联网金融核心受益"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
industry: '证券',
|
industry: '证券',
|
||||||
relevance_score: 88,
|
relevance_score: 88,
|
||||||
impact_level: 'high',
|
impact_level: 'high',
|
||||||
@@ -227,7 +507,26 @@ export const mockEventStocks = {
|
|||||||
{
|
{
|
||||||
stock_code: '002410.SZ',
|
stock_code: '002410.SZ',
|
||||||
stock_name: '广联达',
|
stock_name: '广联达',
|
||||||
relation_desc: '建筑信息化龙头,工程造价软件市占率第一。数字化转型加速,建筑行业信息化需求旺盛。云转型进入收获期,订阅模式收入占比提升,现金流改善明显。施工、设计等新业务拓展顺利,成长空间广阔。政策支持力度大,行业壁垒高。',
|
relation_desc: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
author: "张敏",
|
||||||
|
sentences: "广联达作为建筑信息化龙头,工程造价软件市占率第一。云转型进入收获期,订阅模式收入占比提升,现金流改善明显。",
|
||||||
|
query_part: "建筑信息化龙头,云转型收获期",
|
||||||
|
match_score: "良",
|
||||||
|
declare_date: "2025-07-08T00:00:00",
|
||||||
|
report_title: "广联达:建筑信息化龙头,云转型成效显著"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
author: "李芳",
|
||||||
|
sentences: "数字化转型加速,建筑行业信息化需求旺盛。施工、设计等新业务拓展顺利,成长空间广阔,政策支持力度大,行业壁垒高。",
|
||||||
|
query_part: "数字化转型加速,新业务拓展顺利",
|
||||||
|
match_score: "良",
|
||||||
|
declare_date: "2025-07-15T00:00:00",
|
||||||
|
report_title: "建筑信息化:数字经济下的产业升级机遇"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
industry: '软件',
|
industry: '软件',
|
||||||
relevance_score: 85,
|
relevance_score: 85,
|
||||||
impact_level: 'medium',
|
impact_level: 'medium',
|
||||||
|
|||||||
@@ -19,9 +19,6 @@ export const eventHandlers = [
|
|||||||
try {
|
try {
|
||||||
const relatedStocks = getEventRelatedStocks(eventId);
|
const relatedStocks = getEventRelatedStocks(eventId);
|
||||||
|
|
||||||
console.log('[Mock] 返回的股票数据:', relatedStocks);
|
|
||||||
console.log('[Mock] 第一只股票的 relation_desc:', relatedStocks[0]?.relation_desc);
|
|
||||||
|
|
||||||
return HttpResponse.json({
|
return HttpResponse.json({
|
||||||
success: true,
|
success: true,
|
||||||
data: relatedStocks,
|
data: relatedStocks,
|
||||||
|
|||||||
@@ -26,14 +26,14 @@
|
|||||||
* 输出格式:
|
* 输出格式:
|
||||||
* {
|
* {
|
||||||
* segments: [
|
* segments: [
|
||||||
* { text: "核心结论:...", citationId: 1 }
|
* { text: "国内领先的IT解决方案提供商", citationId: 1 } // 优先使用 query_part
|
||||||
* ],
|
* ],
|
||||||
* citations: {
|
* citations: {
|
||||||
* 1: {
|
* 1: {
|
||||||
* author: "陈彤",
|
* author: "陈彤",
|
||||||
* report_title: "深度布局...",
|
* report_title: "深度布局...",
|
||||||
* declare_date: "2025-04-17",
|
* declare_date: "2025-04-17",
|
||||||
* sentences: "核心结论:..."
|
* sentences: "核心结论:..." // sentences 显示在弹窗中
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
@@ -55,9 +55,9 @@ export const processCitationData = (rawData) => {
|
|||||||
|
|
||||||
// 处理每个引用数据项
|
// 处理每个引用数据项
|
||||||
rawData.data.forEach((item, index) => {
|
rawData.data.forEach((item, index) => {
|
||||||
// 验证必需字段
|
// 验证必需字段(至少需要 query_part 或 sentences 之一)
|
||||||
if (!item.sentences) {
|
if (!item.query_part && !item.sentences) {
|
||||||
console.warn(`citationUtils: Missing 'sentences' field in item ${index}`);
|
console.warn(`citationUtils: Missing both 'query_part' and 'sentences' fields in item ${index}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ export const processCitationData = (rawData) => {
|
|||||||
|
|
||||||
// 构建文本片段
|
// 构建文本片段
|
||||||
segments.push({
|
segments.push({
|
||||||
text: item.sentences,
|
text: item.query_part || item.sentences, // 优先使用 query_part,降级到 sentences
|
||||||
citationId: citationId
|
citationId: citationId
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -126,6 +126,6 @@ export const isValidCitationData = (data) => {
|
|||||||
if (!data.data || !Array.isArray(data.data)) return false;
|
if (!data.data || !Array.isArray(data.data)) return false;
|
||||||
if (data.data.length === 0) return false;
|
if (data.data.length === 0) return false;
|
||||||
|
|
||||||
// 检查至少有一个有效的 sentences 字段
|
// 检查至少有一个有效的 query_part 或 sentences 字段
|
||||||
return data.data.some(item => item && item.sentences);
|
return data.data.some(item => item && (item.query_part || item.sentences));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -452,6 +452,7 @@ function StockDetailPanel({ visible, event, onClose }) {
|
|||||||
|
|
||||||
// 初始化数据加载
|
// 初始化数据加载
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log('[StockDetailPanel] useEffect 触发, visible:', visible, 'event:', event?.id);
|
||||||
if (visible && event) {
|
if (visible && event) {
|
||||||
setActiveTab('stocks');
|
setActiveTab('stocks');
|
||||||
loadAllData();
|
loadAllData();
|
||||||
@@ -460,6 +461,7 @@ function StockDetailPanel({ visible, event, onClose }) {
|
|||||||
|
|
||||||
// 加载所有数据的函数
|
// 加载所有数据的函数
|
||||||
const loadAllData = useCallback(() => {
|
const loadAllData = useCallback(() => {
|
||||||
|
console.log('[StockDetailPanel] loadAllData 被调用, event:', event?.id);
|
||||||
if (!event) return;
|
if (!event) return;
|
||||||
|
|
||||||
// 加载自选股列表
|
// 加载自选股列表
|
||||||
@@ -590,9 +592,30 @@ function StockDetailPanel({ visible, event, onClose }) {
|
|||||||
dataIndex: 'relation_desc',
|
dataIndex: 'relation_desc',
|
||||||
key: 'relation_desc',
|
key: 'relation_desc',
|
||||||
width: 300,
|
width: 300,
|
||||||
render: (text, record) => {
|
render: (relationDesc, record) => {
|
||||||
console.log('[表格渲染] 股票:', record.stock_code, 'relation_desc:', text);
|
console.log('[表格渲染] 股票:', record.stock_code, 'relation_desc:', relationDesc);
|
||||||
if (!text) return '--';
|
|
||||||
|
// 处理 relation_desc 的两种格式
|
||||||
|
let text = '';
|
||||||
|
|
||||||
|
if (!relationDesc) {
|
||||||
|
return '--';
|
||||||
|
} else if (typeof relationDesc === 'string') {
|
||||||
|
// 旧格式:直接是字符串
|
||||||
|
text = relationDesc;
|
||||||
|
} else if (typeof relationDesc === 'object' && relationDesc.data && Array.isArray(relationDesc.data)) {
|
||||||
|
// 新格式:{data: [{query_part: "...", sentences: "..."}]}
|
||||||
|
// 提取所有 query_part,用逗号连接
|
||||||
|
text = relationDesc.data
|
||||||
|
.map(item => item.query_part || item.sentences || '')
|
||||||
|
.filter(s => s)
|
||||||
|
.join(';') || '--';
|
||||||
|
} else {
|
||||||
|
console.warn('[表格渲染] 未知的 relation_desc 格式:', relationDesc);
|
||||||
|
return '--';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!text || text === '--') return '--';
|
||||||
|
|
||||||
const isExpanded = expandedRows.has(record.stock_code);
|
const isExpanded = expandedRows.has(record.stock_code);
|
||||||
const maxLength = 30; // 收缩时显示的最大字符数
|
const maxLength = 30; // 收缩时显示的最大字符数
|
||||||
|
|||||||
@@ -140,6 +140,8 @@ const Community = () => {
|
|||||||
|
|
||||||
// 加载事件列表
|
// 加载事件列表
|
||||||
const loadEvents = useCallback(async (page = 1) => {
|
const loadEvents = useCallback(async (page = 1) => {
|
||||||
|
console.log('[Community] loadEvents 被调用,页码:', page);
|
||||||
|
console.log('[Community] 调用栈:', new Error().stack);
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const filters = getFiltersFromUrl();
|
const filters = getFiltersFromUrl();
|
||||||
@@ -254,12 +256,17 @@ const Community = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 初始化加载
|
// 初始化加载
|
||||||
|
// 注意: 只监听 searchParams 变化,不监听 loadEvents 等函数
|
||||||
|
// 这是为了避免 StockDetailPanel 打开时触发不必要的重新加载
|
||||||
|
// 如果未来 loadEvents 添加了新的状态依赖,需要在此处同步更新
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log('[Community] useEffect 触发,searchParams 变化:', searchParams.toString());
|
||||||
const page = parseInt(searchParams.get('page') || '1', 10);
|
const page = parseInt(searchParams.get('page') || '1', 10);
|
||||||
loadEvents(page);
|
loadEvents(page);
|
||||||
loadPopularKeywords();
|
loadPopularKeywords();
|
||||||
loadHotEvents();
|
loadHotEvents();
|
||||||
}, [searchParams, loadEvents, loadPopularKeywords, loadHotEvents]);
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [searchParams]); // 只监听 URL 参数变化
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user