Browse Source

feat(forecast-form): 添加表格选择同步功能避免回调环

yz 1 week ago
parent
commit
9034840d9c

+ 47 - 1
src/components/forecast-form/forecast-form-mixin.js

@@ -288,6 +288,10 @@ export default {
       /** @type {Array<string|number>} */
       selectedRowKeys: [],
 
+      // 程序化同步选择的守卫标记,避免回调环
+      /** @type {boolean} */
+      selectionSyncing: false,
+
       /** 当前库存 */
       currentInventory: null,
 
@@ -1347,6 +1351,8 @@ export default {
      * @returns {void}
      */
     handleSelectionChange(selection) {
+      // 程序化同步时不触发合并逻辑,避免回调环
+      if (this.selectionSyncing) return
       // 基于当前页数据与新选择集,维护跨页 selection 的“并集 - 当前页未选差集”
       const currentPageRows = Array.isArray(this.pagedStockTableData) ? this.pagedStockTableData : []
       const currentPageKeys = new Set(
@@ -1484,6 +1490,8 @@ export default {
       this.pageSize = newSize
       // 变更每页大小后,将页码重置为 1
       this.currentPage = 1
+      // 同步当前页表格的选择回显
+      this.syncTableSelection()
     },
 
     /**
@@ -1494,6 +1502,8 @@ export default {
     handlePageChange(page) {
       const newPage = Number(page) > 0 ? Number(page) : 1
       this.currentPage = newPage
+      // 同步当前页表格的选择回显
+      this.syncTableSelection()
     },
 
     /**
@@ -1510,6 +1520,8 @@ export default {
       if (this.currentPage < 1) {
         this.currentPage = 1
       }
+      // 校正页码后,确保当前页的表格勾选状态与 selectedRowKeys 保持一致
+      this.syncTableSelection()
     },
 
     /**
@@ -1625,6 +1637,40 @@ export default {
         // 异常时不阻塞新增,默认允许保存
         this.$emit && this.$emit(FORECAST_FORM_EVENTS.SAVE_DISABLED_CHANGE, false)
       }
-    }
+    },
+
+    /**
+     * 程序化同步当前页表格勾选状态到 selectedRowKeys
+     * @returns {void}
+     */
+    syncTableSelection() {
+      try {
+        /** @type {any} */
+        const table = this.$refs && this.$refs.stockTable
+        if (!table || typeof table.clearSelection !== 'function' || typeof table.toggleRowSelection !== 'function') return
+        this.selectionSyncing = true
+        this.$nextTick(() => {
+          try {
+            table.clearSelection()
+            const selectedSet = new Set(Array.isArray(this.selectedRowKeys) ? this.selectedRowKeys : [])
+            const rows = Array.isArray(this.pagedStockTableData) ? this.pagedStockTableData : []
+            rows.forEach(row => {
+              const key = this.getRowUniqueKey(row)
+              if (selectedSet.has(key)) {
+                table.toggleRowSelection(row, true)
+              }
+            })
+          } catch (e) {
+            console.warn('同步表格选择异常:', e)
+          } finally {
+            this.selectionSyncing = false
+          }
+        })
+      } catch (e) {
+        console.warn('syncTableSelection 初始化失败:', e)
+        this.selectionSyncing = false
+      }
+    },
   }
 }
+

+ 2 - 2
src/components/forecast-form/index.vue

@@ -100,7 +100,7 @@
             :reserve-selection="true"
             @selection-change="handleSelectionChange"
           >
-            <el-table-column type="selection" width="55" align="center" />
+            <el-table-column type="selection" width="48" />
             <el-table-column prop="code" label="物料编码" min-width="140" show-overflow-tooltip />
             <el-table-column prop="cname" label="物料名称" min-width="160" show-overflow-tooltip />
             <el-table-column prop="brandName" label="品牌名称" min-width="120" show-overflow-tooltip />
@@ -141,7 +141,7 @@
             <el-pagination
               :current-page="currentPage"
               :page-size="pageSize"
-              :page-sizes="[10, 20, 50, 100]"
+              :page-sizes="[5, 10, 20, 50, 100]"
               :total="total"
               layout="total, sizes, prev, pager, next, jumper"
               @current-change="handlePageChange"

+ 4 - 1
src/components/forecast-form/types.d.ts

@@ -178,6 +178,8 @@ export interface ForecastFormMixinData {
   selectedStockId: string | null;
   /** 选择的行唯一键集合(跨分页保持) */
   selectedRowKeys: Array<string | number>;
+  /** 内部标记:是否正在进行程序化的表格选择同步,避免误触发 selection-change 逻辑 */
+  selectionSyncing: boolean;
 
   /** 分页:当前页(从1开始) */
   currentPage: number;
@@ -323,7 +325,8 @@ export interface ForecastFormMethods {
   setYearMonthDisabled?: (disabled: boolean) => void;
   /** 表格选择变更(跨分页维护 selectedRowKeys) */
   handleSelectionChange(selection: Array<ForecastFormMixinData['stockTableData'][number]>): void;
-  /** 行唯一键生成函数(绑定给 :row-key) */
+  /** 程序化同步表格选择(根据 selectedRowKeys 回显当前页选择) */
+  syncTableSelection?: () => void;
   getRowUniqueKey(row: ForecastFormMixinData['stockTableData'][number]): string | number;
   /** 更新物料下拉选项:过滤已在表格中的物料 */
   updateStockSelectOptions(): void;