feat(data-grid): 优化字段跳转列匹配与回车定位

- 提取字段跳转目标解析逻辑,优先精确匹配再回退模糊匹配
- 旧版跳转列保留补全下拉,选中或回车即可定位
- 移除旧版多余跳转按钮,统一为输入即补全的交互
- 补充 DataGrid 与 dataGridFind 定向回归覆盖
- Refs #509
This commit is contained in:
Syngnat
2026-05-31 13:32:50 +08:00
parent bea938bc34
commit bea16b72df
4 changed files with 83 additions and 64 deletions

View File

@@ -91,6 +91,7 @@ import {
findDataGridTextRanges,
hasDataGridFindRenderVersionChanged,
normalizeDataGridFindQuery,
resolveDataGridColumnQuickFindTarget,
resolveDataGridFindNavigationIndex,
summarizeDataGridFindMatches,
type DataGridFindMatch,
@@ -6284,13 +6285,9 @@ const DataGrid: React.FC<DataGridProps> = ({
[visibleColumnQuickFindMatches],
);
const resolveColumnQuickFindTarget = useCallback((): string => {
const exactMatch = displayColumnNames.find((columnName) => (
normalizeDataGridFindQuery(columnName) === normalizedColumnQuickFindText
));
if (exactMatch) return exactMatch;
return visibleColumnQuickFindMatches[0] || '';
}, [displayColumnNames, normalizedColumnQuickFindText, visibleColumnQuickFindMatches]);
const resolveColumnQuickFindTarget = useCallback((query: string): string => (
resolveDataGridColumnQuickFindTarget(displayColumnNames, query)
), [displayColumnNames]);
const highlightColumnQuickFindTarget = useCallback((columnName: string) => {
setHighlightedColumnName(columnName);
@@ -6530,8 +6527,9 @@ const DataGrid: React.FC<DataGridProps> = ({
syncExternalScrollFromTargets,
]);
const handleSubmitColumnQuickFind = useCallback(() => {
const targetColumnName = resolveColumnQuickFindTarget();
const handleSubmitColumnQuickFind = useCallback((submittedValue?: string) => {
const effectiveQuery = String(submittedValue ?? columnQuickFindText);
const targetColumnName = resolveColumnQuickFindTarget(effectiveQuery);
if (!targetColumnName) {
if (columnQuickFindText.trim()) {
void message.warning(`未找到字段列:${columnQuickFindText.trim()}`);
@@ -7037,7 +7035,7 @@ const DataGrid: React.FC<DataGridProps> = ({
inputProps={noAutoCapInputProps as Record<string, unknown>}
value={columnQuickFindText}
options={columnQuickFindOptions}
hasTarget={!!resolveColumnQuickFindTarget()}
hasTarget={!!resolveColumnQuickFindTarget(columnQuickFindText)}
onChange={setColumnQuickFindText}
onSubmit={handleSubmitColumnQuickFind}
/>

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { AutoComplete, Button, Input, Tooltip } from 'antd';
import { AimOutlined, SearchOutlined } from '@ant-design/icons';
import { AutoComplete, Input, Tooltip } from 'antd';
import { SearchOutlined } from '@ant-design/icons';
export interface DataGridColumnQuickFindProps {
isV2Ui: boolean;
@@ -10,68 +10,62 @@ export interface DataGridColumnQuickFindProps {
options: Array<{ value: string; label?: React.ReactNode }>;
hasTarget: boolean;
onChange: (value: string) => void;
onSubmit: () => void;
onSubmit: (value?: string) => void;
}
const DataGridColumnQuickFind: React.FC<DataGridColumnQuickFindProps> = ({
isV2Ui,
darkMode,
inputProps,
value,
options,
hasTarget,
onChange,
onSubmit,
}) => (
<Tooltip title="输入字段名,回车或点定位按钮即可跳到对应列">
<div
data-grid-column-quick-find="true"
className={isV2Ui ? 'gn-v2-data-grid-column-quick-find' : undefined}
style={isV2Ui ? undefined : { display: 'flex', alignItems: 'center', gap: 6 }}
>
<div className={isV2Ui ? 'gn-v2-data-grid-column-quick-find-row' : undefined}>
<div className={isV2Ui ? 'gn-v2-data-grid-column-quick-find-field' : undefined}>
<AutoComplete
className={isV2Ui ? 'gn-v2-data-grid-column-quick-find-autocomplete' : undefined}
options={options}
value={value}
onChange={onChange}
onSelect={onChange}
filterOption={false}
popupMatchSelectWidth={280}
>
<Input
{...inputProps}
allowClear
size="small"
variant="borderless"
prefix={<SearchOutlined />}
placeholder="跳到字段列..."
value={value}
onChange={(event) => onChange(event.target.value)}
onPressEnter={onSubmit}
style={isV2Ui ? undefined : { width: 220 }}
/>
</AutoComplete>
</div>
<Button
data-grid-column-quick-find-submit="true"
className={isV2Ui ? 'gn-v2-data-grid-column-quick-find-submit' : undefined}
size="small"
icon={<AimOutlined />}
disabled={!hasTarget}
onClick={onSubmit}
}) => {
const legacyDropdownOpen = !isV2Ui && String(value || '').trim().length > 0 && options.length > 0;
return (
<Tooltip title="输入字段名,回车或点定位按钮即可跳到对应列">
<div
data-grid-column-quick-find="true"
className={isV2Ui ? 'gn-v2-data-grid-column-quick-find' : undefined}
style={isV2Ui ? undefined : { display: 'flex', alignItems: 'center', minWidth: 0, width: '100%', height: 32 }}
>
<div
className={isV2Ui ? 'gn-v2-data-grid-column-quick-find-row' : undefined}
style={isV2Ui ? undefined : { display: 'flex', alignItems: 'center', gap: 8, minWidth: 0, width: '100%', flexWrap: 'nowrap', height: 32 }}
>
{isV2Ui ? null : '跳转'}
</Button>
<div className={isV2Ui ? 'gn-v2-data-grid-column-quick-find-field' : undefined} style={isV2Ui ? undefined : { display: 'flex', alignItems: 'center', height: 32 }}>
<AutoComplete
className={isV2Ui ? 'gn-v2-data-grid-column-quick-find-autocomplete' : undefined}
options={options}
value={value}
open={isV2Ui ? undefined : legacyDropdownOpen}
onChange={onChange}
onSelect={(nextValue) => {
onChange(nextValue);
onSubmit(nextValue);
}}
filterOption={false}
popupMatchSelectWidth={280}
>
<Input
{...inputProps}
allowClear
size="small"
variant="borderless"
prefix={<SearchOutlined />}
placeholder="跳到字段列..."
value={value}
onChange={(event) => onChange(event.target.value)}
onPressEnter={() => onSubmit(value)}
style={isV2Ui ? undefined : { width: 168, height: 32 }}
/>
</AutoComplete>
</div>
</div>
</div>
{!isV2Ui && (
<span style={{ fontSize: 12, color: darkMode ? '#999' : '#666', whiteSpace: 'nowrap' }}>
</span>
)}
</div>
</Tooltip>
);
</Tooltip>
);
};
export default DataGridColumnQuickFind;

View File

@@ -6,6 +6,7 @@ import {
findDataGridTextRanges,
hasDataGridFindRenderVersionChanged,
normalizeDataGridFindQuery,
resolveDataGridColumnQuickFindTarget,
resolveDataGridFindNavigationIndex,
summarizeDataGridFindMatches,
} from './dataGridFind';
@@ -89,6 +90,15 @@ describe('dataGridFind', () => {
expect(resolveDataGridFindNavigationIndex(0, 0, 'next')).toBe(-1);
});
it('prefers an exact quick-find column match over earlier fuzzy matches', () => {
const columnNames = ['user_id', 'username', 'created_at'];
expect(resolveDataGridColumnQuickFindTarget(columnNames, 'username')).toBe('username');
expect(resolveDataGridColumnQuickFindTarget(columnNames, 'user')).toBe('user_id');
expect(resolveDataGridColumnQuickFindTarget(columnNames, ' ')).toBe('');
expect(resolveDataGridColumnQuickFindTarget(columnNames, 'missing')).toBe('');
});
it('tracks render version changes without exposing metadata as row data', () => {
const rows = [{ id: 1, name: 'Alpha' }];

View File

@@ -143,3 +143,20 @@ export const resolveDataGridFindNavigationIndex = (
}
return currentIndex < 0 || currentIndex >= matchCount - 1 ? 0 : currentIndex + 1;
};
export const resolveDataGridColumnQuickFindTarget = (
columnNames: string[],
query: string,
): string => {
const normalizedQuery = normalizeDataGridFindQuery(query);
if (!normalizedQuery) return '';
const exactMatch = columnNames.find((columnName) => (
normalizeDataGridFindQuery(columnName) === normalizedQuery
));
if (exactMatch) return exactMatch;
return columnNames.find((columnName) => (
normalizeDataGridFindQuery(columnName).includes(normalizedQuery)
)) || '';
};