feat: Redis单值结果直接展示+JSON中文格式化+悬浮复制
1. GET/HGET/TTL等单值命令: 直接展示raw值, 不再套table 2. JSON自动检测+格式化(中文正常显示, 2空格缩进) 3. 非JSON值(如false/数字)直接文本展示 4. 代码块右上角悬浮复制按钮(hover显示) 5. 工具栏显示值类型(JSON/String)替代行列数
This commit is contained in:
1 parent
18430f3717
commit
03ff845485
2 files changed
+62
-17
No files matched your search
@@ -25,6 +25,11 @@ interface QueryResult {
|
||||
rows: Record<string, unknown>[];
|
||||
affected_rows: number;
|
||||
execution_time_ms: number;
|
||||
cost_ms?: number;
|
||||
raw_value?: boolean;
|
||||
raw_key?: string;
|
||||
raw_text?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
interface QueryHistoryItem {
|
||||
@@ -480,9 +485,15 @@ export default function QueriesPage() {
|
||||
</span>
|
||||
<div className="flex items-center gap-3 text-xs dg-text-secondary">
|
||||
<span className="flex items-center gap-1"><Clock className="w-3 h-3" />{result.execution_time_ms || result.cost_ms || 0}ms</span>
|
||||
<span>{result.rows?.length || 0} 行</span>
|
||||
<span>{result.columns?.length || 0} 列</span>
|
||||
{result.rows && result.rows.length > 0 && (
|
||||
{result.raw_text !== undefined ? (
|
||||
<span>{result.raw_value ? 'JSON' : typeof result.raw_text === 'string' ? 'String' : 'Value'}</span>
|
||||
) : (
|
||||
<>
|
||||
<span>{result.rows?.length || 0} 行</span>
|
||||
<span>{result.columns?.length || 0} 列</span>
|
||||
</>
|
||||
)}
|
||||
{(result.rows?.length > 0 || result.raw_text !== undefined) && (
|
||||
<>
|
||||
<button onClick={handleCopyResult}
|
||||
className="dg-btn dg-btn-ghost dg-btn-sm gap-1">
|
||||
@@ -498,7 +509,30 @@ export default function QueriesPage() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-0">
|
||||
{result.columns && result.columns.length > 0 ? (
|
||||
{result.raw_text !== undefined ? (
|
||||
/* Raw value display (Redis GET/HGET/TTL etc.) */
|
||||
<div className="p-4">
|
||||
{result.raw_key && (
|
||||
<div className="text-xs text-[var(--dg-text-muted)] mb-2 font-mono">{result.raw_key}</div>
|
||||
)}
|
||||
<div className="relative group">
|
||||
<pre className={`text-sm leading-relaxed overflow-auto max-h-[450px] p-3 rounded-lg font-mono ${
|
||||
result.raw_value
|
||||
? 'bg-[var(--dg-bg-primary)] text-blue-300 whitespace-pre-wrap break-all'
|
||||
: 'bg-[var(--dg-bg-primary)] text-[var(--dg-text-primary)] whitespace-pre-wrap break-all'
|
||||
}`}>{result.raw_value
|
||||
? (() => { try { return JSON.stringify(JSON.parse(String(result.raw_text)), null, 2); } catch { return String(result.raw_text); } })()
|
||||
: String(result.raw_text)
|
||||
}</pre>
|
||||
<button onClick={() => {
|
||||
const text = result.raw_value ? (() => { try { return JSON.stringify(JSON.parse(String(result.raw_text)), null, 2); } catch { return String(result.raw_text); } })() : String(result.raw_text);
|
||||
navigator.clipboard.writeText(text).then(() => { setCopied(true); setTimeout(() => setCopied(false), 2000); });
|
||||
}} className="absolute top-2 right-2 dg-btn dg-btn-ghost dg-btn-sm opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
{copied ? <Check className="w-3.5 h-3.5 text-green-400" /> : <Copy className="w-3.5 h-3.5" />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : result.columns && result.columns.length > 0 ? (
|
||||
<div ref={resultContainerRef} onScroll={handleResultScroll} className="overflow-auto max-h-[500px]">
|
||||
<table className="w-full text-sm">
|
||||
<thead className="sticky top-0 z-10">
|
||||
|
||||
Reference in new issue
Block a user