src/views/productionManagement/processRoute/New.vue
@@ -1,54 +1,54 @@
<template>
  <div>
    <el-dialog
        v-model="isShow"
        title="新增工艺路线"
        width="400"
        @close="closeModal"
      v-model="isShow"
      title="新增工艺路线"
      width="800"
      @close="closeModal"
    >
      <el-form label-width="140px" :model="formState" label-position="top" ref="formRef">
      <el-form ref="formRef" label-width="140px" :model="formState" label-position="top">
        <el-form-item
            label="产品大类:"
            prop="productId"
            :rules="[
                {
                required: true,
                message: '请选择产品大类',
              }
            ]"
          label="产品名称"
          prop="selectedProducts"
          :rules="[
            {
              required: true,
              message: '请选择产品',
              trigger: 'change',
            },
          ]"
        >
          <el-tree-select
              v-model="formState.productId"
              placeholder="请选择"
              clearable
              check-strictly
              @change="getModels"
              :data="productOptions"
              :render-after-expand="false"
              style="width: 100%"
          />
          <div class="product-picker">
            <el-button type="primary" @click="showProductSelectDialog = true">
              {{ formState.selectedProducts.length ? "重新选择产品" : "选择产品" }}
            </el-button>
            <div v-if="formState.selectedProducts.length" class="product-tags">
              <el-tag
                v-for="product in formState.selectedProducts"
                :key="product.id"
                type="info"
                effect="plain"
                class="product-tag"
              >
                {{ product.productName }} / {{ product.model }}
              </el-tag>
            </div>
          </div>
        </el-form-item>
        <el-form-item
            label="规格型号:"
            prop="productModelId"
            :rules="[
                {
                required: true,
                message: '请选择规格型号',
              }
            ]"
        >
        <el-form-item label="BOM" prop="bomId">
          <el-select
              v-model="formState.productModelId"
              placeholder="请选择"
              clearable
            v-model="formState.bomId"
            placeholder="请选择BOM"
            clearable
            :disabled="formState.selectedProducts.length !== 1 || bomOptions.length === 0"
            style="width: 100%"
          >
            <el-option
                v-for="item in productModelsOptions"
                :key="item.id"
                :label="item.model"
                :value="item.id"
              v-for="item in bomOptions"
              :key="item.id"
              :label="item.bomNo || `BOM-${item.id}`"
              :value="item.id"
            />
          </el-select>
        </el-form-item>
