From cfba74a9db1b77f8e0b5f52fe15c8a1c4bfcaa76 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 16 四月 2026 13:01:19 +0800
Subject: [PATCH] 种形式想 1.工艺路线编辑的时候可以多选产品
---
src/views/productionManagement/processRoute/index.vue | 2
src/views/productionManagement/processRoute/Edit.vue | 385 +++++++++++++++++++++++++++++++-----------------------
2 files changed, 219 insertions(+), 168 deletions(-)
diff --git a/src/views/productionManagement/processRoute/Edit.vue b/src/views/productionManagement/processRoute/Edit.vue
index 0c0fe0f..4e519c3 100644
--- a/src/views/productionManagement/processRoute/Edit.vue
+++ b/src/views/productionManagement/processRoute/Edit.vue
@@ -1,53 +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="productModelId"
- :rules="[
- {
- required: true,
- message: '璇烽�夋嫨浜у搧',
- trigger: 'change',
- }
- ]"
+ label="浜у搧鍚嶇О"
+ prop="selectedProducts"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨浜у搧',
+ trigger: 'change',
+ },
+ ]"
>
- <el-button type="primary" @click="showProductSelectDialog = true">
- {{ formState.productName && formState.productModelName
- ? `${formState.productName} - ${formState.productModelName}`
- : '閫夋嫨浜у搧' }}
- </el-button>
+ <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="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"
- style="width: 100%"
+ v-model="formState.bomId"
+ placeholder="璇烽�夋嫨BOM"
+ clearable
+ :disabled="bomOptions.length === 0"
+ style="width: 100%"
>
<el-option
- v-for="item in bomOptions"
- :key="item.id"
- :label="item.bomNo || `BOM-${item.id}`"
- :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>
@@ -56,12 +57,10 @@
<el-input v-model="formState.description" type="textarea" />
</el-form-item>
</el-form>
-
- <!-- 浜у搧閫夋嫨寮圭獥 -->
+
<ProductSelectDialog
- v-model="showProductSelectDialog"
- @confirm="handleProductSelect"
- single
+ v-model="showProductSelectDialog"
+ @confirm="handleProductSelect"
/>
<template #footer>
<div class="dialog-footer">
@@ -74,9 +73,9 @@
</template>
<script setup>
-import {ref, computed, getCurrentInstance, onMounted, nextTick, watch} from "vue";
-import {update} from "@/api/productionManagement/processRoute.js";
-import {getByModel} from "@/api/productionManagement/productBom.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({
@@ -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 || "",
- // 娉ㄦ剰锛歳ecord涓殑瀛楁鏄痬odel锛岄渶瑕佹槧灏勫埌productModelName
- productModelName: props.record.model || props.record.productModelName || "",
- bomId: props.record.bomId,
- description: props.record.description || '',
- };
- // 濡傛灉鏈変骇鍝佸瀷鍙稩D锛屽姞杞紹OM鍒楄〃
- 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);
- // 澶勭悊杩斿洖鐨凚OM鏁版嵁锛氬彲鑳芥槸鏁扮粍銆佸璞℃垨鍖呭惈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];
- // 鍏堟煡璇OM鍒楄〃锛堝繀閫夛級
- try {
- const res = await getByModel(product.id);
- // 澶勭悊杩斿洖鐨凚OM鏁版嵁锛氬彲鑳芥槸鏁扮粍銆佸璞℃垨鍖呭惈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];
- }
-
- if (bomList.length > 0) {
- formState.value.productModelId = product.id;
- formState.value.productName = product.productName;
- formState.value.productModelName = product.model;
- // 濡傛灉褰撳墠閫夋嫨鐨凚OM涓嶅湪鏂板垪琛ㄤ腑锛屽垯閲嶇疆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');
- } else {
- proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
- }
- } catch (error) {
- // 濡傛灉鎺ュ彛杩斿洖404鎴栧叾浠栭敊璇紝璇存槑娌℃湁BOM
- proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
- }
+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;
}
+
+ 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) {
- // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝佸拰BOM
- if (!formState.value.productModelId) {
- proxy.$modal.msgError("璇烽�夋嫨浜у搧");
- return;
- }
- if (!formState.value.bomId) {
- proxy.$modal.msgError("璇烽�夋嫨BOM");
- return;
- }
- 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({
@@ -234,19 +270,34 @@
isShow,
});
-
-// 鐩戝惉寮圭獥鎵撳紑锛屽垵濮嬪寲琛ㄥ崟鏁版嵁
-watch(() => props.visible, (visible) => {
- if (visible && props.record) {
- nextTick(() => {
- setFormData();
- });
- }
-}, { immediate: true });
-
-onMounted(() => {
- if (props.visible && props.record) {
- 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>
diff --git a/src/views/productionManagement/processRoute/index.vue b/src/views/productionManagement/processRoute/index.vue
index 41103f9..99d50fe 100644
--- a/src/views/productionManagement/processRoute/index.vue
+++ b/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) => {
--
Gitblit v1.9.3