diff --git a/src/views/app-manager/upload-package/index.vue b/src/views/app-manager/upload-package/index.vue index 119d19a4..70dddd97 100644 --- a/src/views/app-manager/upload-package/index.vue +++ b/src/views/app-manager/upload-package/index.vue @@ -341,15 +341,39 @@ function openDetail(item: AppPackage) { detailVisible.value = true; } -function download(item: AppPackage) { +async function download(item: AppPackage) { if (!item.fileUrl) { ElMessage.warning("文件地址缺失"); return; } + + const url = withBase(item.fileUrl); + const fileName = item.originalName || `${item.packageName}.${item.packageType}`; + + // 先校验资源是否真实存在,避免后端返回的错误页(如 f.txt)被当作文件下载。 + // 受 CORS 限制时 HEAD 可能失败,此时回退为直接下载( 下载不受 CORS 限制),避免误报。 + try { + const resp = await fetch(url, { method: "HEAD" }); + if (!resp.ok) { + ElMessage.error(`下载失败:资源不存在(${resp.status})`); + return; + } + const contentType = resp.headers.get("Content-Type") || ""; + // 资源存在但返回的是文本/HTML/JSON 错误页,而不是实际安装包 + if (/(text\/html|text\/plain|application\/json)/i.test(contentType)) { + ElMessage.error("下载失败:资源未找到或链接无效"); + return; + } + } catch { + // HEAD 不可达(多为跨域限制),直接走原生下载兜底 + } + const a = document.createElement("a"); - a.href = withBase(item.fileUrl); - a.download = item.originalName || `${item.packageName}.${item.packageType}`; + a.href = url; + a.download = fileName; + document.body.appendChild(a); a.click(); + document.body.removeChild(a); } async function handleDelete(item: AppPackage) { diff --git a/src/views/devices/sn/config/add.ts b/src/views/devices/sn/config/add.ts index 59b01984..e9dceca9 100644 --- a/src/views/devices/sn/config/add.ts +++ b/src/views/devices/sn/config/add.ts @@ -35,7 +35,6 @@ const modalConfig: IModalConfig = { { label: "设备型号", prop: "snModel", - rules: [{ required: true, message: "设备型号不能为空", trigger: "blur" }], type: "input", attrs: { placeholder: "请输入设备型号", @@ -48,7 +47,6 @@ const modalConfig: IModalConfig = { { label: "设备昵称", prop: "snName", - rules: [{ required: true, message: "设备昵称不能为空", trigger: "blur" }], type: "input", attrs: { placeholder: "请输入内容",