From d5250f7d3c8d03db455cc973ffd3fc99fa3ed999 Mon Sep 17 00:00:00 2001 From: zzlgreat Date: Sun, 23 Nov 2025 15:58:14 +0800 Subject: [PATCH] update pay function --- app.py | 54 +++++++ src/views/Company/CompanyOverview.js | 231 +++++++++++++++++++++++++-- 2 files changed, 270 insertions(+), 15 deletions(-) diff --git a/app.py b/app.py index 32bd7c22..a7818e23 100755 --- a/app.py +++ b/app.py @@ -11679,6 +11679,60 @@ def get_value_chain_analysis(company_code): }), 500 +@app.route('/api/company/value-chain/related-companies', methods=['GET']) +def get_related_companies_by_node(): + """ + 根据产业链节点名称查询相关公司 + 参数: node_name - 节点名称(如 "中芯国际"、"EDA/IP"等) + 返回: 包含该节点的所有公司列表(去重) + """ + try: + node_name = request.args.get('node_name') + + if not node_name: + return jsonify({ + 'success': False, + 'error': '缺少必需参数 node_name' + }), 400 + + # 查询包含该节点的所有公司 + query = text(""" + SELECT DISTINCT + n.company_code as stock_code, + s.SECNAME as stock_name, + s.ORGNAME as company_name + FROM company_value_chain_nodes n + LEFT JOIN ea_stocklist s ON n.company_code = s.SECCODE + WHERE n.node_name = :node_name + ORDER BY n.company_code + """) + + with engine.connect() as conn: + result = conn.execute(query, {'node_name': node_name}).fetchall() + + # 构建返回数据 + companies = [] + for row in result: + companies.append({ + 'stock_code': row.stock_code, + 'stock_name': row.stock_name or row.stock_code, + 'company_name': row.company_name + }) + + return jsonify({ + 'success': True, + 'data': companies, + 'total': len(companies), + 'node_name': node_name + }) + + except Exception as e: + return jsonify({ + 'success': False, + 'error': str(e) + }), 500 + + @app.route('/api/company/key-factors-timeline/', methods=['GET']) def get_key_factors_timeline(company_code): """获取公司关键因素和时间线数据""" diff --git a/src/views/Company/CompanyOverview.js b/src/views/Company/CompanyOverview.js index d1fc62fe..d05db6c0 100644 --- a/src/views/Company/CompanyOverview.js +++ b/src/views/Company/CompanyOverview.js @@ -792,7 +792,12 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { const [branches, setBranches] = useState([]); const [announcements, setAnnouncements] = useState([]); const [disclosureSchedule, setDisclosureSchedule] = useState([]); - + + // 新闻动态数据 + const [newsEvents, setNewsEvents] = useState([]); + const [newsLoading, setNewsLoading] = useState(false); + const [newsSearchQuery, setNewsSearchQuery] = useState(''); + const [error, setError] = useState(null); const toast = useToast(); @@ -880,6 +885,58 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { } }, [stockCode]); + // 加载新闻事件 + const loadNewsEvents = async (searchQuery = '') => { + setNewsLoading(true); + try { + // 构建查询参数 + const params = new URLSearchParams({ + per_page: '20', + sort: 'new', + include_creator: 'false', + include_stats: 'true' + }); + + // 如果有搜索关键词,添加搜索参数 + if (searchQuery) { + params.append('q', searchQuery); + params.append('search_fields', 'title,description,content'); + } + + // 如果有股票代码,添加相关筛选(这里假设事件表有stock_code字段) + // 如果没有直接的stock_code字段,可以通过tags或keywords搜索 + if (basicInfo?.SECNAME) { + params.append('keywords', basicInfo.SECNAME); + } + + const response = await fetch(`${API_BASE_URL}/api/events?${params.toString()}`); + const data = await response.json(); + + if (data.success !== false && data.events) { + setNewsEvents(data.events); + } else { + setNewsEvents([]); + } + } catch (err) { + logger.error('CompanyOverview', 'loadNewsEvents', err, { stockCode, searchQuery }); + setNewsEvents([]); + } finally { + setNewsLoading(false); + } + }; + + // 当基本信息加载完成后,加载新闻事件 + useEffect(() => { + if (basicInfo) { + loadNewsEvents(); + } + }, [basicInfo]); + + // 处理搜索 + const handleNewsSearch = () => { + loadNewsEvents(newsSearchQuery); + }; + // 管理层职位分类 const getManagementByCategory = () => { const categories = { @@ -2131,22 +2188,166 @@ const CompanyAnalysisComplete = ({ stockCode: propStockCode }) => { - - - - - - + {/* 搜索框 */} + + + + + + setNewsSearchQuery(e.target.value)} + onKeyPress={(e) => e.key === 'Enter' && handleNewsSearch()} + /> + + + -
- - - 新闻接口待接入 - - 即将展示最新的公司新闻动态 - + {/* 新闻列表 */} + {newsLoading ? ( +
+ + + 正在加载新闻... + +
+ ) : newsEvents.length > 0 ? ( + + {newsEvents.map((event, idx) => { + const importanceColor = { + 'S': 'red', + 'A': 'orange', + 'B': 'yellow', + 'C': 'green' + }[event.importance] || 'gray'; + + return ( + + + + + + + + + {event.title} + + + + {event.importance && ( + + 重要度: {event.importance} + + )} + {event.event_type && ( + + {event.event_type} + + )} + {event.tags && event.tags.length > 0 && ( + <> + {event.tags.slice(0, 3).map((tag, tidx) => ( + + {tag} + + ))} + + )} + + + + + {event.created_at ? new Date(event.created_at).toLocaleDateString('zh-CN') : ''} + + {event.view_count && ( + + + + {event.view_count} + + + )} + + + + {event.description && ( + + {event.description} + + )} + + {(event.avg_return_5 || event.avg_return_10 || event.avg_return_20) && ( + + 平均收益率: + {event.avg_return_5 !== undefined && ( + + 5日: + 0 ? 'red.500' : 'green.500'} + > + {event.avg_return_5 > 0 ? '+' : ''}{event.avg_return_5}% + + + )} + {event.avg_return_10 !== undefined && ( + + 10日: + 0 ? 'red.500' : 'green.500'} + > + {event.avg_return_10 > 0 ? '+' : ''}{event.avg_return_10}% + + + )} + {event.avg_return_20 !== undefined && ( + + 20日: + 0 ? 'red.500' : 'green.500'} + > + {event.avg_return_20 > 0 ? '+' : ''}{event.avg_return_20}% + + + )} + + )} + + + + ); + })} -
+ ) : ( +
+ + + 暂无相关新闻 + + {newsSearchQuery ? '尝试修改搜索关键词' : '该公司暂无新闻动态'} + + +
+ )}