// static/script.js
let selectedFile = null;
const uploadSection = document.getElementById('uploadSection');
const uploadArea = document.getElementById('uploadArea');
const fileInput = document.getElementById('fileInput');
const uploadBtn = document.getElementById('uploadBtn');
const loading = document.getElementById('loading');
const resultsSection = document.getElementById('resultsSection');
const errorMessage = document.getElementById('errorMessage');
const taskInfo = document.getElementById('taskInfo');
const geometryData = document.getElementById('geometryData');
const boundingBoxData = document.getElementById('boundingBoxData');
const topologyData = document.getElementById('topologyData');
const featuresData = document.getElementById('featuresData');
const recommendationsData = document.getElementById('recommendationsData');
const metricsData = document.getElementById('metricsData');
const analysisInfo = document.getElementById('analysisInfo');
// 页面加载时初始化
document.addEventListener('DOMContentLoaded', function() {
console.log('页面加载完成');
showUploadSection();
});
// 显示上传区域
function showUploadSection() {
uploadSection.style.display = 'block';
resultsSection.style.display = 'none';
resetUploadArea();
}
// 显示结果区域
function showResultsSection() {
uploadSection.style.display = 'none';
resultsSection.style.display = 'block';
}
// 重置上传区域
function resetUploadArea() {
selectedFile = null;
uploadArea.innerHTML = `
📁
拖放文件到此处或点击选择
最大文件大小: 100MB
`;
uploadBtn.disabled = true;
hideError();
loading.style.display = 'none';
// 重新绑定事件
const newFileInput = document.getElementById('fileInput');
newFileInput.addEventListener('change', (e) => {
if (e.target.files.length > 0) {
handleFileSelect(e.target.files[0]);
}
});
}
// 拖放功能
uploadArea.addEventListener('dragover', (e) => {
e.preventDefault();
uploadArea.classList.add('dragover');
});
uploadArea.addEventListener('dragleave', () => {
uploadArea.classList.remove('dragover');
});
uploadArea.addEventListener('drop', (e) => {
e.preventDefault();
uploadArea.classList.remove('dragover');
const files = e.dataTransfer.files;
if (files.length > 0) {
handleFileSelect(files[0]);
}
});
// 文件选择
fileInput.addEventListener('change', (e) => {
if (e.target.files.length > 0) {
handleFileSelect(e.target.files[0]);
}
});
function handleFileSelect(file) {
if (!file.name.toLowerCase().endsWith('.stp') && !file.name.toLowerCase().endsWith('.step')) {
showError('请选择STP或STEP格式的文件');
return;
}
if (file.size > 100 * 1024 * 1024) {
showError('文件大小不能超过100MB');
return;
}
selectedFile = file;
uploadArea.innerHTML = `
✅
已选择文件
${file.name}
大小: ${(file.size / 1024 / 1024).toFixed(2)} MB
`;
uploadBtn.disabled = false;
hideError();
}
async function uploadFile() {
if (!selectedFile) return;
loading.style.display = 'block';
uploadBtn.disabled = true;
hideError();
const formData = new FormData();
formData.append('file', selectedFile);
try {
const response = await fetch('/upload', {
method: 'POST',
body: formData
});
if (!response.ok) {
throw new Error(`上传失败: ${response.status} ${response.statusText}`);
}
const result = await response.json();
console.log('上传结果:', result);
// 开始轮询任务状态
pollTaskStatus(result.task_id);
} catch (error) {
showError('上传失败: ' + error.message);
loading.style.display = 'none';
uploadBtn.disabled = false;
}
}
async function pollTaskStatus(taskId) {
try {
const response = await fetch(`/status/${taskId}`, {
method: 'POST'
});
const task = await response.json();
console.log('任务状态:', task.status);
console.log('完整任务数据:', task);
updateTaskInfo(task);
if (task.status === 'completed') {
loading.style.display = 'none';
showResultsSection();
displayAllResults(task);
} else if (task.status === 'failed') {
loading.style.display = 'none';
showError('分析失败: ' + (task.error || '未知错误'));
uploadBtn.disabled = false;
} else {
setTimeout(() => pollTaskStatus(taskId), 1000);
}
} catch (error) {
console.error('轮询错误:', error);
loading.style.display = 'none';
showError('查询状态失败: ' + error.message);
uploadBtn.disabled = false;
}
}
function updateTaskInfo(task) {
taskInfo.innerHTML = `
📋 任务ID
${task.task_id || 'N/A'}
🔄 状态
${getStatusText(task.status)}
📁 文件名
${task.filename || 'N/A'}
📏 文件大小
${task.file_size ? formatFileSize(task.file_size) : 'N/A'}
`;
}
function displayAllResults(task) {
console.log('显示所有结果:', task);
displayGeometryData(task);
displayBoundingBoxData(task);
displayTopologyData(task);
// 添加模具型腔数据显示
if (task.cavity_data) {
displayCavityData(task.cavity_data);
}
if (task.key_info) {
displayKeyInfo(task.key_info);
}
displayFeaturesData(task);
displayRecommendationsData(task);
displayMetricsData(task);
displayAnalysisInfo(task);
}
function displayGeometryData(task) {
if (task.geometry_data) {
const geo = task.geometry_data;
geometryData.innerHTML = `
📦 体积
${geo.volume ? formatNumber(geo.volume) : 'N/A'}
mm³
📐 表面积
${geo.surface_area ? formatNumber(geo.surface_area) : 'N/A'}
mm²
📏 体积表面积比
${geo.volume && geo.surface_area ? (geo.volume / geo.surface_area).toFixed(4) : 'N/A'}
`;
} else {
geometryData.innerHTML = '';
}
}
function displayBoundingBoxData(task) {
if (task.geometry_data && task.geometry_data.bounding_box) {
const bbox = task.geometry_data.bounding_box;
boundingBoxData.innerHTML = `
📍 最小坐标
X: ${bbox.min[0].toFixed(2)}
Y: ${bbox.min[1].toFixed(2)}
Z: ${bbox.min[2].toFixed(2)}
📍 最大坐标
X: ${bbox.max[0].toFixed(2)}
Y: ${bbox.max[1].toFixed(2)}
Z: ${bbox.max[2].toFixed(2)}
📏 尺寸
${bbox.dimensions[0].toFixed(2)} × ${bbox.dimensions[1].toFixed(2)} × ${bbox.dimensions[2].toFixed(2)}
mm
`;
} else {
boundingBoxData.innerHTML = '';
}
}
function displayTopologyData(task) {
if (task.geometry_data && task.geometry_data.topology) {
const topo = task.geometry_data.topology;
topologyData.innerHTML = `
📍 顶点数
${topo.vertices || 0}
📊 拓扑复杂度
${calculateTopologyComplexity(topo)}
`;
} else {
topologyData.innerHTML = '';
}
}
function displayFeaturesData(task) {
if (task.analysis_result && task.analysis_result.detected_features) {
const features = task.analysis_result.detected_features;
if (features.length > 0) {
featuresData.innerHTML = features.map(feature => `
📍 位置
${feature.location.map(v => v.toFixed(2)).join(', ')}
📏 尺寸
${feature.dimensions.map(v => v.toFixed(2)).join(' × ')} mm
${feature.recommendations && feature.recommendations.length > 0 ? `
💡 建议
${feature.recommendations.map(rec => `- ${rec}
`).join('')}
` : ''}
`).join('');
} else {
featuresData.innerHTML = '';
}
} else {
featuresData.innerHTML = '';
}
}
function displayRecommendationsData(task) {
if (task.analysis_result && task.analysis_result.design_recommendations) {
const recommendations = task.analysis_result.design_recommendations;
if (recommendations.length > 0) {
recommendationsData.innerHTML = recommendations.map(rec => `
${Object.keys(rec.parameters).length > 0 ? `
⚙️ 参数
${formatParameters(rec.parameters)}
` : ''}
`).join('');
} else {
recommendationsData.innerHTML = '';
}
} else {
recommendationsData.innerHTML = '';
}
}
function displayMetricsData(task) {
if (task.analysis_result && task.analysis_result.quality_metrics) {
const metrics = task.analysis_result.quality_metrics;
metricsData.innerHTML = `
体积利用率
${(metrics.volume_utilization * 100).toFixed(1)}%
${getVolumeUtilizationText(metrics.volume_utilization)}
拓扑复杂度
${metrics.topology_complexity.toFixed(2)}
${getComplexityText(metrics.topology_complexity)}
壁厚均匀性
${(metrics.wall_uniformity * 100).toFixed(1)}%
${getUniformityText(metrics.wall_uniformity)}
`;
} else {
metricsData.innerHTML = '';
}
}
function displayAnalysisInfo(task) {
let infoHTML = '';
if (task.geometry_data) {
const geo = task.geometry_data;
infoHTML += `
🔧 分析方法
${geo.analysis_method || '未知'}
`;
}
if (task.analysis_result) {
const analysis = task.analysis_result;
infoHTML += `
✅ 分析状态
${task.status === 'completed' ? '分析完成' : '分析中'}
📋 分析摘要
${analysis.analysis_summary || '无摘要'}
`;
}
infoHTML += `
📅 处理时间
${task.completed_at ? new Date(task.completed_at).toLocaleString() : new Date().toLocaleString()}
`;
analysisInfo.innerHTML = infoHTML;
}
// 工具函数
function getStatusText(status) {
const statusMap = {
'processing': '处理中',
'completed': '已完成',
'failed': '失败'
};
return statusMap[status] || status;
}
function formatFileSize(bytes) {
if (!bytes || bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
function formatNumber(num) {
if (!num) return 'N/A';
if (num >= 1000000) {
return (num / 1000000).toFixed(2) + 'M';
} else if (num >= 1000) {
return (num / 1000).toFixed(2) + 'K';
} else {
return num.toFixed(2);
}
}
function calculateTopologyComplexity(topo) {
const totalElements = (topo.faces || 0) + (topo.edges || 0) + (topo.vertices || 0);
if (totalElements < 100) return '简单';
if (totalElements < 1000) return '中等';
return '复杂';
}
function getFeatureTypeText(type) {
const typeMap = {
'thin_wall': '薄壁区域',
'thick_wall': '厚壁区域',
'rib_structure': '加强筋结构',
'boss_feature': 'BOSS柱',
'draft_angle': '拔模角度',
'cooling_system': '冷却系统'
};
return typeMap[type] || type;
}
function getRecommendationTypeText(type) {
const typeMap = {
'wall_thickness': '壁厚优化',
'draft_angle': '拔模角度',
'rib_design': '加强筋设计',
'boss_design': 'BOSS柱设计',
'cooling_system': '冷却系统'
};
return typeMap[type] || type;
}
function getPriorityText(priority) {
const priorityMap = {
'high': '高优先级',
'medium': '中优先级',
'low': '低优先级'
};
return priorityMap[priority] || priority;
}
function formatParameters(parameters) {
const parameterMap = {
'min_angle': '最小角度',
'preferred_angle': '推荐角度'
};
return Object.entries(parameters).map(([key, value]) => {
const displayKey = parameterMap[key] || key;
if (typeof value === 'number') {
return `${displayKey}: ${value.toFixed(2)}`;
}
return `${displayKey}: ${value}`;
}).join('; ');
}
function getMetricClass(value, goodThreshold, excellentThreshold, reverse = false) {
if (reverse) {
if (value <= goodThreshold) return 'metric-good';
if (value <= excellentThreshold) return 'metric-warning';
return 'metric-poor';
} else {
if (value >= excellentThreshold) return 'metric-good';
if (value >= goodThreshold) return 'metric-warning';
return 'metric-poor';
}
}
function getVolumeUtilizationText(value) {
if (value >= 0.6) return '优秀';
if (value >= 0.3) return '良好';
return '待优化';
}
function getComplexityText(value) {
if (value <= 0.3) return '简单';
if (value <= 0.7) return '中等';
return '复杂';
}
function getUniformityText(value) {
if (value >= 0.8) return '均匀';
if (value >= 0.6) return '一般';
return '不均匀';
}
function showError(message) {
errorMessage.textContent = message;
errorMessage.style.display = 'block';
}
function hideError() {
errorMessage.style.display = 'none';
}
// 跳转到历史页面
function goToHistory() {
// 创建表单进行POST请求跳转,更安全
const form = document.createElement('form');
form.method = 'POST';
form.action = '/history';
document.body.appendChild(form);
form.submit();
}
// 添加显示函数
function displayCavityData(cavityData) {
const cavityDiv = document.getElementById('cavityData');
cavityDiv.innerHTML = `
${JSON.stringify(cavityData, null, 2)}
`;
}
function displayKeyInfo(keyInfo) {
const keyInfoDiv = document.getElementById('keyInfoData');
if (!keyInfo) {
keyInfoDiv.innerHTML = '';
return;
}
// 从正确的数据结构中提取数据
const metadata = keyInfo.metadata || {};
const manufacturingInfo = keyInfo.manufacturing_info || {};
const moldCavities = keyInfo.mold_cavities || {};
const cavityKeyInfo = moldCavities.cavity_key_info || {};
const geoChars = cavityKeyInfo.geometric_characteristics || {};
keyInfoDiv.innerHTML = `
收缩率
${metadata.shrinkage_rate !== undefined ? metadata.shrinkage_rate : 'N/A'}
拔模角
${metadata.draft_angle !== undefined ? metadata.draft_angle + '°' : 'N/A'}
分型线长度
${manufacturingInfo.parting_line_length || 'N/A'}
产品体积
${geoChars.product_volume || 'N/A'}
产品重量
${geoChars.product_weight || 'N/A'}
壁厚范围
${geoChars.wall_thickness_range || 'N/A'}
型腔材料
${manufacturingInfo.mold_material || 'N/A'}
硬度
${manufacturingInfo.mold_hardness || 'N/A'}
表面光洁度
${manufacturingInfo.surface_finish || 'N/A'}
预估周期
${manufacturingInfo.estimated_cycle_time || 'N/A'}
`;
}