src/views/productionManagement/workOrderManagement/index.vue
@@ -3,17 +3,26 @@
    <div class="search_form">
      <div class="search-row">
        <div class="search-item">
          <span class="search_title">工单编号:</span>
          <el-input v-model="searchForm.workOrderNo"
          <span class="search_title">入库日期:</span>
          <el-date-picker v-model="searchForm.timeStr"
                          type="date"
                          placeholder="请选择日期"
                          value-format="YYYY-MM-DD"
                          format="YYYY-MM-DD"
                          clearable
                          @change="handleQuery"/>
        </div>
        <div class="search-item">
          <span class="search_title">产品大类:</span>
          <el-input v-model="searchForm.productName"
                    style="width: 240px"
                    placeholder="请输入"
                    @change="handleQuery"
                    clearable
                    prefix-icon="Search" />
                    clearable/>
        </div>
        <div class="search-item">
          <el-button type="primary"
                     @click="handleQuery">搜索</el-button>
          <el-button type="primary" @click="openAddDialog" style="margin-left: 10px;">新增</el-button>
        </div>
      </div>
    </div>
@@ -23,13 +32,7 @@
                :tableData="tableData"
                :page="page"
                :tableLoading="tableLoading"
                @pagination="pagination">
        <template #completionStatus="{ row }">
          <el-progress :percentage="toProgressPercentage(row?.completionStatus)"
                       :color="progressColor(toProgressPercentage(row?.completionStatus))"
                       :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''" />
        </template>
      </PIMTable>
                @pagination="pagination" />
    </div>
    
    <!-- 流转卡弹窗 -->
@@ -165,6 +168,67 @@
    </el-dialog>
    
    <FilesDia ref="workOrderFilesRef" />
    <!-- 新增工单弹窗 -->
    <el-dialog v-model="addDialogVisible"
               title="新增工单"
               width="500px"
               @close="closeAddDialog">
      <el-form ref="addFormRef"
               :model="addForm"
               :rules="addFormRules"
               label-width="120px"
               label-position="top">
        <el-form-item label="产品名称:"
                      prop="productId">
          <el-tree-select v-model="addForm.productId"
                          placeholder="请选择产品"
                          clearable
                          check-strictly
                          :data="productOptions"
                          :render-after-expand="false"
                          style="width: 100%"
                          @change="handleProductChange" />
        </el-form-item>
        <el-form-item label="规格型号:"
                      prop="productModelId">
          <el-select v-model="addForm.productModelId"
                     placeholder="请选择规格型号"
                     clearable
                     style="width: 100%"
                     @change="handleModelChange"
                     filterable>
            <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="addForm.unit"
                    placeholder="单位"
                    disabled
                    style="width: 100%" />
        </el-form-item>
        <el-form-item label="数量:"
                      prop="quantity">
          <el-input-number v-model="addForm.quantity"
                           :min="1"
                           :step="1"
                           step-strictly
                           style="width: 100%"
                           placeholder="请输入数量" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary"
                     @click="handleAddSubmit">确定</el-button>
          <el-button @click="closeAddDialog">取消</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
@@ -178,34 +242,35 @@
    downProductWorkOrder,
  } from "@/api/productionManagement/workOrder.js";
  import { getUserProfile, userListNoPageByTenantId } from "@/api/system/user.js";
  import { createStockInventory } from "@/api/inventoryManagement/stockInventory.js";
  import { getStockInRecordListPage } from "@/api/inventoryManagement/stockInRecord.js";
  import { productTreeList, modelList } from "@/api/basicData/product.js";
  import { findAllQualifiedStockInRecordTypeOptions } from "@/api/basicData/enum.js";
  import QRCode from "qrcode";
  import { getCurrentInstance, reactive, toRefs } from "vue";
  import FilesDia from "./components/filesDia.vue";
  const { proxy } = getCurrentInstance();
  // 来源类型选项
  const stockRecordTypeOptions = ref([]);
  const tableColumn = ref([
    {
      label: "工单类型",
      prop: "workOrderType",
      width: "80",
      label: "入库批次",
      prop: "inboundBatches",
      width: "280",
    },
    {
      label: "工单编号",
      prop: "workOrderNo",
      width: "140",
      label: "入库时间",
      prop: "createTime",
      width: "160",
    },
    {
      label: "生产订单号",
      prop: "productOrderNpsNo",
      width: "140",
    },
    {
      label: "产品名称",
      label: "产品大类",
      prop: "productName",
      width: "140",
    },
    {
      label: "规格",
      label: "规格型号",
      prop: "model",
    },
    {
@@ -213,73 +278,19 @@
      prop: "unit",
    },
    {
      label: "工序名称",
      prop: "processName",
      label: "入库数量",
      prop: "stockInNum",
    },
    {
      label: "需求数量",
      prop: "planQuantity",
      width: "140",
      label: "入库人",
      prop: "createBy",
    },
    {
      label: "完成数量",
      prop: "completeQuantity",
      width: "140",
    },
    {
      label: "完成进度",
      prop: "completionStatus",
      dataType: "slot",
      slot: "completionStatus",
      width: "140",
    },
    {
      label: "计划开始时间",
      prop: "planStartTime",
      width: "140",
    },
    {
      label: "计划结束时间",
      prop: "planEndTime",
      width: "140",
    },
    {
      label: "实际开始时间",
      prop: "actualStartTime",
      width: "140",
    },
    {
      label: "实际结束时间",
      prop: "actualEndTime",
      width: "140",
    },
    {
      label: "操作",
      width: "200",
      align: "center",
      dataType: "action",
      fixed: "right",
      operation: [
        {
          name: "流转卡",
          clickFun: row => {
            downloadAndPrintWorkOrder(row);
          },
        },
        {
          name: "附件",
          clickFun: row => {
            openWorkOrderFiles(row);
          },
        },
        {
          name: "报工",
          clickFun: row => {
            showReportDialog(row);
          },
          disabled: row => row.planQuantity <= 0,
        },
      ],
      label: "来源",
      prop: "recordType",
      formatData: (val) => {
        return stockRecordTypeOptions.value.find(item => item.value === val)?.label || val;
      }
    },
  ]);
  
