From 346a988f537228ae44731cd31007f1412b482e83 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 19 十月 2026 16:32:10 +0800
Subject: [PATCH] refactor(mdm): 移除物料主数据中废弃的字段配置

---
 src/views/mes/qc/seedQuality/record.vue |  155 +++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 124 insertions(+), 31 deletions(-)

diff --git a/src/views/mes/qc/seedQuality/record.vue b/src/views/mes/qc/seedQuality/record.vue
index a03ccd8..15396a1 100644
--- a/src/views/mes/qc/seedQuality/record.vue
+++ b/src/views/mes/qc/seedQuality/record.vue
@@ -10,12 +10,16 @@
   getSeedQualityPage,
   getSeedQualityIndicators,
   getSeedQualityActions,
+  getSeedIndicatorRanges,
   retestSeedQuality,
+  resolveSeedRetestScope,
+  submitSeedRetestScope,
   approveSeedQuality,
   approveSeedQualityBatch,
   type SeedQualityRecord,
   type SeedQualityIndicator,
   type SeedQualityAction,
+  type SeedRetestScope,
 } from '#/api/mes/qc/seedQuality';
 
 const records = ref<SeedQualityRecord[]>([]);
@@ -37,13 +41,13 @@
 );
 const { hasAccessByCodes } = useAccess();
 const workflowLabels: Record<number, string> = {
-  10: '寰呭妫�', 20: '寰呭姞宸ラ儴瀹℃壒', 30: '寰呭叕鍙歌川妫�瀹℃壒',
-  40: '宸叉斁琛�', 50: '寰呭姞宸ラ儴涓嶅悎鏍艰瘎瀹�', 60: '寰呭叕鍙镐笉鍚堟牸瀹℃壒', 70: '宸叉姤搴�',
+  10: '寰呭妫�', 20: '寰呭垵妫�瀹℃牳', 25: '寰呭垵妫�涓嶅悎鏍煎鐞�', 30: '寰呭妫�瀹℃牳',
+  40: '宸叉斁琛�', 50: '鍒濇椹冲洖寰呴噸妫�', 60: '寰呭妫�涓嶅悎鏍煎鐞�', 70: '宸叉姤搴�',
 };
 const actionLabels: Record<string, string> = {
-  INITIAL: '鍒濇', RETEST: '澶嶆', PROCESS_APPROVE: '鍔犲伐閮ㄩ�氳繃',
-  PROCESS_REJECT: '鍔犲伐閮ㄩ┏鍥�', COMPANY_APPROVE: '鍏徃璐ㄦ閫氳繃',
-  COMPANY_REJECT: '鍏徃璐ㄦ椹冲洖',
+  INITIAL: '鍒濇', INITIAL_RECHECK: '閲嶆柊鍒濇', RETEST: '澶嶆', PROCESS_APPROVE: '鍒濇瀹℃牳閫氳繃',
+  PROCESS_REJECT: '鍒濇瀹℃牳椹冲洖', COMPANY_APPROVE: '澶嶆瀹℃牳閫氳繃',
+  COMPANY_REJECT: '澶嶆瀹℃牳椹冲洖',
 };
 const indicatorLabels: Record<string, string> = {
   purity: '绾害', cleanliness: '鍑�搴�', germination_rate: '鍙戣娊鐜�', moisture: '姘村垎',
@@ -73,6 +77,13 @@
 const retestBusy = ref(false);
 const retestIndicators = ref<SeedQualityIndicator[]>([]);
 const retestReason = ref('');
+const scopeOpen = ref(false);
+const scopeType = ref<'PALLET' | 'BATCH'>('PALLET');
+const scopeCode = ref('');
+const retestScope = ref<SeedRetestScope>();
+const scopeStatus = ref<10 | 50>(10);
+const scopeBusy = ref(false);
+const scopeIds = computed(() => scopeStatus.value === 10 ? retestScope.value?.retestIds || [] : retestScope.value?.initialRecheckIds || []);
 const reviewOpen = ref(false);
 const reviewBusy = ref(false);
 const reviewStage = ref<'process' | 'company'>('process');
@@ -84,7 +95,7 @@
 const selectableStage = computed(() => {
   if (!selectedRows.value.length) return undefined;
   if (!selectedRows.value.every((record) => record.workflowStatus === selectedRows.value[0]?.workflowStatus)) return undefined;
-  if (selectedRows.value.every((record) => [20, 50].includes(record.workflowStatus))) return 'process';
+  if (selectedRows.value.every((record) => [20, 25].includes(record.workflowStatus))) return 'process';
   if (selectedRows.value.every((record) => [30, 60].includes(record.workflowStatus))) return 'company';
   return undefined;
 });
@@ -92,13 +103,65 @@
 async function openRetest(record: SeedQualityRecord) {
   activeRecord.value = record;
   try {
-    retestIndicators.value = await getSeedQualityIndicators(record.id);
+    const previous = await getSeedQualityIndicators(record.id);
+    const ranges = await getSeedIndicatorRanges().catch(() => []);
+    retestIndicators.value = previous.map((item) => {
+      const range = ranges.find((row) => row.indicatorCode === item.indicatorCode);
+      return { ...item, minValue: range ? Number(range.minValue) : Number(item.minValue), maxValue: range ? Number(range.maxValue) : Number(item.maxValue) };
+    });
     if (retestIndicators.value.length !== 4) throw new Error('璐ㄦ鎸囨爣涓嶅畬鏁�');
+    retestIndicators.value = retestIndicators.value.map((item) => ({ ...item, value: undefined }));
     retestReason.value = '';
     retestOpen.value = true;
   } catch (error) {
     message.error((error as Error).message || '璇诲彇璐ㄦ鎸囨爣澶辫触');
   }
+}
+function openScopeRetest() {
+  scopeOpen.value = true; retestScope.value = undefined; scopeCode.value = ''; retestReason.value = '';
+}
+async function identifyScope() {
+  if (!scopeCode.value.trim()) { message.warning('璇锋壂鎻忔垨杈撳叆鎵樼洏鐮� / 鐢熶骇鎵规鐮�'); return; }
+  scopeBusy.value = true; retestScope.value = undefined;
+  try {
+    const data = await resolveSeedRetestScope(scopeCode.value.trim(), scopeType.value);
+    if (!data.retestIds.length && !data.initialRecheckIds.length) {
+      const pending = [
+        data.pendingProcessCount ? `${data.pendingProcessCount} 鏉″緟鍒濇瀹℃牳鎴栦笉鍚堟牸澶勭悊` : '',
+        data.pendingCompanyCount ? `${data.pendingCompanyCount} 鏉″緟澶嶆瀹℃牳鎴栦笉鍚堟牸澶勭悊` : '',
+      ].filter(Boolean).join('銆�');
+      throw new Error(pending
+        ? `褰撳墠鑼冨洿鏈�${pending}锛岃鍏堝畬鎴愬搴斿鏍告垨澶勭悊`
+        : '褰撳墠鑼冨洿娌℃湁寰呭妫�鎴栧緟閲嶆柊鍒濇鐨勮鐮�');
+    }
+    retestScope.value = data; scopeStatus.value = data.retestIds.length ? 10 : 50;
+    const ranges = await getSeedIndicatorRanges().catch(() => []);
+    retestIndicators.value = Object.entries(indicatorLabels).map(([indicatorCode]) => {
+      const range = ranges.find((row) => row.indicatorCode === indicatorCode);
+      return { indicatorCode, value: undefined, minValue: range ? Number(range.minValue) : undefined as unknown as number,
+        maxValue: range ? Number(range.maxValue) : undefined as unknown as number };
+    });
+    retestReason.value = '';
+  } catch (error) { message.error((error as Error).message || '璇嗗埆澶辫触'); }
+  finally { scopeBusy.value = false; }
+}
+async function saveScopeRetest() {
+  if (!retestScope.value || !scopeIds.value.length) return;
+  if (retestIndicators.value.some(item => item.value === undefined || item.value === null || item.minValue === undefined || item.maxValue === undefined
+    || Number(item.minValue) < 0 || Number(item.maxValue) > 100 || Number(item.minValue) > Number(item.maxValue))) {
+    message.warning('璇峰~鍐欏洓椤规寚鏍囩殑瀹炴祴鍊间笌鏈鍚堟牸鑼冨洿'); return;
+  }
+  const passed = retestIndicators.value.every(item => Number(item.value) >= Number(item.minValue) && Number(item.value) <= Number(item.maxValue));
+  if (!passed && !retestReason.value.trim()) { message.warning('涓嶅悎鏍艰濉啓鍘熷洜'); return; }
+  scopeBusy.value = true;
+  try {
+    const result = await submitSeedRetestScope({ code: retestScope.value.code, scanType: retestScope.value.scanType, workflowStatus: scopeStatus.value,
+      qualityIds: scopeIds.value, reason: retestReason.value.trim(), indicators: retestIndicators.value.map(item => ({
+        code: item.indicatorCode, value: Number(item.value), minValue: Number(item.minValue), maxValue: Number(item.maxValue),
+      })) });
+    message.success(`宸插畬鎴� ${result.processedCount} 琚嬭川妫�`); scopeOpen.value = false; refreshAll();
+  } catch (error) { message.error((error as Error).message || '鎵归噺璐ㄦ澶辫触'); retestScope.value = undefined; }
+  finally { scopeBusy.value = false; }
 }
 async function saveRetest() {
   const record = activeRecord.value;
@@ -106,27 +169,30 @@
   if (retestIndicators.value.some((item) => item.value === null || item.value === undefined
     || item.minValue === null || item.minValue === undefined || item.maxValue === null || item.maxValue === undefined
     || Number(item.minValue) > Number(item.maxValue))) {
-    message.warning('璇峰~鍐欏畬鏁寸殑瀹炴祴鍊煎強鏈夋晥涓婁笅闄�');
+    message.warning('璇峰~鍐欏畬鏁寸殑瀹炴祴鍊�');
     return;
   }
   const passed = retestIndicators.value.every((item) =>
     Number(item.value) >= Number(item.minValue) && Number(item.value) <= Number(item.maxValue));
   if (!passed && !retestReason.value.trim()) {
-    message.warning('澶嶆涓嶅悎鏍艰濉啓鍘熷洜');
+    message.warning('妫�楠屼笉鍚堟牸璇峰~鍐欏師鍥�');
     return;
   }
   retestBusy.value = true;
   try {
-    await retestSeedQuality(record.id, {
-      code: record.code,
+    const payload = {
       reason: retestReason.value.trim(),
       indicators: retestIndicators.value.map((item) => ({
         code: item.indicatorCode, value: Number(item.value),
         minValue: Number(item.minValue), maxValue: Number(item.maxValue),
       })),
-    });
-    message.success(passed ? '澶嶆鍚堟牸锛屽緟鍔犲伐閮ㄥ鎵�' : '澶嶆涓嶅悎鏍硷紝寰呭姞宸ラ儴璇勫');
+    };
+    await retestSeedQuality(record.id, { ...payload, code: record.code });
+    message.success(record.workflowStatus === 50
+      ? passed ? '閲嶆柊鍒濇鍚堟牸锛屽緟鍒濇瀹℃牳' : '閲嶆柊鍒濇涓嶅悎鏍硷紝寰呬笉鍚堟牸澶勭悊'
+      : passed ? '澶嶆鍚堟牸锛屽緟澶嶆瀹℃牳' : '澶嶆涓嶅悎鏍硷紝寰呬笉鍚堟牸澶勭悊');
     retestOpen.value = false;
+    selectedIds.value = [];
     refreshAll();
   } catch (error) {
     message.error((error as Error).message || '澶嶆鎻愪氦澶辫触');
@@ -154,8 +220,8 @@
 }
 async function saveReview() {
   if (!reviewIds.value.length) return;
-  if (!reviewOpinion.value.trim()) {
-    message.warning('璇峰~鍐欏鎵规剰瑙�');
+  if (!reviewApproved.value && !reviewOpinion.value.trim()) {
+    message.warning('椹冲洖鏃惰濉啓瀹℃壒鎰忚');
     return;
   }
   reviewBusy.value = true;
@@ -254,7 +320,7 @@
       <div class="header-copy">
         <div class="eyebrow">MES / 璐ㄩ噺绠$悊</div>
         <h1>璐ㄦ璁板綍</h1>
-        <p>璺熻釜鍒濇銆佸妫�銆佸姞宸ラ儴瀹℃壒鍜屽叕鍙歌川妫�瀹℃壒锛涘畬鎴愬鎵瑰悗鎵嶆祦杞簱瀛�</p>
+        <p>鍒濇瀹℃牳閫氳繃鍚庤繘琛屽妫�锛屽妫�瀹℃牳閫氳繃鍚庢墠鏀捐鍏ュ簱鎴栧缃笉鍚堟牸鍝�</p>
       </div>
       <div class="header-badge">
         <span class="badge-pulse" />
@@ -291,7 +357,8 @@
           <span class="count-chip">{{ total.toLocaleString() }} 鏉�</span>
         </div>
         <div class="filters">
-          <a-button v-if="selectableStage && hasAccessByCodes([`mes:qc-seed-quality:${selectableStage === 'process' ? 'process-approve' : 'company-approve'}`])" @click="openBatchReview">鎵归噺{{ selectableStage === 'process' ? '鍔犲伐閮ㄥ鎵�' : '鍏徃璐ㄦ瀹℃壒' }}锛坽{ selectedRows.length }}锛�</a-button>
+          <a-button v-if="hasAccessByCodes(['mes:qc-seed-quality:retest'])" type="primary" @click="openScopeRetest">鎸夋墭鐩� / 鎵规鎵归噺澶嶆</a-button>
+          <a-button v-if="selectableStage && hasAccessByCodes([`mes:qc-seed-quality:${selectableStage === 'process' ? 'process-approve' : 'company-approve'}`])" @click="openBatchReview">鎵归噺{{ selectableStage === 'process' ? selectedRows[0]?.workflowStatus === 25 ? '鍒濇涓嶅悎鏍煎鐞�' : '鍒濇瀹℃牳' : selectedRows[0]?.workflowStatus === 60 ? '澶嶆涓嶅悎鏍煎鐞�' : '澶嶆瀹℃牳' }}锛坽{ selectedRows.length }}锛�</a-button>
           <a-input v-model:value="code" allow-clear placeholder="琚嬬爜" @press-enter="searchRecords">
             <template #prefix><IconifyIcon icon="ep:box" /></template>
           </a-input>
@@ -320,7 +387,7 @@
         :data-source="records"
         :row-selection="{ selectedRowKeys: selectedIds, onChange: (keys: (string | number)[]) => { selectedIds = keys.map(Number); } }"
         :loading="loading"
-        :scroll="{ x: 1120 }"
+        :scroll="{ x: 1900 }"
         :pagination="{
           current: page,
           pageSize,
@@ -343,6 +410,9 @@
         </a-table-column>
         <a-table-column key="code" title="琚嬬爜" data-index="code" min-width="220">
           <template #default="{ record }"><span class="mono strong">{{ record.code }}</span></template>
+        </a-table-column>
+        <a-table-column key="palletCode" title="鎵樼洏鐮�" data-index="palletCode" min-width="190">
+          <template #default="{ record }"><span class="mono">{{ record.palletCode || '鈥�' }}</span></template>
         </a-table-column>
         <a-table-column key="batchCode" title="鐢熶骇鎵规" data-index="batchCode" min-width="190">
           <template #default="{ record }">{{ record.batchCode || '鈥�' }}</template>
@@ -373,32 +443,53 @@
         <a-table-column key="actions" title="鎿嶄綔" width="260" fixed="right">
           <template #default="{ record }">
             <a-space>
-              <a-button v-if="record.workflowStatus === 10 && hasAccessByCodes(['mes:qc-seed-quality:retest'])" type="link" @click="openRetest(record)">澶嶆</a-button>
-              <a-button v-if="[20, 50].includes(record.workflowStatus) && hasAccessByCodes(['mes:qc-seed-quality:process-approve'])" type="link" @click="openReview(record, 'process')">鍔犲伐閮ㄥ鎵�</a-button>
-              <a-button v-if="[30, 60].includes(record.workflowStatus) && hasAccessByCodes(['mes:qc-seed-quality:company-approve'])" type="link" @click="openReview(record, 'company')">鍏徃璐ㄦ瀹℃壒</a-button>
+              <a-button v-if="[10, 50].includes(record.workflowStatus) && hasAccessByCodes(['mes:qc-seed-quality:retest'])" type="link" @click="openRetest(record)">{{ record.workflowStatus === 50 ? '閲嶆柊鍒濇' : '澶嶆' }}</a-button>
+              <a-button v-if="[20, 25].includes(record.workflowStatus) && hasAccessByCodes(['mes:qc-seed-quality:process-approve'])" type="link" @click="openReview(record, 'process')">{{ record.workflowStatus === 25 ? '涓嶅悎鏍煎鐞�' : '鍒濇瀹℃牳' }}</a-button>
+              <a-button v-if="[30, 60].includes(record.workflowStatus) && hasAccessByCodes(['mes:qc-seed-quality:company-approve'])" type="link" @click="openReview(record, 'company')">{{ record.workflowStatus === 60 ? '涓嶅悎鏍煎鐞�' : '澶嶆瀹℃牳' }}</a-button>
               <a-button v-if="hasAccessByCodes(['mes:qc-seed-quality:query'])" type="link" @click="openHistory(record)">娴佺▼璁板綍</a-button>
             </a-space>
           </template>
         </a-table-column>
       </a-table>
     </section>
-    <a-modal v-model:open="retestOpen" title="绉嶅瓙璐ㄦ澶嶆" :confirm-loading="retestBusy" ok-text="鎻愪氦澶嶆" @ok="saveRetest">
-      <p class="muted">琚嬬爜锛歿{ activeRecord?.code }}銆傚師鎸囨爣鑼冨洿宸插甫鍏ワ紝璇峰綍鍏ユ湰娆″疄娴嬪�煎苟鏍稿涓婁笅闄愩��</p>
+    <a-modal v-model:open="retestOpen" :title="activeRecord?.workflowStatus === 50 ? '閲嶆柊鍒濇' : '绉嶅瓙璐ㄦ澶嶆'" :confirm-loading="retestBusy" :ok-text="activeRecord?.workflowStatus === 50 ? '鎻愪氦鍒濇' : '鎻愪氦澶嶆'" @ok="saveRetest">
+      <p class="muted">琚嬬爜锛歿{ activeRecord?.code }}銆傚洓椤规寚鏍囦笌鍒濇涓�鑷达紱璇峰綍鍏ユ湰娆″疄娴嬪�煎苟鏍稿鍚堟牸鑼冨洿銆�</p>
       <div v-for="item in retestIndicators" :key="item.indicatorCode" class="retest-row">
         <strong>{{ indicatorLabels[item.indicatorCode] || item.indicatorCode }}</strong>
