import { useState, useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { ArrowLeft, Key, Activity, Terminal, Gauge, Plus, RefreshCw, Search } from 'lucide-react'; import { redisApi } from '@/api/redis'; type TabKey = 'keys' | 'monitor' | 'cli' | 'perf'; export default function RedisDetailPage() { var params = useParams<{ id: string }>(); var navigate = useNavigate(); var instanceId = Number(params.id); var [info, setInfo] = useState>({}); var [activeTab, setActiveTab] = useState('keys'); var [selectedDb, setSelectedDb] = useState(0); var [keyPattern, setKeyPattern] = useState('*'); var [keyType, setKeyType] = useState(''); var [keys, setKeys] = useState([]); var [selectedKey, setSelectedKey] = useState(null); var [showAddKey, setShowAddKey] = useState(false); var [newKey, setNewKey] = useState({ key: '', value: '', type: 'string', ttl: -1 }); var [cmdInput, setCmdInput] = useState(''); var [cmdOutput, setCmdOutput] = useState([]); var [slowlog, setSlowlog] = useState([]); var [clients, setClients] = useState([]); var [loading, setLoading] = useState(false); var tabs: { key: TabKey; label: string; icon: React.ElementType }[] = [ { key: 'keys', label: '键管理', icon: Key }, { key: 'monitor', label: '监控信息', icon: Activity }, { key: 'cli', label: '命令行', icon: Terminal }, { key: 'perf', label: '性能分析', icon: Gauge }, ]; useEffect(function () { redisApi.getInfo(instanceId).then(function (res: any) { setInfo(res.info || res || {}); }).catch(function () { setInfo({}); }); }, [instanceId]); var fetchKeys = function () { setLoading(true); redisApi.getKeys(instanceId, { db: selectedDb, pattern: keyPattern, type: keyType || undefined, count: 50 }).then(function (res: any) { setKeys(res.keys || res || []); }).catch(function () { setKeys([]); }).finally(function () { setLoading(false); }); }; var handleAddKey = function () { redisApi.createKey(instanceId, { db: selectedDb, key: newKey.key, value: newKey.value, type: newKey.type, ttl: newKey.ttl > 0 ? newKey.ttl : undefined }).then(function () { setShowAddKey(false); setNewKey({ key: '', value: '', type: 'string', ttl: -1 }); fetchKeys(); }).catch(function () {}); }; var handleDeleteKey = function (keyName: string) { if (!confirm('确定删除键 ' + keyName + '?')) return; redisApi.deleteKey(instanceId, keyName, selectedDb).then(function () { fetchKeys(); }).catch(function () {}); }; var handleCommand = function () { if (!cmdInput.trim()) return; var cmd = cmdInput; setCmdInput(''); setCmdOutput(function (prev) { return prev.concat(['> ' + cmd]); }); redisApi.executeCommand(instanceId, { db: selectedDb, command: cmd }).then(function (res: any) { setCmdOutput(function (prev) { return prev.concat([String(res.result || res.data || JSON.stringify(res))]); }); }).catch(function (e: any) { setCmdOutput(function (prev) { return prev.concat(['ERROR: ' + (e?.response?.data?.detail || '执行失败')]); }); }); }; useEffect(function () { if (activeTab === 'perf') { redisApi.getSlowlog(instanceId, 20).then(function (res: any) { setSlowlog(res.slowlog || res || []); }).catch(function () { setSlowlog([]); }); redisApi.getClients(instanceId).then(function (res: any) { setClients(res.clients || res || []); }).catch(function () { setClients([]); }); } }, [activeTab, instanceId]); var infoSections = Object.entries(info).filter(function (e) { return typeof e[1] === 'object' && e[1] !== null; }); var infoScalars = Object.entries(info).filter(function (e) { return typeof e[1] !== 'object'; }); return (
{/* 头部 */}

Redis 实例

#{instanceId}

{/* 信息卡片 */} {infoScalars.length > 0 && (
{infoScalars.slice(0, 4).map(function (e) { return
{String(e[1])}
{e[0]}
; })}
)} {/* Tab */}
{tabs.map(function (tab) { var Icon = tab.icon; return ; })}
{/* 键管理 */} {activeTab === 'keys' && (
{/* 键列表 */}
{loading ? (
{Array.from({ length: 5 }, function (_, i) { return
; })}
加载中...
) : keys.length === 0 ? (
点击刷新加载键列表
) : ( {keys.map(function (k: any, i: number) { return ; })}
键名类型TTL操作
{k.key || k.name || k} {k.type || '-'} {k.ttl != null ? k.ttl : '-'}
)}
)} {/* 监控信息 */} {activeTab === 'monitor' && (
{infoSections.map(function (section) { var entries = Object.entries(section[1] as Record); return (

{section[0]}

{entries.map(function (e) { return
{e[0]}{String(e[1])}
; })}
); })}
)} {/* 命令行 */} {activeTab === 'cli' && (
{cmdOutput.length === 0 &&
等待输入命令...
} {cmdOutput.map(function (line, i) { return
') ? 'text-green-400' : line.startsWith('ERROR') ? 'text-red-400' : 'text-[var(--dg-text-secondary)]'}>{line}
; })}
)} {/* 性能分析 */} {activeTab === 'perf' && (

慢日志

{slowlog.map(function (s: any, i: number) { return ; })}
命令耗时(μs)时间
{Array.isArray(s.command) ? s.command.join(' ') : s.command || '-'} {s.duration || s.execution_time || '-'} {s.timestamp || '-'}
{slowlog.length === 0 &&
暂无慢日志
}

客户端列表

{clients.map(function (c: any, i: number) { return ; })}
ID地址DB空闲(s)
{c.id || c.fd || '-'} {c.addr || c.host || '-'} {c.db || '-'} {c.idle || '-'}
)} {/* 键详情弹窗 */} {selectedKey && (

键详情

键名:{selectedKey.key || selectedKey.name}
类型:{selectedKey.type}
TTL:{selectedKey.ttl != null ? selectedKey.ttl + 's' : '-'}
值:
                  {typeof selectedKey.value === 'object' ? JSON.stringify(selectedKey.value, null, 2) : String(selectedKey.value || '-')}
                
)} {/* 新增键弹窗 */} {showAddKey && (

新增键