feat(data-grid): 优化查询结果展示宽度

This commit is contained in:
二丫讲梵 2026-07-07 13:00:59 +08:00 committed by GitHub
parent ab186c30a5
commit 2cbce44628
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 59 additions and 17 deletions

View File

@ -0,0 +1,52 @@
import { computed, ref } from "vue";
import { describe, expect, it } from "vitest";
import { DATA_GRID_COL_AUTO_FIT_MAX_WIDTH, DATA_GRID_COL_MAX_WIDTH, DATA_GRID_COL_MIN_WIDTH } from "@/lib/dataGrid/dataGridColumnWidth";
import { DATA_GRID_ROW_NUM_WIDTH, resizeDataGridColumnWidth, useDataGridColumnResize } from "@/composables/useDataGridColumnResize";
function createResizeState(options: { columns: string[]; rows: Array<Array<string | number | boolean | null>>; columnIndexes?: number[] }) {
return useDataGridColumnResize({
columns: computed(() => options.columns),
sourceRows: computed(() => options.rows),
columnIndexes: computed(() => options.columnIndexes ?? options.columns.map((_, index) => index)),
gridRef: ref<HTMLDivElement>(),
scrollbarGutter: ref(0),
});
}
describe("useDataGridColumnResize", () => {
it("keeps compact query result columns at content width instead of filling the viewport", () => {
const state = createResizeState({
columns: ["id", "user_id"],
rows: [
[1, 10],
[2, 20],
],
});
state.initColumnWidths();
expect(state.renderedColumnWidths.value).toEqual(state.columnWidths.value);
expect(state.totalWidth.value).toBe(DATA_GRID_ROW_NUM_WIDTH + state.columnWidths.value.reduce((total, width) => total + width, 0));
expect(Math.max(...state.renderedColumnWidths.value)).toBeLessThan(200);
});
it("keeps default widths bounded but lets auto-fit use the wider cap", () => {
const state = createResizeState({
columns: ["description"],
rows: [["x".repeat(120)]],
});
state.initColumnWidths();
expect(state.columnWidths.value[0]).toBe(DATA_GRID_COL_MAX_WIDTH);
state.autoFitColumn(0);
expect(state.columnWidths.value[0]).toBeGreaterThan(DATA_GRID_COL_MAX_WIDTH);
expect(state.columnWidths.value[0]).toBeLessThanOrEqual(DATA_GRID_COL_AUTO_FIT_MAX_WIDTH);
});
it("clamps manual column resizing to the minimum width", () => {
expect(resizeDataGridColumnWidth(120, -200)).toBe(DATA_GRID_COL_MIN_WIDTH);
expect(resizeDataGridColumnWidth(120, 30)).toBe(150);
});
});

View File

@ -1,11 +1,14 @@
import { ref, computed, watch, type ComputedRef, type Ref } from "vue";
import { useElementSize } from "@vueuse/core";
import { calculateDataGridColumnWidth, DATA_GRID_AUTO_FIT_VALUE_TEXT_LIMIT, DATA_GRID_COL_AUTO_FIT_MAX_WIDTH, DATA_GRID_COL_MIN_WIDTH, DATA_GRID_SAMPLE_ROWS } from "@/lib/dataGrid/dataGridColumnWidth";
type CellValue = string | number | boolean | null;
export const DATA_GRID_ROW_NUM_WIDTH = 48;
export function resizeDataGridColumnWidth(startWidth: number, deltaX: number): number {
return Math.max(DATA_GRID_COL_MIN_WIDTH, startWidth + deltaX);
}
export interface UseDataGridColumnResizeOptions {
columns: ComputedRef<string[]>;
sourceRows: ComputedRef<CellValue[][]>;
@ -15,10 +18,9 @@ export interface UseDataGridColumnResizeOptions {
}
export function useDataGridColumnResize(options: UseDataGridColumnResizeOptions) {
const { columns, sourceRows, columnIndexes, gridRef, scrollbarGutter } = options;
const { columns, sourceRows, columnIndexes } = options;
const columnWidths = ref<number[]>([]);
const { width: gridWidth } = useElementSize(gridRef);
let isResizing = false;
let previousColumnIndexes: number[] = [];
@ -59,7 +61,7 @@ export function useDataGridColumnResize(options: UseDataGridColumnResizeOptions)
const startX = event.clientX;
const startWidth = columnWidths.value[colIdx];
const onMove = (e: MouseEvent) => {
columnWidths.value[colIdx] = Math.max(DATA_GRID_COL_MIN_WIDTH, startWidth + e.clientX - startX);
columnWidths.value[colIdx] = resizeDataGridColumnWidth(startWidth, e.clientX - startX);
};
const onUp = () => {
document.removeEventListener("mousemove", onMove);
@ -83,19 +85,7 @@ export function useDataGridColumnResize(options: UseDataGridColumnResizeOptions)
});
}
const baseTotalWidth = computed(() => columnWidths.value.reduce((a, b) => a + b, 0));
const renderedColumnWidths = computed(() => {
const widths = columnWidths.value;
if (widths.length === 0) return widths;
const availableWidth = Math.max(0, gridWidth.value - (scrollbarGutter?.value ?? 0));
const extraWidth = Math.max(0, availableWidth - DATA_GRID_ROW_NUM_WIDTH - baseTotalWidth.value);
if (extraWidth === 0) return widths;
const extraPerColumn = extraWidth / widths.length;
return widths.map((width) => width + extraPerColumn);
});
const renderedColumnWidths = computed(() => columnWidths.value);
const totalWidth = computed(() => renderedColumnWidths.value.reduce((a, b) => a + b, 0) + DATA_GRID_ROW_NUM_WIDTH);