import React, { useState, useCallback, useRef } from 'react'; import { Button, Space, message } from 'antd'; import { PlayCircleOutlined, ClearOutlined } from '@ant-design/icons'; import { useStore } from '../store'; import Editor, { OnMount } from '@monaco-editor/react'; interface RedisCommandEditorProps { connectionId: string; redisDB: number; } interface CommandResult { command: string; result: any; error?: string; timestamp: number; } const RedisCommandEditor: React.FC = ({ connectionId, redisDB }) => { const { connections } = useStore(); const connection = connections.find(c => c.id === connectionId); const [command, setCommand] = useState(''); const [results, setResults] = useState([]); const [loading, setLoading] = useState(false); const editorRef = useRef(null); const getConfig = useCallback(() => { if (!connection) return null; return { ...connection.config, port: Number(connection.config.port), password: connection.config.password || "", useSSH: connection.config.useSSH || false, ssh: connection.config.ssh || { host: "", port: 22, user: "", password: "", keyPath: "" }, redisDB: redisDB }; }, [connection, redisDB]); const handleEditorMount: OnMount = (editor) => { editorRef.current = editor; // Add keyboard shortcut for execute editor.addCommand( // Ctrl/Cmd + Enter 2048 | 3, // KeyMod.CtrlCmd | KeyCode.Enter () => handleExecute() ); }; const handleExecute = async () => { const config = getConfig(); if (!config) return; const cmdToExecute = command.trim(); if (!cmdToExecute) { message.warning('请输入命令'); return; } // Support multiple commands separated by newlines const commands = cmdToExecute.split('\n').filter(c => c.trim() && !c.trim().startsWith('//') && !c.trim().startsWith('#')); setLoading(true); const newResults: CommandResult[] = []; for (const cmd of commands) { const trimmedCmd = cmd.trim(); if (!trimmedCmd) continue; try { const res = await (window as any).go.app.App.RedisExecuteCommand(config, trimmedCmd); newResults.push({ command: trimmedCmd, result: res.success ? res.data : null, error: res.success ? undefined : res.message, timestamp: Date.now() }); } catch (e: any) { newResults.push({ command: trimmedCmd, result: null, error: e?.message || String(e), timestamp: Date.now() }); } } setResults(prev => [...newResults, ...prev]); setLoading(false); }; const handleClear = () => { setResults([]); }; const formatResult = (result: any): string => { if (result === null || result === undefined) { return '(nil)'; } if (typeof result === 'string') { return `"${result}"`; } if (typeof result === 'number') { return `(integer) ${result}`; } if (Array.isArray(result)) { if (result.length === 0) { return '(empty array)'; } return result.map((item, index) => `${index + 1}) ${formatResult(item)}`).join('\n'); } if (typeof result === 'object') { return JSON.stringify(result, null, 2); } return String(result); }; if (!connection) { return
连接不存在
; } return (
{/* Command Input */}
Redis 命令 db{redisDB}
setCommand(value || '')} onMount={handleEditorMount} options={{ minimap: { enabled: false }, lineNumbers: 'on', fontSize: 14, wordWrap: 'on', scrollBeyondLastLine: false, automaticLayout: true, tabSize: 2 }} />
{/* Results */}
{results.length === 0 ? (
输入 Redis 命令并按 Ctrl+Enter 执行
支持多行命令,每行一个命令
) : ( results.map((item, index) => (
> {item.command}
{item.error ? (
(error) {item.error}
) : (
{formatResult(item.result)}
)}
)) )}
{/* Common Commands Help */}
常用命令: KEYS * | GET key | SET key value | HGETALL key | INFO | DBSIZE
); }; export default RedisCommandEditor;