🐛 fix(data-viewer): 修复多列排序状态残留导致排序失效

- 将表格排序状态改为按当前 sorter 结果重建\n- 避免取消或切换多列排序后保留失效字段\n- 抽取排序状态归一化工具供数据表复用
This commit is contained in:
tianqijiuyun-latiao
2026-04-02 19:28:48 +08:00
parent fbda6917f7
commit eddb9f38c9
2 changed files with 46 additions and 31 deletions

View File

@@ -33,6 +33,7 @@ import { buildOrderBySQL, buildPaginatedSelectSQL, buildWhereSQL, escapeLiteral,
import { isMacLikePlatform, normalizeOpacityForPlatform, resolveAppearanceValues } from '../utils/appearance';
import { getDataSourceCapabilities } from '../utils/dataSourceCapabilities';
import { resolvePaginationPageText, resolvePaginationSummaryText, resolvePaginationTotalForControl } from '../utils/dataGridPagination';
import { resolveGridSortInfoFromTableSorter } from '../utils/dataGridSort';
import { calculateTableBodyBottomPadding, calculateVirtualTableScrollX } from './dataGridLayout';
import { buildCopyInsertSQL, normalizeTemporalLiteralText } from './dataGridCopyInsert';
@@ -2762,39 +2763,10 @@ const DataGrid: React.FC<DataGridProps> = ({
const handleTableChange = useCallback((_pag: any, _filtersArg: any, sorter: any) => {
if (isResizingRef.current) return; // Block sort if resizing
// Ant Design 多列排序模式下 sorter 可能是数组
const sorters = Array.isArray(sorter) ? sorter : (sorter?.field ? [sorter] : []);
if (sorters.length === 0) {
setSortInfo([]);
if (onSort) onSort(JSON.stringify([]), '');
return;
}
// 在现有排序数组基础上增量更新
const next = [...sortInfo];
for (const s of sorters) {
const field = String(s.field || '');
if (!field) continue;
const order = s.order as string;
const normalizedOrder = order === 'ascend' || order === 'descend' ? order : '';
const existIdx = next.findIndex(item => item.columnKey === field);
if (!normalizedOrder) {
// Ant Design 第三次点击想取消排序:
// 如果该字段已在排序数组中,回转为升序而非移除
if (existIdx >= 0) {
next[existIdx] = { ...next[existIdx], order: 'ascend', enabled: true };
}
// 不在数组中则忽略
} else if (existIdx >= 0) {
// 已存在:更新排序方向
next[existIdx] = { ...next[existIdx], order: normalizedOrder, enabled: true };
} else {
// 不存在:追加到末尾
next.push({ columnKey: field, order: normalizedOrder, enabled: true });
}
}
const next = resolveGridSortInfoFromTableSorter({ sorter });
setSortInfo(next);
if (onSort) onSort(JSON.stringify(next), '');
}, [onSort, sortInfo]);
}, [onSort]);
// Native Drag State
const draggingRef = useRef<{

View File

@@ -0,0 +1,43 @@
export type GridSortInfoItem = {
columnKey: string;
order: string;
enabled?: boolean;
};
type TableSorterLike = {
field?: unknown;
columnKey?: unknown;
order?: unknown;
};
export const resolveGridSortInfoFromTableSorter = ({
sorter,
}: {
sorter: TableSorterLike | TableSorterLike[] | null | undefined;
}): GridSortInfoItem[] => {
const sorters = Array.isArray(sorter)
? sorter
: ((sorter?.field || sorter?.columnKey) ? [sorter] : []);
if (sorters.length === 0) {
return [];
}
const next: GridSortInfoItem[] = [];
const seen = new Set<string>();
for (const item of sorters) {
const field = String(item?.field || item?.columnKey || '').trim();
if (!field) continue;
const order = item?.order as string;
const normalizedOrder = order === 'ascend' || order === 'descend' ? order : '';
if (!normalizedOrder) continue;
const dedupeKey = field.toLowerCase();
if (seen.has(dedupeKey)) continue;
seen.add(dedupeKey);
next.push({ columnKey: field, order: normalizedOrder, enabled: true });
}
return next;
};