-        <a-input-number v-model:value="item.value" :min="0" :precision="3" placeholder="瀹炴祴鍊�" />
-        <a-input-number v-model:value="item.minValue" :min="0" :precision="3" placeholder="涓嬮檺" />
-        <a-input-number v-model:value="item.maxValue" :min="0" :precision="3" placeholder="涓婇檺" />
+        <a-input-number v-model:value="item.value" :min="0" :precision="3" placeholder="鏈瀹炴祴鍊�" />
+        <a-input-number v-model:value="item.minValue" :min="0" :max="100" :precision="3" placeholder="涓嬮檺" />
+        <a-input-number v-model:value="item.maxValue" :min="0" :max="100" :precision="3" placeholder="涓婇檺" />
       </div>
-      <a-textarea v-model:value="retestReason" :rows="3" :maxlength="500" placeholder="澶嶆涓嶅悎鏍兼椂濉啓鍘熷洜" />
+      <a-textarea v-model:value="retestReason" :rows="3" :maxlength="500" placeholder="鏈妫�楠屼笉鍚堟牸鏃跺~鍐欏師鍥�" />
     </a-modal>
-    <a-modal v-model:open="reviewOpen" :title="reviewStage === 'process' ? '鍔犲伐閮ㄥ鎵�' : '鍏徃璐ㄦ瀹℃壒'" :confirm-loading="reviewBusy" ok-text="鎻愪氦瀹℃壒" @ok="saveReview">
+    <a-modal v-model:open="scopeOpen" title="鎸夋墭鐩� / 鐢熶骇鎵规鎵归噺澶嶆鎴栭噸鏂板垵妫�" :confirm-loading="scopeBusy" ok-text="鎻愪氦鏈樁娈靛叏閮ㄨ鐮�" :ok-button-props="{ disabled: !scopeIds.length }" @ok="saveScopeRetest">
+      <a-space class="scope-scan">
+        <a-select v-model:value="scopeType" style="width: 130px" :options="[{ label: '鎵樼洏鐮�', value: 'PALLET' }, { label: '鐢熶骇鎵规鐮�', value: 'BATCH' }]" @change="retestScope = undefined" />
+        <a-input-search v-model:value="scopeCode" placeholder="鎵弿鎴栬緭鍏ョ爜鍊�" enter-button="璇嗗埆" :loading="scopeBusy" @search="identifyScope" />
+      </a-space>
+      <template v-if="retestScope">
+        <p>宸茶瘑鍒� {{ retestScope.code }} 路 鏈夋晥琚� {{ retestScope.totalCount }} 路 鐢熶骇鎵规 {{ retestScope.batchCode || '鈥�' }}</p>
+        <a-radio-group v-model:value="scopeStatus">
+          <a-radio-button v-if="retestScope.retestIds.length" :value="10">澶嶆 {{ retestScope.retestIds.length }} 琚�</a-radio-button>
+          <a-radio-button v-if="retestScope.initialRecheckIds.length" :value="50">閲嶆柊鍒濇 {{ retestScope.initialRecheckIds.length }} 琚�</a-radio-button>
+        </a-radio-group>
+        <p class="muted">鍚屼竴缁勬寚鏍囧皢搴旂敤浜庢湰闃舵鍏ㄩ儴 {{ scopeIds.length }} 琚嬨�傛ā鏉胯寖鍥村彲浠ヤ慨鏀广��</p>
+        <div v-for="item in retestIndicators" :key="item.indicatorCode" class="retest-row">
+          <strong>{{ indicatorLabels[item.indicatorCode] }}</strong>
+          <a-input-number v-model:value="item.value" :min="0" :max="100" :precision="3" placeholder="瀹炴祴鍊�" />
+          <a-input-number v-model:value="item.minValue" :min="0" :max="100" :precision="3" placeholder="涓嬮檺" />
+          <a-input-number v-model:value="item.maxValue" :min="0" :max="100" :precision="3" placeholder="涓婇檺" />
+        </div>
+        <a-textarea v-model:value="retestReason" :rows="3" :maxlength="500" placeholder="涓嶅悎鏍兼椂濉啓鍘熷洜" />
+      </template>
+    </a-modal>
+    <a-modal v-model:open="reviewOpen" :title="[25, 60].includes(activeRecord?.workflowStatus ?? 0) ? '涓嶅悎鏍煎鐞�' : reviewStage === 'process' ? '鍒濇瀹℃牳' : '澶嶆瀹℃牳'" :confirm-loading="reviewBusy" ok-text="鎻愪氦瀹℃牳" @ok="saveReview">
       <p>{{ reviewIds.length > 1 ? `鍏� ${reviewIds.length} 鏉¤褰昤 : activeRecord?.code }} 路 {{ workflowLabels[activeRecord?.workflowStatus ?? 0] }}</p>
       <a-radio-group v-model:value="reviewApproved" class="review-choice">
-        <a-radio :value="true">鍚屾剰{{ reviewStage === 'company' ? activeRecord?.workflowStatus === 30 ? '鏀捐鍏ュ簱' : '鎶ュ簾澶勭疆' : '涓婃姤鍏徃璐ㄦ' }}</a-radio>
-        <a-radio :value="false">椹冲洖閲嶆</a-radio>
+        <a-radio :value="true">{{ reviewStage === 'process' ? activeRecord?.workflowStatus === 25 ? '纭涓嶅悎鏍硷紝瀹夋帓澶嶆' : '閫氳繃锛岃繘鍏ュ妫�' : activeRecord?.workflowStatus === 30 ? '閫氳繃锛屾斁琛屽叆搴�' : '纭涓嶅悎鏍硷紝鎶ュ簾澶勭疆' }}</a-radio>
+        <a-radio :value="false">{{ reviewStage === 'process' ? '椹冲洖锛岄噸鏂板垵妫�' : '椹冲洖锛岄噸鏂板妫�' }}</a-radio>
       </a-radio-group>
-      <a-textarea v-model:value="reviewOpinion" :rows="3" :maxlength="500" placeholder="璇峰~鍐欏鎵规剰瑙�" />
+      <a-textarea v-model:value="reviewOpinion" :rows="3" :maxlength="500" :placeholder="reviewApproved ? '瀹℃壒鎰忚锛堥�夊~锛�' : '璇峰~鍐欓┏鍥炴剰瑙�'" />
     </a-modal>
     <a-modal v-model:open="historyOpen" :title="`娴佺▼璁板綍 路 ${activeRecord?.code || ''}`" :footer="null">
       <a-timeline v-if="historyActions.length">
@@ -458,6 +549,8 @@
 .filters :deep(.ant-btn .iconify) { font-size: 14px; }
 .retest-row { display: grid; grid-template-columns: 60px repeat(3, 1fr); gap: 8px; align-items: center; margin-bottom: 10px; }
 .retest-row :deep(.ant-input-number) { width: 100%; }
+.scope-scan { display: flex; width: 100%; margin-bottom: 16px; }
+.scope-scan :deep(.ant-space-item:last-child) { flex: 1; }
 .review-choice { display: flex; gap: 16px; margin: 10px 0 18px; }
 
 /* ===== 鍗曞厓鏍� ===== */

--
Gitblit v1.9.3