From 7b895474ef9e85c5213f0f87e60b87920739edcc Mon Sep 17 00:00:00 2001 From: Syngnat Date: Mon, 18 May 2026 19:45:52 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(DataGrid):=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E9=87=91=E4=BB=93=20bit=20=E7=B1=BB=E5=9E=8B=E5=80=BC?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 按列类型将 bit/varbit 的十六进制值显示为十进制标志 - 同步表格、当前页查找和文本视图的显示逻辑 - 补充 bit 类型显示回归测试 Refs #472 --- .../src/components/DataGrid.layout.test.tsx | 7 +++ frontend/src/components/DataGrid.tsx | 47 ++++++++++++++----- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/frontend/src/components/DataGrid.layout.test.tsx b/frontend/src/components/DataGrid.layout.test.tsx index 853638f..22e1a7d 100644 --- a/frontend/src/components/DataGrid.layout.test.tsx +++ b/frontend/src/components/DataGrid.layout.test.tsx @@ -87,6 +87,13 @@ describe('DataGrid layout', () => { expect(formatCellDisplayText('2026-05-10T09:12:33.456+08:00')).toBe('2026-05-10 09:12:33.456'); }); + it('renders bit column hex values as decimal flags', () => { + expect(formatCellDisplayText('0x00', 'bit(1)')).toBe('0'); + expect(formatCellDisplayText('0x01', 'bit(1)')).toBe('1'); + expect(formatCellDisplayText('0x02', 'bit varying(8)')).toBe('2'); + expect(formatCellDisplayText('0x01', 'bytea')).toBe('0x01'); + }); + it('resolves the field name copied from the cell context menu', () => { expect(resolveContextMenuFieldName('created_at', '创建时间')).toBe('created_at'); expect(resolveContextMenuFieldName('', 'fallback_name')).toBe('fallback_name'); diff --git a/frontend/src/components/DataGrid.tsx b/frontend/src/components/DataGrid.tsx index 607d18d..e60c74a 100644 --- a/frontend/src/components/DataGrid.tsx +++ b/frontend/src/components/DataGrid.tsx @@ -219,9 +219,27 @@ const normalizeDateTimeString = (val: string) => { }; // --- Helper: Format Value --- -export const formatCellDisplayText = (val: any): string => { +const normalizeBitHexDisplayText = (val: any, columnType?: string): string | null => { + const typeText = String(columnType || '').trim().toLowerCase(); + if (!/^varbit(?:\s*\(\s*\d+\s*\))?$/.test(typeText) + && !/^bit(?:\s+varying)?(?:\s*\(\s*\d+\s*\))?$/.test(typeText)) { + return null; + } + if (typeof val !== 'string') return null; + const raw = val.trim(); + if (!/^0x[0-9a-f]+$/i.test(raw)) return null; + try { + return BigInt(raw).toString(10); + } catch { + return null; + } +}; + +export const formatCellDisplayText = (val: any, columnType?: string): string => { try { if (val === null) return 'NULL'; + const bitText = normalizeBitHexDisplayText(val, columnType); + if (bitText !== null) return bitText; if (typeof val === 'object') { if (!Array.isArray(val) && !isPlainObject(val)) { return String(val); @@ -279,8 +297,8 @@ const renderHighlightedCellText = (text: string, query: string): React.ReactNode return <>{nodes}; }; -const renderCellDisplayValue = (val: any, query: string): React.ReactNode => { - const text = formatCellDisplayText(val); +const renderCellDisplayValue = (val: any, query: string, columnType?: string): React.ReactNode => { + const text = formatCellDisplayText(val, columnType); const content = renderHighlightedCellText(text, query); if (val === null) return {content}; return content; @@ -3572,16 +3590,16 @@ const DataGrid: React.FC = ({ mergedDisplayData, displayColumnNames, normalizedPageFindText, - (value) => formatCellDisplayText(value), + (value, _row, columnName) => formatCellDisplayText(value, (columnMetaMap[columnName] || columnMetaMapByLowerName[columnName.toLowerCase()])?.type), (row, rowIndex) => String(row?.[GONAVI_ROW_KEY] ?? `row-${rowIndex}`), - ), [mergedDisplayData, displayColumnNames, normalizedPageFindText]); + ), [mergedDisplayData, displayColumnNames, normalizedPageFindText, columnMetaMap, columnMetaMapByLowerName]); const pageFindSummary = useMemo(() => summarizeDataGridFindMatches( mergedDisplayData, displayColumnNames, normalizedPageFindText, - (value) => formatCellDisplayText(value), - ), [mergedDisplayData, displayColumnNames, normalizedPageFindText]); + (value, _row, columnName) => formatCellDisplayText(value, (columnMetaMap[columnName] || columnMetaMapByLowerName[columnName.toLowerCase()])?.type), + ), [mergedDisplayData, displayColumnNames, normalizedPageFindText, columnMetaMap, columnMetaMapByLowerName]); useEffect(() => { setActivePageFindMatchIndex(-1); @@ -3630,7 +3648,12 @@ const DataGrid: React.FC = ({ return textViewRows[textRecordIndex] || null; }, [viewMode, textViewRows, textRecordIndex]); - const formatTextViewValue = useCallback((val: any): string => { + const formatTextViewValue = useCallback((val: any, columnName?: string): string => { + const columnType = columnName + ? (columnMetaMap[columnName] || columnMetaMapByLowerName[columnName.toLowerCase()])?.type + : undefined; + const bitText = normalizeBitHexDisplayText(val, columnType); + if (bitText !== null) return bitText; if (val === null) return 'NULL'; if (val === undefined) return ''; if (typeof val === 'string') return normalizeDateTimeString(val); @@ -3642,7 +3665,7 @@ const DataGrid: React.FC = ({ } } return String(val); - }, []); + }, [columnMetaMap, columnMetaMapByLowerName]); const closeRowEditor = useCallback(() => { setRowEditorOpen(false); @@ -3956,7 +3979,7 @@ const DataGrid: React.FC = ({ editable: canModifyData && isWritableResultColumn(key, effectiveEditLocator), render: (text: any) => (
- {renderCellDisplayValue(text, normalizedPageFindText)} + {renderCellDisplayValue(text, normalizedPageFindText, (columnMetaMap[key] || columnMetaMapByLowerName[key.toLowerCase()])?.type)}
), shouldCellUpdate: (record: Item, prevRecord: Item) => { @@ -3993,7 +4016,7 @@ const DataGrid: React.FC = ({ }, }), })); - }, [displayColumnNames, columnWidths, sortInfo, handleResizeStart, handleResizeAutoFit, canModifyData, onSort, renderColumnTitle, dataTableDensity, normalizedPageFindText]); + }, [displayColumnNames, columnWidths, sortInfo, handleResizeStart, handleResizeAutoFit, canModifyData, onSort, renderColumnTitle, dataTableDensity, normalizedPageFindText, columnMetaMap, columnMetaMapByLowerName]); const mergedColumns = useMemo(() => columns.map((col): ColumnType => { const dataIndex = String(col.dataIndex); @@ -6492,7 +6515,7 @@ const DataGrid: React.FC = ({ {col} :
- {formatTextViewValue((currentTextRow as any)[col])} + {formatTextViewValue((currentTextRow as any)[col], col)}
)) : (