@@ -57,6 +57,11 @@
          <el-input v-model="formState.description" type="textarea" />
        </el-form-item>
      </el-form>
      <ProductSelectDialog
        v-model="showProductSelectDialog"
        @confirm="handleProductSelect"
      />
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="handleSubmit">确认</el-button>
@@ -68,9 +73,10 @@
</template>
<script setup>
import {ref, computed, getCurrentInstance, onMounted} from "vue";
import {add} from "@/api/productionManagement/processRoute.js";
import {modelList, productTreeList} from "@/api/basicData/product.js";
import { computed, getCurrentInstance, ref } from "vue";
import { add } from "@/api/productionManagement/processRoute.js";
import { getByModel } from "@/api/productionManagement/productBom.js";
import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
const props = defineProps({
  visible: {
@@ -79,13 +85,20 @@
  },
});
const emit = defineEmits(['update:visible', 'completed']);
const emit = defineEmits(["update:visible", "completed"]);
// 响应式数据(替代选项式的 data)
const formRef = ref();
const showProductSelectDialog = ref(false);
const bomOptions = ref([]);
const formState = ref({
  productId: undefined,
  productModelId: undefined,
  description: '',
  productModelIds: "",
  productName: "",
  productModelName: "",
  selectedProducts: [],
  bomId: undefined,
  description: "",
});
const isShow = computed({
@@ -93,89 +106,141 @@
    return props.visible;
  },
  set(val) {
    emit('update:visible', val);
    emit("update:visible", val);
  },
});
const productModelsOptions = ref([])
const productOptions = ref([])
const { proxy } = getCurrentInstance();
let { proxy } = getCurrentInstance()
const resetForm = () => {
  formState.value = {
    productId: undefined,
    productModelId: undefined,
    productModelIds: "",
    productName: "",
    productModelName: "",
    selectedProducts: [],
    bomId: undefined,
    description: "",
  };
  bomOptions.value = [];
};
const closeModal = () => {
  resetForm();
  isShow.value = false;
};
const getProductOptions = () => {
  productTreeList().then((res) => {
    productOptions.value = convertIdToValue(res);
  });
};
const getModels = (value) => {
  formState.value.productId = undefined;
  formState.value.productModelId = undefined;
  productModelsOptions.value = [];
const loadBomList = async (productModelId) => {
  if (!productModelId) {
    bomOptions.value = [];
    return;
  }
  if (value) {
    formState.value.productId = findNodeById(productOptions.value, value) || undefined;
    modelList({ id: value }).then((res) => {
      productModelsOptions.value = res;
    });
  try {
    const res = await getByModel(productModelId);
    if (Array.isArray(res)) {
      bomOptions.value = res;
      return;
    }
    if (res && res.data) {
      bomOptions.value = Array.isArray(res.data) ? res.data : [res.data];
      return;
    }
    bomOptions.value = res && typeof res === "object" ? [res] : [];
  } catch (error) {
    bomOptions.value = [];
  }
};
const findNodeById = (nodes, productId) => {
  for (let i = 0; i < nodes.length; i++) {
    if (nodes[i].value === productId) {
      return nodes[i].label; // 找到节点,返回该节点的label
    }
    if (nodes[i].children && nodes[i].children.length > 0) {
      const foundNode = findNodeById(nodes[i].children, productId);
      if (foundNode) {
        return foundNode; // 在子节点中找到,直接返回(已经是label字符串)
      }
    }
const handleProductSelect = async (products) => {
  if (!products?.length) {
    return;
  }
  return null; // 没有找到节点,返回null
  formState.value.selectedProducts = products;
  formState.value.productModelIds = products.map((product) => product.id).join(",");
  formState.value.bomId = undefined;
  if (products.length === 1) {
    const product = products[0];
    formState.value.productId = product.productId;
    formState.value.productModelId = product.id;
    formState.value.productName = product.productName;
    formState.value.productModelName = product.model;
    await loadBomList(product.id);
  } else {
    formState.value.productId = undefined;
    formState.value.productModelId = undefined;
    formState.value.productName = "";
    formState.value.productModelName = "";
    bomOptions.value = [];
  }
  showProductSelectDialog.value = false;
  formRef.value?.validateField("selectedProducts");
};
function convertIdToValue(data) {
  return data.map((item) => {
    const { id, children, ...rest } = item;
    const newItem = {
      ...rest,
      value: id, // 将 id 改为 value
    };
    if (children && children.length > 0) {
      newItem.children = convertIdToValue(children);
    }
    return newItem;
  });
}
const handleSubmit = () => {
  proxy.$refs["formRef"].validate(valid => {
    if (valid) {
      add(formState.value).then(res => {
        // 关闭模态框
        isShow.value = false;
        // 告知父组件已完成
        emit('completed');
        proxy.$modal.msgSuccess("提交成功");
      })
  formRef.value.validate((valid) => {
    if (!valid) {
      return;
    }
  })
};
    if (!formState.value.selectedProducts.length) {
      proxy.$modal.msgError("请选择产品");
      return;
    }
    add({
      productId: formState.value.selectedProducts.length === 1
        ? formState.value.selectedProducts[0].productId
        : undefined,
      productModelId: formState.value.selectedProducts.length === 1
        ? formState.value.selectedProducts[0].id
        : undefined,
      productModelIds: formState.value.productModelIds,
      productName: formState.value.selectedProducts.length === 1
        ? formState.value.selectedProducts[0].productName
        : undefined,
      productModelName: formState.value.selectedProducts.length === 1
        ? formState.value.selectedProducts[0].model
        : undefined,
      bomId: formState.value.selectedProducts.length === 1 ? formState.value.bomId : undefined,
      description: formState.value.description,
    })
      .then(() => {
        isShow.value = false;
        emit("completed");
        proxy.$modal.msgSuccess("提交成功");
        resetForm();
      })
      .catch(() => {});
  });
};
defineExpose({
  closeModal,
  handleSubmit,
  isShow,
});
onMounted(() => {
  getProductOptions()
})
</script>
<style scoped>
.product-picker {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-start;
}
.product-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.product-tag {
  max-width: 220px;
}
</style>