- Backend: GET /api/export/:type/:id returns .md file download - Backend: POST /api/export/text for direct text-to-md export - Frontend: downloadMarkdown() utility for client-side .md download - Frontend: printAsPdf() utility via browser print dialog - GenerateView: export dropdown button (MD / PDF) on result card Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
98 lines
3.2 KiB
Python
98 lines
3.2 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
内容导出路由:Markdown 文件下载
|
||
"""
|
||
from flask import Blueprint, request, jsonify, Response
|
||
from src.flask_prompt_master.models.models import Prompt, MealPlan, WeeklyReport, TravelPlan, MeetingMinutes, ResumeOptimization
|
||
from src.flask_prompt_master.models.history_models import PromptHistory
|
||
from src.flask_prompt_master.user_context import get_current_user_id
|
||
from datetime import datetime
|
||
|
||
export_bp = Blueprint('export', __name__)
|
||
|
||
CONTENT_MODELS = {
|
||
'prompt': Prompt,
|
||
'meal': MealPlan,
|
||
'report': WeeklyReport,
|
||
'travel': TravelPlan,
|
||
'meeting': MeetingMinutes,
|
||
'resume': ResumeOptimization,
|
||
'history': PromptHistory,
|
||
}
|
||
|
||
FIELD_MAP = {
|
||
'prompt': ('input_text', 'generated_text'),
|
||
'meal': ('meal_plan_content',),
|
||
'report': ('report_content',),
|
||
'travel': ('plan_content',),
|
||
'meeting': ('summary_content',),
|
||
'resume': ('optimized_content',),
|
||
'history': ('generated_prompt',),
|
||
}
|
||
|
||
TITLE_MAP = {
|
||
'prompt': '提示词生成结果',
|
||
'meal': '饭菜规划',
|
||
'report': '周报/日报',
|
||
'travel': '旅行攻略',
|
||
'meeting': '会议纪要',
|
||
'resume': '简历优化',
|
||
'history': '历史记录',
|
||
}
|
||
|
||
|
||
@export_bp.route('/api/export/<content_type>/<int:content_id>', methods=['GET'])
|
||
def export_content(content_type, content_id):
|
||
"""导出内容为 Markdown 文件下载"""
|
||
if content_type not in CONTENT_MODELS:
|
||
return jsonify({'success': False, 'message': f'不支持的内容类型: {content_type}'}), 400
|
||
|
||
model = CONTENT_MODELS[content_type]
|
||
record = model.query.get(content_id)
|
||
if not record:
|
||
return jsonify({'success': False, 'message': '内容不存在'}), 404
|
||
|
||
fields = FIELD_MAP.get(content_type, [])
|
||
title = TITLE_MAP.get(content_type, '导出内容')
|
||
|
||
# 组装 Markdown 内容
|
||
lines = [f'# {title}', '', f'> 导出时间: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}', '']
|
||
for field in fields:
|
||
val = getattr(record, field, None) or ''
|
||
lines.append(val)
|
||
lines.append('')
|
||
|
||
markdown = '\n'.join(lines)
|
||
|
||
filename = f'{content_type}_{content_id}_{datetime.now().strftime("%Y%m%d%H%M%S")}.md'
|
||
return Response(
|
||
markdown,
|
||
mimetype='text/markdown; charset=utf-8',
|
||
headers={
|
||
'Content-Disposition': f'attachment; filename="{filename}"',
|
||
'X-Content-Type-Options': 'nosniff',
|
||
},
|
||
)
|
||
|
||
|
||
@export_bp.route('/api/export/text', methods=['POST'])
|
||
def export_text():
|
||
"""直接导出文本内容为 Markdown(无需存储记录)"""
|
||
data = request.get_json(silent=True) or {}
|
||
content = (data.get('content') or '').strip()
|
||
title = (data.get('title') or '导出内容').strip()
|
||
|
||
if not content:
|
||
return jsonify({'success': False, 'message': '内容为空'}), 400
|
||
|
||
markdown = f'# {title}\n\n> 导出时间: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}\n\n{content}\n'
|
||
filename = f'export_{datetime.now().strftime("%Y%m%d%H%M%S")}.md'
|
||
return Response(
|
||
markdown,
|
||
mimetype='text/markdown; charset=utf-8',
|
||
headers={
|
||
'Content-Disposition': f'attachment; filename="{filename}"',
|
||
'X-Content-Type-Options': 'nosniff',
|
||
},
|
||
)
|