gaoluyang
17 小时以前 cfba74a9db1b77f8e0b5f52fe15c8a1c4bfcaa76
种形式想
1.工艺路线编辑的时候可以多选产品
已修改2个文件
311 ■■■■■ 文件已修改
src/views/productionManagement/processRoute/Edit.vue 309 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/processRoute/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/processRoute/Edit.vue
@@ -3,44 +3,45 @@
    <el-dialog
        v-model="isShow"
        title="编辑工艺路线"
        width="400"
      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="productModelId"
          prop="selectedProducts"
            :rules="[
                {
                required: true,
                message: '请选择产品',
                trigger: 'change',
              }
            },
            ]"
        >
          <div class="product-picker">
          <el-button type="primary" @click="showProductSelectDialog = true">
            {{ formState.productName && formState.productModelName
              ? `${formState.productName} - ${formState.productModelName}`
              : '选择产品' }}
              {{ 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="BOM"
            prop="bomId"
            :rules="[
                {
                required: true,
                message: '请选择BOM',
                trigger: 'change',
              }
            ]"
        >
        <el-form-item label="BOM" prop="bomId">
          <el-select
              v-model="formState.bomId"
              placeholder="请选择BOM"
              clearable
              :disabled="!formState.productModelId || bomOptions.length === 0"
            :disabled="bomOptions.length === 0"
              style="width: 100%"
          >
            <el-option
@@ -57,11 +58,9 @@
        </el-form-item>
      </el-form>
      
      <!-- 产品选择弹窗 -->
      <ProductSelectDialog
          v-model="showProductSelectDialog"
          @confirm="handleProductSelect"
          single
      />
      <template #footer>
        <div class="dialog-footer">
@@ -74,9 +73,9 @@
</template>
<script setup>
import {ref, computed, getCurrentInstance, onMounted, nextTick, watch} from "vue";
import { computed, getCurrentInstance, nextTick, ref, watch } from "vue";
import {update} from "@/api/productionManagement/processRoute.js";
import {getByModel} from "@/api/productionManagement/productBom.js";
import { getByModelList } from "@/api/productionManagement/productBom.js";
import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
const props = defineProps({
@@ -84,148 +83,185 @@
    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({
  productId: undefined,
  productModelId: undefined,
  productName: "",
  productModelName: "",
  bomId: undefined,
  description: '',
});
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);
  },
});
const showProductSelectDialog = ref(false);
const bomOptions = ref([]);
const { proxy } = getCurrentInstance();
let { 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 = () => {
  if (props.record) {
    formState.value = {
      ...props.record,
      productId: props.record.productId,
      productModelId: props.record.productModelId,
      productName: props.record.productName || "",
      // 注意:record中的字段是model,需要映射到productModelName
      productModelName: props.record.model || props.record.productModelName || "",
      bomId: props.record.bomId,
      description: props.record.description || '',
    };
    // 如果有产品型号ID,加载BOM列表
    if (props.record.productModelId) {
      loadBomList(props.record.productModelId);
    }
  }
}
// 加载BOM列表
const loadBomList = async (productModelId) => {
  if (!productModelId) {
const loadBomList = async productModelIds => {
  if (!productModelIds?.length) {
    bomOptions.value = [];
    return;
  }
  try {
    const res = await getByModel(productModelId);
    // 处理返回的BOM数据:可能是数组、对象或包含data字段
    let bomList = [];
    const res = await getByModelList(productModelIds);
    if (Array.isArray(res)) {
      bomList = res;
    } else if (res && res.data) {
      bomList = Array.isArray(res.data) ? res.data : [res.data];
    } else if (res && typeof res === 'object') {
      bomList = [res];
      bomOptions.value = res;
      return;
    }
    bomOptions.value = bomList;
    if (res && res.data) {
      bomOptions.value = Array.isArray(res.data) ? res.data : [res.data];
      return;
    }
    bomOptions.value = res && typeof res === "object" ? [res] : [];
  } catch (error) {
    console.error("加载BOM列表失败:", error);
    bomOptions.value = [];
  }
};
// 产品选择处理
const handleProductSelect = async (products) => {
  if (products && products.length > 0) {
    const product = products[0];
    // 先查询BOM列表(必选)
    try {
      const res = await getByModel(product.id);
      // 处理返回的BOM数据:可能是数组、对象或包含data字段
      let bomList = [];
      if (Array.isArray(res)) {
        bomList = res;
      } else if (res && res.data) {
        bomList = Array.isArray(res.data) ? res.data : [res.data];
      } else if (res && typeof res === 'object') {
        bomList = [res];
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 || "",
  }));
};
const setFormData = async () => {
  if (!props.record) return;
  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;
      }
      
      if (bomList.length > 0) {
  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;
        // 如果当前选择的BOM不在新列表中,则重置BOM选择
        const currentBomExists = bomList.some(bom => bom.id === formState.value.bomId);
        if (!currentBomExists) {
          formState.value.bomId = undefined;
        }
        bomOptions.value = bomList;
        showProductSelectDialog.value = false;
        // 触发表单验证更新
        proxy.$refs["formRef"]?.validateField('productModelId');
    await loadBomList([product.id]);
      } else {
        proxy.$modal.msgError("该产品没有BOM,请先创建BOM");
    formState.value.productId = undefined;
    formState.value.productModelId = undefined;
    formState.value.productName = "";
    formState.value.productModelName = "";
    await loadBomList(products.map(product => product.id));
      }
    } catch (error) {
      // 如果接口返回404或其他错误,说明没有BOM
      proxy.$modal.msgError("该产品没有BOM,请先创建BOM");
    }
  }
  showProductSelectDialog.value = false;
  formRef.value?.validateField("selectedProducts");
};
const handleSubmit = () => {
  proxy.$refs["formRef"].validate(valid => {
    if (valid) {
      // 验证是否选择了产品和BOM
      if (!formState.value.productModelId) {
  formRef.value.validate(valid => {
    if (!valid) {
      return;
    }
    if (!formState.value.selectedProducts.length) {
        proxy.$modal.msgError("请选择产品");
        return;
      }
      if (!formState.value.bomId) {
        proxy.$modal.msgError("请选择BOM");
        return;
      }
      update(formState.value).then(res => {
        // 关闭模态框
    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');
      emit("completed");
        proxy.$modal.msgSuccess("提交成功");
      })
    }
  })
      resetForm();
    });
  });
};
defineExpose({
@@ -234,19 +270,34 @@
  isShow,
});
// 监听弹窗打开,初始化表单数据
watch(() => props.visible, (visible) => {
  if (visible && props.record) {
watch(
  () => [props.visible, props.record?.id],
  ([visible]) => {
    if (visible && props.record?.id) {
    nextTick(() => {
      setFormData();
    });
  }
}, { immediate: true });
onMounted(() => {
  if (props.visible && props.record) {
    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>
src/views/productionManagement/processRoute/index.vue
@@ -162,8 +162,8 @@
};
const showEditModal = (row) => {
  isShowEditModal.value = true
  record.value = row
  isShowEditModal.value = true
};
const showItemModal = (row) => {