buhuazhen
2 天以前 1ad589405bf2b26a8e896fa6ac5361c316bb9026
src/views/customerService/feedbackRegistration/components/ProductSelectDialog.vue
@@ -16,8 +16,8 @@
    </el-form>
    <!-- 列表 -->
    <el-table ref="tableRef" v-loading="loading" :data="tableData" height="420" highlight-current-row row-key="id"
      @selection-change="handleSelectionChange" @select="handleSelect">
    <el-table ref="tableRef" v-loading="loading" :data="tableData" height="420" highlight-current-row :row-key="getRowKey"
      @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" />
      <el-table-column type="index" label="序号" width="60" />
      <template v-for="column in visibleColumns" :key="column.prop">
@@ -79,8 +79,8 @@
});
const query = reactive({
  productName: "",
  model: "",
  productCategory: "",
  unit: "",
});
const page = reactive({
@@ -92,6 +92,7 @@
const tableData = ref([]);
const total = ref(0);
const multipleSelection = ref([]);
const selectedRowMap = ref(new Map());
const tableRef = ref();
const columnsDialogVisible = ref(false);
@@ -106,6 +107,29 @@
const visibleColumns = computed(() => {
  return allColumns.value.filter(c => selectedColumns.value.includes(c.prop));
});
const getRowKey = (row) => {
  return row?.id ?? row?.productModelId ?? `${row?.productCategory || ""}-${row?.specificationModel || row?.model || ""}-${row?.unit || ""}`;
};
const syncMultipleSelection = () => {
  multipleSelection.value = Array.from(selectedRowMap.value.values());
};
const initSelectionFromProps = () => {
  const selectedIdSet = new Set((props.selectedIds || []).map((id) => String(id)));
  selectedRowMap.value = new Map();
  if (!selectedIdSet.size) {
    syncMultipleSelection();
    return;
  }
  (props.products || []).forEach((row) => {
    if (selectedIdSet.has(String(row?.id))) {
      selectedRowMap.value.set(getRowKey(row), row);
    }
  });
  syncMultipleSelection();
};
const resetColumns = () => {
  selectedColumns.value = allColumns.value.filter(c => c.selected).map(c => c.prop);
@@ -124,39 +148,33 @@
}
const handleSelectionChange = (val) => {
  const currentPageKeys = new Set(tableData.value.map((item) => getRowKey(item)));
  currentPageKeys.forEach((key) => selectedRowMap.value.delete(key));
  if (props.single && val.length > 1) {
    // 如果限制为单个选择,只保留最后一个选中的
    const lastSelected = val[val.length - 1];
    multipleSelection.value = [lastSelected];
    // 清空表格选中状态,然后重新选中最后一个
    selectedRowMap.value = new Map();
    if (lastSelected) {
      selectedRowMap.value.set(getRowKey(lastSelected), lastSelected);
    }
    syncMultipleSelection();
    nextTick(() => {
      if (tableRef.value) {
        tableRef.value.clearSelection();
        tableRef.value.toggleRowSelection(lastSelected, true);
      }
    });
  } else {
    multipleSelection.value = val;
  }
}
// 处理单个选择
const handleSelect = (selection, row) => {
  if (props.single) {
    // 如果限制为单个,清空其他选择,只保留当前行
    if (selection.includes(row)) {
      // 选中当前行时,清空其他选中
      multipleSelection.value = [row];
      nextTick(() => {
        if (tableRef.value) {
          tableData.value.forEach((item) => {
            if (item.id !== row.id) {
              tableRef.value.toggleRowSelection(item, false);
            }
          });
        }
      });
  } else if (props.single) {
    selectedRowMap.value = new Map();
    if (val[0]) {
      selectedRowMap.value.set(getRowKey(val[0]), val[0]);
    }
    syncMultipleSelection();
  } else {
    val.forEach((row) => {
      selectedRowMap.value.set(getRowKey(row), row);
    });
    syncMultipleSelection();
  }
}
@@ -166,8 +184,8 @@
}
function onReset() {
  query.productName = "";
  query.model = "";
  query.productCategory = "";
  query.unit = "";
  page.pageNum = 1;
  loadData();
}
@@ -192,32 +210,29 @@
async function loadData() {
  loading.value = true;
  try {
    multipleSelection.value = []; // 翻页/搜索后清空选择更符合预期
    let filtered = props.products || [];
    // 本地搜索过滤
    if (query.productName) {
      filtered = filtered.filter(item => item.productName && item.productName.includes(query.productName));
    if (query.productCategory) {
      filtered = filtered.filter(item => item.productCategory && item.productCategory.includes(query.productCategory));
    }
    if (query.model) {
      filtered = filtered.filter(item => item.model && item.model.includes(query.model));
    if (query.unit) {
      filtered = filtered.filter(item => item.unit && item.unit.includes(query.unit));
    }
    total.value = filtered.length;
    // 前端分页
    const start = (page.pageNum - 1) * page.pageSize;
    const end = start + page.pageSize;
    tableData.value = filtered.slice(start, end);
    // 自动回显选中状态
    nextTick(() => {
      if (tableRef.value) {
        tableRef.value.clearSelection();
        tableData.value.forEach(row => {
          if (props.selectedIds && props.selectedIds.includes(row.id)) {
          if (selectedRowMap.value.has(getRowKey(row))) {
            tableRef.value.toggleRowSelection(row, true);
          }
        });
      }
      syncMultipleSelection();
    });
  } finally {
    loading.value = false;
@@ -227,16 +242,31 @@
// 监听弹窗打开,重置选择
watch(() => props.modelValue, (visible) => {
  if (visible) {
    // 每次打开时重新初始化选中状态(multipleSelection 会通过 loadData 中的回显逻辑自动更新,但初始需置空避免重复)
    multipleSelection.value = [];
    initSelectionFromProps();
    page.pageNum = 1;
    loadData();
  }
});
// 监听数据源变化
watch(() => props.products, () => {
  loadData();
  const latestMap = new Map();
  const currentKeys = new Set(selectedRowMap.value.keys());
  (props.products || []).forEach((row) => {
    const key = getRowKey(row);
    if (currentKeys.has(key)) {
      latestMap.set(key, row);
    }
  });
  selectedRowMap.value.forEach((row, key) => {
    if (!latestMap.has(key)) {
      latestMap.set(key, row);
    }
  });
  selectedRowMap.value = latestMap;
  syncMultipleSelection();
  if (props.modelValue) {
    loadData();
  }
}, { deep: true });
onMounted(() => {