feat(ui): 为暗黑模式添加亮度调整并优化颜色对比度

添加暗黑模式下的亮度调整,优化颜色对比度以提高可读性
更新多个组件的颜色变量以支持亮色和暗色主题
添加可折叠的扫描配置区域以改善用户体验
This commit is contained in:
lintsinghua 2025-12-18 22:55:05 +08:00
parent 46f7a46f22
commit cb1cdb77b8
5 changed files with 138 additions and 95 deletions

View File

@ -453,6 +453,12 @@
/* ============ Severity Badges ============ */ /* ============ Severity Badges ============ */
.severity-critical { .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); background: rgba(220, 38, 38, 0.2);
color: #fca5a5; color: #fca5a5;
border: 1px solid rgba(220, 38, 38, 0.5); border: 1px solid rgba(220, 38, 38, 0.5);
@ -460,6 +466,12 @@
} }
.severity-high { .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); background: rgba(234, 88, 12, 0.2);
color: #fdba74; color: #fdba74;
border: 1px solid rgba(234, 88, 12, 0.5); border: 1px solid rgba(234, 88, 12, 0.5);
@ -467,6 +479,12 @@
} }
.severity-medium { .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); background: rgba(245, 158, 11, 0.2);
color: #fcd34d; color: #fcd34d;
border: 1px solid rgba(245, 158, 11, 0.5); border: 1px solid rgba(245, 158, 11, 0.5);
@ -474,6 +492,12 @@
} }
.severity-low { .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); background: rgba(14, 181, 196, 0.2);
color: #67e8f9; color: #67e8f9;
border: 1px solid rgba(14, 181, 196, 0.5); border: 1px solid rgba(14, 181, 196, 0.5);
@ -481,6 +505,12 @@
} }
.severity-info { .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); background: rgba(100, 116, 139, 0.2);
color: #cbd5e1; color: #cbd5e1;
border: 1px solid rgba(100, 116, 139, 0.5); border: 1px solid rgba(100, 116, 139, 0.5);

View File

