gaoluyang
2025-11-26 1c4ff7adf79cd9abc1ea644a3161780a623b9f5c
src/views/productionManagement/productionOrder/index.vue
@@ -2,32 +2,26 @@
   <div class="app-container">
      <div class="search_form">
         <div>
            <span class="search_title">客户名称:</span>
            <el-input
               v-model="searchForm.customerName"
               style="width: 240px"
               placeholder="请输入"
               @change="handleQuery"
            <span class="search_title">产品大类:</span>
            <el-tree-select
               v-model="searchForm.productCategory"
               :data="productOptions"
               placeholder="请选择"
               clearable
               prefix-icon="Search"
            />
            <span class="search_title ml10">项目名称:</span>
            <el-input
               v-model="searchForm.projectName"
               check-strictly
               :render-after-expand="false"
               style="width: 240px"
               placeholder="请输入"
               @change="handleQuery"
               clearable
               prefix-icon="Search"
            />
            <span class="search_title ml10">录入日期:</span>
            <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
            <el-date-picker v-model="searchForm.registerDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
                                    placeholder="请选择" clearable @change="changeDaterange" />
            <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
            >搜索</el-button
            >
         </div>
         <div>
            <el-button type="primary" @click="openDialog('create')">新增订单</el-button>
            <el-button @click="handleOut">导出</el-button>
         </div>
      </div>
@@ -39,102 +33,356 @@
            :page="page"
            :tableLoading="tableLoading"
            @pagination="pagination"
         ></PIMTable>
         >
            <template #action="{ row }">
               <el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
               <el-button type="danger" link @click="handleDelete(row)">删除</el-button>
            </template>
         </PIMTable>
      </div>
   <el-dialog v-model="dialogVisible" :title="dialogTitle" width="40%" @close="closeDialog">
      <el-form ref="formRef" :model="form" :rules="formRules" label-width="100px">
         <el-form-item label="录入日期" prop="registerDate">
            <el-date-picker v-model="form.registerDate" type="date" value-format="YYYY-MM-DD" format="YYYY-MM-DD" placeholder="请选择录入日期" style="width: 100%"/>
         </el-form-item>
         <el-form-item label="产品大类" prop="productCategory">
            <el-tree-select
               v-model="form.productCategory"
               :data="productOptions"
               placeholder="请选择产品大类"
               clearable
               check-strictly
               :render-after-expand="false"
               style="width: 100%"
               @change="handleCategoryChange"
            />
         </el-form-item>
         <el-form-item label="规格型号" prop="productModelId">
            <el-select v-model="form.productModelId" placeholder="请选择规格型号" style="width: 100%" @change="handleModelChange">
               <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id"/>
            </el-select>
         </el-form-item>
         <el-form-item label="单位" prop="unit">
            <el-input v-model="form.unit" placeholder="自动带出" disabled/>
         </el-form-item>
         <el-form-item label="数量" prop="quantity">
            <el-input-number v-model="form.quantity" :min="0" :step="0.1" style="width: 100%"/>
         </el-form-item>
      </el-form>
      <template #footer>
         <div class="dialog-footer">
            <el-button type="primary" @click="submitForm">确认</el-button>
            <el-button @click="closeDialog">取消</el-button>
         </div>
      </template>
   </el-dialog>
   </div>
