|
|
|
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=True, 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 |