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({
+