From 4f48ddc823dacf4b3ea800cc943366e2a76f6a19 Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Tue, 12 May 2026 17:09:20 +0800 Subject: [PATCH] feat(grid): add first-page and last-page pagination buttons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add « and » buttons to the pagination bar. First-page jumps to page 1. Last-page runs a COUNT(*) query to calculate total pages, then jumps to the final page. --- src/components/grid/DataGrid.vue | 45 +++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/components/grid/DataGrid.vue b/src/components/grid/DataGrid.vue index 9e5a6e644..c72506448 100644 --- a/src/components/grid/DataGrid.vue +++ b/src/components/grid/DataGrid.vue @@ -16,6 +16,8 @@ import { Save, ChevronLeft, ChevronRight, + ChevronsLeft, + ChevronsRight, Search, Inbox, SearchX, @@ -60,7 +62,12 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip import DangerConfirmDialog from "@/components/editor/DangerConfirmDialog.vue"; import type { QueryResult, ColumnInfo, DatabaseType } from "@/types/database"; import * as api from "@/lib/api"; -import { buildTableSelectSql, quoteTableIdentifier } from "@/lib/tableSelectSql"; +import { + buildTableSelectSql, + qualifiedTableName, + normalizeWhereInput, + quoteTableIdentifier, +} from "@/lib/tableSelectSql"; import { isHiddenGridColumn, usesSyntheticRowIdKey } from "@/lib/tableEditing"; import { formatGridSqlLiteral } from "@/lib/dataGridSql"; import { matchesRowStatusFilter, type RowStatus, type RowStatusFilter } from "@/lib/gridRowStatus"; @@ -810,6 +817,12 @@ function currentOrderBy(): string | undefined { ); } +function firstPage() { + if (currentPage.value <= 1) return; + currentPage.value = 1; + resetGridVerticalScroll(true); + emit("paginate", 0, pageSize.value, currentWhereInput(), currentOrderBy()); +} function prevPage() { if (currentPage.value <= 1) return; currentPage.value--; @@ -829,6 +842,30 @@ function changePageSize(size: number) { emit("paginate", 0, size, currentWhereInput(), currentOrderBy()); } +async function lastPage() { + if (!props.connectionId || !props.tableMeta) return; + const table = qualifiedTableName({ + databaseType: props.databaseType, + schema: props.tableMeta.schema, + tableName: props.tableMeta.tableName, + }); + const predicate = normalizeWhereInput(currentWhereInput()); + const where = predicate ? ` WHERE (${predicate})` : ""; + const sql = `SELECT COUNT(*) AS cnt FROM ${table}${where}`; + try { + const result = await api.executeQuery(props.connectionId, props.database ?? "", sql, props.tableMeta.schema); + const total = Number(result.rows?.[0]?.[0] ?? 0); + if (total <= 0) return; + const lastPageNum = Math.ceil(total / pageSize.value); + if (lastPageNum <= currentPage.value) return; + currentPage.value = lastPageNum; + resetGridVerticalScroll(true); + emit("paginate", (lastPageNum - 1) * pageSize.value, pageSize.value, currentWhereInput(), currentOrderBy()); + } catch { + // COUNT query failed — ignore silently + } +} + // --- Editing (composable) --- interface RowItem { @@ -2585,6 +2622,9 @@ defineExpose({ + @@ -2592,6 +2632,9 @@ defineExpose({ +