update pay function

This commit is contained in:
2025-11-27 11:28:57 +08:00
parent 4560467523
commit 2a71924076
5 changed files with 1469 additions and 121 deletions

254
app.py
View File

@@ -4609,20 +4609,10 @@ def get_my_following_future_events():
)
events = []
# 所有返回的事件都是已关注的
following_ids = set(future_event_ids)
for row in result:
event_data = {
'id': row.data_id,
'title': row.title,
'type': row.type,
'calendar_time': row.calendar_time.isoformat(),
'star': row.star,
'former': row.former,
'forecast': row.forecast,
'fact': row.fact,
'is_following': True, # 这些都是已关注的
'related_stocks': parse_json_field(row.related_stocks),
'concepts': parse_json_field(row.concepts)
}
event_data = process_future_event_row(row, following_ids)
events.append(event_data)
return jsonify({'success': True, 'data': events})
@@ -6094,17 +6084,9 @@ def account_calendar_events():
future_events = []
if future_event_ids:
# 使用 SELECT * 以便获取所有字段(包括新字段)
base_sql = """
SELECT data_id, \
title, \
type, \
calendar_time, \
star, \
former, \
forecast, \
fact, \
related_stocks, \
concepts
SELECT *
FROM future_events
WHERE data_id IN :event_ids \
"""
@@ -6122,12 +6104,24 @@ def account_calendar_events():
result = db.session.execute(text(base_sql), params)
for row in result:
# related_stocks 形如 [[code,name,reason,score], ...]
rs = parse_json_field(row.related_stocks)
# 使用新字段回退逻辑获取 former
former_value = get_future_event_field(row, 'second_modified_text', 'former')
# 获取 related_stocks优先使用 best_matches
best_matches = getattr(row, 'best_matches', None) if hasattr(row, 'best_matches') else None
if best_matches and str(best_matches).strip():
rs = parse_best_matches(best_matches)
else:
rs = parse_json_field(getattr(row, 'related_stocks', None))
# 生成股票标签列表
stock_tags = []
try:
for it in rs:
if isinstance(it, (list, tuple)) and len(it) >= 2:
if isinstance(it, dict):
# 新结构
stock_tags.append(f"{it.get('code', '')} {it.get('name', '')}")
elif isinstance(it, (list, tuple)) and len(it) >= 2:
stock_tags.append(f"{it[0]} {it[1]}")
elif isinstance(it, str):
stock_tags.append(it)
@@ -6140,7 +6134,7 @@ def account_calendar_events():
'event_date': (row.calendar_time.date().isoformat() if row.calendar_time else None),
'type': 'future_event',
'importance': int(row.star) if getattr(row, 'star', None) is not None else 3,
'description': row.former or '',
'description': former_value or '',
'stocks': stock_tags,
'is_following': True,
'source': 'future'
@@ -7548,47 +7542,8 @@ def get_calendar_events():
user_following_ids = {f.future_event_id for f in follows}
for row in result:
event_data = {
'id': row.data_id,
'title': row.title,
'type': row.type,
'calendar_time': row.calendar_time.isoformat(),
'star': row.star,
'former': row.former,
'forecast': row.forecast,
'fact': row.fact,
'is_following': row.data_id in user_following_ids
}
# 解析相关股票和概念
if row.related_stocks:
try:
if isinstance(row.related_stocks, str):
if row.related_stocks.startswith('['):
event_data['related_stocks'] = json.loads(row.related_stocks)
else:
event_data['related_stocks'] = row.related_stocks.split(',')
else:
event_data['related_stocks'] = row.related_stocks
except:
event_data['related_stocks'] = []
else:
event_data['related_stocks'] = []
if row.concepts:
try:
if isinstance(row.concepts, str):
if row.concepts.startswith('['):
event_data['concepts'] = json.loads(row.concepts)
else:
event_data['concepts'] = row.concepts.split(',')
else:
event_data['concepts'] = row.concepts
except:
event_data['concepts'] = []
else:
event_data['concepts'] = []
# 使用统一的处理函数,支持新字段回退和 best_matches 解析
event_data = process_future_event_row(row, user_following_ids)
events.append(event_data)
return jsonify({
@@ -7614,28 +7569,18 @@ def get_calendar_event_detail(event_id):
'error': 'Event not found'
}), 404
event_data = {
'id': result.data_id,
'title': result.title,
'type': result.type,
'calendar_time': result.calendar_time.isoformat(),
'star': result.star,
'former': result.former,
'forecast': result.forecast,
'fact': result.fact,
'related_stocks': parse_json_field(result.related_stocks),
'concepts': parse_json_field(result.concepts)
}
# 检查当前用户是否关注了该未来事件
user_following_ids = set()
if 'user_id' in session:
is_following = FutureEventFollow.query.filter_by(
user_id=session['user_id'],
future_event_id=event_id
).first() is not None
event_data['is_following'] = is_following
else:
event_data['is_following'] = False
if is_following:
user_following_ids.add(event_id)
# 使用统一的处理函数,支持新字段回退和 best_matches 解析
event_data = process_future_event_row(result, user_following_ids)
return jsonify({
'success': True,
@@ -7727,6 +7672,147 @@ def parse_json_field(field_value):
return []
def get_future_event_field(row, new_field, old_field):
"""
获取 future_events 表字段值,支持新旧字段回退
如果新字段存在且不为空,使用新字段;否则使用旧字段
"""
new_value = getattr(row, new_field, None) if hasattr(row, new_field) else None
old_value = getattr(row, old_field, None) if hasattr(row, old_field) else None
# 如果新字段有值(不为空字符串),使用新字段
if new_value is not None and str(new_value).strip():
return new_value
return old_value
def parse_best_matches(best_matches_value):
"""
解析新的 best_matches 数据结构(含研报引用信息)
新结构示例:
[
{
"stock_code": "300451.SZ",
"company_name": "创业慧康",
"original_description": "核心标的,医疗信息化...",
"best_report_title": "报告标题",
"best_report_author": "作者",
"best_report_sentences": "相关内容",
"best_report_match_score": "",
"best_report_match_ratio": 0.9285714285714286,
"best_report_declare_date": "2023-04-25T00:00:00",
"total_reports": 9,
"high_score_reports": 6
},
...
]
返回统一格式的股票列表,兼容旧格式
"""
if not best_matches_value:
return []
try:
# 解析 JSON
if isinstance(best_matches_value, str):
data = json.loads(best_matches_value)
else:
data = best_matches_value
if not isinstance(data, list):
return []
result = []
for item in data:
if isinstance(item, dict):
# 新结构:包含研报信息的字典
stock_info = {
'code': item.get('stock_code', ''),
'name': item.get('company_name', ''),
'description': item.get('original_description', ''),
'score': item.get('best_report_match_ratio', 0),
# 研报引用信息
'report': {
'title': item.get('best_report_title', ''),
'author': item.get('best_report_author', ''),
'sentences': item.get('best_report_sentences', ''),
'match_score': item.get('best_report_match_score', ''),
'match_ratio': item.get('best_report_match_ratio', 0),
'declare_date': item.get('best_report_declare_date', ''),
'total_reports': item.get('total_reports', 0),
'high_score_reports': item.get('high_score_reports', 0)
} if item.get('best_report_title') else None
}
result.append(stock_info)
elif isinstance(item, (list, tuple)) and len(item) >= 2:
# 旧结构:[code, name, description, score]
result.append({
'code': item[0],
'name': item[1],
'description': item[2] if len(item) > 2 else '',
'score': item[3] if len(item) > 3 else 0,
'report': None
})
return result
except Exception as e:
print(f"parse_best_matches error: {e}")
return []
def process_future_event_row(row, user_following_ids=None):
"""
统一处理 future_events 表的行数据
支持新字段回退和 best_matches 解析
"""
if user_following_ids is None:
user_following_ids = set()
# 获取字段值,支持新旧回退
# second_modified_text -> former
# second_modified_text.1 -> forecast (MySQL 中用反引号)
former_value = get_future_event_field(row, 'second_modified_text', 'former')
# 处理 second_modified_text.1 字段(特殊字段名)
forecast_new = None
if hasattr(row, 'second_modified_text.1'):
forecast_new = getattr(row, 'second_modified_text.1', None)
# 尝试其他可能的属性名
for attr_name in ['second_modified_text.1', 'second_modified_text_1']:
if hasattr(row, attr_name):
val = getattr(row, attr_name, None)
if val and str(val).strip():
forecast_new = val
break
forecast_value = forecast_new if (forecast_new and str(forecast_new).strip()) else getattr(row, 'forecast', None)
# best_matches -> related_stocks
best_matches = getattr(row, 'best_matches', None) if hasattr(row, 'best_matches') else None
if best_matches and str(best_matches).strip():
related_stocks = parse_best_matches(best_matches)
else:
related_stocks = parse_json_field(getattr(row, 'related_stocks', None))
# 构建事件数据
event_data = {
'id': row.data_id,
'title': row.title,
'type': getattr(row, 'type', None),
'calendar_time': row.calendar_time.isoformat() if row.calendar_time else None,
'star': row.star,
'former': former_value,
'forecast': forecast_value,
'fact': getattr(row, 'fact', None),
'is_following': row.data_id in user_following_ids,
'related_stocks': related_stocks,
'concepts': parse_json_field(getattr(row, 'concepts', None)),
'update_time': getattr(row, 'update_time', None).isoformat() if getattr(row, 'update_time', None) else None
}
return event_data
# ==================== 行业API ====================
@app.route('/api/classifications', methods=['GET'])
def get_classifications():