mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-23 11:41:53 +08:00
## 架构重构
- 全局变量消除,迁移至 Config/State 对象
- SMB 插件融合(smb/smb2/smbghost/smbinfo)
- 服务探测重构,实现 Nmap 风格 fallback 机制
- 输出系统重构,TXT 实时刷盘 + 双写机制
- i18n 框架升级至 go-i18n
## 性能优化
- 正则表达式预编译
- 内存优化 map[string]struct{}
- 并发指纹匹配
- SOCKS5 连接复用
- 滑动窗口调度 + 自适应线程池
## 新功能
- Web 管理界面
- 多格式 POC 适配(xray/afrog)
- 增强指纹库(3139条)
- Favicon hash 指纹识别
- 插件选择性编译(Build Tags)
- fscan-lab 靶场环境
- 默认端口扩展(62→133)
## 构建系统
- 添加 no_local tag 支持排除本地插件
- 多版本构建:fscan/fscan-nolocal/fscan-web
- CI 添加 snapshot 模式支持仅测试构建
## Bug 修复
- 修复 120+ 个问题,包括 RDP panic、批量扫描漏报、
JSON 输出格式、Redis 检测、Context 超时等
## 测试增强
- 单元测试覆盖率 74-100%
- 并发安全测试
- 集成测试(Web/端口/服务/SSH/ICMP)
258 lines
5.9 KiB
CSS
258 lines
5.9 KiB
CSS
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans:wght@400;500;600&display=swap');
|
|
|
|
@tailwind base;
|
|
@tailwind components;
|
|
@tailwind utilities;
|
|
|
|
@layer base {
|
|
:root {
|
|
--background: 0 0% 99%;
|
|
--foreground: 220 14% 10%;
|
|
--card: 0 0% 100%;
|
|
--card-foreground: 220 14% 10%;
|
|
--popover: 0 0% 100%;
|
|
--popover-foreground: 220 14% 10%;
|
|
--primary: 220 14% 10%;
|
|
--primary-foreground: 0 0% 99%;
|
|
--secondary: 220 13% 95%;
|
|
--secondary-foreground: 220 14% 10%;
|
|
--muted: 220 13% 95%;
|
|
--muted-foreground: 220 9% 46%;
|
|
--accent: 220 13% 95%;
|
|
--accent-foreground: 220 14% 10%;
|
|
--destructive: 0 72% 51%;
|
|
--destructive-foreground: 0 0% 99%;
|
|
--border: 220 13% 90%;
|
|
--input: 220 13% 90%;
|
|
--ring: 220 14% 10%;
|
|
--radius: 0.5rem;
|
|
--success: 142 71% 45%;
|
|
--warning: 38 92% 50%;
|
|
/* Chart colors */
|
|
--chart-1: 217 91% 60%;
|
|
--chart-2: 160 84% 39%;
|
|
--chart-3: 43 96% 56%;
|
|
--chart-4: 0 72% 51%;
|
|
--chart-5: 262 83% 58%;
|
|
}
|
|
|
|
.dark {
|
|
--background: 220 16% 6%;
|
|
--foreground: 220 13% 95%;
|
|
--card: 220 16% 8%;
|
|
--card-foreground: 220 13% 95%;
|
|
--popover: 220 16% 8%;
|
|
--popover-foreground: 220 13% 95%;
|
|
--primary: 220 13% 95%;
|
|
--primary-foreground: 220 16% 6%;
|
|
--secondary: 220 14% 14%;
|
|
--secondary-foreground: 220 13% 95%;
|
|
--muted: 220 14% 14%;
|
|
--muted-foreground: 220 9% 55%;
|
|
--accent: 220 14% 14%;
|
|
--accent-foreground: 220 13% 95%;
|
|
--destructive: 0 62% 50%;
|
|
--destructive-foreground: 220 13% 95%;
|
|
--border: 220 14% 16%;
|
|
--input: 220 14% 16%;
|
|
--ring: 220 13% 95%;
|
|
--success: 142 71% 45%;
|
|
--warning: 38 92% 50%;
|
|
/* Chart colors */
|
|
--chart-1: 217 91% 65%;
|
|
--chart-2: 160 84% 45%;
|
|
--chart-3: 43 96% 60%;
|
|
--chart-4: 0 72% 55%;
|
|
--chart-5: 262 83% 65%;
|
|
}
|
|
}
|
|
|
|
@layer base {
|
|
* {
|
|
@apply border-border;
|
|
}
|
|
|
|
/* 响应式基础字体 - 放大 */
|
|
html {
|
|
font-size: 15px;
|
|
-webkit-font-smoothing: antialiased;
|
|
-moz-osx-font-smoothing: grayscale;
|
|
}
|
|
|
|
@media (min-width: 640px) {
|
|
html {
|
|
font-size: 16px;
|
|
}
|
|
}
|
|
|
|
@media (min-width: 1024px) {
|
|
html {
|
|
font-size: 17px;
|
|
}
|
|
}
|
|
|
|
@media (min-width: 1280px) {
|
|
html {
|
|
font-size: 18px;
|
|
}
|
|
}
|
|
|
|
body {
|
|
@apply bg-background text-foreground;
|
|
font-family: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
margin: 0;
|
|
line-height: 1.6;
|
|
}
|
|
}
|
|
|
|
@layer components {
|
|
/* 响应式容器 - 全屏宽度 */
|
|
.container {
|
|
@apply mx-auto px-3 sm:px-4 lg:px-6 xl:px-8;
|
|
max-width: 100%;
|
|
}
|
|
|
|
/* Stat pill - 放大 */
|
|
.stat-pill {
|
|
@apply flex items-center gap-2 px-3 py-1.5 rounded-md bg-muted/60 text-sm;
|
|
}
|
|
|
|
.stat-pill-value {
|
|
@apply font-mono font-semibold tabular-nums text-base;
|
|
}
|
|
|
|
/* Card - 放大 */
|
|
.card-compact {
|
|
@apply rounded-lg border bg-card shadow-sm;
|
|
}
|
|
|
|
.card-compact-header {
|
|
@apply flex items-center justify-between px-4 py-3 border-b bg-muted/30;
|
|
}
|
|
|
|
.card-compact-body {
|
|
@apply p-4;
|
|
}
|
|
|
|
/* Form field - 放大 */
|
|
.field-label {
|
|
@apply text-xs font-medium text-muted-foreground uppercase tracking-wide mb-1.5;
|
|
}
|
|
|
|
.field-input {
|
|
@apply h-10 text-sm px-3;
|
|
}
|
|
|
|
.field-input-mono {
|
|
@apply h-10 text-sm px-3 font-mono;
|
|
}
|
|
|
|
/* Live log styling - 放大 */
|
|
.log-line {
|
|
@apply flex items-center gap-3 py-1.5 px-2 text-sm font-mono rounded-md;
|
|
@apply hover:bg-muted/50 transition-colors;
|
|
}
|
|
|
|
.log-time {
|
|
@apply text-muted-foreground w-20 shrink-0 text-xs sm:text-sm;
|
|
}
|
|
|
|
.log-type {
|
|
@apply w-16 shrink-0 font-medium text-xs sm:text-sm;
|
|
}
|
|
|
|
.log-target {
|
|
@apply truncate text-xs sm:text-sm;
|
|
}
|
|
|
|
/* Type colors */
|
|
.type-host { @apply text-blue-600 dark:text-blue-400; }
|
|
.type-port { @apply text-emerald-600 dark:text-emerald-400; }
|
|
.type-service { @apply text-amber-600 dark:text-amber-400; }
|
|
.type-vuln { @apply text-red-600 dark:text-red-400; }
|
|
|
|
/* Badge - 放大 */
|
|
.badge {
|
|
@apply inline-flex items-center px-2 py-1 rounded-md text-xs font-medium uppercase tracking-wide;
|
|
}
|
|
|
|
.badge-host { @apply bg-blue-500/10 text-blue-600 dark:text-blue-400; }
|
|
.badge-port { @apply bg-emerald-500/10 text-emerald-600 dark:text-emerald-400; }
|
|
.badge-service { @apply bg-amber-500/10 text-amber-600 dark:text-amber-400; }
|
|
.badge-vuln { @apply bg-red-500/10 text-red-600 dark:text-red-400; }
|
|
|
|
/* Switch row - 放大 */
|
|
.switch-row {
|
|
@apply flex items-center justify-between py-2 px-3 rounded-md bg-muted/40 text-sm;
|
|
}
|
|
|
|
/* Scrollbar */
|
|
.scrollbar-thin {
|
|
scrollbar-width: thin;
|
|
scrollbar-color: hsl(var(--border)) transparent;
|
|
}
|
|
|
|
.scrollbar-thin::-webkit-scrollbar {
|
|
width: 6px;
|
|
height: 6px;
|
|
}
|
|
|
|
.scrollbar-thin::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
|
|
.scrollbar-thin::-webkit-scrollbar-thumb {
|
|
background-color: hsl(var(--border));
|
|
border-radius: 3px;
|
|
}
|
|
|
|
/* Animations */
|
|
@keyframes fade-in {
|
|
from { opacity: 0; transform: translateY(-2px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
.animate-fade-in {
|
|
animation: fade-in 0.15s ease-out;
|
|
}
|
|
|
|
@keyframes slide-up {
|
|
from { opacity: 0; transform: translateY(4px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
.animate-slide-up {
|
|
animation: slide-up 0.2s ease-out;
|
|
}
|
|
|
|
@keyframes pulse-soft {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0.6; }
|
|
}
|
|
|
|
.animate-pulse-soft {
|
|
animation: pulse-soft 2s ease-in-out infinite;
|
|
}
|
|
|
|
/* Focus ring */
|
|
.focus-ring {
|
|
@apply focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background;
|
|
}
|
|
|
|
/* Hover lift effect */
|
|
.hover-lift {
|
|
@apply transition-transform hover:-translate-y-0.5;
|
|
}
|
|
|
|
/* Subtle shadow on hover */
|
|
.hover-shadow {
|
|
@apply transition-shadow hover:shadow-md;
|
|
}
|
|
}
|
|
|
|
@layer utilities {
|
|
.font-mono {
|
|
font-family: 'IBM Plex Mono', ui-monospace, monospace;
|
|
}
|
|
}
|