"use client" import { useState, useEffect } from "react" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { Button } from "@/components/ui/button" import { Badge } from "@/components/ui/badge" import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion" import { Database, TableIcon, Key, Download, RefreshCw } from "lucide-react" import { Skeleton } from "@/components/ui/skeleton" interface TableField { Field: string Type: string Null: string Key: string Default: string | null Extra: string } interface DatabaseStructure { [tableName: string]: TableField[] } export function DatabaseStructureViewer() { const [databases, setDatabases] = useState([]) const [selectedDatabase, setSelectedDatabase] = useState("") const [structure, setStructure] = useState(null) const [loading, setLoading] = useState(false) const [error, setError] = useState(null) // 获取数据库列表 useEffect(() => { const fetchDatabases = async () => { try { setLoading(true) const response = await fetch("/api/database-structure") const result = await response.json() if (result.success) { const dbList = result.data.map((item: any) => Object.values(item)[0] as string) setDatabases(dbList) // 默认选择第一个非系统数据库 const nonSystemDbs = dbList.filter( (db: string) => !["information_schema", "mysql", "performance_schema", "sys"].includes(db), ) if (nonSystemDbs.length > 0) { setSelectedDatabase(nonSystemDbs[0]) } } else { setError(result.message || "获取数据库列表失败") } } catch (err) { setError("获取数据库列表失败") console.error(err) } finally { setLoading(false) } } fetchDatabases() }, []) // 获取数据库结构 useEffect(() => { if (!selectedDatabase) return const fetchDatabaseStructure = async () => { try { setLoading(true) setStructure(null) const response = await fetch(`/api/database-structure?database=${selectedDatabase}`) const result = await response.json() if (result.success) { setStructure(result.data) setError(null) } else { setError(result.message || "获取数据库结构失败") } } catch (err) { setError("获取数据库结构失败") console.error(err) } finally { setLoading(false) } } fetchDatabaseStructure() }, [selectedDatabase]) // 获取字段类型的简化描述 const getSimplifiedType = (type: string) => { if (type.includes("int")) return "Integer" if (type.includes("varchar") || type.includes("text") || type.includes("char")) return "String" if (type.includes("datetime") || type.includes("timestamp")) return "DateTime" if (type.includes("date")) return "Date" if (type.includes("decimal") || type.includes("float") || type.includes("double")) return "Decimal" if (type.includes("bool")) return "Boolean" if (type.includes("json")) return "JSON" if (type.includes("blob")) return "Binary" return type } // 获取字段类型的标签颜色 const getTypeColor = (type: string) => { if (type.includes("int")) return "bg-blue-100 text-blue-800" if (type.includes("varchar") || type.includes("text") || type.includes("char")) return "bg-green-100 text-green-800" if (type.includes("datetime") || type.includes("timestamp") || type.includes("date")) return "bg-purple-100 text-purple-800" if (type.includes("decimal") || type.includes("float") || type.includes("double")) return "bg-yellow-100 text-yellow-800" if (type.includes("bool")) return "bg-orange-100 text-orange-800" if (type.includes("json")) return "bg-indigo-100 text-indigo-800" if (type.includes("blob")) return "bg-red-100 text-red-800" return "bg-gray-100 text-gray-800" } // 导出数据库结构为JSON const exportDatabaseStructure = () => { if (!structure) return const dataStr = JSON.stringify(structure, null, 2) const dataUri = `data:application/json;charset=utf-8,${encodeURIComponent(dataStr)}` const exportFileDefaultName = `${selectedDatabase}-structure.json` const linkElement = document.createElement("a") linkElement.setAttribute("href", dataUri) linkElement.setAttribute("download", exportFileDefaultName) linkElement.click() } // 刷新数据库结构 const refreshDatabaseStructure = async () => { if (!selectedDatabase) return try { setLoading(true) setStructure(null) const response = await fetch(`/api/database-structure?database=${selectedDatabase}`) const result = await response.json() if (result.success) { setStructure(result.data) setError(null) } else { setError(result.message || "刷新数据库结构失败") } } catch (err) { setError("刷新数据库结构失败") console.error(err) } finally { setLoading(false) } } return (
数据库结构查看器 查看和分析数据库表结构
{loading && (
)} {error && (

{error}

)} {!loading && !error && (
{databases.map((db) => ( ))}
{structure && (

数据库: {selectedDatabase}

共 {Object.keys(structure).length} 张表

{Object.entries(structure).map(([tableName, fields]) => (
{tableName} {fields.length} 字段
字段名 类型 允许空值 默认值 额外 {fields.map((field, index) => ( {field.Field} {field.Key === "PRI" && } {getSimplifiedType(field.Type)} {field.Type} {field.Null === "YES" ? ( 可空 ) : ( 非空 )} {field.Key === "PRI" && 主键} {field.Key === "UNI" && 唯一} {field.Key === "MUL" && ( 索引 )} {field.Default !== null ? ( field.Default ) : ( NULL )} {field.Extra} ))}
))}
)}
)}
) }