277 lines
8.7 KiB
Python
277 lines
8.7 KiB
Python
"""
|
||
主程序入口 - 集成周报生成器
|
||
"""
|
||
|
||
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')
|
||
|
||
|