This commit is contained in:
cjw
2026-02-16 02:56:11 +08:00
parent d63ee4245b
commit 5ee99413e5
3 changed files with 194 additions and 13 deletions
+119 -13
View File
@@ -119,12 +119,15 @@ async def upload_stp(
async def get_status(task_id: str, db_session: AsyncSession = Depends(get_db_session)): async def get_status(task_id: str, db_session: AsyncSession = Depends(get_db_session)):
"""获取任务状态""" """获取任务状态"""
from sqlalchemy import select from sqlalchemy import select
from models.database import ProcessingTask, STPFile from models.database import ProcessingTask, STPFile, GeometryData, MoldCavityData, HTMLFile
# 从数据库查询任务详情 # 从数据库查询任务详情及相关数据
result = await db_session.execute( result = await db_session.execute(
select(ProcessingTask, STPFile) select(ProcessingTask, STPFile, GeometryData, MoldCavityData, HTMLFile)
.join(STPFile, ProcessingTask.stp_file_id == STPFile.id) .join(STPFile, ProcessingTask.stp_file_id == STPFile.id)
.outerjoin(GeometryData, STPFile.id == GeometryData.stp_file_id)
.outerjoin(MoldCavityData, STPFile.id == MoldCavityData.stp_file_id)
.outerjoin(HTMLFile, STPFile.id == HTMLFile.stp_file_id)
.where(ProcessingTask.task_id == task_id) .where(ProcessingTask.task_id == task_id)
) )
@@ -133,7 +136,7 @@ async def get_status(task_id: str, db_session: AsyncSession = Depends(get_db_ses
if not task_record: if not task_record:
raise HTTPException(404, "任务不存在") raise HTTPException(404, "任务不存在")
task, stp_file = task_record task, stp_file, geometry_data, mold_cavity_data, html_file = task_record
# 构建任务详情数据 # 构建任务详情数据
task_data = { task_data = {
@@ -148,6 +151,60 @@ async def get_status(task_id: str, db_session: AsyncSession = Depends(get_db_ses
"error": task.error_message if task.error_message else "" "error": task.error_message if task.error_message else ""
} }
# 如果有几何数据,添加到返回结果
if geometry_data:
task_data["geometry_data"] = {
"volume": geometry_data.volume,
"surface_area": geometry_data.surface_area,
"bounding_box": {
"min": geometry_data.bounding_box_min,
"max": geometry_data.bounding_box_max,
"dimensions": [
geometry_data.bounding_box_max[0] - geometry_data.bounding_box_min[0] if geometry_data.bounding_box_max and geometry_data.bounding_box_min else 0,
geometry_data.bounding_box_max[1] - geometry_data.bounding_box_min[1] if geometry_data.bounding_box_max and geometry_data.bounding_box_min else 0,
geometry_data.bounding_box_max[2] - geometry_data.bounding_box_min[2] if geometry_data.bounding_box_max and geometry_data.bounding_box_min else 0
]
},
"topology": {
"faces": geometry_data.topology_faces,
"edges": geometry_data.topology_edges,
"vertices": geometry_data.topology_vertices
},
"center_of_mass": geometry_data.center_of_mass
}
# 如果有模具型腔数据,添加到返回结果
if mold_cavity_data:
task_data["key_info"] = {
"metadata": {
"shrinkage_rate": mold_cavity_data.shrinkage_rate,
"draft_angle": mold_cavity_data.draft_angle
},
"manufacturing_info": {
"mold_material": mold_cavity_data.mold_material,
"estimated_clamping_force": mold_cavity_data.estimated_clamping_force,
"parting_line_length": mold_cavity_data.parting_line_length
},
"mold_cavities": {
"cavity_key_info": {
"geometric_characteristics": {
"product_weight": mold_cavity_data.product_weight,
"product_volume": mold_cavity_data.product_volume,
"wall_thickness_range": mold_cavity_data.wall_thickness_range,
"complexity_score": mold_cavity_data.complexity_score
}
}
}
}
# 如果有HTML文件信息,添加到返回结果
if html_file:
task_data["html_info"] = {
"filename": html_file.filename,
"file_path": html_file.file_path,
"generated_time": html_file.generated_time.isoformat() if html_file.generated_time else ""
}
logger.info(f"返回任务状态: {task_id} - {task.status}") logger.info(f"返回任务状态: {task_id} - {task.status}")
return task_data return task_data
@@ -270,17 +327,18 @@ async def history_page(request: Request):
}) })
@router.get("/result/{task_id}") @router.get("/api/html-info/{task_id}")
@router.post("/result/{task_id}") @router.post("/api/html-info/{task_id}")
async def result_page(request: Request, task_id: str, db_session: AsyncSession = Depends(get_db_session)): async def get_html_info(task_id: str, db_session: AsyncSession = Depends(get_db_session)):
"""结果详情页面""" """获取任务的HTML文件信息"""
from sqlalchemy import select from sqlalchemy import select
from models.database import ProcessingTask, STPFile, GeometryData, MoldCavityData, HTMLFile from models.database import ProcessingTask, STPFile, HTMLFile
# 从数据库查询任务详情 # 从数据库查询HTML文件信息
result = await db_session.execute( result = await db_session.execute(
select(ProcessingTask, STPFile) select(ProcessingTask, STPFile, HTMLFile)
.join(STPFile, ProcessingTask.stp_file_id == STPFile.id) .join(STPFile, ProcessingTask.stp_file_id == STPFile.id)
.outerjoin(HTMLFile, STPFile.id == HTMLFile.stp_file_id)
.where(ProcessingTask.task_id == task_id) .where(ProcessingTask.task_id == task_id)
) )
@@ -289,9 +347,47 @@ async def result_page(request: Request, task_id: str, db_session: AsyncSession =
if not task_record: if not task_record:
raise HTTPException(404, "任务不存在") raise HTTPException(404, "任务不存在")
task, stp_file = task_record task, stp_file, html_file = task_record
# 构建任务详情数据(先只包含基本数据) if not html_file:
return {"message": "该任务没有HTML可视化报告"}
# 返回HTML文件信息
html_info = {
"filename": html_file.filename,
"file_path": html_file.file_path,
"generated_time": html_file.generated_time.isoformat() if html_file.generated_time else "",
"visualization_type": html_file.visualization_type
}
return html_info
@router.get("/result/{task_id}")
@router.post("/result/{task_id}")
async def result_page(request: Request, task_id: str, db_session: AsyncSession = Depends(get_db_session)):
"""结果详情页面"""
from sqlalchemy import select
from models.database import ProcessingTask, STPFile, GeometryData, MoldCavityData, HTMLFile
# 从数据库查询任务详情及相关数据
result = await db_session.execute(
select(ProcessingTask, STPFile, GeometryData, MoldCavityData, HTMLFile)
.join(STPFile, ProcessingTask.stp_file_id == STPFile.id)
.outerjoin(GeometryData, STPFile.id == GeometryData.stp_file_id)
.outerjoin(MoldCavityData, STPFile.id == MoldCavityData.stp_file_id)
.outerjoin(HTMLFile, STPFile.id == HTMLFile.stp_file_id)
.where(ProcessingTask.task_id == task_id)
)
task_record = result.first()
if not task_record:
raise HTTPException(404, "任务不存在")
task, stp_file, geometry_data, mold_cavity_data, html_file = task_record
# 构建任务详情数据
task_data = { task_data = {
"task_id": task.task_id, "task_id": task.task_id,
"filename": stp_file.original_filename if stp_file else "", "filename": stp_file.original_filename if stp_file else "",
@@ -304,6 +400,15 @@ async def result_page(request: Request, task_id: str, db_session: AsyncSession =
"error": task.error_message if task.error_message else "" "error": task.error_message if task.error_message else ""
} }
# 如果有HTML文件,添加HTML文件信息
html_info = None
if html_file:
html_info = {
"filename": html_file.filename,
"file_path": html_file.file_path,
"generated_time": html_file.generated_time.isoformat() if html_file.generated_time else ""
}
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
import os import os
# 简化路径配置,直接使用当前工作目录下的templates文件夹 # 简化路径配置,直接使用当前工作目录下的templates文件夹
@@ -312,6 +417,7 @@ async def result_page(request: Request, task_id: str, db_session: AsyncSession =
return templates.TemplateResponse("result.html", { return templates.TemplateResponse("result.html", {
"request": request, "request": request,
"task": task_data, "task": task_data,
"html_info": html_info,
"pythonocc_available": True, "pythonocc_available": True,
"version": "3.0.0" "version": "3.0.0"
}) })
+4
View File
@@ -96,6 +96,10 @@ import os
static_dir = os.path.join(os.getcwd(), "static") static_dir = os.path.join(os.getcwd(), "static")
app.mount("/static", StaticFiles(directory=static_dir), name="static") app.mount("/static", StaticFiles(directory=static_dir), name="static")
# 挂载HTML输出目录
html_output_dir = os.path.join(os.getcwd(), "html_output")
app.mount("/html-output", StaticFiles(directory=html_output_dir), name="html_output")
# 注册路由 # 注册路由
app.include_router(router) app.include_router(router)
+71
View File
@@ -178,6 +178,14 @@
<div class="results-grid" id="resultsGrid"> <div class="results-grid" id="resultsGrid">
<!-- 结果内容将通过JavaScript动态加载 --> <!-- 结果内容将通过JavaScript动态加载 -->
</div> </div>
<!-- HTML可视化展示区域 -->
<div id="htmlVisualization" class="result-section" style="grid-column: 1 / -1; margin-top: 20px; display: none;">
<div class="section-title">🖥️ 3D可视化报告</div>
<div id="htmlViewerContainer">
<!-- HTML内容将在这里加载 -->
</div>
</div>
</div> </div>
<script> <script>
@@ -201,6 +209,9 @@
displayTaskInfo(task); displayTaskInfo(task);
displayResults(task); displayResults(task);
// 加载HTML可视化内容
await loadHtmlVisualization(taskId);
} catch (error) { } catch (error) {
document.getElementById('taskInfo').innerHTML = ` document.getElementById('taskInfo').innerHTML = `
<div class="error-message"> <div class="error-message">
@@ -214,6 +225,66 @@
} }
} }
async function loadHtmlVisualization(taskId) {
try {
// 从后端获取HTML文件信息
const response = await fetch(`/api/html-info/${taskId}`);
if (response.ok) {
const htmlInfo = await response.json();
if (htmlInfo && htmlInfo.file_path) {
displayHtmlVisualization(htmlInfo);
} else {
console.log('该任务没有HTML可视化报告');
}
} else {
console.log('获取HTML信息失败');
}
} catch (error) {
console.error('加载HTML可视化失败:', error);
}
}
function displayHtmlVisualization(htmlInfo) {
const htmlContainer = document.getElementById('htmlVisualization');
const viewerContainer = document.getElementById('htmlViewerContainer');
// 显示HTML可视化区域
htmlContainer.style.display = 'block';
// 创建iframe来显示HTML内容
viewerContainer.innerHTML = `
<div style="margin-bottom: 15px;">
<div class="data-item">
<div class="data-label">报告文件</div>
<div class="data-value">${htmlInfo.filename || 'N/A'}</div>
</div>
<div class="data-item">
<div class="data-label">生成时间</div>
<div class="data-value">${htmlInfo.generated_time ? new Date(htmlInfo.generated_time).toLocaleString() : 'N/A'}</div>
</div>
</div>
<div style="border: 1px solid #e0e0e0; border-radius: 8px; overflow: hidden; height: 600px;">
<iframe
src="/html-output/${htmlInfo.filename}"
style="width: 100%; height: 100%; border: none;"
title="3D可视化报告"
></iframe>
</div>
<div class="action-buttons">
<button class="upload-btn" onclick="window.open('/html-output/${htmlInfo.filename}', '_blank')">
🔗 在新窗口中打开
</button>
<button class="upload-btn" onclick="downloadHtmlReport('${htmlInfo.filename}')">
📥 下载HTML报告
</button>
</div>
`;
}
function downloadHtmlReport(filename) {
window.open(`/html-output/${filename}?download=true`, '_blank');
}
function displayTaskInfo(task) { function displayTaskInfo(task) {
const taskInfo = document.getElementById('taskInfo'); const taskInfo = document.getElementById('taskInfo');