gaoluyang
昨天 cfba74a9db1b77f8e0b5f52fe15c8a1c4bfcaa76
src/views/productionManagement/processRoute/Edit.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="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,105 +73,195 @@
</template>
<script setup>
import {ref, computed, getCurrentInstance, onMounted} from "vue";
import {update} from "@/api/productionManagement/processRoute.js";
import {modelList, productTreeList} from "@/api/basicData/product.js";
import { computed, getCurrentInstance, nextTick, ref, watch } from "vue";
import { update } from "@/api/productionManagement/processRoute.js";
import { getByModelList } from "@/api/productionManagement/productBom.js";
import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
const props = defineProps({
  visible: {
    type: Boolean,
    required: true,
  },
  record: {
    type: Object,
    required: true,
  }
  },
});
const emit = defineEmits(['update:visible', 'completed']);
const emit = defineEmits(["update:visible", "completed"]);
// 响应式数据(替代选项式的 data)
const formState = ref({});
const formRef = ref();
const showProductSelectDialog = ref(false);
const bomOptions = ref([]);
const formState = ref(createDefaultFormState());
const isShow = computed({
  get() {
    return props.visible;
  },
  set(val) {
    emit('update:visible', val);
    emit("update:visible", val);
  },
});
let { proxy } = getCurrentInstance()
const productModelsOptions = ref([])
const productOptions = ref([])
const { proxy } = getCurrentInstance();
const splitFieldValues = value =>
  String(value || "")
    .split(/[,\uff0c]/)
    .map(item => item.trim())
    .filter(Boolean);
function createDefaultFormState() {
  return {
    id: undefined,
    productId: undefined,
    productModelId: undefined,
    productModelIds: "",
    productName: "",
    productModelName: "",
    selectedProducts: [],
    bomId: undefined,
    description: "",
  };
}
const resetForm = () => {
  formState.value = createDefaultFormState();
  bomOptions.value = [];
};
const closeModal = () => {
  resetForm();
  isShow.value = false;
};
const setFormData = () => {
  formState.value = props.record
}
const loadBomList = async productModelIds => {
  if (!productModelIds?.length) {
    bomOptions.value = [];
    return;
  }
const getProductOptions = () => {
  productTreeList().then((res) => {
    productOptions.value = convertIdToValue(res);
  });
};
const getModels = (value) => {
  formState.value.productModelId = undefined;
  productModelsOptions.value = [];
  if (value) {
    modelList({ id: value }).then((res) => {
      productModelsOptions.value = res;
    });
  try {
    const res = await getByModelList(productModelIds);
    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字符串)
      }
    }
  }
  return null; // 没有找到节点,返回null
const buildSelectedProducts = record => {
  const ids = splitFieldValues(record.productModelIds || record.productModelId);
  const productNames = splitFieldValues(record.productName);
  const modelNames = splitFieldValues(record.model || record.productModelName);
  const productIds = splitFieldValues(record.productIds || record.productId);
  return ids.map((id, index) => ({
    id,
    productId: productIds[index] || undefined,
    productName: productNames[index] || record.productName || "",
    model: modelNames[index] || record.model || record.productModelName || "",
  }));
};
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);
    }
const setFormData = async () => {
  if (!props.record) return;
    return newItem;
  });
}
  const selectedProducts = buildSelectedProducts(props.record);
  const productModelIds = props.record.productModelIds
    || (props.record.productModelId ? String(props.record.productModelId) : "");
  formState.value = {
    id: props.record.id,
    productId: props.record.productId,
    productModelId: props.record.productModelId,
    productModelIds,
    productName: props.record.productName || "",
    productModelName: props.record.model || props.record.productModelName || "",
    selectedProducts,
    bomId: props.record.bomId,
    description: props.record.description || "",
  };
  const ids = productModelIds
    ? splitFieldValues(productModelIds)
    : [];
  await loadBomList(ids);
};
const handleProductSelect = async products => {
  if (!products?.length) {
    return;
  }
  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 = "";
    await loadBomList(products.map(product => product.id));
  }
  showProductSelectDialog.value = false;
  formRef.value?.validateField("selectedProducts");
};
const handleSubmit = () => {
  proxy.$refs["formRef"].validate(valid => {
    if (valid) {
      update(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;
    }
    update({
      ...props.record,
      id: formState.value.id,
      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.bomId,
      description: formState.value.description,
    }).then(() => {
      isShow.value = false;
      emit("completed");
      proxy.$modal.msgSuccess("提交成功");
      resetForm();
    });
  });
};
defineExpose({
@@ -175,12 +270,34 @@
  isShow,
});
onMounted(() => {
  getProductOptions()
  getModels(props.record.productId)
  nextTick(() => {
    setFormData()
  });
})
watch(
  () => [props.visible, props.record?.id],
  ([visible]) => {
    if (visible && props.record?.id) {
      nextTick(() => {
        setFormData();
      });
    }
  },
  { immediate: true }
);
</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>