From 025835c5b37fd5446b414d17bacc2101e4a18b48 Mon Sep 17 00:00:00 2001 From: zhangshun <453905631@qq.com> Date: Wed, 8 Jul 2026 18:18:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=89=B9=E9=87=8F=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=E6=A8=A1=E5=9E=8B=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/pages/app/dialogs.css | 16 ++++++++ web/src/pages/app/modules/models.ts | 59 ++++++++++++++++++++++++----- 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/web/src/pages/app/dialogs.css b/web/src/pages/app/dialogs.css index 291d814..43dd822 100644 --- a/web/src/pages/app/dialogs.css +++ b/web/src/pages/app/dialogs.css @@ -79,6 +79,22 @@ word-break: break-all; } +.upload-status { + padding: 8px 10px; + border: 1px solid #b9d7c1; + border-radius: 6px; + background: #eef8f1; + color: #27613a; + font-size: 13px; + line-height: 1.45; + word-break: break-all; +} + +.upload-popup-form.is-uploading .drop-zone { + cursor: progress; + opacity: 0.72; +} + .upload-target-path { display: grid; grid-template-columns: 64px minmax(0, 1fr); diff --git a/web/src/pages/app/modules/models.ts b/web/src/pages/app/modules/models.ts index 1c94db5..a008e73 100644 --- a/web/src/pages/app/modules/models.ts +++ b/web/src/pages/app/modules/models.ts @@ -509,6 +509,7 @@ async function openUploadModelDialog() { + ${dictionaryDatalistHtml()} `, @@ -527,22 +528,38 @@ async function openUploadModelDialog() { const properties = { model: String(form.get("model") ?? "") }; - for (const file of state.files) { - await uploadModelToBackend({ - file, - name: state.files.length === 1 ? name ?? "" : modelNameFromFile(file.name), - fileName: file.name, - brandName, - typeName, - operationTree: defaultOperationTree, - properties - }); + let completedCount = 0; + setUploadDialogBusy(state, true); + try { + for (const [index, file] of state.files.entries()) { + updateUploadStatus(`正在上传 ${index + 1}/${state.files.length}:${file.name}`); + await waitForUploadStatusPaint(); + await uploadModelToBackend({ + file, + name: state.files.length === 1 ? name ?? "" : modelNameFromFile(file.name), + fileName: file.name, + brandName, + typeName, + operationTree: defaultOperationTree, + properties + }); + completedCount += 1; + updateUploadStatus(`已完成 ${completedCount}/${state.files.length}`); + } + } catch (error) { + updateUploadStatus(`上传失败,已完成 ${completedCount}/${state.files.length},请处理后重试。`); + throw error; + } finally { + if (completedCount < state.files.length) { + setUploadDialogBusy(state, false); + } } return true; } }); if (result) { + notify("模型上传完成"); invalidateDictionaries(); await reloadFoldersAndModels(); } @@ -674,6 +691,28 @@ function bindUploadDialogEvents(state: UploadFormState) { }); } +function updateUploadStatus(message: string) { + const status = document.querySelector("#modelUploadStatus"); + if (!status) return; + status.hidden = false; + status.textContent = message; +} + +function waitForUploadStatusPaint() { + return new Promise((resolve) => { + window.requestAnimationFrame(() => window.setTimeout(resolve, 0)); + }); +} + +function setUploadDialogBusy(state: UploadFormState, busy: boolean) { + const form = document.querySelector("#modelUploadPopupForm"); + if (!form) return; + form.classList.toggle("is-uploading", busy); + form.querySelectorAll("input").forEach((input) => { + input.disabled = busy || (input.id === "modelUploadName" && state.files.length > 1); + }); +} + function bindProcessUploadDialogEvents(state: UploadFormState) { // const dropZone = document.querySelector("#processModelDropZone")!; // const fileInput = document.querySelector("#processModelUploadFile")!;