This commit is contained in:
cjw
2026-02-17 00:47:39 +08:00
parent 06225e0d65
commit 519279a7d1
3 changed files with 78 additions and 19 deletions
+12 -2
View File
@@ -156,8 +156,18 @@ async def get_status(task_id: str, db_session: AsyncSession = Depends(get_db_ses
geometry_json: Optional[Dict[str, Any]] = None
if file_with_data.get("geometry_data"):
# save_geometry_data 支持两种格式,这里直接拿回来的就是几何字典
geometry_json = file_with_data["geometry_data"]
# save_geometry_data 保存时可能有两种格式:
# 1. 直接保存 geometry_data 字典
# 2. 保存 {"geometry_data": {...}} 格式
# get_stp_file_with_data 返回的是从RustFS下载的原始JSON
geo_raw = file_with_data["geometry_data"]
if isinstance(geo_raw, dict):
# 如果是包装格式,提取内部数据
if "geometry_data" in geo_raw:
geometry_json = geo_raw["geometry_data"]
else:
# 直接就是几何数据字典
geometry_json = geo_raw
cavity_json: Optional[Dict[str, Any]] = file_with_data.get("mold_cavity_data")
+24 -1
View File
@@ -790,7 +790,8 @@ body {
color: #e5e7eb;
}
.upload-dropzone:hover {
.upload-dropzone:hover,
.upload-dropzone.drag-over {
border-color: #60a5fa;
background: linear-gradient(135deg, rgba(15, 23, 42, 1), rgba(37, 99, 235, 0.6));
}
@@ -800,6 +801,23 @@ body {
margin-bottom: 6px;
}
.clear-file-btn {
margin-top: 8px;
padding: 4px 12px;
font-size: 0.8rem;
background: rgba(239, 68, 68, 0.2);
color: #fca5a5;
border: 1px solid rgba(239, 68, 68, 0.4);
border-radius: 6px;
cursor: pointer;
transition: all 0.2s ease;
}
.clear-file-btn:hover {
background: rgba(239, 68, 68, 0.3);
border-color: rgba(239, 68, 68, 0.6);
}
.upload-btn {
background: linear-gradient(135deg, #3b82f6, #6366f1);
color: white;
@@ -947,6 +965,11 @@ body {
text-transform: none;
}
.status-pending {
background: rgba(148, 163, 184, 0.15);
color: #94a3b8;
}
.status-processing {
background: rgba(250, 204, 21, 0.15);
color: #facc15;
+42 -16
View File
@@ -287,12 +287,26 @@ const DashboardView = {
const startPolling = async (taskId) => {
state.polling = true;
let pollCount = 0;
const maxPolls = 300; // 最多轮询5分钟(300秒)
const poll = async () => {
try {
pollCount++;
const res = await fetch(`/status/${taskId}`, { method: "POST" });
if (!res.ok) {
throw new Error("查询任务状态失败");
if (res.status === 404) {
// 任务不存在,停止轮询
state.polling = false;
state.error = "任务不存在或已被删除";
addNotification("任务不存在或已被删除", 'error');
return;
}
if (!res.ok) {
throw new Error(`查询任务状态失败: ${res.status} ${res.statusText}`);
}
const task = await res.json();
state.currentTask = task;
@@ -307,6 +321,11 @@ const DashboardView = {
const errorMsg = task.error || "未知错误";
state.error = `分析失败: ${errorMsg}`;
addNotification(`分析失败: ${errorMsg}`, 'error');
} else if (pollCount >= maxPolls) {
// 超时停止轮询
state.polling = false;
state.error = "任务处理超时,请稍后查看结果";
addNotification("任务处理超时,请稍后查看结果", 'warning');
} else {
setTimeout(poll, 1000);
}
@@ -365,50 +384,57 @@ const DashboardView = {
<p class="card-subtitle">上传后系统会自动解析几何、生成模具型腔并计算关键工艺参数。</p>
<div class="upload-panel">
<label class="upload-dropzone">
<label
class="upload-dropzone"
:class="{ 'drag-over': state.dragOver }"
@dragover.prevent="handleDragOver"
@dragleave.prevent="handleDragLeave"
@drop.prevent="handleDrop"
>
<input type="file" accept=".stp,.step" @change="handleFileChange" hidden />
<div class="upload-icon">📂</div>
<div v-if="!selectedFile">
<div v-if="!state.selectedFile">
<h3>点击选择或拖拽文件到此处</h3>
<p>最大 100MB,支持 .stp / .step</p>
</div>
<div v-else>
<h3>已选择文件:</h3>
<p><strong>{{ selectedFile.name }}</strong></p>
<p>大小:{{ formatFileSize(selectedFile.size) }}</p>
<p><strong>{{ state.selectedFile.name }}</strong></p>
<p>大小:{{ formatFileSize(state.selectedFile.size) }}</p>
<button class="clear-file-btn" @click.stop="clearFile">清除</button>
</div>
</label>
<button
class="upload-btn"
:disabled="!selectedFile || uploading"
:disabled="!state.selectedFile || state.uploading"
@click="uploadFile"
>
<span v-if="!uploading">开始分析</span>
<span v-if="!state.uploading">开始分析</span>
<span v-else>正在上传...</span>
</button>
<p v-if="error" class="error-text">{{ error }}</p>
<p v-if="state.error" class="error-text">{{ state.error }}</p>
</div>
<div v-if="currentTask" class="card current-task">
<div v-if="state.currentTask" class="card current-task">
<h3>当前任务</h3>
<div class="info-row">
<span>任务 ID:</span><span>{{ currentTask.task_id }}</span>
<span>任务 ID:</span><span>{{ state.currentTask.task_id }}</span>
</div>
<div class="info-row">
<span>文件名:</span><span>{{ currentTask.filename || 'N/A' }}</span>
<span>文件名:</span><span>{{ state.currentTask.filename || 'N/A' }}</span>
</div>
<div class="info-row">
<span>文件大小:</span><span>{{ currentTask.file_size ? formatFileSize(currentTask.file_size) : 'N/A' }}</span>
<span>文件大小:</span><span>{{ state.currentTask.file_size ? formatFileSize(state.currentTask.file_size) : 'N/A' }}</span>
</div>
<div class="info-row">
<span>状态:</span>
<span class="status-pill" :class="'status-' + currentTask.status">
{{ statusText(currentTask.status) }}
<span class="status-pill" :class="getStatusClass(state.currentTask.status)">
{{ statusText(state.currentTask.status) }}
</span>
</div>
<div v-if="polling" class="small-hint">正在后台分析,请稍候,完成后会跳转到结果页。</div>
<div v-if="state.polling" class="small-hint">正在后台分析,请稍候,完成后会跳转到结果页。</div>
</div>
</div>