@ -419,11 +419,11 @@ export default function TerminalProgressDialog({
const getLogColor = (type: LogEntry["type"]) => { const getLogColor = (type: LogEntry["type"]) => {
switch (type) { switch (type) {
case "success": case "success":
return "text-emerald-400"; return "text-emerald-600 dark:text-emerald-400";
case "error": case "error":
return "text-rose-400"; return "text-rose-600 dark:text-rose-400";
case "warning": case "warning":
return "text-amber-400"; return "text-amber-600 dark:text-amber-400";
default: default:
return "text-muted-foreground"; return "text-muted-foreground";
} }
@ -432,13 +432,13 @@ export default function TerminalProgressDialog({
return ( return (
<Dialog open={open} onOpenChange={onOpenChange}> <Dialog open={open} onOpenChange={onOpenChange}>
<DialogPortal> <DialogPortal>
<DialogOverlay className="bg-black/85 backdrop-blur-md" /> <DialogOverlay className="bg-black/50 dark:bg-black/85 backdrop-blur-md" />
<DialogPrimitive.Content <DialogPrimitive.Content
className={cn( className={cn(
"fixed left-[50%] top-[50%] z-50 translate-x-[-50%] translate-y-[-50%]", "fixed left-[50%] top-[50%] z-50 translate-x-[-50%] translate-y-[-50%]",
"w-[95vw] max-w-[1000px] h-[85vh] max-h-[700px]", "w-[95vw] max-w-[1000px] h-[85vh] max-h-[700px]",
"bg-[#08090d] border border-[#1a2535] rounded overflow-hidden", "bg-white dark:bg-[#08090d] border border-slate-200 dark: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)]", "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=open]:animate-in data-[state=closed]:animate-out",
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95", "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
@ -454,44 +454,43 @@ export default function TerminalProgressDialog({
</DialogPrimitive.Description> </DialogPrimitive.Description>
</VisuallyHidden.Root> </VisuallyHidden.Root>
{/* Scanline overlay */} {/* Scanline overlay - only in dark mode */}
<div className="absolute inset-0 pointer-events-none z-20 opacity-30" <div className="absolute inset-0 pointer-events-none z-20 opacity-0 dark:opacity-30"
style={{ style={{
backgroundImage: "repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0,0,0,0.1) 2px, rgba(0,0,0,0.1) 4px)", backgroundImage: "repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0,0,0,0.1) 2px, rgba(0,0,0,0.1) 4px)",
}} }}
/> />
{/* Header */} {/* Header */}
<div className="flex items-center justify-between px-4 py-3 cyber-bg-elevated border-b border-[#1a2535]" <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]">
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 gap-3"> <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> <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-lg font-bold uppercase tracking-[0.15em] text-slate-800 dark:text-[#f0e6d3]">AUDIT_TERMINAL</span>
<span className="text-xs text-[#5a6577] ml-2 tracking-wider">v3.0</span> <span className="text-xs text-slate-500 dark:text-[#5a6577] ml-2 tracking-wider">v3.0</span>
</div> </div>
</div> </div>
<div className="flex items-center gap-4"> <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 <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-emerald-500 dark:bg-[#3dd68c] shadow-[0_0_10px_rgba(61,214,140,0.7)] animate-pulse'
: 'bg-[#3a4555]'}`} /> : 'bg-slate-300 dark:bg-[#3a4555]'}`} />
<div className={`w-2.5 h-2.5 rounded-full transition-all duration-300 ${isFailed <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-rose-500 dark:bg-[#f87171] shadow-[0_0_10px_rgba(248,113,113,0.7)]'
: 'bg-[#3a4555]'}`} /> : 'bg-slate-300 dark:bg-[#3a4555]'}`} />
<div className={`w-2.5 h-2.5 rounded-full transition-all duration-300 ${isCompleted <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-cyan-500 dark:bg-[#22d3ee] shadow-[0_0_10px_rgba(34,211,238,0.7)]'
: 'bg-[#3a4555]'}`} /> : 'bg-slate-300 dark:bg-[#3a4555]'}`} />
</div> </div>
<button <button
type="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)} 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> </button>
</div> </div>
</div> </div>
@ -499,22 +498,21 @@ export default function TerminalProgressDialog({
{/* Main Content */} {/* Main Content */}
<div className="flex h-[calc(100%-56px)]"> <div className="flex h-[calc(100%-56px)]">
{/* Left Sidebar - Task Info */} {/* 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="space-y-1.5">
<div className="text-xs font-bold text-[#5a6577] uppercase tracking-[0.15em]">Task ID</div> <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 cyber-bg-elevated p-2.5 rounded border border-[#1a2535]" <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]">
style={{ textShadow: "0 0 10px rgba(255, 95, 31, 0.3)" }}>
{taskId?.slice(0, 8)}... {taskId?.slice(0, 8)}...
</div> </div>
</div> </div>
<div className="space-y-1.5"> <div className="space-y-1.5">
<div className="text-xs font-bold text-[#5a6577] uppercase tracking-[0.15em]">Type</div> <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 cyber-bg-elevated p-2.5 rounded border border-[#1a2535]"> <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' {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))" }} /> ? <Cpu className="w-3.5 h-3.5 text-cyan-600 dark:text-[#22d3ee]" />
: <HardDrive className="w-3.5 h-3.5 text-[#fbbf24]" style={{ filter: "drop-shadow(0 0 6px rgba(251, 191, 36, 0.5))" }} />} : <HardDrive className="w-3.5 h-3.5 text-amber-600 dark:text-[#fbbf24]" />}
<span className="text-xs font-bold text-[#d0d8e8] uppercase tracking-wider">{taskType}</span> <span className="text-xs font-bold text-slate-700 dark:text-[#d0d8e8] uppercase tracking-wider">{taskType}</span>
</div> </div>
</div> </div>
@ -522,7 +520,7 @@ export default function TerminalProgressDialog({
{/* Status Badge */} {/* Status Badge */}
<div className="space-y-2"> <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 ? ( {isCancelled ? (
<Badge className="w-full justify-center cyber-badge-warning">CANCELLED</Badge> <Badge className="w-full justify-center cyber-badge-warning">CANCELLED</Badge>
) : isCompleted ? ( ) : isCompleted ? (
@ -538,18 +536,17 @@ export default function TerminalProgressDialog({
{/* Terminal Screen */} {/* Terminal Screen */}
<div className="flex-1 flex flex-col"> <div className="flex-1 flex flex-col">
{/* Terminal Output */} {/* Terminal Output */}
<div className="flex-1 bg-[#050608] p-4 overflow-y-auto font-mono text-sm custom-scrollbar relative"> <div className="flex-1 bg-slate-100 dark:bg-[#050608] p-4 overflow-y-auto font-mono text-sm custom-scrollbar relative">
{/* Grid background */} {/* Grid background - only in dark mode */}
<div className="absolute inset-0 cyber-grid-subtle pointer-events-none opacity-40" /> <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"> <div className="relative z-10 space-y-0.5 pb-10">
{logs.map((log) => ( {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"> <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-[#4a5565] text-xs flex-shrink-0 w-20 font-mono"> <span className="text-slate-500 dark:text-[#4a5565] text-xs flex-shrink-0 w-20 font-mono">
{log.timestamp} {log.timestamp}
</span> </span>
<span className={`${getLogColor(log.type)} flex-1 font-mono text-sm`} <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' }}>
{log.message} {log.message}
</span> </span>
</div> </div>
@ -557,8 +554,8 @@ export default function TerminalProgressDialog({
{!isCompleted && !isFailed && !isCancelled && ( {!isCompleted && !isFailed && !isCancelled && (
<div className="flex items-center gap-3 mt-4 px-2"> <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-slate-500 dark: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-primary animate-pulse font-bold">_</span>
</div> </div>
)} )}
<div ref={logsEndRef} /> <div ref={logsEndRef} />
@ -566,8 +563,8 @@ export default function TerminalProgressDialog({
</div> </div>
{/* Bottom Controls */} {/* Bottom Controls */}
<div className="h-14 px-4 border-t border-[#1a2535] cyber-bg-elevated/90 flex items-center justify-between"> <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-[#6a7587] font-mono tracking-wide"> <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" /> <Activity className="w-3.5 h-3.5" />
<span> <span>
{isCompleted ? "TASK COMPLETED" : isFailed ? "TASK FAILED" : isCancelled ? "TASK CANCELLED" : "EXECUTING..."} {isCompleted ? "TASK COMPLETED" : isFailed ? "TASK FAILED" : isCancelled ? "TASK CANCELLED" : "EXECUTING..."}
@ -580,7 +577,7 @@ export default function TerminalProgressDialog({
size="sm" size="sm"
variant="outline" variant="outline"
onClick={handleCancel} 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" /> <AlertTriangle className="w-3 h-3 mr-1.5" />
@ -592,7 +589,7 @@ export default function TerminalProgressDialog({
size="sm" size="sm"
variant="outline" variant="outline"
onClick={() => window.open('/logs', '_blank')} 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" /> <Activity className="w-3 h-3 mr-1.5" />

View File

@ -390,12 +390,12 @@ public class Example {
<div className="w-4 h-4 bg-primary rounded flex items-center justify-center"> <div className="w-4 h-4 bg-primary rounded flex items-center justify-center">
<Code className="w-2 h-2 text-foreground" /> <Code className="w-2 h-2 text-foreground" />
</div> </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> </div>
<span className="text-muted-foreground text-xs font-mono">LINE: {issue.line}</span> <span className="text-muted-foreground text-xs font-mono">LINE: {issue.line}</span>
</div> </div>
<div className="bg-black/40 p-2 border border-border rounded"> <div className="bg-slate-100 dark:bg-black/40 p-2 border border-border rounded">
<pre className="text-xs text-emerald-400 font-mono overflow-x-auto"> <pre className="text-xs text-emerald-700 dark:text-emerald-400 font-mono overflow-x-auto">
<code>{issue.code_snippet}</code> <code>{issue.code_snippet}</code>
</pre> </pre>
</div> </div>
@ -407,11 +407,11 @@ public class Example {
<div className="bg-sky-500/10 border border-sky-500/30 p-3 rounded"> <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="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"> <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> </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> </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> </div>
)} )}
@ -423,37 +423,37 @@ public class Example {
<div className="bg-violet-500/10 border border-violet-500/30 p-3 rounded"> <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="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"> <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> </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>
<div className="space-y-2 text-xs font-mono"> <div className="space-y-2 text-xs font-mono">
{parsedExplanation.what && ( {parsedExplanation.what && (
<div className="border-l-2 border-rose-500 pl-2"> <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> <span className="text-foreground ml-1">{parsedExplanation.what}</span>
</div> </div>
)} )}
{parsedExplanation.why && ( {parsedExplanation.why && (
<div className="border-l-2 border-amber-500 pl-2"> <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> <span className="text-foreground ml-1">{parsedExplanation.why}</span>
</div> </div>
)} )}
{parsedExplanation.how && ( {parsedExplanation.how && (
<div className="border-l-2 border-emerald-500 pl-2"> <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> <span className="text-foreground ml-1">{parsedExplanation.how}</span>
</div> </div>
)} )}
{parsedExplanation.learn_more && ( {parsedExplanation.learn_more && (
<div className="border-l-2 border-sky-500 pl-2"> <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 <a
href={parsedExplanation.learn_more} href={parsedExplanation.learn_more}
target="_blank" target="_blank"
rel="noopener noreferrer" 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} {parsedExplanation.learn_more}
</a> </a>
@ -466,8 +466,8 @@ public class Example {
return ( return (
<div className="bg-violet-500/10 border border-violet-500/30 p-3 rounded"> <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="flex items-center mb-2 border-b border-violet-500/20 pb-1">
<Zap className="w-4 h-4 text-violet-400 mr-2" /> <Zap className="w-4 h-4 text-violet-600 dark:text-violet-400 mr-2" />
<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>
<p className="text-foreground text-xs leading-relaxed font-mono">{issue.ai_explanation}</p> <p className="text-foreground text-xs leading-relaxed font-mono">{issue.ai_explanation}</p>
</div> </div>
@ -855,11 +855,11 @@ public class Example {
</Tabs> </Tabs>
) : ( ) : (
<div className="cyber-card p-16 text-center border-dashed"> <div className="cyber-card p-16 text-center border-dashed">
<CheckCircle className="w-16 h-16 text-emerald-400 mx-auto mb-4" /> <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-300 mb-2 uppercase"></h3> <h3 className="text-xl font-bold text-emerald-700 dark:text-emerald-300 mb-2 uppercase"></h3>
<p className="text-emerald-400/80 mb-4 font-mono"></p> <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"> <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> </p>
</div> </div>

View File

@ -677,10 +677,10 @@ export default function ProjectDetail() {
<div className="flex items-start justify-between"> <div className="flex items-start justify-between">
<div className="flex items-start space-x-3"> <div className="flex items-start space-x-3">
<div className={`w-8 h-8 rounded-lg flex items-center justify-center ${ <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 === 'critical' ? 'bg-rose-500/20 text-rose-600 dark:text-rose-400' :
issue.severity === 'high' ? 'bg-orange-500/20 text-orange-400' : issue.severity === 'high' ? 'bg-orange-500/20 text-orange-600 dark:text-orange-400' :
issue.severity === 'medium' ? 'bg-amber-500/20 text-amber-400' : issue.severity === 'medium' ? 'bg-amber-500/20 text-amber-600 dark:text-amber-400' :
'bg-sky-500/20 text-sky-400' 'bg-sky-500/20 text-sky-600 dark:text-sky-400'
}`}> }`}>
<AlertTriangle className="w-4 h-4" /> <AlertTriangle className="w-4 h-4" />
</div> </div>
@ -712,7 +712,7 @@ export default function ProjectDetail() {
</div> </div>
) : ( ) : (
<div className="cyber-card p-12 text-center"> <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> <h3 className="text-lg font-bold text-foreground mb-2 uppercase"></h3>
<p className="text-sm text-muted-foreground font-mono"></p> <p className="text-sm text-muted-foreground font-mono"></p>
</div> </div>

View File

@ -27,7 +27,9 @@ import {
Info, Info,
Zap, Zap,
XCircle, XCircle,
Terminal Terminal,
ChevronDown,
ChevronRight
} from "lucide-react"; } from "lucide-react";
import { api } from "@/shared/config/database"; import { api } from "@/shared/config/database";
import type { AuditTask, AuditIssue } from "@/shared/types"; 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"> <div className="w-4 h-4 bg-primary rounded flex items-center justify-center">
<Code className="w-2 h-2 text-foreground" /> <Code className="w-2 h-2 text-foreground" />
</div> </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> </div>
{issue.line_number && ( {issue.line_number && (
<span className="text-muted-foreground text-xs font-mono">LINE: {issue.line_number}</span> <span className="text-muted-foreground text-xs font-mono">LINE: {issue.line_number}</span>
)} )}
</div> </div>
<div className="bg-black/40 p-2 border border-border rounded"> <div className="bg-slate-100 dark:bg-black/40 p-2 border border-border rounded">
<pre className="text-xs text-emerald-400 font-mono overflow-x-auto"> <pre className="text-xs text-emerald-700 dark:text-emerald-400 font-mono overflow-x-auto">
<code>{issue.code_snippet}</code> <code>{issue.code_snippet}</code>
</pre> </pre>
</div> </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="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="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"> <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> </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> </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> </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="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="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"> <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> </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>
<div className="space-y-2 text-xs font-mono"> <div className="space-y-2 text-xs font-mono">
{parsedExplanation.what && ( {parsedExplanation.what && (
<div className="border-l-2 border-rose-500 pl-2"> <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> <span className="text-foreground ml-1">{parsedExplanation.what}</span>
</div> </div>
)} )}
{parsedExplanation.why && ( {parsedExplanation.why && (
<div className="border-l-2 border-amber-500 pl-2"> <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> <span className="text-foreground ml-1">{parsedExplanation.why}</span>
</div> </div>
)} )}
{parsedExplanation.how && ( {parsedExplanation.how && (
<div className="border-l-2 border-emerald-500 pl-2"> <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> <span className="text-foreground ml-1">{parsedExplanation.how}</span>
</div> </div>
)} )}
{parsedExplanation.learn_more && ( {parsedExplanation.learn_more && (
<div className="border-l-2 border-sky-500 pl-2"> <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 <a
href={parsedExplanation.learn_more} href={parsedExplanation.learn_more}
target="_blank" target="_blank"
rel="noopener noreferrer" 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} {parsedExplanation.learn_more}
</a> </a>
@ -215,8 +217,8 @@ function IssuesList({ issues }: { issues: AuditIssue[] }) {
return ( return (
<div className="bg-violet-500/10 border border-violet-500/30 p-3 rounded"> <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="flex items-center mb-2 border-b border-violet-500/20 pb-1">
<Zap className="w-4 h-4 text-violet-400 mr-2" /> <Zap className="w-4 h-4 text-violet-600 dark:text-violet-400 mr-2" />
<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>
<p className="text-foreground text-xs leading-relaxed font-mono">{issue.ai_explanation}</p> <p className="text-foreground text-xs leading-relaxed font-mono">{issue.ai_explanation}</p>
</div> </div>
@ -230,11 +232,11 @@ function IssuesList({ issues }: { issues: AuditIssue[] }) {
if (issues.length === 0) { if (issues.length === 0) {
return ( return (
<div className="cyber-card p-16 text-center border-dashed"> <div className="cyber-card p-16 text-center border-dashed">
<CheckCircle className="w-16 h-16 text-emerald-400 mx-auto mb-4" /> <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-300 mb-2 uppercase"></h3> <h3 className="text-xl font-bold text-emerald-700 dark:text-emerald-300 mb-2 uppercase"></h3>
<p className="text-emerald-400/80 mb-4 font-mono"></p> <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"> <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> </p>
</div> </div>
@ -324,6 +326,7 @@ export default function TaskDetail() {
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [exportDialogOpen, setExportDialogOpen] = useState(false); const [exportDialogOpen, setExportDialogOpen] = useState(false);
const [cancelling, setCancelling] = useState(false); const [cancelling, setCancelling] = useState(false);
const [scanConfigExpanded, setScanConfigExpanded] = useState(false);
// Zombie task detection // Zombie task detection
const [lastProgressTime, setLastProgressTime] = useState<number>(Date.now()); const [lastProgressTime, setLastProgressTime] = useState<number>(Date.now());
@ -646,12 +649,25 @@ export default function TaskDetail() {
{task.scan_config && ( {task.scan_config && (
<div> <div>
<p className="text-xs font-bold text-muted-foreground uppercase mb-2"></p> <button
<div className="cyber-bg-elevated border border-border p-3 rounded"> type="button"
<pre className="text-xs text-emerald-400 font-mono overflow-x-auto"> onClick={() => setScanConfigExpanded(!scanConfigExpanded)}
{JSON.stringify(JSON.parse(task.scan_config), null, 2)} className="flex items-center gap-2 text-xs font-bold text-muted-foreground uppercase mb-2 hover:text-foreground transition-colors"
</pre> >
</div> {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>
)} )}
</div> </div>