Files
SmartChat/api/v3.py
2026-01-08 01:06:27 +08:00

277 lines
8.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
主程序入口 - 集成周报生成器
"""
from datetime import datetime, timedelta
from . import Blueprint
from api.lib import db_manager
from weekly_report_generator import WeeklyReportGenerator
from flask import request, jsonify, render_template
v3 = Blueprint('v3', __name__)
# 初始化周报生成器
weekly_report_generator = None
def init_weekly_report_generator():
"""初始化周报生成器"""
global weekly_report_generator
if weekly_report_generator is None:
weekly_report_generator = WeeklyReportGenerator(db_manager)
@v3.route('/api/weekly_report/generate', methods=['GET', 'POST'])
def generate_weekly_report_api():
"""生成周报API接口 (v3版本,基于需求文档样式)"""
try:
init_weekly_report_generator()
# 获取参数
if request.method == 'POST':
data = request.get_json()
week_str = data.get('week')
use_deepseek = data.get('use_deepseek', True)
else:
week_str = request.args.get('week')
use_deepseek = request.args.get('use_deepseek', 'true').lower() == 'true'
# 如果没有提供周次,使用当前周
if not week_str:
current_date = datetime.now()
year = current_date.isocalendar()[0]
week_num = current_date.isocalendar()[1]
week_str = f"{year}-{week_num:02d}"
# 生成周报
result = weekly_report_generator.generate_weekly_report(week_str, use_deepseek)
if result['success']:
return jsonify({
'success': True,
'data': {
'report': result['report'],
'week': result['week'],
'statistics': result.get('statistics', {})
}
})
else:
return jsonify({
'success': False,
'error': result['error']
}), 500
except Exception as e:
return jsonify({
'success': False,
'error': f"生成周报失败: {str(e)}"
}), 500
@v3.route('/api/weekly_report/weeks', methods=['GET'])
def get_available_weeks_v3():
"""获取可用的周次列表 (v3版本)"""
try:
init_weekly_report_generator()
# 获取数据库中最早和最晚的消息时间
result = db_manager.execute_query('''
SELECT MIN(time) as min_time, MAX(time) as max_time
FROM message
WHERE LENGTH(time) >= 10
''', fetch_all=False)
if result and result['min_time'] and result['max_time']:
min_timestamp = int(result['min_time'][:10])
max_timestamp = int(result['max_time'][:10])
min_date = datetime.fromtimestamp(min_timestamp)
max_date = datetime.fromtimestamp(max_timestamp)
# 生成可用的周次列表
weeks = []
current_date = min_date
while current_date <= max_date:
year = current_date.isocalendar()[0]
week_num = current_date.isocalendar()[1]
week_str = f"{year}-{week_num:02d}"
# 计算周的开始和结束日期
start_of_week = current_date - timedelta(days=current_date.weekday())
end_of_week = start_of_week + timedelta(days=6)
weeks.append({
'week': week_str,
'start_date': start_of_week.strftime('%Y-%m-%d'),
'end_date': end_of_week.strftime('%Y-%m-%d'),
'display': f"{year}年第{week_num}周 ({start_of_week.strftime('%m.%d')}-{end_of_week.strftime('%m.%d')})"
})
current_date += timedelta(weeks=1)
return jsonify({
'success': True,
'data': {
'weeks': weeks[-20:] # 返回最近20周
}
})
else:
return jsonify({
'success': False,
'error': '无法获取时间范围数据'
}), 500
except Exception as e:
return jsonify({
'success': False,
'error': f"获取周次列表失败: {str(e)}"
}), 500
@v3.route('/api/weekly_report/preview', methods=['POST'])
def preview_weekly_report():
"""预览周报API接口 (v3版本)"""
try:
init_weekly_report_generator()
data = request.get_json()
week_str = data.get('week')
if not week_str:
return jsonify({
'success': False,
'error': '请提供周次参数'
}), 400
# 生成预览数据(不调用DeepSeek API)
result = weekly_report_generator.generate_weekly_report(week_str, use_deepseek=False)
if result['success']:
return jsonify({
'success': True,
'data': {
'preview': result['report'],
'statistics': result.get('statistics', {})
}
})
else:
return jsonify({
'success': False,
'error': result['error']
}), 500
except Exception as e:
return jsonify({
'success': False,
'error': f"预览周报失败: {str(e)}"
}), 500
@v3.route('/api/weekly_report/export', methods=['POST'])
def export_weekly_report():
"""导出周报API接口 (v3版本)"""
try:
init_weekly_report_generator()
data = request.get_json()
week_str = data.get('week')
export_format = data.get('format', 'markdown') # markdown, html, pdf
if not week_str:
return jsonify({
'success': False,
'error': '请提供周次参数'
}), 400
# 生成完整周报
result = weekly_report_generator.generate_weekly_report(week_str, use_deepseek=True)
if result['success']:
report_content = result['report']
# 根据格式处理内容
if export_format == 'html':
# 简单的Markdown转HTML(实际项目中可以使用专业库)
html_content = markdown_to_html(report_content)
return jsonify({
'success': True,
'data': {
'content': html_content,
'filename': f"周报_{week_str}.html",
'mime_type': 'text/html'
}
})
elif export_format == 'pdf':
# PDF导出(需要额外库支持)
return jsonify({
'success': False,
'error': 'PDF导出功能暂未实现'
}), 501
else: # markdown
return jsonify({
'success': True,
'data': {
'content': report_content,
'filename': f"周报_{week_str}.md",
'mime_type': 'text/markdown'
}
})
else:
return jsonify({
'success': False,
'error': result['error']
}), 500
except Exception as e:
return jsonify({
'success': False,
'error': f"导出周报失败: {str(e)}"
}), 500
def markdown_to_html(markdown_text: str) -> str:
"""简单的Markdown转HTML函数"""
# 基本转换规则
html = markdown_text
# 标题转换
html = html.replace('\n# ', '\n<h1>').replace('\n## ', '\n<h2>').replace('\n### ', '\n<h3>')
html = html.replace('\n#### ', '\n<h4>').replace('\n##### ', '\n<h5>').replace('\n###### ', '\n<h6>')
# 表格处理
html = html.replace('\t', '</td><td>')
html = html.replace('\n', '</td></tr>\n<tr><td>')
# 基本的HTML包装
html = f"""<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>周报</title>
<style>
body {{ font-family: Arial, sans-serif; margin: 20px; }}
table {{ border-collapse: collapse; width: 100%; }}
th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
th {{ background-color: #f2f2f2; }}
</style>
</head>
<body>
{html}
</body>
</html>"""
return html
# v3周报页面路由
@v3.route('/weekly_report')
def weekly_report_page():
"""周报页面 v3版本"""
return render_template('weekly_report_v3.html')