|
|
| from flask import Blueprint, request, jsonify, send_file
|
| import os
|
| import time
|
| import re
|
| import requests
|
| import plotly.graph_objects as go
|
| import numpy as np
|
| from mpl_toolkits.mplot3d import Axes3D
|
| import matplotlib.pyplot as plt
|
| from io import BytesIO
|
| import matplotlib
|
| import json
|
| matplotlib.use('Agg')
|
|
|
| visualization_bp = Blueprint('visualization', __name__)
|
|
|
|
|
| os.makedirs('static', exist_ok=True)
|
|
|
| @visualization_bp.route('/mindmap', methods=['POST'])
|
| def generate_mindmap():
|
| """生成思维导图"""
|
| try:
|
| data = request.json
|
| content = data.get('content', '')
|
|
|
| if not content:
|
| return jsonify({
|
| "success": False,
|
| "message": "思维导图内容不能为空"
|
| }), 400
|
|
|
|
|
| pattern = r'@startmindmap\n([\s\S]*?)@endmindmap'
|
| match = re.search(pattern, content)
|
|
|
| if match:
|
| processed_content = f"@startmindmap\n{match.group(1)}\n@endmindmap"
|
| else:
|
|
|
| processed_content = content
|
|
|
|
|
| if '@startmindmap' not in processed_content:
|
| processed_content = "@startmindmap\n" + processed_content
|
| if '@endmindmap' not in processed_content:
|
| processed_content += "\n@endmindmap"
|
|
|
|
|
| response = requests.post(
|
| 'https://mistpe-flask.hf.space/v1/images/generations',
|
| headers={
|
| 'Authorization': 'Bearer sk-xxx',
|
| 'Content-Type': 'application/json'
|
| },
|
| json={
|
| 'model': 'dall-e-3',
|
| 'prompt': processed_content,
|
| 'n': 1,
|
| 'size': '1024x1024'
|
| }
|
| )
|
|
|
| if response.status_code != 200:
|
| return jsonify({
|
| "success": False,
|
| "message": "生成思维导图图像失败",
|
| "status_code": response.status_code
|
| }), 500
|
|
|
| response_data = response.json()
|
|
|
| if not response_data.get('data') or not response_data['data'][0].get('url'):
|
| return jsonify({
|
| "success": False,
|
| "message": "API返回的数据中没有图像URL"
|
| }), 500
|
|
|
| image_url = response_data['data'][0]['url']
|
|
|
|
|
| img_response = requests.get(image_url)
|
| if img_response.status_code != 200:
|
| return jsonify({
|
| "success": False,
|
| "message": "下载生成的图像失败"
|
| }), 500
|
|
|
|
|
| img_filename = f'mindmap_{int(time.time())}.png'
|
| img_path = os.path.join('static', img_filename)
|
|
|
| with open(img_path, 'wb') as f:
|
| f.write(img_response.content)
|
|
|
|
|
| local_img_url = f'/static/{img_filename}'
|
|
|
| return jsonify({
|
| "success": True,
|
| "url": local_img_url,
|
| "original_url": image_url,
|
| "message": "思维导图生成成功"
|
| })
|
|
|
| except Exception as e:
|
| import traceback
|
| traceback.print_exc()
|
| return jsonify({
|
| "success": False,
|
| "message": str(e)
|
| }), 500
|
| @visualization_bp.route('/3d-surface', methods=['POST'])
|
| def generate_3d_surface():
|
| """生成3D表面图并返回嵌入式HTML"""
|
| try:
|
| data = request.json
|
| code = data.get('code', '')
|
|
|
| if not code:
|
| return jsonify({
|
| "success": False,
|
| "message": "请提供函数代码"
|
| }), 400
|
|
|
|
|
| code = re.sub(r'```python\n', '', code)
|
| code = re.sub(r'```', '', code)
|
|
|
|
|
| local_vars = {}
|
| try:
|
|
|
| exec(code, {"__builtins__": __builtins__, "np": np, "numpy": np}, local_vars)
|
|
|
|
|
| if 'create_3d_plot' not in local_vars:
|
| return jsonify({
|
| "success": False,
|
| "message": "提供的代码未包含create_3d_plot函数"
|
| }), 500
|
|
|
|
|
| plot_data = local_vars['create_3d_plot']()
|
|
|
| if not isinstance(plot_data, dict) or not all(k in plot_data for k in ['x', 'y', 'z']):
|
| return jsonify({
|
| "success": False,
|
| "message": "函数未返回有效的3D数据"
|
| }), 500
|
|
|
|
|
| fig = go.Figure()
|
|
|
|
|
| if plot_data.get('type') == 'scatter3d':
|
| fig.add_trace(go.Scatter3d(
|
| x=plot_data['x'],
|
| y=plot_data['y'],
|
| z=plot_data['z'],
|
| mode='markers',
|
| marker=dict(
|
| size=4,
|
| color=plot_data.get('color', plot_data['z']),
|
| colorscale='Viridis',
|
| opacity=0.8
|
| )
|
| ))
|
| else:
|
|
|
| try:
|
| x = np.array(plot_data['x'])
|
| y = np.array(plot_data['y'])
|
| z = np.array(plot_data['z'])
|
|
|
| if len(x.shape) == 1 and len(y.shape) == 1:
|
| X, Y = np.meshgrid(x, y)
|
| if len(z.shape) == 1:
|
| Z = z.reshape(len(y), len(x))
|
| else:
|
| Z = z
|
| else:
|
| X = x
|
| Y = y
|
| Z = z
|
|
|
| fig.add_trace(go.Surface(
|
| z=Z,
|
| x=X,
|
| y=Y,
|
| colorscale='Viridis'
|
| ))
|
| except Exception as data_error:
|
| return jsonify({
|
| "success": False,
|
| "message": f"处理3D数据时出错: {str(data_error)}"
|
| }), 500
|
|
|
|
|
| fig.update_layout(
|
| title=plot_data.get('title', '3D 可视化'),
|
| scene=dict(
|
| xaxis_title='X',
|
| yaxis_title='Y',
|
| zaxis_title='Z'
|
| ),
|
| width=800,
|
| height=600,
|
| margin=dict(l=0, r=0, b=0, t=30)
|
| )
|
|
|
|
|
| html_content = fig.to_html(include_plotlyjs='cdn', full_html=True)
|
|
|
|
|
| html_filename = f'3d_plot_{int(time.time())}.html'
|
| html_path = os.path.join('static', html_filename)
|
|
|
| with open(html_path, 'w', encoding='utf-8') as f:
|
| f.write(html_content)
|
|
|
| return jsonify({
|
| "success": True,
|
| "html_url": f'/static/{html_filename}',
|
| "message": "3D图形生成成功"
|
| })
|
|
|
| except Exception as e:
|
| import traceback
|
| error_traceback = traceback.format_exc()
|
| print(f"3D可视化执行错误: {error_traceback}")
|
| return jsonify({
|
| "success": False,
|
| "message": f"执行代码时出错: {str(e)}"
|
| }), 500
|
|
|
| except Exception as e:
|
| import traceback
|
| traceback.print_exc()
|
| return jsonify({
|
| "success": False,
|
| "message": str(e)
|
| }), 500 |