gaoluyang
5 天以前 2b72d8220cf274e9b6586c7d4d9fae612fec3a14
src/views/basicData/product/index.vue
@@ -145,7 +145,7 @@
            :on-success="handleDrawingUploadSuccess"
            :on-remove="handleDrawingRemove"
            :before-upload="handleDrawingBeforeUpload"
            :limit="1"
            :limit="5"
            accept=".pdf,.jpg,.jpeg,.png,.dwg"
            list-type="picture-card"
          >
@@ -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";
@@ -259,6 +261,16 @@
    minWidth: 100,
  },
  {
    label: "工艺路线",
    prop: "routeName",
    minWidth: 100,
  },
  {
    label: "子项数量",
    prop: "subItemCount",
    minWidth: 100,
  },
  {
    label: "产品属性",
    prop: "productType",
    width: 100,
@@ -269,6 +281,16 @@
      return typeMap[String(v)] || "info";
    },
  },
   {
      label: "创建时间",
      prop: "createTime",
      width: 120,
   },
   {
      label: "修改时间",
      prop: "updateTime",
      width: 120,
   },
  {
    dataType: "action",
    label: "操作",
@@ -309,12 +331,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;
@@ -337,7 +426,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) {
@@ -385,7 +474,14 @@
    modelForm.value = { ...data };
    modelForm.value.tempFileIds = data.tempFileIds || [];
    modelForm.value.salesLedgerFiles = data.salesLedgerFiles || [];
    if (data.drawingFile) {
    // 处理图纸文件反显
    if (data.salesLedgerFiles && data.salesLedgerFiles.length > 0) {
      drawingFileList.value = data.salesLedgerFiles.map(file => ({
        id: file.id,  // 带上id用于删除时调用接口
        name: file.name,
        url: file.url
      }));
    } else if (data.drawingFile) {
      drawingFileList.value = [{
        name: data.drawingFile.split('/').pop(),
        url: data.drawingFile
@@ -397,7 +493,13 @@
const submitModelForm = () => {
  modelFormRef.value.validate((valid) => {
    if (valid) {
      addOrEditProductModel(modelForm.value).then((res) => {
      // 构建提交数据,确保 routeId 为空时传 null,同时清空 routeName
      const submitData = {
        ...modelForm.value,
        routeId: modelForm.value.routeId || 0,
        routeName: modelForm.value.routeId ? modelForm.value.routeName : null
      };
      addOrEditProductModel(submitData).then((res) => {
        proxy.$modal.msgSuccess("提交成功");
        closeModelDia();
        getModelList();
@@ -515,13 +617,14 @@
  console.log('上传成功响应', response);
  console.log('response.data', response.data);
  if (response.code === 200) {
    modelForm.value.tempFileIds = [response.data?.tempId];
    modelForm.value.salesLedgerFiles = [{
    // 支持多文件,追加到数组
    modelForm.value.tempFileIds.push(response.data?.tempId);
    modelForm.value.salesLedgerFiles.push({
      tempId: response.data?.tempId,
      originalName: response.data?.originalName || file.name,
      tempPath: response.data?.tempPath,
      type: response.data?.type || 13
    }];
    });
    proxy.$modal.msgSuccess("上传成功");
  } else {
    proxy.$modal.msgError(response.msg || "上传失败");
@@ -529,8 +632,24 @@
};
const handleDrawingRemove = (file) => {
  modelForm.value.tempFileIds = [];
  modelForm.value.salesLedgerFiles = [];
  // 如果是编辑模式下已存在的文件(带有id),调用删除接口
  if (file.id) {
    delLedgerFile({ id: file.id }).then(res => {
      if (res.code === 200) {
        proxy.$modal.msgSuccess("删除成功");
      }
    }).catch(err => {
      console.error("删除文件失败:", err);
    });
  }
  // 从数组中移除对应的文件
  const index = modelForm.value.salesLedgerFiles.findIndex(item =>
    item.tempId === file.response?.data?.tempId || item.tempId === file.tempId
  );
  if (index > -1) {
    modelForm.value.tempFileIds.splice(index, 1);
    modelForm.value.salesLedgerFiles.splice(index, 1);
  }
};
onMounted(() => {
@@ -586,11 +705,6 @@
}
:deep(.el-upload--picture-card) {
  width: 148px;
  height: 148px;
}
:deep(.el-upload-list__item) {
  width: 148px;
  height: 148px;
}