From 801a3bc53415f6214800c561a562d17ea58b88f1 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期三, 01 四月 2026 11:40:14 +0800
Subject: [PATCH] 军泰伟业 1.bom导入和产品导入成功和失败逻辑修改
---
src/views/basicData/product/index.vue | 76 +++++++++++++++++-
src/components/Dialog/ImportDialog.vue | 119 ++++++++++++++++++++++++-----
src/views/productionManagement/productStructure/index.vue | 39 ++++++++-
3 files changed, 201 insertions(+), 33 deletions(-)
diff --git a/src/components/Dialog/ImportDialog.vue b/src/components/Dialog/ImportDialog.vue
index 5b126dc..9388b20 100644
--- a/src/components/Dialog/ImportDialog.vue
+++ b/src/components/Dialog/ImportDialog.vue
@@ -8,17 +8,16 @@
>
<el-upload
ref="uploadRef"
+ v-model:file-list="fileList"
:limit="limit"
:accept="accept"
:headers="headers"
:action="action"
:disabled="disabled"
:before-upload="beforeUpload"
- :on-progress="onProgress"
- :on-success="onSuccess"
- :on-error="onError"
- :on-change="onChange"
- :auto-upload="autoUpload"
+ :http-request="handleHttpRequest"
+ :on-change="onChange || (() => {})"
+ :auto-upload="false"
drag
>
<el-icon class="el-icon--upload"><UploadFilled /></el-icon>
@@ -39,7 +38,7 @@
</el-upload>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary" @click="handleConfirm">纭� 瀹�</el-button>
+ <el-button type="primary" @click="handleConfirm" :loading="uploading">纭� 瀹�</el-button>
<el-button @click="handleCancel">鍙� 娑�</el-button>
</div>
</template>
@@ -49,6 +48,9 @@
<script setup>
import { computed, ref } from 'vue'
import { UploadFilled } from '@element-plus/icons-vue'
+import axios from 'axios'
+import { getToken } from '@/utils/auth'
+import { ElMessage } from 'element-plus'
const props = defineProps({
modelValue: {
@@ -84,10 +86,6 @@
required: true
},
disabled: {
- type: Boolean,
- default: false
- },
- autoUpload: {
type: Boolean,
default: false
},
@@ -129,19 +127,96 @@
})
const uploadRef = ref(null)
+const fileList = ref([])
+const uploading = ref(false)
const handleClose = () => {
emit('close')
}
-const handleConfirm = () => {
- emit('confirm')
+const handleHttpRequest = async (options) => {
+ const { file, onProgress, onSuccess, onError } = options
+
+ uploading.value = true
+
+ const formData = new FormData()
+ formData.append('file', file)
+
+ try {
+ const response = await axios({
+ url: props.action,
+ method: 'post',
+ data: formData,
+ headers: {
+ 'Authorization': 'Bearer ' + getToken(),
+ ...props.headers,
+ 'Content-Type': 'multipart/form-data'
+ },
+ responseType: 'blob',
+ onUploadProgress: (progressEvent) => {
+ const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total)
+ if (onProgress) {
+ onProgress({ percent })
+ }
+ if (props.onProgress) {
+ props.onProgress({ percent }, file)
+ }
+ }
+ })
+
+ uploading.value = false
+ const blob = response.data
+
+ // 鍏堝皾璇曞皢 blob 瑙f瀽涓� JSON锛堟棤璁� content-type 鏄粈涔堬級
+ try {
+ const text = await blob.text()
+ const jsonResponse = JSON.parse(text)
+ // 鎴愬姛瑙f瀽涓� JSON
+ if (jsonResponse.code === 200) {
+ if (onSuccess) onSuccess(jsonResponse)
+ if (props.onSuccess) props.onSuccess(jsonResponse, file)
+ } else {
+ const error = new Error(jsonResponse.msg || '瀵煎叆澶辫触')
+ error.response = { data: jsonResponse }
+ if (onError) onError(error)
+ if (props.onError) props.onError(jsonResponse, file)
+ }
+ } catch (e) {
+ // 涓嶆槸 JSON锛屾槸鏂囦欢娴侊紝涓嬭浇閿欒鏂囦欢
+ downloadBlob(blob, '瀵煎叆閿欒鏁版嵁.xlsx')
+ if (onError) {
+ const error = new Error('瀵煎叆澶辫触锛岃鏌ョ湅涓嬭浇鐨勯敊璇枃浠�')
+ error.response = { data: blob }
+ onError(error)
+ }
+ if (props.onError) {
+ props.onError(blob, file)
+ }
+ }
+ } catch (error) {
+ uploading.value = false
+ if (options.onError) options.onError(error)
+ if (props.onError) props.onError(error, file)
+ }
}
-const submit = () => {
- if (uploadRef.value) {
- uploadRef.value.submit()
+const downloadBlob = (blob, filename) => {
+ const downloadElement = document.createElement('a')
+ const href = window.URL.createObjectURL(blob)
+ downloadElement.href = href
+ downloadElement.download = filename
+ document.body.appendChild(downloadElement)
+ downloadElement.click()
+ document.body.removeChild(downloadElement)
+ window.URL.revokeObjectURL(href)
+}
+
+const handleConfirm = () => {
+ if (!fileList.value || fileList.value.length === 0) {
+ ElMessage.warning('璇烽�夋嫨鏂囦欢')
+ return
}
+ uploadRef.value.submit()
}
const handleCancel = () => {
@@ -153,14 +228,15 @@
emit('download-template')
}
+const clearFiles = () => {
+ if (uploadRef.value) {
+ uploadRef.value.clearFiles()
+ }
+}
+
defineExpose({
uploadRef,
- submit,
- clearFiles: () => {
- if (uploadRef.value) {
- uploadRef.value.clearFiles()
- }
- }
+ clearFiles
})
</script>
@@ -169,4 +245,3 @@
text-align: center;
}
</style>
-
diff --git a/src/views/basicData/product/index.vue b/src/views/basicData/product/index.vue
index b887d9d..6f1fed3 100644
--- a/src/views/basicData/product/index.vue
+++ b/src/views/basicData/product/index.vue
@@ -172,6 +172,7 @@
:limit="1"
accept=".xlsx,.xls"
:action="importUpload.url"
+ :http-request="importUpload.httpRequest"
:headers="importUpload.headers"
:before-upload="importUpload.beforeUpload"
:on-success="importUpload.onSuccess"
@@ -198,6 +199,7 @@
<script setup>
import { ref, reactive, onMounted } from "vue";
+import axios from "axios";
import { ElMessageBox } from "element-plus";
import { Plus } from "@element-plus/icons-vue";
import { getToken } from "@/utils/auth.js";
@@ -314,12 +316,79 @@
});
const { modelForm, modelRules } = toRefs(data);
+const downloadImportErrorFile = (blob, filename = "import-error.xlsx") => {
+ const downloadElement = document.createElement("a");
+ const href = window.URL.createObjectURL(blob);
+ downloadElement.href = href;
+ downloadElement.download = filename;
+ document.body.appendChild(downloadElement);
+ downloadElement.click();
+ document.body.removeChild(downloadElement);
+ window.URL.revokeObjectURL(href);
+};
+
+const tryParseJsonBlob = async (blob) => {
+ try {
+ const text = await blob.text();
+ if (!text || !text.trim()) {
+ return null;
+ }
+ return JSON.parse(text);
+ } catch (_) {
+ return null;
+ }
+};
+
const importUpload = reactive({
title: "浜у搧瀵煎叆",
open: false,
url: import.meta.env.VITE_APP_BASE_API + "/basic/product/import",
headers: { Authorization: "Bearer " + getToken() },
isUploading: false,
+ httpRequest: async (options) => {
+ const { file, onProgress, onSuccess, onError } = options;
+ importUpload.isUploading = true;
+ const formData = new FormData();
+ formData.append("file", file);
+ try {
+ const response = await axios({
+ url: importUpload.url,
+ method: "post",
+ headers: {
+ ...importUpload.headers,
+ "Content-Type": "multipart/form-data",
+ },
+ data: formData,
+ responseType: "blob",
+ onUploadProgress: (progressEvent) => {
+ const total = progressEvent.total || 1;
+ const percent = Math.round((progressEvent.loaded * 100) / total);
+ onProgress?.({ percent }, file);
+ },
+ });
+ importUpload.isUploading = false;
+ const blob = response.data;
+ // Contract: success => empty response body; failure => binary error file.
+ if (!blob || blob.size === 0) {
+ onSuccess?.({ code: 200, msg: "import success" }, file);
+ return;
+ }
+ const json = await tryParseJsonBlob(blob);
+ if (json) {
+ if (String(json.code) === "200" || json.success === true) {
+ onSuccess?.(json, file);
+ } else {
+ onError?.(new Error(json.msg || json.message || "import failed"), file);
+ }
+ return;
+ }
+ downloadImportErrorFile(blob);
+ onError?.(new Error("import failed, error file downloaded"), file);
+ } catch (error) {
+ importUpload.isUploading = false;
+ onError?.(error, file);
+ }
+ },
beforeUpload: (file) => {
const isExcel = file.name.endsWith('.xlsx') || file.name.endsWith('.xls');
const isLt10M = file.size / 1024 / 1024 < 10;
@@ -342,7 +411,7 @@
onSuccess: (response, file, fileList) => {
console.log('涓婁紶鎴愬姛', response, file, fileList);
importUpload.isUploading = false;
- if (response.code === 200) {
+ if (String(response?.code) === "200" || response?.success === true) {
proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
importDia.value = false;
if (importUploadRef.value) {
@@ -621,11 +690,6 @@
}
:deep(.el-upload--picture-card) {
- width: 148px;
- height: 148px;
-}
-
-:deep(.el-upload-list__item) {
width: 148px;
height: 148px;
}
diff --git a/src/views/productionManagement/productStructure/index.vue b/src/views/productionManagement/productStructure/index.vue
index 93f9112..fb9e7d8 100644
--- a/src/views/productionManagement/productStructure/index.vue
+++ b/src/views/productionManagement/productStructure/index.vue
@@ -45,7 +45,7 @@
<!-- BOM瀵煎叆瀵硅瘽妗� -->
<ImportDialog ref="uploadRef" v-model="upload.open" :title="upload.title" :action="upload.url"
:headers="upload.headers" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress"
- :on-success="handleFileSuccess" :show-download-template="true" @confirm="submitFileForm"
+ :on-success="handleFileSuccess" :on-error="handleFileError" :show-download-template="true" @confirm="submitFileForm"
@download-template="handleDownloadTemplate" @close="handleImportClose" />
</div>
</template>
@@ -334,7 +334,7 @@
};
// 鏂囦欢涓婁紶鎴愬姛澶勭悊
-const handleFileSuccess = (response, file, fileList) => {
+const handleFileSuccess = (response, file) => {
upload.open = false;
upload.isUploading = false;
proxy.$refs["uploadRef"].clearFiles();
@@ -342,13 +342,42 @@
proxy.$modal.msgSuccess(response.msg || "瀵煎叆鎴愬姛");
getList();
} else {
- proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "瀵煎叆缁撴灉", { dangerouslyUseHTMLString: true });
+ proxy.$modal.msgError(response.msg || "瀵煎叆澶辫触");
}
};
-// 鎻愪氦涓婁紶鏂囦欢
+// 鏂囦欢涓婁紶澶辫触澶勭悊 - 鍚庣杩斿洖閿欒鏂囦欢娴�
+const handleFileError = (error, file) => {
+ upload.open = false;
+ upload.isUploading = false;
+ proxy.$refs["uploadRef"].clearFiles();
+
+ // error 鍙兘鏄� Blob 瀵硅薄锛堝悗绔繑鍥炵殑閿欒鏂囦欢锛�
+ if (error instanceof Blob) {
+ // 涓嬭浇閿欒鏂囦欢
+ const blob = error;
+ const downloadElement = document.createElement('a');
+ const href = window.URL.createObjectURL(blob);
+ downloadElement.href = href;
+ downloadElement.download = "瀵煎叆閿欒鏁版嵁.xlsx";
+ document.body.appendChild(downloadElement);
+ downloadElement.click();
+ document.body.removeChild(downloadElement);
+ window.URL.revokeObjectURL(href);
+ proxy.$modal.msgError("瀵煎叆澶辫触锛岃鏌ョ湅涓嬭浇鐨勯敊璇枃浠�");
+ } else if (error && error.msg) {
+ // 鍚庣杩斿洖鐨勯敊璇俊鎭�
+ proxy.$modal.msgError(error.msg);
+ } else {
+ // 鏅�氶敊璇�
+ proxy.$modal.msgError("瀵煎叆澶辫触");
+ }
+};
+
+// 鎻愪氦涓婁紶鏂囦欢 - 鐜板湪鐢� ImportDialog 鍐呴儴澶勭悊
const submitFileForm = () => {
- proxy.$refs["uploadRef"].submit();
+ // ImportDialog 鐨� handleConfirm 浼氳皟鐢� uploadRef.value.submit()
+ // 杩欓噷涓嶉渶瑕侀澶栨搷浣�
};
// 瀵煎嚭鎸夐挳鎿嶄綔
--
Gitblit v1.9.3