feat: enhance redis and production IA
This commit is contained in:
1 parent
644981eef4
commit
58bbc394e9
76 files changed
+1702
-721
No files matched your search
@@ -1,10 +1,11 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { ArrowLeft, Database, Table2, Users, Cpu, Play, RefreshCw } from 'lucide-react';
|
||||
import { ArrowLeft, Database, Table2, Users, Cpu, Play } from 'lucide-react';
|
||||
import { instanceDetailApi } from '@/api/instanceDetail';
|
||||
import { instanceApi } from '@/api/instance';
|
||||
import { queryApi } from '@/api/query';
|
||||
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
||||
import DataDictionaryPanel from '@/components/DataDictionaryPanel';
|
||||
|
||||
interface InstanceInfo {
|
||||
id: number; name: string; db_type: string; host: string; port: number;
|
||||
@@ -22,7 +23,6 @@ export default function InstanceDetailPage() {
|
||||
var [activeTab, setActiveTab] = useState<TabKey>('overview');
|
||||
var [databases, setDatabases] = useState<string[]>([]);
|
||||
var [selectedDb, setSelectedDb] = useState('');
|
||||
var [tables, setTables] = useState<any[]>([]);
|
||||
var [users, setUsers] = useState<any[]>([]);
|
||||
var [processes, setProcesses] = useState<any[]>([]);
|
||||
var [sqlText, setSqlText] = useState('');
|
||||
@@ -32,7 +32,7 @@ export default function InstanceDetailPage() {
|
||||
|
||||
var tabs: { key: TabKey; label: string; icon: React.ElementType }[] = [
|
||||
{ key: 'overview', label: '概览', icon: Database },
|
||||
{ key: 'tables', label: '表管理', icon: Table2 },
|
||||
{ key: 'tables', label: '表结构', icon: Table2 },
|
||||
{ key: 'query', label: 'SQL查询', icon: Play },
|
||||
{ key: 'users', label: '用户权限', icon: Users },
|
||||
{ key: 'process', label: '进程列表', icon: Cpu },
|
||||
@@ -45,7 +45,7 @@ export default function InstanceDetailPage() {
|
||||
}, [instanceId]);
|
||||
|
||||
useEffect(function () {
|
||||
if (activeTab === 'overview' || activeTab === 'tables') {
|
||||
if (activeTab === 'overview' || activeTab === 'tables' || activeTab === 'query') {
|
||||
instanceDetailApi.listDatabases(instanceId).then(function (res: any) {
|
||||
var dbs = res.databases || res || [];
|
||||
setDatabases(Array.isArray(dbs) ? dbs : []);
|
||||
@@ -64,14 +64,6 @@ export default function InstanceDetailPage() {
|
||||
}
|
||||
}, [activeTab, selectedDb, instanceId]);
|
||||
|
||||
useEffect(function () {
|
||||
if (activeTab === 'tables' && selectedDb) {
|
||||
instanceDetailApi.listTables(instanceId, selectedDb).then(function (res: any) {
|
||||
setTables(res.tables || res || []);
|
||||
}).catch(function () { setTables([]); });
|
||||
}
|
||||
}, [activeTab, selectedDb, instanceId]);
|
||||
|
||||
var handleQuery = function () {
|
||||
if (!sqlText.trim()) return;
|
||||
setLoading(true);
|
||||
@@ -136,7 +128,7 @@ export default function InstanceDetailPage() {
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div className="dg-card p-4"><div className="text-2xl font-bold text-blue-400">{databases.length}</div><div className="text-xs text-[var(--dg-text-muted)]">数据库</div></div>
|
||||
<div className="dg-card p-4"><div className="text-2xl font-bold text-green-400">{instance.status === 'connected' ? '在线' : '离线'}</div><div className="text-xs text-[var(--dg-text-muted)]">状态</div></div>
|
||||
<div className="dg-card p-4"><div className="text-2xl font-bold text-purple-400">{instance.version || '-'}</div><div className="text-xs text-[var(--dg-text-muted)]">版本</div></div>
|
||||
<div className="dg-card p-4"><div className="text-2xl font-bold text-cyan-400">{instance.version || '-'}</div><div className="text-xs text-[var(--dg-text-muted)]">版本</div></div>
|
||||
</div>
|
||||
<div className="dg-card p-4">
|
||||
<h3 className="text-sm font-semibold mb-3">数据库列表</h3>
|
||||
@@ -151,35 +143,7 @@ export default function InstanceDetailPage() {
|
||||
|
||||
{/* 表管理 */}
|
||||
{activeTab === 'tables' && (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<select value={selectedDb} onChange={function (e) { setSelectedDb(e.target.value); }} className="px-3 py-2 bg-[var(--dg-bg-primary)] border border-[var(--dg-border)] rounded-lg text-sm">
|
||||
<option value="">选择数据库</option>
|
||||
{databases.map(function (db) { return <option key={db} value={db}>{db}</option>; })}
|
||||
</select>
|
||||
<button onClick={function () { if (selectedDb) setActiveTab('tables'); }} className="px-3 py-2 bg-[var(--dg-bg-tertiary)] rounded-lg text-sm hover:bg-[var(--dg-bg-hover)]"><RefreshCw className="w-4 h-4" /></button>
|
||||
</div>
|
||||
{tables.length === 0 ? <div className="text-center py-8 text-[var(--dg-text-muted)]">选择数据库查看表列表</div> : (
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-sm">
|
||||
<thead><tr className="text-left text-[var(--dg-text-muted)] border-b border-[var(--dg-border)]">
|
||||
<th className="px-4 py-2">表名</th><th className="px-4 py-2">引擎</th><th className="px-4 py-2">行数</th><th className="px-4 py-2">大小</th><th className="px-4 py-2">注释</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
{tables.map(function (t: any, i: number) {
|
||||
return <tr key={i} className="border-b border-[var(--dg-border)] hover:bg-[var(--dg-bg-hover)]">
|
||||
<td className="px-4 py-2 font-medium">{t.Name || t.name}</td>
|
||||
<td className="px-4 py-2">{t.Engine || t.engine || '-'}</td>
|
||||
<td className="px-4 py-2">{t.Rows || t.rows || '-'}</td>
|
||||
<td className="px-4 py-2">{t.Data_length ? (t.Data_length / 1024 / 1024).toFixed(2) + ' MB' : '-'}</td>
|
||||
<td className="px-4 py-2 text-[var(--dg-text-muted)]">{t.Comment || t.comment || '-'}</td>
|
||||
</tr>;
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<DataDictionaryPanel instanceId={instanceId} />
|
||||
)}
|
||||
|
||||
{/* SQL查询 */}
|
||||
|
||||
Reference in new issue
Block a user