zhangwencui
3 天以前 0a9495113009836423b450f3598debd61eefa237
Merge branch 'dev_New' of http://114.132.189.42:9002/r/product-inventory-management into dev_New
已修改5个文件
303 ■■■■ 文件已修改
src/api/basicData/product.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Upload/FileUpload.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/product/ImportExcel/index.vue 73 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/product/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/workOrder/index.vue 214 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/basicData/product.js
@@ -56,3 +56,12 @@
        params: query
    })
}
//  下载产品导入模板
export function downloadProductModelImportTemplate() {
    return request({
        url: '/basic/product/export',
        method: 'get',
        responseType: 'blob'
    })
}
src/components/Upload/FileUpload.vue
@@ -49,9 +49,14 @@
  emits("remove", file);
};
const clearFiles = () => {
  fileList.value = [];
};
defineExpose({
  fileList,
  uploadApi,
  clearFiles,
});
</script>
src/views/basicData/product/ImportExcel/index.vue
@@ -2,16 +2,10 @@
  <el-button type="info" plain icon="Upload" @click="handleImport">
    导入
  </el-button>
  <el-dialog v-model="upload.open" :title="upload.title">
    <FileUpload
      ref="fileUploadRef"
      accept=".xlsx, .xls"
      :headers="upload.headers"
      :action="upload.url + '?updateSupport=' + upload.updateSupport"
      :disabled="upload.isUploading"
      :showTip="false"
      @success="handleFileSuccess"
    />
  <el-dialog v-model="upload.open" :title="upload.title" @close="handleDialogClose">
    <FileUpload ref="fileUploadRef" accept=".xlsx, .xls" :headers="upload.headers" :action="uploadUrl"
      :disabled="upload.isUploading" :showTip="true" @success="handleFileSuccess"
      :downloadTemplate="handleDownloadTemplate" />
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="submitFileForm">确 定</el-button>
@@ -22,15 +16,19 @@
</template>
<script setup>
import { reactive } from "vue";
import { reactive, computed } from "vue";
import { getToken } from "@/utils/auth.js";
import { FileUpload } from "@/components/Upload";
import { ElMessage } from "element-plus";
import { downloadProductModelImportTemplate } from "@/api/basicData/product.js";
defineOptions({
  name: "产品维护导入",
});
const props = defineProps({
  productId: { type: [String, Number], default: "" },
});
const emits = defineEmits(["uploadSuccess"]);
const fileUploadRef = ref();
const upload = reactive({
@@ -42,17 +40,31 @@
  isUploading: false,
  // 设置上传的请求头部
  headers: { Authorization: "Bearer " + getToken() },
  // 上传的地址
  url: import.meta.env.VITE_APP_BASE_API + "/system/supplier/import",
});
// 上传的地址(携带 productId 参数,传给后端的 importProduct 接口)
const uploadUrl = computed(
  () =>
    import.meta.env.VITE_APP_BASE_API +
    "/basic/product/import" +
    (props.productId ? `?productId=${props.productId}` : "")
);
// 点击导入
const handleImport = () => {
  if (!props.productId) {
    ElMessage({ message: "请先选择产品", type: "warning" });
    return;
  }
  upload.open = true;
  upload.title = "产品导入";
};
const submitFileForm = () => {
  fileUploadRef.value.uploadApi();
};
// 关闭弹窗时清除已选文件
const handleDialogClose = () => {
  fileUploadRef.value?.clearFiles?.();
};
const handleFileSuccess = (response) => {
@@ -65,4 +77,39 @@
    ElMessage({ message: msg, type: "error" });
  }
};
// 下载 Excel 导入模板
const handleDownloadTemplate = () => {
  downloadProductModelImportTemplate()
    .then((blobData) => {
      const blob =
        blobData instanceof Blob
          ? blobData
          : new Blob([blobData], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.download = "产品导入模板.xlsx";
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(url);
      ElMessage({ message: "模板下载成功", type: "success" });
    })
    .catch(() => {
      ElMessage({ message: "模板下载失败", type: "error" });
    });
};
</script>
<style scoped>
.import-tip {
  margin-top: 12px;
  font-size: 12px;
  color: var(--el-text-color-secondary);
}
.import-tip .el-button {
  margin-left: 8px;
}
</style>
src/views/basicData/product/index.vue
@@ -73,7 +73,7 @@
        <el-button type="primary" @click="openModelDia('add')">
          新增规格型号
        </el-button>
        <ImportExcel @uploadSuccess="getModelList" />
        <ImportExcel :product-id="currentId" @uploadSuccess="getModelList" />
        <el-button
          type="danger"
          @click="handleDelete"
src/views/productionManagement/workOrder/index.vue
@@ -166,26 +166,32 @@
    <el-dialog v-model="reportDialogVisible"
               title="报工"
               width="500px">
      <el-form :model="reportForm"
      <el-form ref="reportFormRef"
               :model="reportForm"
               :rules="reportFormRules"
               label-width="120px">
        <el-form-item label="待生产数量">
          <el-input v-model="reportForm.planQuantity"
                    readonly
                    style="width: 300px" />
        </el-form-item>
        <el-form-item label="本次生产数量">
        <el-form-item label="本次生产数量" prop="quantity">
          <el-input v-model.number="reportForm.quantity"
                    type="number"
                    min="1"
                    step="1"
                    style="width: 300px"
                    placeholder="请输入本次生产数量" />
                    placeholder="请输入本次生产数量"
                    @input="handleQuantityInput" />
        </el-form-item>
        <el-form-item label="报废数量">
        <el-form-item label="报废数量" prop="scrapQty">
          <el-input v-model.number="reportForm.scrapQty"
                    type="number"
                    min="1"
                    min="0"
                    step="1"
                    style="width: 300px"
                    placeholder="请输入报废数量" />
                    placeholder="请输入报废数量"
                    @input="handleScrapQtyInput" />
        </el-form-item>
        <el-form-item label="班组信息">
          <el-select v-model="reportForm.userId"
@@ -214,7 +220,7 @@
</template>
<script setup>
  import { onMounted, ref } from "vue";
  import { onMounted, ref, nextTick } from "vue";
  import { ElMessageBox } from "element-plus";
  import dayjs from "dayjs";
  import {
@@ -345,10 +351,12 @@
  const transferCardRowData = ref(null);
  const reportDialogVisible = ref(false);
  const workOrderFilesRef = ref(null);
  const reportFormRef = ref(null);
  const userOptions = ref([]);
  const reportForm = reactive({
    planQuantity: 0,
    quantity: 0,
    quantity: null,
    scrapQty: null,
    userName: "",
    workOrderId: "",
    reportWork: "",
@@ -356,6 +364,100 @@
    userId: "",
    productMainId: null,
  });
  // 本次生产数量验证规则
  const validateQuantity = (rule, value, callback) => {
    if (value === null || value === undefined || value === '') {
      callback(new Error('请输入本次生产数量'));
      return;
    }
    const num = Number(value);
    // 整数且大于等于1
    if (isNaN(num) || !Number.isInteger(num) || num < 1) {
      callback(new Error('本次生产数量必须大于等于1'));
      return;
    }
    callback();
  };
  // 报废数量验证规则
  const validateScrapQty = (rule, value, callback) => {
    if (value === null || value === undefined || value === '') {
      callback();
      return;
    }
    const num = Number(value);
    // 整数且大于等于0
    if (isNaN(num) || !Number.isInteger(num) || num < 0) {
      callback(new Error('报废数量必须大于等于0'));
      return;
    }
    callback();
  };
  // 验证规则
  const reportFormRules = {
    quantity: [
      { required: true, validator: validateQuantity, trigger: 'blur' }
    ],
    scrapQty: [
      { validator: validateScrapQty, trigger: 'blur' }
    ]
  };
  // 处理本次生产数量输入,限制必须大于等于1
  const handleQuantityInput = (value) => {
    if (value === '' || value === null || value === undefined) {
      reportForm.quantity = null;
      return;
    }
    const num = Number(value);
    if (isNaN(num)) {
      return;
    }
    // 如果小于1,清除
    if (num < 1) {
      reportForm.quantity = null;
      return;
    }
    // 如果是小数取整数部分
    if (!Number.isInteger(num)) {
      const intValue = Math.floor(num);
      // 如果取整后小于1,清除
      if (intValue < 1) {
        reportForm.quantity = null;
        return;
      }
      reportForm.quantity = intValue;
      return;
    }
    reportForm.quantity = num;
  };
  // 处理报废数量
  const handleScrapQtyInput = (value) => {
    if (value === '' || value === null || value === undefined) {
      reportForm.scrapQty = null;
      return;
    }
    const num = Number(value);
    // 如果是NaN,保持原值
    if (isNaN(num)) {
      return;
    }
    // 如果是负数,清除输入
    if (num < 0) {
      reportForm.scrapQty = null;
      return;
    }
    // 如果是小数,取整数部分
    if (!Number.isInteger(num)) {
      reportForm.scrapQty = Math.floor(num);
      return;
    }
    // 有效的非负整数(包括0)
    reportForm.scrapQty = num;
  };
  const currentReportRowData = ref(null);
  const page = reactive({
    current: 1,
@@ -494,12 +596,15 @@
  const showReportDialog = row => {
    currentReportRowData.value = row;
    reportForm.planQuantity = row.planQuantity;
    reportForm.quantity = row.quantity;
    reportForm.quantity = row.quantity !== undefined && row.quantity !== null ? row.quantity : null;
    reportForm.productProcessRouteItemId = row.productProcessRouteItemId;
    reportForm.workOrderId = row.id;
    reportForm.reportWork = row.reportWork;
    reportForm.productMainId = row.productMainId;
    reportForm.scrapQty = row.scrapQty;
    reportForm.scrapQty = row.scrapQty !== undefined && row.scrapQty !== null ? row.scrapQty : null;
    nextTick(() => {
      reportFormRef.value?.clearValidate();
    });
    // 获取当前登录用户信息,设置为默认选中
    getUserProfile()
      .then(res => {
@@ -520,35 +625,72 @@
  };
  const handleReport = () => {
    if (reportForm.planQuantity <= 0) {
      ElMessageBox.alert("待生产数量为0,无法报工", "提示", {
        confirmButtonText: "确定",
      });
      return;
    }
    if (!reportForm.quantity || reportForm.quantity <= 0) {
      ElMessageBox.alert("请输入有效的本次生产数量", "提示", {
        confirmButtonText: "确定",
      });
      return;
    }
    if (reportForm.quantity > reportForm.planQuantity) {
      ElMessageBox.alert("本次生产数量不能超过待生产数量", "提示", {
        confirmButtonText: "确定",
      });
      return;
    }
    // console.log(reportForm);
    addProductMain(reportForm).then(res => {
      if (res.code === 200) {
        proxy.$modal.msgSuccess("报工成功");
        reportDialogVisible.value = false;
        getList();
      } else {
        ElMessageBox.alert(res.msg || "报工失败", "提示", {
    reportFormRef.value?.validate((valid) => {
      if (!valid) {
        return false;
      }
      if (reportForm.planQuantity <= 0) {
        ElMessageBox.alert("待生产数量为0,无法报工", "提示", {
          confirmButtonText: "确定",
        });
        return;
      }
      // 验证本次生产数量
      if (reportForm.quantity === null || reportForm.quantity === undefined || reportForm.quantity === '') {
        ElMessageBox.alert("请输入本次生产数量", "提示", {
          confirmButtonText: "确定",
        });
        return;
      }
      const quantity = Number(reportForm.quantity);
      const scrapQty = reportForm.scrapQty === null || reportForm.scrapQty === undefined || reportForm.scrapQty === ''
        ? 0
        : Number(reportForm.scrapQty);
      // 本次生产数量
      if (isNaN(quantity) || !Number.isInteger(quantity) || quantity < 1) {
        ElMessageBox.alert("本次生产数量必须大于等于1", "提示", {
          confirmButtonText: "确定",
        });
        return;
      }
      // 报废数量必须是整数且大于等于0
      if (isNaN(scrapQty) || !Number.isInteger(scrapQty) || scrapQty < 0) {
        ElMessageBox.alert("报废数量必须大于等于0", "提示", {
          confirmButtonText: "确定",
        });
        return;
      }
      if (quantity > reportForm.planQuantity) {
        ElMessageBox.alert("本次生产数量不能超过待生产数量", "提示", {
          confirmButtonText: "确定",
        });
        return;
      }
      const submitData = {
        ...reportForm,
        quantity: quantity,
        scrapQty: scrapQty
      };
      // console.log(submitData);
      addProductMain(submitData).then(res => {
        if (res.code === 200) {
          proxy.$modal.msgSuccess("报工成功");
          reportDialogVisible.value = false;
          getList();
        } else {
          ElMessageBox.alert(res.msg || "报工失败", "提示", {
            confirmButtonText: "确定",
          });
        }
      });
    });
  };