</template>
<script setup>
import {onMounted, ref} from "vue";
import {onMounted, ref, reactive, toRefs, getCurrentInstance} from "vue";
import { ElMessageBox } from "element-plus";
import dayjs from "dayjs";
import {schedulingListPage} from "@/api/productionManagement/productionOrder.js";
import {schedulingListPage, addProductionOrder, updateProductionOrder, deleteProductionOrder} from "@/api/productionManagement/productionOrder.js";
import {productTreeList, modelList} from "@/api/basicData/product.js";
const { proxy } = getCurrentInstance();
const tableColumn = ref([
   {
      label: "录入日期",
      prop: "entryDate",
      prop: "registerDate",
      width: 120,
   },
   {
      label: "合同号",
      prop: "salesContractNo",
      width: 220,
   },
   {
      label: "客户合同号",
      prop: "customerContractNo",
      width: 250,
   },
   {
      label: "客户名称",
      prop: "customerName",
      width: 250,
   },
   {
      label: "项目名称",
      prop: "projectName",
      width:300
      label: "生产订单号",
      prop: "orderNo",
   },
   {
      label: "产品大类",
      prop: "productCategory",
      width: 160,
   },
   {
      label: "规格型号",
      prop: "specificationModel",
      width: 220,
   },
   {
      label: "单位",
      prop: "unit",
      width:90
   },
   {
      label: "数量",
      prop: "quantity",
   },
   // {
   //    label: "排产数量",
   //    prop: "schedulingNum",
   //    width: 100,
   // },
   // {
   //    label: "完工数量",
   //    prop: "successNum",
   //    width: 100,
   // },
   {
      label: "排产数量",
      prop: "schedulingNum",
      width: 100,
   },
   {
      label: "完工数量",
      prop: "successNum",
      width: 100,
   },
      label: "操作",
      prop: "action",
      width: 120,
      fixed: "right",
      dataType: "slot",
      align: "center",
      slot: "action"
   }
]);
const tableData = ref([]);
const tableLoading = ref(false);
const page = reactive({
const page = ref({
   current: 1,
   size: 100,
   total: 0,
});
const dialogVisible = ref(false);
const dialogTitle = ref("");
const dialogMode = ref(""); // 'create' 或 'edit'
const formRef = ref();
const productOptions = ref([]);
const modelOptions = ref([]);
const form = reactive({
   id: null,
   registerDate: dayjs().format("YYYY-MM-DD"),
   productCategory: "",
   productCategoryName: "",
   productModelId: "",
   specificationModel: "",
   unit: "",
   quantity: null,
});
const formRules = {
   registerDate: [{ required: true, message: "请选择录入日期", trigger: "change" }],
   productCategory: [{ required: true, message: "请选择产品大类", trigger: "change" }],
   productModelId: [{ required: true, message: "请选择规格型号", trigger: "change" }],
   quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
};
const data = reactive({
   searchForm: {
      customerName: "",
      projectName: "",
      entryDate: null, // 录入日期
      productCategory: "",
      registerDate: null, // 录入日期
      entryDateStart: undefined,
      entryDateEnd: undefined,
   },
});
const { searchForm } = toRefs(data);
const openDialog = (mode, row = null) => {
   dialogMode.value = mode;
   if (mode === 'create') {
      dialogTitle.value = "新增生产订单";
      resetForm();
   } else if (mode === 'edit') {
      dialogTitle.value = "编辑生产订单";
      resetForm();
      console.log('编辑数据:', row);
      // 填充编辑数据
      form.id = row.id;
      form.registerDate = row.registerDate;
      form.productCategoryName = row.productCategory;
      form.specificationModel = row.specificationModel;
      form.unit = row.unit;
      form.quantity = row.quantity;
      // 先加载产品选项,然后根据名称查找对应的ID
      if (productOptions.value.length === 0) {
         getProductOptions().then(() => {
            findAndSetProductCategory(row.productCategory);
         });
      } else {
         findAndSetProductCategory(row.productCategory);
      }
   }
   dialogVisible.value = true;
   if (productOptions.value.length === 0) {
      getProductOptions();
   }
};
const closeDialog = () => {
   dialogVisible.value = false;
};
const resetForm = () => {
   form.id = null;
   form.registerDate = dayjs().format("YYYY-MM-DD");
   form.productCategory = "";
   form.productCategoryName = "";
   form.productModelId = "";
   form.specificationModel = "";
   form.unit = "";
   form.quantity = null;
   modelOptions.value = [];
};
const handleCategoryChange = (value) => {
   form.productCategory = value;
   form.productCategoryName = findNodeById(productOptions.value, value) || "";
   form.productModelId = "";
   form.specificationModel = "";
   form.unit = "";
   modelOptions.value = [];
   if (value) {
      getModels(value);
   }
};
const handleModelChange = (value) => {
   form.productModelId = value;
   const selected = modelOptions.value.find(item => item.id === value);
   if (selected) {
      form.specificationModel = selected.model;
      form.unit = selected.unit || "";
   } else {
      form.specificationModel = "";
      form.unit = "";
   }
};
const submitForm = () => {
   formRef.value?.validate(async (valid) => {
      if (!valid) return;
      if (!form.unit) {
         proxy.$modal.msgWarning("请先选择规格型号以带出单位");
         return;
      }
      try {
         const payload = {
            registerDate: form.registerDate,
            productCategory: form.productCategoryName,
            specificationModel: form.specificationModel,
            unit: form.unit,
            quantity: form.quantity,
         };
         if (dialogMode.value === 'create') {
            await addProductionOrder(payload);
            proxy.$modal.msgSuccess("新增成功");
         } else if (dialogMode.value === 'edit') {
            payload.id = form.id;
            await updateProductionOrder(payload);
            proxy.$modal.msgSuccess("编辑成功");
         }
         closeDialog();
         getList();
      } catch (err) {
         console.error(`${dialogMode.value === 'create' ? '新增' : '编辑'}失败`, err);
         proxy.$modal.msgError(`${dialogMode.value === 'create' ? '新增' : '编辑'}失败,请重试`);
      }
   });
};
// 编辑方法
const handleEdit = (row) => {
   openDialog('edit', row);
};
// 删除方法
const handleDelete = (row) => {
   proxy.$modal.confirm(`确定要删除生产订单"${row.orderNo}"吗?`, "删除确认", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
   }).then(async () => {
      try {
         await deleteProductionOrder([row.id]);
         proxy.$modal.msgSuccess("删除成功");
         getList(); // 刷新列表
      } catch (err) {
         console.error("删除失败", err);
         proxy.$modal.msgError("删除失败,请重试");
      }
   }).catch(() => {
      proxy.$modal.msg("已取消删除");
   });
};
const getProductOptions = () => {
   return productTreeList().then((res) => {
      productOptions.value = convertIdToValue(res || []);
   });
};
const getModels = (value) => {
   return modelList({ id: value }).then((res) => {
      modelOptions.value = res || [];
   });
};
const convertIdToValue = (data) => {
   return data.map((item) => {
      const { id, children, ...rest } = item;
      const newItem = {
         ...rest,
         value: id,
      };
      if (children && children.length > 0) {
         newItem.children = convertIdToValue(children);
      }
      return newItem;
   });
};
const findNodeById = (nodes, value) => {
   for (let i = 0; i < nodes.length; i++) {
      if (nodes[i].value === value) {
         return nodes[i].label;
      }
      if (nodes[i].children && nodes[i].children.length > 0) {
         const label = findNodeById(nodes[i].children, value);
         if (label) return label;
      }
   }
   return null;
};
const findNodeByLabel = (nodes, label) => {
   for (let i = 0; i < nodes.length; i++) {
      if (nodes[i].label === label) {
         return nodes[i].value;
      }
      if (nodes[i].children && nodes[i].children.length > 0) {
         const value = findNodeByLabel(nodes[i].children, label);
         if (value) return value;
      }
   }
   return null;
};
const findAndSetProductCategory = (categoryName) => {
   const categoryId = findNodeByLabel(productOptions.value, categoryName);
   if (categoryId) {
      form.productCategory = categoryId;
      // 加载对应的规格型号选项
      getModels(categoryId).then(() => {
         // 根据规格型号名称查找对应的ID
         const modelItem = modelOptions.value.find(item => item.model === form.specificationModel);
         if (modelItem) {
            form.productModelId = modelItem.id;
         }
      });
   }
};
// 查询列表
/** 搜索按钮操作 */
const handleQuery = () => {
   page.current = 1;
   page.value.current = 1;
   getList();
};
const pagination = (obj) => {
   page.current = obj.page;
   page.size = obj.limit;
   page.value.current = obj.page;
   page.value.size = obj.limit;
   getList();
};
const changeDaterange = (value) => {
@@ -150,12 +398,26 @@
const getList = () => {
   tableLoading.value = true;
   // 构造一个新的对象,不包含entryDate字段
   const params = { ...searchForm.value, ...page };
   params.entryDate = undefined
   const params = { ...searchForm.value, ...page.value };
   params.registerDate = undefined
   if (params.productCategory) {
      // 如果是对象类型,获取其label(名称)而不是value(ID)
      if (typeof params.productCategory === "object") {
         params.productCategory = findNodeById(productOptions.value, params.productCategory) || params.productCategory;
      }
      // 如果是ID,转换为名称
      else if (typeof params.productCategory === "string" || typeof params.productCategory === "number") {
         const categoryName = findNodeById(productOptions.value, params.productCategory);
         if (categoryName) {
            params.productCategory = categoryName;
         }
      }
   }
   schedulingListPage(params).then((res) => {
      console.log('params---', res)
      tableLoading.value = false;
      tableData.value = res.data.records;
      page.total = res.data.total;
      tableData.value = res.data.data.records;
      page.value.total = res.data.data.total;
   }).catch(() => {
      tableLoading.value = false;
   })
@@ -178,6 +440,7 @@
onMounted(() => {
   getList();
   getProductOptions();
});
</script>