community增加事件详情

This commit is contained in:
2026-01-07 16:33:30 +08:00
parent 9b42c2c7c2
commit 131e92b0b9
3 changed files with 324 additions and 149 deletions

213
app.py
View File

@@ -10541,6 +10541,219 @@ def get_event_counts():
}), 500
@app.route('/api/v1/calendar/combined-data', methods=['GET'])
def get_calendar_combined_data():
"""获取日历综合数据(涨停数据 + 事件数量 + 上证涨跌幅)
一次性返回日历显示所需的所有数据,避免前端多次请求
参数:
year: 年份(可选,默认当前年份)
month: 月份(可选,默认当前月份)
返回:
{
success: true,
data: [
{
date: "20260107",
zt_count: 80, // 涨停数量
top_sector: "人工智能", // 最热概念
event_count: 8, // 事件数量
index_change: 1.38 // 上证涨跌幅(%)
},
...
]
}
"""
import os
import json
try:
year = request.args.get('year', datetime.now().year, type=int)
month = request.args.get('month', datetime.now().month, type=int)
# 计算月份的开始和结束日期
start_date = datetime(year, month, 1)
if month == 12:
end_date = datetime(year + 1, 1, 1)
else:
end_date = datetime(year, month + 1, 1)
# 用 Map 存储数据key 为 YYYYMMDD 格式
data_map = {}
# 1. 从静态文件加载涨停数据
zt_dates_path = os.path.join(app.static_folder or 'static', 'data', 'zt', 'dates.json')
# 尝试多个可能的路径
possible_paths = [
zt_dates_path,
os.path.join('public', 'data', 'zt', 'dates.json'),
os.path.join('data', 'zt', 'dates.json'),
'/var/www/vf_react/data/zt/dates.json', # 服务器路径
]
zt_dates = []
for path in possible_paths:
if os.path.exists(path):
try:
with open(path, 'r', encoding='utf-8') as f:
zt_data = json.load(f)
zt_dates = zt_data.get('dates', [])
break
except Exception as e:
print(f"[calendar] 读取涨停数据失败 {path}: {e}")
# 处理涨停数据
for item in zt_dates:
date_str = item.get('date', '')
if not date_str:
continue
# 检查是否在当月范围内
try:
item_date = datetime.strptime(date_str, '%Y%m%d')
if start_date <= item_date < end_date:
data_map[date_str] = {
'date': date_str,
'zt_count': item.get('count', 0),
'top_sector': '',
'event_count': 0,
'index_change': None
}
except ValueError:
continue
# 2. 加载涨停详情获取 top_sector从 daily 文件)
zt_daily_dir = None
possible_daily_dirs = [
os.path.join(app.static_folder or 'static', 'data', 'zt', 'daily'),
os.path.join('public', 'data', 'zt', 'daily'),
os.path.join('data', 'zt', 'daily'),
'/var/www/vf_react/data/zt/daily',
]
for dir_path in possible_daily_dirs:
if os.path.isdir(dir_path):
zt_daily_dir = dir_path
break
if zt_daily_dir:
for date_str in data_map.keys():
daily_file = os.path.join(zt_daily_dir, f'{date_str}.json')
if os.path.exists(daily_file):
try:
with open(daily_file, 'r', encoding='utf-8') as f:
daily_data = json.load(f)
# 优先使用词云图最高频词
word_freq = daily_data.get('word_freq_data', [])
if word_freq:
data_map[date_str]['top_sector'] = word_freq[0].get('name', '')
elif daily_data.get('sector_data'):
# 找出涨停数最多的板块
max_sector = ''
max_count = 0
for sector, info in daily_data['sector_data'].items():
if info.get('count', 0) > max_count:
max_count = info['count']
max_sector = sector
data_map[date_str]['top_sector'] = max_sector
except Exception as e:
print(f"[calendar] 读取涨停详情失败 {daily_file}: {e}")
# 3. 查询事件数量
event_query = """
SELECT DATE(calendar_time) as date, COUNT(*) as count
FROM future_events
WHERE calendar_time BETWEEN :start_date AND :end_date
AND type = 'event'
GROUP BY DATE(calendar_time)
"""
event_result = db.session.execute(text(event_query), {
'start_date': start_date,
'end_date': end_date
})
for row in event_result:
event_date = row[0]
event_count = row[1]
date_str = event_date.strftime('%Y%m%d') if hasattr(event_date, 'strftime') else str(event_date).replace('-', '')
if date_str in data_map:
data_map[date_str]['event_count'] = event_count
else:
data_map[date_str] = {
'date': date_str,
'zt_count': 0,
'top_sector': '',
'event_count': event_count,
'index_change': None
}
# 4. 查询上证指数涨跌幅(从 MySQL 的 ea_exchangetrade 表)
index_query = """
SELECT TRADEDATE, F006N, F007N
FROM ea_exchangetrade
WHERE INDEXCODE = '000001'
AND TRADEDATE BETWEEN :start_date AND :end_date
ORDER BY TRADEDATE
"""
try:
with engine.connect() as conn:
index_result = conn.execute(text(index_query), {
'start_date': start_date,
'end_date': end_date
}).fetchall()
# 构建前一天收盘价映射,用于计算涨跌幅
prev_close = None
for row in index_result:
trade_date = row[0]
close_price = float(row[1]) if row[1] else None
db_prev_close = float(row[2]) if row[2] else None
date_str = trade_date.strftime('%Y%m%d') if hasattr(trade_date, 'strftime') else str(trade_date).replace('-', '')
# 计算涨跌幅
actual_prev = prev_close if prev_close else db_prev_close
if close_price and actual_prev:
change_pct = ((close_price - actual_prev) / actual_prev) * 100
if date_str in data_map:
data_map[date_str]['index_change'] = round(change_pct, 2)
else:
data_map[date_str] = {
'date': date_str,
'zt_count': 0,
'top_sector': '',
'event_count': 0,
'index_change': round(change_pct, 2)
}
prev_close = close_price
except Exception as e:
print(f"[calendar] 查询上证指数失败: {e}")
# 按日期排序返回
result = sorted(data_map.values(), key=lambda x: x['date'])
return jsonify({
'success': True,
'data': result,
'year': year,
'month': month
})
except Exception as e:
import traceback
traceback.print_exc()
return jsonify({
'success': False,
'error': str(e)
}), 500
@app.route('/api/v1/calendar/events', methods=['GET'])
def get_calendar_events():
"""获取指定日期的事件列表"""