"use client" import * as React from "react" import {useCallback, useEffect, useState} from "react" import {toast} from "sonner" import {Layers, RefreshCw} from "lucide-react" import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/components/ui/card" import {Skeleton} from "@/components/ui/skeleton" import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue} from "@/components/ui/select" import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table" import {Button} from "@/components/ui/button" import type {TableDataResponse} from "@/lib/services/db-manage" import {DbManageService} from "@/lib/services/db-manage" /** * 格式化数字,每3位加逗号 */ const formatNumber = (num: number | string) => { if (num === undefined || num === null) return "0" return num.toString().replace(/\B(?=(\d{3})+(?!\B))/g, ",") } /** * 格式化表格单元格内容 */ const formatCellValue = (val: unknown): string => { if (val === null || val === undefined) return "-" if (typeof val === "boolean") return val ? "true" : "false" if (typeof val === "object") { try { return JSON.stringify(val) } catch { return "[Object]" } } return String(val) } interface TableBrowserProps { tables: string[] loadingTables: boolean refreshTrigger: number } export function TableBrowser({ tables, loadingTables, refreshTrigger }: TableBrowserProps) { const [selectedTable, setSelectedTable] = useState("") const [tableData, setTableData] = useState(null) const [page, setPage] = useState(1) const [loadingData, setLoadingData] = useState(false) const pageSize = 10 // 获取具体表数据 const fetchTableData = useCallback(async (tableName: string, targetPage: number, size: number) => { if (!tableName) return setLoadingData(true) try { const data = await DbManageService.getTableData({ table: tableName, page: targetPage, pageSize: size, }) setTableData(data) } catch (err) { toast.error(`获取数据表 ${tableName} 数据失败`, { description: err instanceof Error ? err.message : "未知错误", }) } finally { setLoadingData(false) } }, []) // 默认选择第一张表 useEffect(() => { if (tables.length > 0 && !selectedTable) { setSelectedTable(tables[0]) } }, [tables, selectedTable]) // 当选中的表、页码或外部刷新触发器改变时获取数据 useEffect(() => { if (selectedTable) { fetchTableData(selectedTable, page, pageSize) } }, [selectedTable, page, pageSize, refreshTrigger, fetchTableData]) // 处理页码改变 const handlePageChange = (newPage: number) => { setPage(newPage) } // 处理表切换 const handleTableChange = (value: string) => { setSelectedTable(value) setPage(1) // 切换表重置为第一页 } return (
数据表浏览器 浏览数据库中的物理数据表详情及内容
{loadingTables ? ( ) : ( )}
{loadingData && !tableData ? (
) : tableData && tableData.columns.length > 0 ? (
{/* 数据表格区域 */}
{loadingData && (
)} {tableData.columns.map((col) => ( {col} ))} {tableData.results && tableData.results.length > 0 ? ( tableData.results.map((row, rIndex) => ( {tableData.columns.map((col) => ( {formatCellValue(row[col])} ))} )) ) : ( 表中无记录数据 )}
{/* 分页控制 */}
总行数: {formatNumber(tableData.total)} 条记录
第 {page} / {Math.max(1, Math.ceil(tableData.total / pageSize))} 页
) : (
未选择数据表或表结构无法加载
)}
) }