Merge branch 'feature_bugfix/251113_ui' into feature_bugfix/251113_bugfix
* feature_bugfix/251113_ui: update ui update ui update ui update ui update ui
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
127
app.py
127
app.py
@@ -68,6 +68,17 @@ def load_trading_days():
|
|||||||
print(f"加载交易日数据失败: {e}")
|
print(f"加载交易日数据失败: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
def row_to_dict(row):
|
||||||
|
"""
|
||||||
|
将 SQLAlchemy Row 对象转换为字典
|
||||||
|
兼容 SQLAlchemy 1.4+ 版本
|
||||||
|
"""
|
||||||
|
if row is None:
|
||||||
|
return None
|
||||||
|
# 使用 _mapping 属性来访问列数据
|
||||||
|
return dict(row._mapping)
|
||||||
|
|
||||||
|
|
||||||
def get_trading_day_near_date(target_date):
|
def get_trading_day_near_date(target_date):
|
||||||
"""
|
"""
|
||||||
获取距离目标日期最近的交易日
|
获取距离目标日期最近的交易日
|
||||||
@@ -5642,7 +5653,8 @@ def get_stock_basic_info(stock_code):
|
|||||||
|
|
||||||
# 转换为字典
|
# 转换为字典
|
||||||
basic_info = {}
|
basic_info = {}
|
||||||
for key, value in zip(result.keys(), result):
|
result_dict = row_to_dict(result)
|
||||||
|
for key, value in result_dict.items():
|
||||||
if isinstance(value, datetime):
|
if isinstance(value, datetime):
|
||||||
basic_info[key] = value.strftime('%Y-%m-%d')
|
basic_info[key] = value.strftime('%Y-%m-%d')
|
||||||
elif isinstance(value, Decimal):
|
elif isinstance(value, Decimal):
|
||||||
@@ -5685,7 +5697,7 @@ def get_stock_announcements(stock_code):
|
|||||||
announcements = []
|
announcements = []
|
||||||
for row in result:
|
for row in result:
|
||||||
announcement = {}
|
announcement = {}
|
||||||
for key, value in zip(row.keys(), row):
|
for key, value in row_to_dict(row).items():
|
||||||
if value is None:
|
if value is None:
|
||||||
announcement[key] = None
|
announcement[key] = None
|
||||||
elif isinstance(value, datetime):
|
elif isinstance(value, datetime):
|
||||||
@@ -5734,7 +5746,7 @@ def get_stock_disclosure_schedule(stock_code):
|
|||||||
schedules = []
|
schedules = []
|
||||||
for row in result:
|
for row in result:
|
||||||
schedule = {}
|
schedule = {}
|
||||||
for key, value in zip(row.keys(), row):
|
for key, value in row_to_dict(row).items():
|
||||||
if value is None:
|
if value is None:
|
||||||
schedule[key] = None
|
schedule[key] = None
|
||||||
elif isinstance(value, datetime):
|
elif isinstance(value, datetime):
|
||||||
@@ -5815,7 +5827,7 @@ def get_stock_actual_control(stock_code):
|
|||||||
control_info = []
|
control_info = []
|
||||||
for row in result:
|
for row in result:
|
||||||
control_record = {}
|
control_record = {}
|
||||||
for key, value in zip(row.keys(), row):
|
for key, value in row_to_dict(row).items():
|
||||||
if value is None:
|
if value is None:
|
||||||
control_record[key] = None
|
control_record[key] = None
|
||||||
elif isinstance(value, datetime):
|
elif isinstance(value, datetime):
|
||||||
@@ -5864,7 +5876,7 @@ def get_stock_concentration(stock_code):
|
|||||||
concentration_info = []
|
concentration_info = []
|
||||||
for row in result:
|
for row in result:
|
||||||
concentration_record = {}
|
concentration_record = {}
|
||||||
for key, value in zip(row.keys(), row):
|
for key, value in row_to_dict(row).items():
|
||||||
if value is None:
|
if value is None:
|
||||||
concentration_record[key] = None
|
concentration_record[key] = None
|
||||||
elif isinstance(value, datetime):
|
elif isinstance(value, datetime):
|
||||||
@@ -5933,7 +5945,7 @@ def get_stock_management(stock_code):
|
|||||||
management_info = []
|
management_info = []
|
||||||
for row in result:
|
for row in result:
|
||||||
management_record = {}
|
management_record = {}
|
||||||
for key, value in zip(row.keys(), row):
|
for key, value in row_to_dict(row).items():
|
||||||
if value is None:
|
if value is None:
|
||||||
management_record[key] = None
|
management_record[key] = None
|
||||||
elif isinstance(value, datetime):
|
elif isinstance(value, datetime):
|
||||||
@@ -5992,7 +6004,7 @@ def get_stock_top_circulation_shareholders(stock_code):
|
|||||||
shareholders_info = []
|
shareholders_info = []
|
||||||
for row in result:
|
for row in result:
|
||||||
shareholder_record = {}
|
shareholder_record = {}
|
||||||
for key, value in zip(row.keys(), row):
|
for key, value in row_to_dict(row).items():
|
||||||
if value is None:
|
if value is None:
|
||||||
shareholder_record[key] = None
|
shareholder_record[key] = None
|
||||||
elif isinstance(value, datetime):
|
elif isinstance(value, datetime):
|
||||||
@@ -6051,7 +6063,7 @@ def get_stock_top_shareholders(stock_code):
|
|||||||
shareholders_info = []
|
shareholders_info = []
|
||||||
for row in result:
|
for row in result:
|
||||||
shareholder_record = {}
|
shareholder_record = {}
|
||||||
for key, value in zip(row.keys(), row):
|
for key, value in row_to_dict(row).items():
|
||||||
if value is None:
|
if value is None:
|
||||||
shareholder_record[key] = None
|
shareholder_record[key] = None
|
||||||
elif isinstance(value, datetime):
|
elif isinstance(value, datetime):
|
||||||
@@ -6102,7 +6114,7 @@ def get_stock_branches(stock_code):
|
|||||||
branches_info = []
|
branches_info = []
|
||||||
for row in result:
|
for row in result:
|
||||||
branch_record = {}
|
branch_record = {}
|
||||||
for key, value in zip(row.keys(), row):
|
for key, value in row_to_dict(row).items():
|
||||||
if value is None:
|
if value is None:
|
||||||
branch_record[key] = None
|
branch_record[key] = None
|
||||||
elif isinstance(value, datetime):
|
elif isinstance(value, datetime):
|
||||||
@@ -6169,7 +6181,7 @@ def get_stock_patents(stock_code):
|
|||||||
patents_info = []
|
patents_info = []
|
||||||
for row in result:
|
for row in result:
|
||||||
patent_record = {}
|
patent_record = {}
|
||||||
for key, value in zip(row.keys(), row):
|
for key, value in row_to_dict(row).items():
|
||||||
if value is None:
|
if value is None:
|
||||||
patent_record[key] = None
|
patent_record[key] = None
|
||||||
elif isinstance(value, datetime):
|
elif isinstance(value, datetime):
|
||||||
@@ -8644,7 +8656,8 @@ def get_stock_info(seccode):
|
|||||||
ORDER BY a.ENDDATE DESC LIMIT 1
|
ORDER BY a.ENDDATE DESC LIMIT 1
|
||||||
""")
|
""")
|
||||||
|
|
||||||
result = engine.execute(query, seccode=seccode).fetchone()
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(query, {'seccode': seccode}).fetchone()
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -8667,7 +8680,8 @@ def get_stock_info(seccode):
|
|||||||
ORDER BY F001D DESC LIMIT 1
|
ORDER BY F001D DESC LIMIT 1
|
||||||
""")
|
""")
|
||||||
|
|
||||||
forecast_result = engine.execute(forecast_query, seccode=seccode).fetchone()
|
with engine.connect() as conn:
|
||||||
|
forecast_result = conn.execute(forecast_query, {'seccode': seccode}).fetchone()
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'stock_code': result.SECCODE,
|
'stock_code': result.SECCODE,
|
||||||
@@ -8828,7 +8842,8 @@ def get_balance_sheet(seccode):
|
|||||||
ORDER BY ENDDATE DESC LIMIT :limit
|
ORDER BY ENDDATE DESC LIMIT :limit
|
||||||
""")
|
""")
|
||||||
|
|
||||||
result = engine.execute(query, seccode=seccode, limit=limit)
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(query, {'seccode': seccode, 'limit': limit})
|
||||||
data = []
|
data = []
|
||||||
|
|
||||||
for row in result:
|
for row in result:
|
||||||
@@ -9018,7 +9033,8 @@ def get_income_statement(seccode):
|
|||||||
ORDER BY ENDDATE DESC LIMIT :limit
|
ORDER BY ENDDATE DESC LIMIT :limit
|
||||||
""")
|
""")
|
||||||
|
|
||||||
result = engine.execute(query, seccode=seccode, limit=limit)
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(query, {'seccode': seccode, 'limit': limit})
|
||||||
data = []
|
data = []
|
||||||
|
|
||||||
for row in result:
|
for row in result:
|
||||||
@@ -9227,7 +9243,8 @@ def get_cashflow(seccode):
|
|||||||
ORDER BY ENDDATE DESC LIMIT :limit
|
ORDER BY ENDDATE DESC LIMIT :limit
|
||||||
""")
|
""")
|
||||||
|
|
||||||
result = engine.execute(query, seccode=seccode, limit=limit)
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(query, {'seccode': seccode, 'limit': limit})
|
||||||
data = []
|
data = []
|
||||||
|
|
||||||
for row in result:
|
for row in result:
|
||||||
@@ -9462,7 +9479,8 @@ def get_financial_metrics(seccode):
|
|||||||
ORDER BY ENDDATE DESC LIMIT :limit
|
ORDER BY ENDDATE DESC LIMIT :limit
|
||||||
""")
|
""")
|
||||||
|
|
||||||
result = engine.execute(query, seccode=seccode, limit=limit)
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(query, {'seccode': seccode, 'limit': limit})
|
||||||
data = []
|
data = []
|
||||||
|
|
||||||
for row in result:
|
for row in result:
|
||||||
@@ -9602,7 +9620,8 @@ def get_main_business(seccode):
|
|||||||
ORDER BY ENDDATE DESC LIMIT :limit
|
ORDER BY ENDDATE DESC LIMIT :limit
|
||||||
""")
|
""")
|
||||||
|
|
||||||
periods = engine.execute(period_query, seccode=seccode, limit=limit).fetchall()
|
with engine.connect() as conn:
|
||||||
|
periods = conn.execute(period_query, {'seccode': seccode, 'limit': limit}).fetchall()
|
||||||
|
|
||||||
# 产品分类数据
|
# 产品分类数据
|
||||||
product_data = []
|
product_data = []
|
||||||
@@ -9620,7 +9639,8 @@ def get_main_business(seccode):
|
|||||||
ORDER BY F005N DESC
|
ORDER BY F005N DESC
|
||||||
""")
|
""")
|
||||||
|
|
||||||
result = engine.execute(query, seccode=seccode, enddate=period[0])
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(query, {'seccode': seccode, 'enddate': period[0]})
|
||||||
# Convert result to list to allow multiple iterations
|
# Convert result to list to allow multiple iterations
|
||||||
rows = list(result)
|
rows = list(result)
|
||||||
|
|
||||||
@@ -9669,7 +9689,8 @@ def get_main_business(seccode):
|
|||||||
ORDER BY F007N DESC
|
ORDER BY F007N DESC
|
||||||
""")
|
""")
|
||||||
|
|
||||||
result = engine.execute(query, seccode=seccode, enddate=period[0])
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(query, {'seccode': seccode, 'enddate': period[0]})
|
||||||
# Convert result to list to allow multiple iterations
|
# Convert result to list to allow multiple iterations
|
||||||
rows = list(result)
|
rows = list(result)
|
||||||
|
|
||||||
@@ -9730,7 +9751,8 @@ def get_forecast(seccode):
|
|||||||
ORDER BY F001D DESC, UPDATE_DATE DESC LIMIT 10
|
ORDER BY F001D DESC, UPDATE_DATE DESC LIMIT 10
|
||||||
""")
|
""")
|
||||||
|
|
||||||
forecast_result = engine.execute(forecast_query, seccode=seccode)
|
with engine.connect() as conn:
|
||||||
|
forecast_result = conn.execute(forecast_query, {'seccode': seccode})
|
||||||
forecast_data = []
|
forecast_data = []
|
||||||
|
|
||||||
for row in forecast_result:
|
for row in forecast_result:
|
||||||
@@ -9771,7 +9793,8 @@ def get_forecast(seccode):
|
|||||||
ORDER BY F001D DESC LIMIT 8
|
ORDER BY F001D DESC LIMIT 8
|
||||||
""")
|
""")
|
||||||
|
|
||||||
pretime_result = engine.execute(pretime_query, seccode=seccode)
|
with engine.connect() as conn:
|
||||||
|
pretime_result = conn.execute(pretime_query, {'seccode': seccode})
|
||||||
pretime_data = []
|
pretime_data = []
|
||||||
|
|
||||||
for row in pretime_result:
|
for row in pretime_result:
|
||||||
@@ -9870,7 +9893,8 @@ def get_industry_rank(seccode):
|
|||||||
""")
|
""")
|
||||||
|
|
||||||
# 获取多个报告期的数据
|
# 获取多个报告期的数据
|
||||||
result = engine.execute(query, seccode=seccode, limit_total=limit * 4)
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(query, {'seccode': seccode, 'limit_total': limit * 4})
|
||||||
|
|
||||||
# 按报告期和行业级别组织数据
|
# 按报告期和行业级别组织数据
|
||||||
data_by_period = {}
|
data_by_period = {}
|
||||||
@@ -9990,7 +10014,8 @@ def get_period_comparison(seccode):
|
|||||||
ORDER BY fi.ENDDATE DESC LIMIT :periods
|
ORDER BY fi.ENDDATE DESC LIMIT :periods
|
||||||
""")
|
""")
|
||||||
|
|
||||||
result = engine.execute(query, seccode=seccode, periods=periods)
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(query, {'seccode': seccode, 'periods': periods})
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
for row in result:
|
for row in result:
|
||||||
@@ -10114,7 +10139,8 @@ def get_trade_data(seccode):
|
|||||||
LIMIT :days
|
LIMIT :days
|
||||||
""")
|
""")
|
||||||
|
|
||||||
result = engine.execute(query, seccode=seccode, end_date=end_date, days=days)
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(query, {'seccode': seccode, 'end_date': end_date, 'days': days})
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
for row in result:
|
for row in result:
|
||||||
@@ -10190,7 +10216,8 @@ def get_funding_data(seccode):
|
|||||||
ORDER BY TRADEDATE DESC LIMIT :days
|
ORDER BY TRADEDATE DESC LIMIT :days
|
||||||
""")
|
""")
|
||||||
|
|
||||||
result = engine.execute(query, seccode=seccode, days=days)
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(query, {'seccode': seccode, 'days': days})
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
for row in result:
|
for row in result:
|
||||||
@@ -10248,7 +10275,8 @@ def get_bigdeal_data(seccode):
|
|||||||
ORDER BY TRADEDATE DESC, F007N LIMIT :days
|
ORDER BY TRADEDATE DESC, F007N LIMIT :days
|
||||||
""")
|
""")
|
||||||
|
|
||||||
result = engine.execute(query, seccode=seccode, days=days)
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(query, {'seccode': seccode, 'days': days})
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
for row in result:
|
for row in result:
|
||||||
@@ -10322,7 +10350,8 @@ def get_unusual_data(seccode):
|
|||||||
ORDER BY TRADEDATE DESC, F004N LIMIT 100
|
ORDER BY TRADEDATE DESC, F004N LIMIT 100
|
||||||
""")
|
""")
|
||||||
|
|
||||||
result = engine.execute(query, seccode=seccode)
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(query, {'seccode': seccode})
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
for row in result:
|
for row in result:
|
||||||
@@ -10400,7 +10429,8 @@ def get_pledge_data(seccode):
|
|||||||
ORDER BY ENDDATE DESC LIMIT 12
|
ORDER BY ENDDATE DESC LIMIT 12
|
||||||
""")
|
""")
|
||||||
|
|
||||||
result = engine.execute(query, seccode=seccode)
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(query, {'seccode': seccode})
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
for row in result:
|
for row in result:
|
||||||
@@ -10457,9 +10487,12 @@ def get_market_summary(seccode):
|
|||||||
ORDER BY ENDDATE DESC LIMIT 1
|
ORDER BY ENDDATE DESC LIMIT 1
|
||||||
""")
|
""")
|
||||||
|
|
||||||
trade_result = engine.execute(trade_query, seccode=seccode).fetchone()
|
with engine.connect() as conn:
|
||||||
funding_result = engine.execute(funding_query, seccode=seccode).fetchone()
|
trade_result = conn.execute(trade_query, {'seccode': seccode}).fetchone()
|
||||||
pledge_result = engine.execute(pledge_query, seccode=seccode).fetchone()
|
with engine.connect() as conn:
|
||||||
|
funding_result = conn.execute(funding_query, {'seccode': seccode}).fetchone()
|
||||||
|
with engine.connect() as conn:
|
||||||
|
pledge_result = conn.execute(pledge_query, {'seccode': seccode}).fetchone()
|
||||||
|
|
||||||
summary = {
|
summary = {
|
||||||
'stock_code': seccode,
|
'stock_code': seccode,
|
||||||
@@ -10954,7 +10987,8 @@ def get_rise_analysis(seccode):
|
|||||||
ORDER BY trade_date DESC LIMIT 100
|
ORDER BY trade_date DESC LIMIT 100
|
||||||
""")
|
""")
|
||||||
|
|
||||||
result = engine.execute(query, **params).fetchall()
|
with engine.connect() as conn:
|
||||||
|
result = conn.execute(query, params).fetchall()
|
||||||
|
|
||||||
# 格式化数据
|
# 格式化数据
|
||||||
rise_analysis_data = []
|
rise_analysis_data = []
|
||||||
@@ -11016,7 +11050,8 @@ def get_comprehensive_analysis(company_code):
|
|||||||
WHERE company_code = :company_code
|
WHERE company_code = :company_code
|
||||||
""")
|
""")
|
||||||
|
|
||||||
qualitative_result = engine.execute(qualitative_query, company_code=company_code).fetchone()
|
with engine.connect() as conn:
|
||||||
|
qualitative_result = conn.execute(qualitative_query, {'company_code': company_code}).fetchone()
|
||||||
|
|
||||||
# 获取业务板块分析
|
# 获取业务板块分析
|
||||||
segments_query = text("""
|
segments_query = text("""
|
||||||
@@ -11033,7 +11068,8 @@ def get_comprehensive_analysis(company_code):
|
|||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
""")
|
""")
|
||||||
|
|
||||||
segments_result = engine.execute(segments_query, company_code=company_code).fetchall()
|
with engine.connect() as conn:
|
||||||
|
segments_result = conn.execute(segments_query, {'company_code': company_code}).fetchall()
|
||||||
|
|
||||||
# 获取竞争地位数据 - 最新一期
|
# 获取竞争地位数据 - 最新一期
|
||||||
competitive_query = text("""
|
competitive_query = text("""
|
||||||
@@ -11058,7 +11094,8 @@ def get_comprehensive_analysis(company_code):
|
|||||||
ORDER BY report_period DESC LIMIT 1
|
ORDER BY report_period DESC LIMIT 1
|
||||||
""")
|
""")
|
||||||
|
|
||||||
competitive_result = engine.execute(competitive_query, company_code=company_code).fetchone()
|
with engine.connect() as conn:
|
||||||
|
competitive_result = conn.execute(competitive_query, {'company_code': company_code}).fetchone()
|
||||||
|
|
||||||
# 获取业务结构数据 - 最新一期
|
# 获取业务结构数据 - 最新一期
|
||||||
business_structure_query = text("""
|
business_structure_query = text("""
|
||||||
@@ -11085,7 +11122,8 @@ def get_comprehensive_analysis(company_code):
|
|||||||
ORDER BY revenue_ratio DESC
|
ORDER BY revenue_ratio DESC
|
||||||
""")
|
""")
|
||||||
|
|
||||||
business_structure_result = engine.execute(business_structure_query, company_code=company_code).fetchall()
|
with engine.connect() as conn:
|
||||||
|
business_structure_result = conn.execute(business_structure_query, {'company_code': company_code}).fetchall()
|
||||||
|
|
||||||
# 构建返回数据
|
# 构建返回数据
|
||||||
response_data = {
|
response_data = {
|
||||||
@@ -11222,7 +11260,8 @@ def get_value_chain_analysis(company_code):
|
|||||||
ORDER BY node_level ASC, importance_score DESC
|
ORDER BY node_level ASC, importance_score DESC
|
||||||
""")
|
""")
|
||||||
|
|
||||||
nodes_result = engine.execute(nodes_query, company_code=company_code).fetchall()
|
with engine.connect() as conn:
|
||||||
|
nodes_result = conn.execute(nodes_query, {'company_code': company_code}).fetchall()
|
||||||
|
|
||||||
# 获取产业链流向数据
|
# 获取产业链流向数据
|
||||||
flows_query = text("""
|
flows_query = text("""
|
||||||
@@ -11242,7 +11281,8 @@ def get_value_chain_analysis(company_code):
|
|||||||
ORDER BY flow_ratio DESC
|
ORDER BY flow_ratio DESC
|
||||||
""")
|
""")
|
||||||
|
|
||||||
flows_result = engine.execute(flows_query, company_code=company_code).fetchall()
|
with engine.connect() as conn:
|
||||||
|
flows_result = conn.execute(flows_query, {'company_code': company_code}).fetchall()
|
||||||
|
|
||||||
# 构建节点数据结构
|
# 构建节点数据结构
|
||||||
nodes_by_level = {}
|
nodes_by_level = {}
|
||||||
@@ -11352,7 +11392,8 @@ def get_key_factors_timeline(company_code):
|
|||||||
ORDER BY display_order ASC, created_at ASC
|
ORDER BY display_order ASC, created_at ASC
|
||||||
""")
|
""")
|
||||||
|
|
||||||
categories_result = engine.execute(categories_query, company_code=company_code).fetchall()
|
with engine.connect() as conn:
|
||||||
|
categories_result = conn.execute(categories_query, {'company_code': company_code}).fetchall()
|
||||||
|
|
||||||
# 获取关键因素详情
|
# 获取关键因素详情
|
||||||
factors_query = text("""
|
factors_query = text("""
|
||||||
@@ -11417,7 +11458,8 @@ def get_key_factors_timeline(company_code):
|
|||||||
ORDER BY kf.report_period DESC, kf.impact_weight DESC, kf.updated_at DESC
|
ORDER BY kf.report_period DESC, kf.impact_weight DESC, kf.updated_at DESC
|
||||||
""")
|
""")
|
||||||
|
|
||||||
factors_result = engine.execute(factors_query, **params).fetchall()
|
with engine.connect() as conn:
|
||||||
|
factors_result = conn.execute(factors_query, params).fetchall()
|
||||||
|
|
||||||
# 获取发展时间线事件
|
# 获取发展时间线事件
|
||||||
timeline_query = text("""
|
timeline_query = text("""
|
||||||
@@ -11436,9 +11478,8 @@ def get_key_factors_timeline(company_code):
|
|||||||
ORDER BY event_date DESC LIMIT :limit
|
ORDER BY event_date DESC LIMIT :limit
|
||||||
""")
|
""")
|
||||||
|
|
||||||
timeline_result = engine.execute(timeline_query,
|
with engine.connect() as conn:
|
||||||
company_code=company_code,
|
timeline_result = conn.execute(timeline_query, {'company_code': company_code, 'limit': event_limit}).fetchall()
|
||||||
limit=event_limit).fetchall()
|
|
||||||
|
|
||||||
# 构建关键因素数据结构
|
# 构建关键因素数据结构
|
||||||
key_factors_data = {}
|
key_factors_data = {}
|
||||||
|
|||||||
12556
app.py.backup
Normal file
12556
app.py.backup
Normal file
File diff suppressed because it is too large
Load Diff
12556
app.py.backup_20251114_145340
Normal file
12556
app.py.backup_20251114_145340
Normal file
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,8 @@ const { Text } = Typography;
|
|||||||
* @param {Object} props.prefixStyle - 前缀标签的自定义样式(可选)
|
* @param {Object} props.prefixStyle - 前缀标签的自定义样式(可选)
|
||||||
* @param {boolean} props.showAIBadge - 是否显示右上角 AI 标识,默认 true(可选)
|
* @param {boolean} props.showAIBadge - 是否显示右上角 AI 标识,默认 true(可选)
|
||||||
* @param {Object} props.containerStyle - 容器额外样式(可选)
|
* @param {Object} props.containerStyle - 容器额外样式(可选)
|
||||||
|
* @param {string} props.textColor - 文本颜色,默认自动判断背景色(可选)
|
||||||
|
* @param {string} props.titleColor - 标题颜色,默认继承 textColor(可选)
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* <CitedContent
|
* <CitedContent
|
||||||
@@ -30,6 +32,7 @@ const { Text } = Typography;
|
|||||||
* prefixStyle={{ color: '#666' }}
|
* prefixStyle={{ color: '#666' }}
|
||||||
* showAIBadge={true}
|
* showAIBadge={true}
|
||||||
* containerStyle={{ marginTop: 16 }}
|
* containerStyle={{ marginTop: 16 }}
|
||||||
|
* textColor="#E2E8F0"
|
||||||
* />
|
* />
|
||||||
*/
|
*/
|
||||||
const CitedContent = ({
|
const CitedContent = ({
|
||||||
@@ -38,7 +41,9 @@ const CitedContent = ({
|
|||||||
prefix = '',
|
prefix = '',
|
||||||
prefixStyle = {},
|
prefixStyle = {},
|
||||||
showAIBadge = true,
|
showAIBadge = true,
|
||||||
containerStyle = {}
|
containerStyle = {},
|
||||||
|
textColor,
|
||||||
|
titleColor
|
||||||
}) => {
|
}) => {
|
||||||
// 处理数据
|
// 处理数据
|
||||||
const processed = processCitationData(data);
|
const processed = processCitationData(data);
|
||||||
@@ -52,6 +57,19 @@ const CitedContent = ({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 自动判断文本颜色:如果容器背景是深色,使用浅色文本
|
||||||
|
const bgColor = containerStyle.backgroundColor;
|
||||||
|
const isDarkBg = bgColor && (
|
||||||
|
bgColor.includes('rgba(0,0,0') ||
|
||||||
|
bgColor.includes('rgba(0, 0, 0') ||
|
||||||
|
bgColor === 'transparent' ||
|
||||||
|
bgColor.includes('#1A202C') ||
|
||||||
|
bgColor.includes('#171923')
|
||||||
|
);
|
||||||
|
|
||||||
|
const finalTextColor = textColor || (isDarkBg ? '#E2E8F0' : '#262626');
|
||||||
|
const finalTitleColor = titleColor || finalTextColor;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -87,7 +105,7 @@ const CitedContent = ({
|
|||||||
{/* 标题栏 */}
|
{/* 标题栏 */}
|
||||||
{title && (
|
{title && (
|
||||||
<div style={{ marginBottom: 12, paddingRight: 80 }}>
|
<div style={{ marginBottom: 12, paddingRight: 80 }}>
|
||||||
<Text strong style={{ fontSize: 14 }}>
|
<Text strong style={{ fontSize: 14, color: finalTitleColor }}>
|
||||||
{title}
|
{title}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
@@ -105,6 +123,7 @@ const CitedContent = ({
|
|||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
display: 'inline',
|
display: 'inline',
|
||||||
marginRight: 4,
|
marginRight: 4,
|
||||||
|
color: finalTextColor,
|
||||||
...prefixStyle
|
...prefixStyle
|
||||||
}}>
|
}}>
|
||||||
{prefix}
|
{prefix}
|
||||||
@@ -114,7 +133,7 @@ const CitedContent = ({
|
|||||||
{processed.segments.map((segment, index) => (
|
{processed.segments.map((segment, index) => (
|
||||||
<React.Fragment key={`segment-${segment.citationId}`}>
|
<React.Fragment key={`segment-${segment.citationId}`}>
|
||||||
{/* 文本片段 */}
|
{/* 文本片段 */}
|
||||||
<Text style={{ fontSize: 14, display: 'inline' }}>
|
<Text style={{ fontSize: 14, display: 'inline', color: finalTextColor }}>
|
||||||
{segment.text}
|
{segment.text}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
@@ -126,7 +145,7 @@ const CitedContent = ({
|
|||||||
|
|
||||||
{/* 在片段之间添加逗号分隔符(最后一个不加) */}
|
{/* 在片段之间添加逗号分隔符(最后一个不加) */}
|
||||||
{index < processed.segments.length - 1 && (
|
{index < processed.segments.length - 1 && (
|
||||||
<Text style={{ fontSize: 14, display: 'inline' }}>,</Text>
|
<Text style={{ fontSize: 14, display: 'inline', color: finalTextColor }}>,</Text>
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -311,6 +311,7 @@ const StockListItem = ({
|
|||||||
data={stock.relation_desc}
|
data={stock.relation_desc}
|
||||||
title=""
|
title=""
|
||||||
showAIBadge={true}
|
showAIBadge={true}
|
||||||
|
textColor={PROFESSIONAL_COLORS.text.primary}
|
||||||
containerStyle={{
|
containerStyle={{
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
borderRadius: '0',
|
borderRadius: '0',
|
||||||
|
|||||||
@@ -344,6 +344,7 @@ const HistoricalEvents = ({
|
|||||||
data={content}
|
data={content}
|
||||||
title=""
|
title=""
|
||||||
showAIBadge={true}
|
showAIBadge={true}
|
||||||
|
textColor={PROFESSIONAL_COLORS.text.primary}
|
||||||
containerStyle={{
|
containerStyle={{
|
||||||
backgroundColor: useColorModeValue('#f7fafc', 'rgba(45, 55, 72, 0.6)'),
|
backgroundColor: useColorModeValue('#f7fafc', 'rgba(45, 55, 72, 0.6)'),
|
||||||
borderRadius: '8px',
|
borderRadius: '8px',
|
||||||
|
|||||||
@@ -972,6 +972,7 @@ const TransmissionChainAnalysis = ({ eventId }) => {
|
|||||||
<CitedContent
|
<CitedContent
|
||||||
data={selectedNode.extra.description}
|
data={selectedNode.extra.description}
|
||||||
title=""
|
title=""
|
||||||
|
textColor={PROFESSIONAL_COLORS.text.primary}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
`${selectedNode.extra.description}(AI合成)`
|
`${selectedNode.extra.description}(AI合成)`
|
||||||
@@ -1081,7 +1082,8 @@ const TransmissionChainAnalysis = ({ eventId }) => {
|
|||||||
data={parent.transmission_mechanism}
|
data={parent.transmission_mechanism}
|
||||||
title=""
|
title=""
|
||||||
prefix="机制:"
|
prefix="机制:"
|
||||||
prefixStyle={{ fontSize: 12, color: '#666', fontWeight: 'bold' }}
|
prefixStyle={{ fontSize: 12, color: PROFESSIONAL_COLORS.text.secondary, fontWeight: 'bold' }}
|
||||||
|
textColor={PROFESSIONAL_COLORS.text.primary}
|
||||||
containerStyle={{ marginTop: 8 }}
|
containerStyle={{ marginTop: 8 }}
|
||||||
showAIBadge={false}
|
showAIBadge={false}
|
||||||
/>
|
/>
|
||||||
@@ -1136,7 +1138,8 @@ const TransmissionChainAnalysis = ({ eventId }) => {
|
|||||||
data={child.transmission_mechanism}
|
data={child.transmission_mechanism}
|
||||||
title=""
|
title=""
|
||||||
prefix="机制:"
|
prefix="机制:"
|
||||||
prefixStyle={{ fontSize: 12, color: '#666', fontWeight: 'bold' }}
|
prefixStyle={{ fontSize: 12, color: PROFESSIONAL_COLORS.text.secondary, fontWeight: 'bold' }}
|
||||||
|
textColor={PROFESSIONAL_COLORS.text.primary}
|
||||||
containerStyle={{ marginTop: 8 }}
|
containerStyle={{ marginTop: 8 }}
|
||||||
showAIBadge={false}
|
showAIBadge={false}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user