@@ -304,6 +315,27 @@
    userId: "",
    productMainId: null,
  });
  // 新增工单相关
  const addDialogVisible = ref(false);
  const addFormRef = ref(null);
  const productOptions = ref([]);
  const modelOptions = ref([]);
  const addForm = reactive({
    productId: null,
    productModelId: null,
    productName: "",
    productModelName: "",
    unit: "",
    quantity: 1,
  });
  // 新增表单校验规则
  const addFormRules = {
    productId: [{ required: true, message: "请选择产品", trigger: "change" }],
    productModelId: [{ required: true, message: "请选择规格型号", trigger: "change" }],
    quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
  };
  // 本次生产数量验证规则
  const validateQuantity = (rule, value, callback) => {
@@ -404,7 +436,8 @@
  const data = reactive({
    searchForm: {
      workOrderNo: "",
      timeStr: "",
      productName: "",
    },
  });
  const { searchForm } = toRefs(data);
@@ -438,8 +471,12 @@
  
  const getList = () => {
    tableLoading.value = true;
    const params = { ...searchForm.value, ...page };
    productWorkOrderPage(params)
    const params = { ...page };
    params.timeStr = searchForm.value.timeStr;
    params.productName = searchForm.value.productName;
    params.recordType = 2; // 默认查询 recordType 为 2(生产报工-合格入库)的数据
    params.type = '0'; // 合格入库类型
    getStockInRecordListPage(params)
      .then(res => {
        tableLoading.value = false;
        tableData.value = res.data.records;
@@ -634,6 +671,127 @@
    reportForm.userName = user ? user.nickName : "";
  };
  // 打开新增弹窗
  const openAddDialog = () => {
    // 重置表单
    addForm.productId = null;
    addForm.productModelId = null;
    addForm.productName = "";
    addForm.productModelName = "";
    addForm.unit = "";
    addForm.quantity = 1;
    modelOptions.value = [];
    // 加载产品树
    getProductOptions();
    addDialogVisible.value = true;
  };
  // 关闭新增弹窗
  const closeAddDialog = () => {
    addFormRef.value?.resetFields();
    addDialogVisible.value = false;
  };
  // 获取产品树
  const getProductOptions = () => {
    productTreeList().then((res) => {
      productOptions.value = convertIdToValue(res);
    });
  };
  // 转换产品树数据
  function 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;
    });
  }
  // 根据ID查找产品名称
  function findNodeById(nodes, productId) {
    for (let i = 0; i < nodes.length; i++) {
      if (nodes[i].value === productId) {
        return nodes[i].label;
      }
      if (nodes[i].children && nodes[i].children.length > 0) {
        const foundNode = findNodeById(nodes[i].children, productId);
        if (foundNode) {
          return foundNode;
        }
      }
    }
    return null;
  }
  // 产品选择变化
  const handleProductChange = (value) => {
    addForm.productModelId = null;
    addForm.unit = "";
    addForm.productModelName = "";
    if (value) {
      addForm.productName = findNodeById(productOptions.value, value);
      // 加载规格型号
      modelList({ id: value }).then((res) => {
        modelOptions.value = res;
      });
    } else {
      modelOptions.value = [];
    }
  };
  // 规格型号选择变化
  const handleModelChange = (value) => {
    if (value) {
      const model = modelOptions.value.find((item) => item.id === value);
      if (model) {
        addForm.unit = model.unit;
        addForm.productModelName = model.model;
      }
    } else {
      addForm.unit = "";
      addForm.productModelName = "";
    }
  };
  // 提交新增
  const handleAddSubmit = () => {
    addFormRef.value?.validate((valid) => {
      if (valid) {
        const params = {
          productId: addForm.productId,
          productModelId: addForm.productModelId,
          productName: addForm.productName,
          productModelName: addForm.productModelName,
          unit: addForm.unit,
          qualitity: addForm.quantity,
          type: "qualified",
          warnNum: 0,
          recordType: 2,
        };
        createStockInventory(params).then((res) => {
          proxy.$modal.msgSuccess("新增成功");
          closeAddDialog();
          getList();
        });
      }
    });
  };
  // 获取来源类型选项
  const fetchStockRecordTypeOptions = () => {
    findAllQualifiedStockInRecordTypeOptions()
      .then(res => {
        stockRecordTypeOptions.value = res.data;
      });
  };
  onMounted(() => {
    getList();
    // 获取用户列表
@@ -642,6 +800,8 @@
        userOptions.value = res.data;
      }
    });
    // 获取来源类型选项
    fetchStockRecordTypeOptions();
  });
</script>