Selaa lähdekoodia

fix(s0): preserve production line organization rehydration

Keep edit-form organization and domain values during record rehydration.

Show historical organization values for invalid company and factory references.

Block saves when production line records are not linked to valid company and factory options.
YY968XX 3 viikkoa sitten
vanhempi
commit
b383e931a1
1 muutettua tiedostoa jossa 48 lisäystä ja 19 poistoa
  1. 48 19
      Web/src/views/aidop/s0/manufacturing/ProductionLineList.vue

+ 48 - 19
Web/src/views/aidop/s0/manufacturing/ProductionLineList.vue

@@ -79,6 +79,12 @@
 						<el-form-item label="公司" prop="companyRefId">
 							<el-select v-model="form.companyRefId" filterable style="width: 100%" @change="onFormCompanyChange">
 								<el-option v-for="item in companyOptions" :key="item.id" :label="item.name || item.code || `${item.id}`" :value="item.id" />
+								<el-option
+									v-if="form.companyRefId != null && form.companyRefId !== '' && !companyOptions.some((o) => o.id === String(form.companyRefId))"
+									:key="`__compat_company_${form.companyRefId}`"
+									:label="`未关联组织(历史值:${form.companyRefId})`"
+									:value="form.companyRefId"
+								/>
 							</el-select>
 						</el-form-item>
 					</el-col>
@@ -86,6 +92,12 @@
 						<el-form-item label="工厂" prop="factoryRefId">
 							<el-select v-model="form.factoryRefId" filterable style="width: 100%" @change="syncDomainFromFactory">
 								<el-option v-for="item in formFactories" :key="item.id" :label="item.name || item.code || `${item.id}`" :value="item.id" />
+								<el-option
+									v-if="form.factoryRefId != null && form.factoryRefId !== '' && !factoryOptions.some((o) => o.id === String(form.factoryRefId))"
+									:key="`__compat_factory_${form.factoryRefId}`"
+									:label="`未关联组织(历史值:${form.factoryRefId})`"
+									:value="form.factoryRefId"
+								/>
 							</el-select>
 						</el-form-item>
 					</el-col>
@@ -172,7 +184,7 @@
 </template>
 
 <script setup lang="ts" name="aidopS0MfgProductionLine">
-import { computed, onMounted, reactive, ref, watch } from 'vue';
+import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue';
 import { useRoute } from 'vue-router';
 import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus';
 import AidopDemoShell from '../../components/AidopDemoShell.vue';
@@ -184,7 +196,7 @@ import DictDataMaintainPanel from '../sales/components/DictDataMaintainPanel.vue
 const route = useRoute();
 const pageTitle = computed(() => (route.meta?.title as string) || '生产线编码清单');
 
-const { companyOptions, loadOrgs, factoriesForCompany } = useS0MfgOrgScope();
+const { companyOptions, factoryOptions, loadOrgs, factoriesForCompany } = useS0MfgOrgScope();
 const queryFactories = computed(() => factoriesForCompany(query.companyRefId));
 const formFactories = computed(() => factoriesForCompany(form.companyRefId));
 
@@ -214,6 +226,8 @@ const lineLocationOptions = ref<OptionItem[]>([]);
 const configDialogVisible = ref(false);
 const configActiveTab = ref('lineType');
 
+const isRehydrating = ref(false);
+
 async function loadDictOptionsAll() {
 	const [lineType, lineCategory, lineLocation] = await Promise.all([
 		loadDictOptions('s0_line_type'),
@@ -256,6 +270,7 @@ watch(
 watch(
 	() => form.companyRefId,
 	() => {
+		if (isRehydrating.value) return;
 		if (!formFactories.value.some((x) => x.id === form.factoryRefId)) {
 			form.factoryRefId = undefined;
 			form.domain = '';
@@ -347,28 +362,42 @@ async function openEdit(row: S0LineMasterRow) {
 	editingId.value = row.id;
 	dialogTitle.value = `编辑 ${row.line}`;
 	const detail = await s0MfgProductionLinesApi.get(row.id);
-	Object.assign(form, {
-		companyRefId: detail.companyRefId,
-		factoryRefId: detail.factoryRefId,
-		domain: detail.domain || '',
-		line: detail.line || '',
-		describe: (detail as any).describe ?? '',
-		lineType: detail.lineType || '',
-		lineCategory: detail.lineCategory || '',
-		location: detail.location || '',
-		workshop: detail.workshop || '',
-		vLocation: detail.vLocation || '',
-		location2: detail.location2 || '',
-		location3: detail.location3 || '',
-		pickingLocation: detail.pickingLocation || '',
-		midLocation: detail.midLocation || '',
-		isActive: (detail as any).isActive !== false,
-	});
+	isRehydrating.value = true;
+	try {
+		Object.assign(form, {
+			companyRefId: detail.companyRefId,
+			factoryRefId: detail.factoryRefId,
+			domain: detail.domain || '',
+			line: detail.line || '',
+			describe: (detail as any).describe ?? '',
+			lineType: detail.lineType || '',
+			lineCategory: detail.lineCategory || '',
+			location: detail.location || '',
+			workshop: detail.workshop || '',
+			vLocation: detail.vLocation || '',
+			location2: detail.location2 || '',
+			location3: detail.location3 || '',
+			pickingLocation: detail.pickingLocation || '',
+			midLocation: detail.midLocation || '',
+			isActive: (detail as any).isActive !== false,
+		});
+		await nextTick();
+	} finally {
+		isRehydrating.value = false;
+	}
 	dialogVisible.value = true;
 }
 
 async function submitForm() {
 	await formRef.value?.validate();
+
+	const companyHit = companyOptions.value.some((o) => o.id === String(form.companyRefId));
+	const factoryHit = factoryOptions.value.some((o) => o.id === String(form.factoryRefId));
+	if (!companyHit || !factoryHit) {
+		ElMessage.warning('当前记录未关联有效公司/工厂,请先选择公司和工厂后再保存。');
+		return;
+	}
+
 	const payload: S0LineMasterUpsert = {
 		companyRefId: form.companyRefId,
 		factoryRefId: form.factoryRefId,