community增加事件详情
This commit is contained in:
213
app.py
213
app.py
@@ -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():
|
||||
"""获取指定日期的事件列表"""
|
||||
|
||||
Reference in New Issue
Block a user