From 5da7229873479767c34ed215032d7faf0bcaf31f Mon Sep 17 00:00:00 2001 From: yyhuni Date: Thu, 8 Jan 2026 07:31:54 +0800 Subject: [PATCH] feat(scan-overview): add yaml configuration tab and improve logs layout - Add yaml_configuration field to ScanHistorySerializer for backend exposure - Implement tabbed interface with Logs and Configuration tabs in scan overview - Add YamlEditor component to display scan configuration in read-only mode - Refactor logs section to show status bar only when logs tab is active - Move auto-refresh toggle to logs tab header for better UX - Add padding to stage progress items for improved visual alignment - Add internationalization strings for new UI elements (en and zh) - Update ScanHistory type to include yamlConfiguration field - Improve tab switching state management with activeTab state --- .../apps/scan/serializers/scan_serializers.py | 2 +- .../components/scan/history/scan-overview.tsx | 79 +++++++++++++------ frontend/messages/en.json | 3 + frontend/messages/zh.json | 3 + frontend/types/scan.types.ts | 1 + 5 files changed, 64 insertions(+), 24 deletions(-) diff --git a/backend/apps/scan/serializers/scan_serializers.py b/backend/apps/scan/serializers/scan_serializers.py index 85349419..e1eef8ab 100644 --- a/backend/apps/scan/serializers/scan_serializers.py +++ b/backend/apps/scan/serializers/scan_serializers.py @@ -41,7 +41,7 @@ class ScanHistorySerializer(serializers.ModelSerializer): fields = [ 'id', 'target', 'target_name', 'engine_ids', 'engine_names', 'worker_name', 'created_at', 'status', 'error_message', 'summary', - 'progress', 'current_stage', 'stage_progress' + 'progress', 'current_stage', 'stage_progress', 'yaml_configuration' ] def get_summary(self, obj): diff --git a/frontend/components/scan/history/scan-overview.tsx b/frontend/components/scan/history/scan-overview.tsx index 6eb07b19..e8062c5b 100644 --- a/frontend/components/scan/history/scan-overview.tsx +++ b/frontend/components/scan/history/scan-overview.tsx @@ -31,9 +31,11 @@ import { Badge } from "@/components/ui/badge" import { Switch } from "@/components/ui/switch" import { Label } from "@/components/ui/label" import { Separator } from "@/components/ui/separator" +import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs" import { useScan } from "@/hooks/use-scans" import { useScanLogs } from "@/hooks/use-scan-logs" import { ScanLogList } from "@/components/scan/scan-log-list" +import { YamlEditor } from "@/components/ui/yaml-editor" import { getDateLocale } from "@/lib/date-utils" import { cn } from "@/lib/utils" import type { StageStatus } from "@/types/scan.types" @@ -96,6 +98,9 @@ export function ScanOverview({ scanId }: ScanOverviewProps) { // Auto-refresh state (default: on when running) const [autoRefresh, setAutoRefresh] = useState(true) + // Tab state for logs/config + const [activeTab, setActiveTab] = useState<'logs' | 'config'>('logs') + // Logs hook const { logs, loading: logsLoading } = useScanLogs({ scanId, @@ -329,7 +334,7 @@ export function ScanOverview({ scanId }: ScanOverviewProps) {
- {/* Right Column: Logs */} + {/* Right Column: Logs / Config */}
-
- -
- {/* Bottom status bar */} -
-
- {t("logsTitle")} - - {logs.length} 条记录 - {isRunning && autoRefresh && ( - <> - - - - 每 3 秒刷新 - - - )} -
- {isRunning && ( + {/* Tab Header */} +
+ setActiveTab(v as 'logs' | 'config')}> + + {t("logsTitle")} + {t("configTitle")} + + + {/* Auto-refresh toggle (only for logs tab when running) */} + {activeTab === 'logs' && isRunning && (
)}
+ + {/* Tab Content */} +
+ {activeTab === 'logs' ? ( + + ) : ( +
+ {scan.yamlConfiguration ? ( + {}} + disabled={true} + height="100%" + /> + ) : ( +
+ {t("noConfig")} +
+ )} +
+ )} +
+ + {/* Bottom status bar (only for logs tab) */} + {activeTab === 'logs' && ( +
+ {logs.length} 条记录 + {isRunning && autoRefresh && ( + <> + + + + 每 3 秒刷新 + + + )} +
+ )}
diff --git a/frontend/messages/en.json b/frontend/messages/en.json index ded38297..00e41ad2 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -749,6 +749,9 @@ "stagesTitle": "Scan Progress", "stagesCompleted": "completed", "logsTitle": "Scan Logs", + "configTitle": "Configuration", + "autoRefresh": "Auto Refresh", + "noConfig": "No configuration available", "noStages": "No stage progress available", "totalFound": "total found", "totalVulns": "{count} total", diff --git a/frontend/messages/zh.json b/frontend/messages/zh.json index ff5b3e3b..6a36074e 100644 --- a/frontend/messages/zh.json +++ b/frontend/messages/zh.json @@ -749,6 +749,9 @@ "stagesTitle": "扫描进度", "stagesCompleted": "完成", "logsTitle": "扫描日志", + "configTitle": "扫描配置", + "autoRefresh": "自动刷新", + "noConfig": "暂无配置信息", "noStages": "暂无阶段进度", "totalFound": "个漏洞", "totalVulns": "共 {count} 个", diff --git a/frontend/types/scan.types.ts b/frontend/types/scan.types.ts index 537dcd52..8cb01be9 100644 --- a/frontend/types/scan.types.ts +++ b/frontend/types/scan.types.ts @@ -59,6 +59,7 @@ export interface ScanRecord { progress: number // 0-100 currentStage?: ScanStage // Current scan stage (only has value in running status) stageProgress?: StageProgress // Stage progress details + yamlConfiguration?: string // YAML configuration string } export interface GetScansParams {