feat(ui): 为暗黑模式添加亮度调整并优化颜色对比度
添加暗黑模式下的亮度调整,优化颜色对比度以提高可读性 更新多个组件的颜色变量以支持亮色和暗色主题 添加可折叠的扫描配置区域以改善用户体验
This commit is contained in:
parent
46f7a46f22
commit
cb1cdb77b8
|
|
@ -453,6 +453,12 @@
|
|||
|
||||
/* ============ Severity Badges ============ */
|
||||
.severity-critical {
|
||||
background: rgba(220, 38, 38, 0.15);
|
||||
color: #b91c1c;
|
||||
border: 1px solid rgba(220, 38, 38, 0.4);
|
||||
}
|
||||
|
||||
.dark .severity-critical {
|
||||
background: rgba(220, 38, 38, 0.2);
|
||||
color: #fca5a5;
|
||||
border: 1px solid rgba(220, 38, 38, 0.5);
|
||||
|
|
@ -460,6 +466,12 @@
|
|||
}
|
||||
|
||||
.severity-high {
|
||||
background: rgba(234, 88, 12, 0.15);
|
||||
color: #c2410c;
|
||||
border: 1px solid rgba(234, 88, 12, 0.4);
|
||||
}
|
||||
|
||||
.dark .severity-high {
|
||||
background: rgba(234, 88, 12, 0.2);
|
||||
color: #fdba74;
|
||||
border: 1px solid rgba(234, 88, 12, 0.5);
|
||||
|
|
@ -467,6 +479,12 @@
|
|||
}
|
||||
|
||||
.severity-medium {
|
||||
background: rgba(245, 158, 11, 0.15);
|
||||
color: #b45309;
|
||||
border: 1px solid rgba(245, 158, 11, 0.4);
|
||||
}
|
||||
|
||||
.dark .severity-medium {
|
||||
background: rgba(245, 158, 11, 0.2);
|
||||
color: #fcd34d;
|
||||
border: 1px solid rgba(245, 158, 11, 0.5);
|
||||
|
|
@ -474,6 +492,12 @@
|
|||
}
|
||||
|
||||
.severity-low {
|
||||
background: rgba(14, 181, 196, 0.15);
|
||||
color: #0e7490;
|
||||
border: 1px solid rgba(14, 181, 196, 0.4);
|
||||
}
|
||||
|
||||
.dark .severity-low {
|
||||
background: rgba(14, 181, 196, 0.2);
|
||||
color: #67e8f9;
|
||||
border: 1px solid rgba(14, 181, 196, 0.5);
|
||||
|
|
@ -481,6 +505,12 @@
|
|||
}
|
||||
|
||||
.severity-info {
|
||||
background: rgba(100, 116, 139, 0.15);
|
||||
color: #475569;
|
||||
border: 1px solid rgba(100, 116, 139, 0.4);
|
||||
}
|
||||
|
||||
.dark .severity-info {
|
||||
background: rgba(100, 116, 139, 0.2);
|
||||
color: #cbd5e1;
|
||||
border: 1px solid rgba(100, 116, 139, 0.5);
|
||||
|
|
|
|||
|
|
@ -419,11 +419,11 @@ export default function TerminalProgressDialog({
|
|||
const getLogColor = (type: LogEntry["type"]) => {
|
||||
switch (type) {
|
||||
case "success":
|
||||
return "text-emerald-400";
|
||||
return "text-emerald-600 dark:text-emerald-400";
|
||||
case "error":
|
||||
return "text-rose-400";
|
||||
return "text-rose-600 dark:text-rose-400";
|
||||
case "warning":
|
||||
return "text-amber-400";
|
||||
return "text-amber-600 dark:text-amber-400";
|
||||
default:
|
||||
return "text-muted-foreground";
|
||||
}
|
||||
|
|
@ -432,13 +432,13 @@ export default function TerminalProgressDialog({
|
|||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogPortal>
|
||||
<DialogOverlay className="bg-black/85 backdrop-blur-md" />
|
||||
<DialogOverlay className="bg-black/50 dark:bg-black/85 backdrop-blur-md" />
|
||||
<DialogPrimitive.Content
|
||||
className={cn(
|
||||
"fixed left-[50%] top-[50%] z-50 translate-x-[-50%] translate-y-[-50%]",
|
||||
"w-[95vw] max-w-[1000px] h-[85vh] max-h-[700px]",
|
||||
"bg-[#08090d] border border-[#1a2535] rounded overflow-hidden",
|
||||
"shadow-[0_0_60px_rgba(0,0,0,0.8),inset_0_1px_0_rgba(255,255,255,0.02)]",
|
||||
"bg-white dark:bg-[#08090d] border border-slate-200 dark:border-[#1a2535] rounded overflow-hidden",
|
||||
"shadow-xl dark:shadow-[0_0_60px_rgba(0,0,0,0.8),inset_0_1px_0_rgba(255,255,255,0.02)]",
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
||||
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
||||
|
|
@ -454,44 +454,43 @@ export default function TerminalProgressDialog({
|
|||
</DialogPrimitive.Description>
|
||||
</VisuallyHidden.Root>
|
||||
|
||||
{/* Scanline overlay */}
|
||||
<div className="absolute inset-0 pointer-events-none z-20 opacity-30"
|
||||
{/* Scanline overlay - only in dark mode */}
|
||||
<div className="absolute inset-0 pointer-events-none z-20 opacity-0 dark:opacity-30"
|
||||
style={{
|
||||
backgroundImage: "repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0,0,0,0.1) 2px, rgba(0,0,0,0.1) 4px)",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between px-4 py-3 cyber-bg-elevated border-b border-[#1a2535]"
|
||||
style={{ backgroundImage: "linear-gradient(90deg, rgba(255, 95, 31, 0.05) 0%, transparent 50%, rgba(14, 181, 196, 0.05) 100%)" }}>
|
||||
<div className="flex items-center justify-between px-4 py-3 bg-slate-50 dark:cyber-bg-elevated border-b border-slate-200 dark:border-[#1a2535]">
|
||||
<div className="flex items-center gap-3">
|
||||
<Terminal className="w-5 h-5 text-primary" style={{ filter: "drop-shadow(0 0 8px rgba(255, 95, 31, 0.5))" }} />
|
||||
<Terminal className="w-5 h-5 text-primary" />
|
||||
<div>
|
||||
<span className="text-lg font-bold uppercase tracking-[0.15em] text-[#f0e6d3]" style={{ textShadow: "0 0 20px rgba(255, 95, 31, 0.3)" }}>AUDIT_TERMINAL</span>
|
||||
<span className="text-xs text-[#5a6577] ml-2 tracking-wider">v3.0</span>
|
||||
<span className="text-lg font-bold uppercase tracking-[0.15em] text-slate-800 dark:text-[#f0e6d3]">AUDIT_TERMINAL</span>
|
||||
<span className="text-xs text-slate-500 dark:text-[#5a6577] ml-2 tracking-wider">v3.0</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-4">
|
||||
{/* 状态指示灯 */}
|
||||
<div className="flex items-center gap-2.5 px-3 py-1.5 bg-[#060810] rounded border border-[#1a2535]">
|
||||
<div className="flex items-center gap-2.5 px-3 py-1.5 bg-slate-100 dark:bg-[#060810] rounded border border-slate-200 dark:border-[#1a2535]">
|
||||
<div className={`w-2.5 h-2.5 rounded-full transition-all duration-300 ${!isCompleted && !isFailed && !isCancelled
|
||||
? 'bg-[#3dd68c] shadow-[0_0_10px_rgba(61,214,140,0.7)] animate-pulse'
|
||||
: 'bg-[#3a4555]'}`} />
|
||||
? 'bg-emerald-500 dark:bg-[#3dd68c] shadow-[0_0_10px_rgba(61,214,140,0.7)] animate-pulse'
|
||||
: 'bg-slate-300 dark:bg-[#3a4555]'}`} />
|
||||
<div className={`w-2.5 h-2.5 rounded-full transition-all duration-300 ${isFailed
|
||||
? 'bg-[#f87171] shadow-[0_0_10px_rgba(248,113,113,0.7)]'
|
||||
: 'bg-[#3a4555]'}`} />
|
||||
? 'bg-rose-500 dark:bg-[#f87171] shadow-[0_0_10px_rgba(248,113,113,0.7)]'
|
||||
: 'bg-slate-300 dark:bg-[#3a4555]'}`} />
|
||||
<div className={`w-2.5 h-2.5 rounded-full transition-all duration-300 ${isCompleted
|
||||
? 'bg-[#22d3ee] shadow-[0_0_10px_rgba(34,211,238,0.7)]'
|
||||
: 'bg-[#3a4555]'}`} />
|
||||
? 'bg-cyan-500 dark:bg-[#22d3ee] shadow-[0_0_10px_rgba(34,211,238,0.7)]'
|
||||
: 'bg-slate-300 dark:bg-[#3a4555]'}`} />
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="w-8 h-8 flex items-center justify-center hover:bg-[#e53935]/20 rounded transition-all duration-200 group"
|
||||
className="w-8 h-8 flex items-center justify-center hover:bg-rose-100 dark:hover:bg-[#e53935]/20 rounded transition-all duration-200 group"
|
||||
onClick={() => onOpenChange(false)}
|
||||
>
|
||||
<XIcon className="w-5 h-5 text-[#6a7587] group-hover:text-[#f87171] transition-colors" />
|
||||
<XIcon className="w-5 h-5 text-slate-500 dark:text-[#6a7587] group-hover:text-rose-500 dark:group-hover:text-[#f87171] transition-colors" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -499,22 +498,21 @@ export default function TerminalProgressDialog({
|
|||
{/* Main Content */}
|
||||
<div className="flex h-[calc(100%-56px)]">
|
||||
{/* Left Sidebar - Task Info */}
|
||||
<div className="w-48 p-4 border-r border-[#1a2535] bg-[#060810] flex flex-col gap-4">
|
||||
<div className="w-48 p-4 border-r border-slate-200 dark:border-[#1a2535] bg-slate-50 dark:bg-[#060810] flex flex-col gap-4">
|
||||
<div className="space-y-1.5">
|
||||
<div className="text-xs font-bold text-[#5a6577] uppercase tracking-[0.15em]">Task ID</div>
|
||||
<div className="text-xs font-mono text-primary truncate cyber-bg-elevated p-2.5 rounded border border-[#1a2535]"
|
||||
style={{ textShadow: "0 0 10px rgba(255, 95, 31, 0.3)" }}>
|
||||
<div className="text-xs font-bold text-slate-500 dark:text-[#5a6577] uppercase tracking-[0.15em]">Task ID</div>
|
||||
<div className="text-xs font-mono text-primary truncate bg-white dark:cyber-bg-elevated p-2.5 rounded border border-slate-200 dark:border-[#1a2535]">
|
||||
{taskId?.slice(0, 8)}...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<div className="text-xs font-bold text-[#5a6577] uppercase tracking-[0.15em]">Type</div>
|
||||
<div className="flex items-center gap-2 cyber-bg-elevated p-2.5 rounded border border-[#1a2535]">
|
||||
<div className="text-xs font-bold text-slate-500 dark:text-[#5a6577] uppercase tracking-[0.15em]">Type</div>
|
||||
<div className="flex items-center gap-2 bg-white dark:cyber-bg-elevated p-2.5 rounded border border-slate-200 dark:border-[#1a2535]">
|
||||
{taskType === 'repository'
|
||||
? <Cpu className="w-3.5 h-3.5 text-[#22d3ee]" style={{ filter: "drop-shadow(0 0 6px rgba(34, 211, 238, 0.5))" }} />
|
||||
: <HardDrive className="w-3.5 h-3.5 text-[#fbbf24]" style={{ filter: "drop-shadow(0 0 6px rgba(251, 191, 36, 0.5))" }} />}
|
||||
<span className="text-xs font-bold text-[#d0d8e8] uppercase tracking-wider">{taskType}</span>
|
||||
? <Cpu className="w-3.5 h-3.5 text-cyan-600 dark:text-[#22d3ee]" />
|
||||
: <HardDrive className="w-3.5 h-3.5 text-amber-600 dark:text-[#fbbf24]" />}
|
||||
<span className="text-xs font-bold text-slate-700 dark:text-[#d0d8e8] uppercase tracking-wider">{taskType}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -522,7 +520,7 @@ export default function TerminalProgressDialog({
|
|||
|
||||
{/* Status Badge */}
|
||||
<div className="space-y-2">
|
||||
<div className="text-xs font-bold text-[#5a6577] uppercase tracking-[0.15em]">Status</div>
|
||||
<div className="text-xs font-bold text-slate-500 dark:text-[#5a6577] uppercase tracking-[0.15em]">Status</div>
|
||||
{isCancelled ? (
|
||||
<Badge className="w-full justify-center cyber-badge-warning">CANCELLED</Badge>
|
||||
) : isCompleted ? (
|
||||
|
|
@ -538,18 +536,17 @@ export default function TerminalProgressDialog({
|
|||
{/* Terminal Screen */}
|
||||
<div className="flex-1 flex flex-col">
|
||||
{/* Terminal Output */}
|
||||
<div className="flex-1 bg-[#050608] p-4 overflow-y-auto font-mono text-sm custom-scrollbar relative">
|
||||
{/* Grid background */}
|
||||
<div className="absolute inset-0 cyber-grid-subtle pointer-events-none opacity-40" />
|
||||
<div className="flex-1 bg-slate-100 dark:bg-[#050608] p-4 overflow-y-auto font-mono text-sm custom-scrollbar relative">
|
||||
{/* Grid background - only in dark mode */}
|
||||
<div className="absolute inset-0 cyber-grid-subtle pointer-events-none opacity-0 dark:opacity-40" />
|
||||
|
||||
<div className="relative z-10 space-y-0.5 pb-10">
|
||||
{logs.map((log) => (
|
||||
<div key={log.id} className="flex items-start gap-3 hover:bg-[#ffffff]/[0.03] px-2 py-0.5 transition-colors group rounded">
|
||||
<span className="text-[#4a5565] text-xs flex-shrink-0 w-20 font-mono">
|
||||
<div key={log.id} className="flex items-start gap-3 hover:bg-slate-200/50 dark:hover:bg-[#ffffff]/[0.03] px-2 py-0.5 transition-colors group rounded">
|
||||
<span className="text-slate-500 dark:text-[#4a5565] text-xs flex-shrink-0 w-20 font-mono">
|
||||
{log.timestamp}
|
||||
</span>
|
||||
<span className={`${getLogColor(log.type)} flex-1 font-mono text-sm`}
|
||||
style={{ textShadow: log.type === 'success' ? '0 0 8px rgba(61, 214, 140, 0.3)' : log.type === 'error' ? '0 0 8px rgba(248, 113, 113, 0.3)' : log.type === 'warning' ? '0 0 8px rgba(251, 191, 36, 0.3)' : 'none' }}>
|
||||
<span className={`${getLogColor(log.type)} flex-1 font-mono text-sm`}>
|
||||
{log.message}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -557,8 +554,8 @@ export default function TerminalProgressDialog({
|
|||
|
||||
{!isCompleted && !isFailed && !isCancelled && (
|
||||
<div className="flex items-center gap-3 mt-4 px-2">
|
||||
<span className="text-[#4a5565] text-xs w-20 font-mono">{currentTime}</span>
|
||||
<span className="text-primary animate-pulse font-bold" style={{ textShadow: "0 0 10px rgba(255, 95, 31, 0.5)" }}>_</span>
|
||||
<span className="text-slate-500 dark:text-[#4a5565] text-xs w-20 font-mono">{currentTime}</span>
|
||||
<span className="text-primary animate-pulse font-bold">_</span>
|
||||
</div>
|
||||
)}
|
||||
<div ref={logsEndRef} />
|
||||
|
|
@ -566,8 +563,8 @@ export default function TerminalProgressDialog({
|
|||
</div>
|
||||
|
||||
{/* Bottom Controls */}
|
||||
<div className="h-14 px-4 border-t border-[#1a2535] cyber-bg-elevated/90 flex items-center justify-between">
|
||||
<div className="flex items-center gap-2 text-xs text-[#6a7587] font-mono tracking-wide">
|
||||
<div className="h-14 px-4 border-t border-slate-200 dark:border-[#1a2535] bg-slate-50 dark:cyber-bg-elevated/90 flex items-center justify-between">
|
||||
<div className="flex items-center gap-2 text-xs text-slate-600 dark:text-[#6a7587] font-mono tracking-wide">
|
||||
<Activity className="w-3.5 h-3.5" />
|
||||
<span>
|
||||
{isCompleted ? "TASK COMPLETED" : isFailed ? "TASK FAILED" : isCancelled ? "TASK CANCELLED" : "EXECUTING..."}
|
||||
|
|
@ -580,7 +577,7 @@ export default function TerminalProgressDialog({
|
|||
size="sm"
|
||||
variant="outline"
|
||||
onClick={handleCancel}
|
||||
className="h-8 bg-transparent border-[#fbbf24]/40 text-[#fbbf24] hover:bg-[#fbbf24]/10 hover:border-[#fbbf24]/60 font-mono uppercase tracking-wider text-xs"
|
||||
className="h-8 bg-transparent border-amber-500/40 text-amber-600 dark:text-[#fbbf24] hover:bg-amber-50 dark:hover:bg-[#fbbf24]/10 hover:border-amber-500/60 font-mono uppercase tracking-wider text-xs"
|
||||
>
|
||||
<AlertTriangle className="w-3 h-3 mr-1.5" />
|
||||
取消任务
|
||||
|
|
@ -592,7 +589,7 @@ export default function TerminalProgressDialog({
|
|||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => window.open('/logs', '_blank')}
|
||||
className="h-8 bg-transparent border-[#6a7587]/40 text-[#a8b0c0] hover:bg-[#1a2030]/50 hover:border-[#6a7587]/60 font-mono uppercase tracking-wider text-xs"
|
||||
className="h-8 bg-transparent border-slate-300 dark:border-[#6a7587]/40 text-slate-600 dark:text-[#a8b0c0] hover:bg-slate-100 dark:hover:bg-[#1a2030]/50 hover:border-slate-400 dark:hover:border-[#6a7587]/60 font-mono uppercase tracking-wider text-xs"
|
||||
>
|
||||
<Activity className="w-3 h-3 mr-1.5" />
|
||||
查看日志
|
||||
|
|
|
|||
|
|
@ -390,12 +390,12 @@ public class Example {
|
|||
<div className="w-4 h-4 bg-primary rounded flex items-center justify-center">
|
||||
<Code className="w-2 h-2 text-foreground" />
|
||||
</div>
|
||||
<span className="text-emerald-400 text-xs font-bold font-mono uppercase">CODE_SNIPPET</span>
|
||||
<span className="text-emerald-600 dark:text-emerald-400 text-xs font-bold font-mono uppercase">CODE_SNIPPET</span>
|
||||
</div>
|
||||
<span className="text-muted-foreground text-xs font-mono">LINE: {issue.line}</span>
|
||||
</div>
|
||||
<div className="bg-black/40 p-2 border border-border rounded">
|
||||
<pre className="text-xs text-emerald-400 font-mono overflow-x-auto">
|
||||
<div className="bg-slate-100 dark:bg-black/40 p-2 border border-border rounded">
|
||||
<pre className="text-xs text-emerald-700 dark:text-emerald-400 font-mono overflow-x-auto">
|
||||
<code>{issue.code_snippet}</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
|
@ -407,11 +407,11 @@ public class Example {
|
|||
<div className="bg-sky-500/10 border border-sky-500/30 p-3 rounded">
|
||||
<div className="flex items-center mb-2 border-b border-sky-500/20 pb-1">
|
||||
<div className="w-5 h-5 bg-sky-500/20 border border-sky-500/40 rounded flex items-center justify-center mr-2">
|
||||
<Lightbulb className="w-3 h-3 text-sky-400" />
|
||||
<Lightbulb className="w-3 h-3 text-sky-600 dark:text-sky-400" />
|
||||
</div>
|
||||
<span className="font-bold text-sky-300 text-sm uppercase">修复建议</span>
|
||||
<span className="font-bold text-sky-700 dark:text-sky-300 text-sm uppercase">修复建议</span>
|
||||
</div>
|
||||
<p className="text-sky-200/80 text-xs leading-relaxed font-mono">{issue.suggestion}</p>
|
||||
<p className="text-sky-800 dark:text-sky-200/80 text-xs leading-relaxed font-mono">{issue.suggestion}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
@ -423,37 +423,37 @@ public class Example {
|
|||
<div className="bg-violet-500/10 border border-violet-500/30 p-3 rounded">
|
||||
<div className="flex items-center mb-2 border-b border-violet-500/20 pb-1">
|
||||
<div className="w-5 h-5 bg-violet-500/20 border border-violet-500/40 rounded flex items-center justify-center mr-2">
|
||||
<Zap className="w-3 h-3 text-violet-400" />
|
||||
<Zap className="w-3 h-3 text-violet-600 dark:text-violet-400" />
|
||||
</div>
|
||||
<span className="font-bold text-violet-300 text-sm uppercase">AI 解释</span>
|
||||
<span className="font-bold text-violet-700 dark:text-violet-300 text-sm uppercase">AI 解释</span>
|
||||
</div>
|
||||
<div className="space-y-2 text-xs font-mono">
|
||||
{parsedExplanation.what && (
|
||||
<div className="border-l-2 border-rose-500 pl-2">
|
||||
<span className="font-bold text-rose-400 uppercase">问题:</span>
|
||||
<span className="font-bold text-rose-600 dark:text-rose-400 uppercase">问题:</span>
|
||||
<span className="text-foreground ml-1">{parsedExplanation.what}</span>
|
||||
</div>
|
||||
)}
|
||||
{parsedExplanation.why && (
|
||||
<div className="border-l-2 border-amber-500 pl-2">
|
||||
<span className="font-bold text-amber-400 uppercase">原因:</span>
|
||||
<span className="font-bold text-amber-600 dark:text-amber-400 uppercase">原因:</span>
|
||||
<span className="text-foreground ml-1">{parsedExplanation.why}</span>
|
||||
</div>
|
||||
)}
|
||||
{parsedExplanation.how && (
|
||||
<div className="border-l-2 border-emerald-500 pl-2">
|
||||
<span className="font-bold text-emerald-400 uppercase">方案:</span>
|
||||
<span className="font-bold text-emerald-600 dark:text-emerald-400 uppercase">方案:</span>
|
||||
<span className="text-foreground ml-1">{parsedExplanation.how}</span>
|
||||
</div>
|
||||
)}
|
||||
{parsedExplanation.learn_more && (
|
||||
<div className="border-l-2 border-sky-500 pl-2">
|
||||
<span className="font-bold text-sky-400 uppercase">链接:</span>
|
||||
<span className="font-bold text-sky-600 dark:text-sky-400 uppercase">链接:</span>
|
||||
<a
|
||||
href={parsedExplanation.learn_more}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-sky-400 hover:text-sky-300 hover:underline ml-1 font-bold"
|
||||
className="text-sky-600 dark:text-sky-400 hover:text-sky-500 dark:hover:text-sky-300 hover:underline ml-1 font-bold"
|
||||
>
|
||||
{parsedExplanation.learn_more}
|
||||
</a>
|
||||
|
|
@ -466,8 +466,8 @@ public class Example {
|
|||
return (
|
||||
<div className="bg-violet-500/10 border border-violet-500/30 p-3 rounded">
|
||||
<div className="flex items-center mb-2 border-b border-violet-500/20 pb-1">
|
||||
<Zap className="w-4 h-4 text-violet-400 mr-2" />
|
||||
<span className="font-bold text-violet-300 text-sm uppercase">AI 解释</span>
|
||||
<Zap className="w-4 h-4 text-violet-600 dark:text-violet-400 mr-2" />
|
||||
<span className="font-bold text-violet-700 dark:text-violet-300 text-sm uppercase">AI 解释</span>
|
||||
</div>
|
||||
<p className="text-foreground text-xs leading-relaxed font-mono">{issue.ai_explanation}</p>
|
||||
</div>
|
||||
|
|
@ -855,11 +855,11 @@ public class Example {
|
|||
</Tabs>
|
||||
) : (
|
||||
<div className="cyber-card p-16 text-center border-dashed">
|
||||
<CheckCircle className="w-16 h-16 text-emerald-400 mx-auto mb-4" />
|
||||
<h3 className="text-xl font-bold text-emerald-300 mb-2 uppercase">代码质量优秀!</h3>
|
||||
<p className="text-emerald-400/80 mb-4 font-mono">恭喜!没有发现任何问题</p>
|
||||
<CheckCircle className="w-16 h-16 text-emerald-600 dark:text-emerald-400 mx-auto mb-4" />
|
||||
<h3 className="text-xl font-bold text-emerald-700 dark:text-emerald-300 mb-2 uppercase">代码质量优秀!</h3>
|
||||
<p className="text-emerald-600 dark:text-emerald-400/80 mb-4 font-mono">恭喜!没有发现任何问题</p>
|
||||
<div className="bg-emerald-500/10 border border-emerald-500/30 p-4 max-w-md mx-auto rounded">
|
||||
<p className="text-emerald-300/80 text-sm font-mono">
|
||||
<p className="text-emerald-700 dark:text-emerald-300/80 text-sm font-mono">
|
||||
您的代码通过了所有质量检查,包括安全性、性能、可维护性等各个方面的评估。
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -677,10 +677,10 @@ export default function ProjectDetail() {
|
|||
<div className="flex items-start justify-between">
|
||||
<div className="flex items-start space-x-3">
|
||||
<div className={`w-8 h-8 rounded-lg flex items-center justify-center ${
|
||||
issue.severity === 'critical' ? 'bg-rose-500/20 text-rose-400' :
|
||||
issue.severity === 'high' ? 'bg-orange-500/20 text-orange-400' :
|
||||
issue.severity === 'medium' ? 'bg-amber-500/20 text-amber-400' :
|
||||
'bg-sky-500/20 text-sky-400'
|
||||
issue.severity === 'critical' ? 'bg-rose-500/20 text-rose-600 dark:text-rose-400' :
|
||||
issue.severity === 'high' ? 'bg-orange-500/20 text-orange-600 dark:text-orange-400' :
|
||||
issue.severity === 'medium' ? 'bg-amber-500/20 text-amber-600 dark:text-amber-400' :
|
||||
'bg-sky-500/20 text-sky-600 dark:text-sky-400'
|
||||
}`}>
|
||||
<AlertTriangle className="w-4 h-4" />
|
||||
</div>
|
||||
|
|
@ -712,7 +712,7 @@ export default function ProjectDetail() {
|
|||
</div>
|
||||
) : (
|
||||
<div className="cyber-card p-12 text-center">
|
||||
<CheckCircle className="w-16 h-16 text-emerald-500 mx-auto mb-4" />
|
||||
<CheckCircle className="w-16 h-16 text-emerald-600 dark:text-emerald-500 mx-auto mb-4" />
|
||||
<h3 className="text-lg font-bold text-foreground mb-2 uppercase">未发现问题</h3>
|
||||
<p className="text-sm text-muted-foreground font-mono">最近一次审计未发现明显问题,或尚未进行审计。</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ import {
|
|||
Info,
|
||||
Zap,
|
||||
XCircle,
|
||||
Terminal
|
||||
Terminal,
|
||||
ChevronDown,
|
||||
ChevronRight
|
||||
} from "lucide-react";
|
||||
import { api } from "@/shared/config/database";
|
||||
import type { AuditTask, AuditIssue } from "@/shared/types";
|
||||
|
|
@ -133,14 +135,14 @@ function IssuesList({ issues }: { issues: AuditIssue[] }) {
|
|||
<div className="w-4 h-4 bg-primary rounded flex items-center justify-center">
|
||||
<Code className="w-2 h-2 text-foreground" />
|
||||
</div>
|
||||
<span className="text-emerald-400 text-xs font-bold font-mono uppercase">CODE_SNIPPET</span>
|
||||
<span className="text-emerald-600 dark:text-emerald-400 text-xs font-bold font-mono uppercase">CODE_SNIPPET</span>
|
||||
</div>
|
||||
{issue.line_number && (
|
||||
<span className="text-muted-foreground text-xs font-mono">LINE: {issue.line_number}</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="bg-black/40 p-2 border border-border rounded">
|
||||
<pre className="text-xs text-emerald-400 font-mono overflow-x-auto">
|
||||
<div className="bg-slate-100 dark:bg-black/40 p-2 border border-border rounded">
|
||||
<pre className="text-xs text-emerald-700 dark:text-emerald-400 font-mono overflow-x-auto">
|
||||
<code>{issue.code_snippet}</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
|
@ -152,11 +154,11 @@ function IssuesList({ issues }: { issues: AuditIssue[] }) {
|
|||
<div className="bg-sky-500/10 border border-sky-500/30 p-3 rounded">
|
||||
<div className="flex items-center mb-2 border-b border-sky-500/20 pb-1">
|
||||
<div className="w-5 h-5 bg-sky-500/20 border border-sky-500/40 rounded flex items-center justify-center mr-2">
|
||||
<Lightbulb className="w-3 h-3 text-sky-400" />
|
||||
<Lightbulb className="w-3 h-3 text-sky-600 dark:text-sky-400" />
|
||||
</div>
|
||||
<span className="font-bold text-sky-300 text-sm uppercase">修复建议</span>
|
||||
<span className="font-bold text-sky-700 dark:text-sky-300 text-sm uppercase">修复建议</span>
|
||||
</div>
|
||||
<p className="text-sky-200/80 text-xs leading-relaxed font-mono">{issue.suggestion}</p>
|
||||
<p className="text-sky-800 dark:text-sky-200/80 text-xs leading-relaxed font-mono">{issue.suggestion}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
@ -168,41 +170,41 @@ function IssuesList({ issues }: { issues: AuditIssue[] }) {
|
|||
<div className="bg-violet-500/10 border border-violet-500/30 p-3 rounded">
|
||||
<div className="flex items-center mb-2 border-b border-violet-500/20 pb-1">
|
||||
<div className="w-5 h-5 bg-violet-500/20 border border-violet-500/40 rounded flex items-center justify-center mr-2">
|
||||
<Zap className="w-3 h-3 text-violet-400" />
|
||||
<Zap className="w-3 h-3 text-violet-600 dark:text-violet-400" />
|
||||
</div>
|
||||
<span className="font-bold text-violet-300 text-sm uppercase">AI 解释</span>
|
||||
<span className="font-bold text-violet-700 dark:text-violet-300 text-sm uppercase">AI 解释</span>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2 text-xs font-mono">
|
||||
{parsedExplanation.what && (
|
||||
<div className="border-l-2 border-rose-500 pl-2">
|
||||
<span className="font-bold text-rose-400 uppercase">问题:</span>
|
||||
<span className="font-bold text-rose-600 dark:text-rose-400 uppercase">问题:</span>
|
||||
<span className="text-foreground ml-1">{parsedExplanation.what}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{parsedExplanation.why && (
|
||||
<div className="border-l-2 border-amber-500 pl-2">
|
||||
<span className="font-bold text-amber-400 uppercase">原因:</span>
|
||||
<span className="font-bold text-amber-600 dark:text-amber-400 uppercase">原因:</span>
|
||||
<span className="text-foreground ml-1">{parsedExplanation.why}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{parsedExplanation.how && (
|
||||
<div className="border-l-2 border-emerald-500 pl-2">
|
||||
<span className="font-bold text-emerald-400 uppercase">方案:</span>
|
||||
<span className="font-bold text-emerald-600 dark:text-emerald-400 uppercase">方案:</span>
|
||||
<span className="text-foreground ml-1">{parsedExplanation.how}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{parsedExplanation.learn_more && (
|
||||
<div className="border-l-2 border-sky-500 pl-2">
|
||||
<span className="font-bold text-sky-400 uppercase">链接:</span>
|
||||
<span className="font-bold text-sky-600 dark:text-sky-400 uppercase">链接:</span>
|
||||
<a
|
||||
href={parsedExplanation.learn_more}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-sky-400 hover:text-sky-300 hover:underline ml-1 font-bold"
|
||||
className="text-sky-600 dark:text-sky-400 hover:text-sky-500 dark:hover:text-sky-300 hover:underline ml-1 font-bold"
|
||||
>
|
||||
{parsedExplanation.learn_more}
|
||||
</a>
|
||||
|
|
@ -215,8 +217,8 @@ function IssuesList({ issues }: { issues: AuditIssue[] }) {
|
|||
return (
|
||||
<div className="bg-violet-500/10 border border-violet-500/30 p-3 rounded">
|
||||
<div className="flex items-center mb-2 border-b border-violet-500/20 pb-1">
|
||||
<Zap className="w-4 h-4 text-violet-400 mr-2" />
|
||||
<span className="font-bold text-violet-300 text-sm uppercase">AI 解释</span>
|
||||
<Zap className="w-4 h-4 text-violet-600 dark:text-violet-400 mr-2" />
|
||||
<span className="font-bold text-violet-700 dark:text-violet-300 text-sm uppercase">AI 解释</span>
|
||||
</div>
|
||||
<p className="text-foreground text-xs leading-relaxed font-mono">{issue.ai_explanation}</p>
|
||||
</div>
|
||||
|
|
@ -230,11 +232,11 @@ function IssuesList({ issues }: { issues: AuditIssue[] }) {
|
|||
if (issues.length === 0) {
|
||||
return (
|
||||
<div className="cyber-card p-16 text-center border-dashed">
|
||||
<CheckCircle className="w-16 h-16 text-emerald-400 mx-auto mb-4" />
|
||||
<h3 className="text-xl font-bold text-emerald-300 mb-2 uppercase">代码质量优秀!</h3>
|
||||
<p className="text-emerald-400/80 mb-4 font-mono">恭喜!没有发现任何问题</p>
|
||||
<CheckCircle className="w-16 h-16 text-emerald-600 dark:text-emerald-400 mx-auto mb-4" />
|
||||
<h3 className="text-xl font-bold text-emerald-700 dark:text-emerald-300 mb-2 uppercase">代码质量优秀!</h3>
|
||||
<p className="text-emerald-600 dark:text-emerald-400/80 mb-4 font-mono">恭喜!没有发现任何问题</p>
|
||||
<div className="bg-emerald-500/10 border border-emerald-500/30 p-4 max-w-md mx-auto rounded">
|
||||
<p className="text-emerald-300/80 text-sm font-mono">
|
||||
<p className="text-emerald-700 dark:text-emerald-300/80 text-sm font-mono">
|
||||
您的代码通过了所有质量检查,包括安全性、性能、可维护性等各个方面的评估。
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -324,6 +326,7 @@ export default function TaskDetail() {
|
|||
const [loading, setLoading] = useState(true);
|
||||
const [exportDialogOpen, setExportDialogOpen] = useState(false);
|
||||
const [cancelling, setCancelling] = useState(false);
|
||||
const [scanConfigExpanded, setScanConfigExpanded] = useState(false);
|
||||
|
||||
// Zombie task detection
|
||||
const [lastProgressTime, setLastProgressTime] = useState<number>(Date.now());
|
||||
|
|
@ -646,12 +649,25 @@ export default function TaskDetail() {
|
|||
|
||||
{task.scan_config && (
|
||||
<div>
|
||||
<p className="text-xs font-bold text-muted-foreground uppercase mb-2">扫描配置</p>
|
||||
<div className="cyber-bg-elevated border border-border p-3 rounded">
|
||||
<pre className="text-xs text-emerald-400 font-mono overflow-x-auto">
|
||||
{JSON.stringify(JSON.parse(task.scan_config), null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setScanConfigExpanded(!scanConfigExpanded)}
|
||||
className="flex items-center gap-2 text-xs font-bold text-muted-foreground uppercase mb-2 hover:text-foreground transition-colors"
|
||||
>
|
||||
{scanConfigExpanded ? (
|
||||
<ChevronDown className="w-4 h-4" />
|
||||
) : (
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
)}
|
||||
扫描配置
|
||||
</button>
|
||||
{scanConfigExpanded && (
|
||||
<div className="cyber-bg-elevated border border-border p-3 rounded">
|
||||
<pre className="text-xs text-emerald-700 dark:text-emerald-400 font-mono overflow-x-auto">
|
||||
{JSON.stringify(JSON.parse(task.scan_config), null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue