From 3a590e505328b7865a9ffd898f085ba5f9ad0b95 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 12 Aug 2026 13:51:29 +0800 Subject: [PATCH] =?UTF-8?q?UI=E9=87=8D=E6=9E=84:=20=E9=87=87=E7=94=A8NapCa?= =?UTF-8?q?t=E8=AE=BE=E8=AE=A1=E8=AF=AD=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 坚持单文件embed(go:embed ui/*),保留全部既有JS功能 - 从NapCat WebUI提取设计DNA并产出 napcat-design-dna.json - 新增主色调切换:Sakura(默认)/Ocean/Violet 三套完整色板 - 全部emoji替换为内联SVG图标 - 侧边栏响应式折叠(≤900px),背景毛玻璃+动态梯度blobs - 优化性能:降低blur强度、记录表仅渲染最近300条、支持prefers-reduced-motion、页面隐藏暂停轮询 - 修正焦点轮廓、移除方形框提示 - 面包屑+hamburger+sidebar+accent picker完整chrome - 通过Playwright无头浏览器全链路验证:登录/导航/主题/语言/响应式/聊天/统计 --- internal/gateway/ui/index.html | 1044 +++++++++++++++++--------------- napcat-design-dna.json | 348 +++++++++++ 2 files changed, 915 insertions(+), 477 deletions(-) create mode 100644 napcat-design-dna.json diff --git a/internal/gateway/ui/index.html b/internal/gateway/ui/index.html index c7915cc..6499176 100644 --- a/internal/gateway/ui/index.html +++ b/internal/gateway/ui/index.html @@ -6,469 +6,523 @@ ModelRouter - - -
-
- -

ModelRouter

统一 LLM 网关
+ + + +
+ +
+
+ +
+
+ + + + + +
- -
-
- - - -
-
-
-
- - - - - -
+
+ - \ No newline at end of file + diff --git a/napcat-design-dna.json b/napcat-design-dna.json new file mode 100644 index 0000000..2f7318f --- /dev/null +++ b/napcat-design-dna.json @@ -0,0 +1,348 @@ +{ + "meta": { + "name": "NapCat WebUI Design DNA", + "description": "Design DNA extracted from NapCat WebUI (napcat-webui-frontend) — ACG/cherry-blossom aesthetic with glassmorphism, motion/react animations, HeroUI components, sakura/frost color palette", + "source_references": [ + "https://github.com/NapNeko/NapCatQQ/tree/main/packages/napcat-webui-frontend", + "packages/napcat-webui-frontend/tailwind.config.js", + "packages/napcat-webui-frontend/src/styles/globals.css", + "packages/napcat-webui-frontend/src/components/page_background.tsx", + "packages/napcat-webui-frontend/src/components/effect_card.tsx", + "packages/napcat-webui-frontend/src/layouts/default.tsx", + "packages/napcat-webui-frontend/src/layouts/pure.tsx", + "packages/napcat-webui-frontend/src/pages/web_login.tsx", + "packages/napcat-webui-frontend/src/pages/dashboard/index.tsx", + "packages/napcat-webui-frontend/src/components/sidebar/index.tsx", + "packages/napcat-webui-frontend/src/components/display_network_item.tsx", + "packages/napcat-webui-frontend/src/components/system_status_display.tsx", + "packages/napcat-webui-frontend/src/config/site.tsx" + ], + "created_at": "2026-08-12T00:00:00Z" + }, + "design_system": { + "color": { + "palette_type": "split-complementary", + "primary": { + "hex": "#FF7FAC", + "role": "Sakura pink - dominant accent, CTAs, focus rings, interactive elements" + }, + "secondary": { + "hex": "#88C0D0", + "role": "Frost blue - supporting accent, secondary actions, info states" + }, + "accent": { + "hex": "#F33B7C", + "role": "Deep rose - hover/active primary, destructive actions" + }, + "neutral": { + "scale": { + "50": "#FFF0F5", + "100": "#FFE4E9", + "200": "#FFCDD9", + "300": "#FF9EB5", + "400": "#FF7FAC", + "500": "#F33B7C", + "600": "#C92462", + "700": "#991B4B", + "800": "#691233", + "900": "#380A1B" + }, + "usage": "Pink-tinted neutrals for light mode; inverted for dark mode" + }, + "semantic": { + "success": "#17a964", + "warning": "#b7791f", + "error": "#DB3694", + "info": "#3f6ef5" + }, + "surface": { + "background": "gradient-to-br from-indigo-50 via-white to-pink-50 (light) / dark:from-gray-900 dark:via-gray-800 dark:to-gray-900", + "card": "bg-white/60 dark:bg-black/40 with backdrop-blur-sm border border-white/40 dark:border-white/10", + "elevated": "bg-white/70 dark:bg-black/30 hover:bg-white/80 dark:hover:bg-black/20 with shadow-sm" + }, + "contrast_strategy": "subtle layers with glassmorphism — semi-transparent cards over gradient backgrounds, white/black text with opacity modulation" + }, + "typography": { + "type_scale": { + "display": { + "size": "4xl-5xl (36-48px)", + "weight": "bold", + "line_height": "1.1", + "tracking": "-0.02em" + }, + "heading_1": { + "size": "2xl-3xl (24-30px)", + "weight": "semibold", + "line_height": "1.2", + "tracking": "-0.02em" + }, + "heading_2": { + "size": "xl-2xl (20-24px)", + "weight": "semibold", + "line_height": "1.3", + "tracking": "-0.01em" + }, + "heading_3": { + "size": "lg-xl (18-20px)", + "weight": "medium", + "line_height": "1.4", + "tracking": "0" + }, + "body": { + "size": "base (16px)", + "weight": "normal", + "line_height": "1.55", + "tracking": "0.02em" + }, + "body_small": { + "size": "sm (14px)", + "weight": "normal", + "line_height": "1.5", + "tracking": "0.01em" + }, + "caption": { + "size": "xs (12px)", + "weight": "normal", + "line_height": "1.4", + "tracking": "0.02em" + }, + "overline": { + "size": "xs (12px)", + "weight": "medium", + "line_height": "1.3", + "tracking": "0.08em" + } + }, + "font_families": { + "heading": "'Quicksand', 'Nunito', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'PingFang SC', 'Microsoft YaHei', sans-serif", + "body": "'Quicksand', 'Nunito', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'PingFang SC', 'Microsoft YaHei', sans-serif", + "mono": "'JetBrains Mono', 'ui-monospace', 'SFMono-Regular', 'SF Mono', 'Menlo', 'Consolas', 'Liberation Mono', monospace" + }, + "font_style_notes": "Rounded geometric sans (Quicksand/Nunito) for friendly ACG feel; JetBrains Mono for code/terminal; letter-spacing 0.02em body, negative for headings; -webkit-font-smoothing antialiased" + }, + "spacing": { + "base_unit": "4px (0.25rem)", + "scale": [0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40, 48, 64], + "content_density": "comfortable with generous breathing room; cards use p-4/p-5/p-6; sections gap-4/gap-6", + "section_rhythm": "Consistent 4-unit (16px) base rhythm; md:gap-4 (16px) / lg:gap-6 (24px) for grid gaps; py-5 (20px) vertical section padding" + }, + "layout": { + "grid_system": "CSS Grid + Flexbox hybrid; 8-col mobile / 3-col md / 6-col lg for dashboards; sidebar 16rem (256px) fixed", + "max_content_width": "1000px (md:max-w-[1000px]) for main content; full-width for login/pure layouts", + "columns": "Responsive: 1col < 3col md < 6col lg", + "gutter": "gap-1 (4px) sm / gap-4 (16px) md", + "breakpoints": "sm: 640px, md: 768px, lg: 1024px, xl: 1280px (Tailwind defaults)", + "alignment_tendency": "centered for auth/pure layouts; left-aligned grid for dashboards; sticky top breadcrumbs" + }, + "shape": { + "border_radius": { + "small": "0.375rem (6px) - inputs, buttons", + "medium": "0.5rem (8px) - cards, modals", + "large": "0.75rem (12px) - HeroUI default radius (--heroui-radius: 0.75rem)", + "pill": "9999px (full) - primary CTAs, pills, tags" + }, + "border_usage": "subtle 1px border-white/40 dark:border-white/10 on glass cards; no hard borders elsewhere", + "divider_style": "hairline via backdrop-blur edges; HeroUI divider component for lists" + }, + "elevation": { + "shadow_style": "soft diffused with backdrop-blur; layering via transparency not heavy shadows", + "levels": { + "low": "shadow-sm (0 1px 2px rgba(0,0,0,0.05)) + backdrop-blur-sm", + "medium": "shadow-md (0 4px 6px rgba(0,0,0,0.07)) + backdrop-blur-md", + "high": "shadow-xl (0 20px 25px rgba(0,0,0,0.1)) + backdrop-blur-xl + backdrop-saturate-200" + }, + "depth_cues": ["backdrop-blur", "transparency/opacity", "subtle borders", "hover elevation increase", "motion scale on interaction"] + }, + "iconography": { + "style": "Lucide React (Lu*) icons — clean 2px stroke, rounded caps; react-icons for brand icons (Gi, Bi, Io, Md)", + "stroke_weight": "2px equivalent (w-5 h-5 default, w-4 h-4 small, w-6 h-6 large)", + "size_scale": "xs: 14px, sm: 16px, md: 20px, lg: 24px, xl: 32px", + "preferred_set": "Lucide React for UI; react-icons for brand/logos" + }, + "motion": { + "easing": "spring (stiffness: 120-150, damping: 15-20) for layout; ease-out for micro-interactions", + "duration_scale": { + "micro": "150-200ms (hover, focus, tap)", + "normal": "300-400ms (page transitions, sidebar, modals)", + "macro": "500ms (initial entrance, spring animations)" + }, + "entrance_pattern": "fade-up (opacity 0→1, y: 20→0) + scale (0.95→1) with spring; staggered children via AnimatePresence", + "exit_pattern": "fade-down (opacity 1→0, y: 0→10) fast tween (150ms)", + "philosophy": "playful spring physics for layout; snappy functional for interactions; motion/redux (framer-motion) for complex choreography" + }, + "components": { + "button_style": "HeroUI Button variants: shadow (primary CTA), flat (secondary), light (ghost), bordered; pill radius (full) for primary; size lg with py-7; startContent icons; isLoading state", + "input_style": "HeroUI Input: backdrop-blur-xl bg-transparent innerWrapper; shadow-xl inputWrapper with focus glow; radius lg; startContent icons; isClearable for token fields", + "card_style": "HeroUI Card: backdrop-blur-sm border border-white/40 dark:border-white/10 shadow-sm; bg-white/60 dark:bg-black/40; hover elevation; optional background image overlay with opacity-30", + "navigation_pattern": "Collapsible sidebar (16rem→0) with spring animation; breadcrumbs with motion stagger; mobile overlay backdrop-blur", + "modal_style": "HeroUI Dialog/Modal with backdrop-blur; HoverEffectCard for login (3D tilt on hover); spring entrance", + "list_style": "Network item cards: grid layout, large mono count + label; System status: grid 2-col with icon headers; UsagePie canvas charts", + "component_notes": "HoverEffectCard: 3D perspective tilt (rotateX/rotateY) + moving gradient light blob on hover; PageBackground: static gradient blobs (primary/secondary/pink) with massive blur; Toast: react-hot-toast top-right" + } + }, + "design_style": { + "aesthetic": { + "mood": ["playful", "dreamy", "technical", "friendly", "modern"], + "visual_metaphor": "Cherry blossoms in digital frost — ACG aesthetic meets developer tooling", + "era_influence": "Modern web (2020s) with anime/moe culture influences; glassmorphism 2.0", + "genre": "Developer dashboard with ACG personality", + "personality_traits": ["approachable", "meticulous", "whimsical", "competent"], + "adjectives": ["sakura", "frost", "glass", "animated", "responsive"] + }, + "visual_language": { + "complexity": "moderate — rich but not cluttered; breathing room via glass cards", + "ornamentation": "subtle accents — gradient blobs, 3D tilt cards, animated breadcrumbs, scrollbar theming", + "whitespace_usage": "generous — cards have internal padding, grid gaps 16-24px, section padding 20px+", + "visual_weight_distribution": "balanced — sidebar + main content; dashboard cards equal weight; login centered hero", + "focal_strategy": "progressive reveal — entrance animations, hover discoveries, layered depth", + "contrast_level": "medium — relies on opacity layers not high contrast; dark mode inverts surfaces", + "texture_usage": "glassmorphism (backdrop-blur), gradient mesh blobs, subtle noise via saturation" + }, + "composition": { + "hierarchy_method": "scale contrast + typographic hierarchy + spatial isolation (cards)", + "balance_type": "asymmetric — sidebar fixed, main fluid; dashboard grid balanced", + "flow_direction": "vertical primary (sidebar→content), horizontal secondary (breadcrumbs, card grids)", + "grouping_strategy": "cards as containers; grid for peer items; sections separated by gap", + "negative_space_role": "breathing room between cards; focus isolation for modals/login" + }, + "imagery": { + "photo_treatment": "custom background image upload (base64) with overlay opacity-30 object-contain", + "illustration_style": "ACG/moe logo (NapCat cat), gradient blob art", + "graphic_elements": "gradient orbs (primary/secondary/pink), moving light blob on hover cards", + "pattern_usage": "none explicit; glassmorphism creates implied pattern", + "image_shape": "full-bleed background; logo 7em height on login" + }, + "interaction_feel": { + "feedback_style": "immediate visual — 3D tilt on cards, light blob follows cursor, spring scale on buttons", + "hover_behavior": "card: perspective rotateX/rotateY + gradient light follows mouse; button: shadow elevation + scale; input: focus glow ring", + "transition_personality": "spring physics (stiffness 120-150) for layout; snappy ease-out for micro", + "loading_style": "PageLoading full-screen overlay; Skeleton cards for dashboard; Suspense boundaries per route", + "microinteraction_density": "high — every interactive element has hover/tap/transition choreography" + }, + "brand_voice_in_ui": { + "tone": "friendly technical — '猫猫日志', '喵~', emoji in hints", + "formality": "casual developer — Chinese labels with English terms mixed", + "cta_style": "direct imperative with playful twist — '登录' with logo animation, '切换主题', '重启进程'", + "empty_state_approach": "illustrated (ring logo) + welcoming copy + hint", + "error_tone": "helpful not alarming — toast errors, confirm dialogs for destructive actions" + } + }, + "visual_effects": { + "overview": { + "effect_intensity": "moderate", + "performance_tier": "medium", + "fallback_strategy": "reduce to CSS (disable motion spring, keep glassmorphism)", + "primary_technology": "CSS (Tailwind) + motion/react (Framer Motion) + Canvas 2D (UsagePie charts) + HeroUI" + }, + "background_effects": { + "type": "gradient-mesh-blobs", + "description": "Three large radial gradient blobs (primary-200/40, secondary-200/40, pink-200/30) with massive blur (90-110px) positioned at corners, static but imply depth", + "technology": "CSS (absolute positioned divs with blur)", + "params": { + "color_palette": ["#FF7FAC", "#88C0D0", "#FF9EB5"], + "speed": "static", + "density": "3 blobs", + "opacity": "0.3-0.4", + "blend_mode": "normal (opacity stacking)" + } + }, + "particle_systems": { + "enabled": false + }, + "3d_elements": { + "enabled": true, + "type": "card-3d-tilt", + "description": "HoverEffectCard uses CSS 3D transforms (perspective 1000px, rotateX/rotateY up to ±5deg) with a moving gradient light blob that follows cursor", + "technology": "CSS 3D + React mouse tracking", + "params": { + "renderer": "CSS transform3d", + "lighting": "moving gradient blob (from-primary-400 to-secondary-400) follows cursor", + "camera": "perspective(1000px)", + "materials": "glassmorphism card surface", + "geometry": "flat card with perspective rotation", + "post_processing": "blur-[100px] on light blob", + "interaction_model": "mouse-move tracking within card bounds" + } + }, + "shader_effects": { + "enabled": false + }, + "scroll_effects": { + "parallax": { + "enabled": false + }, + "scroll_triggered_animations": { + "enabled": true, + "trigger_points": "route mount (Suspense), sidebar open/close, breadcrumb items", + "animation_type": "fade-up + scale (spring stagger)", + "scrub_behavior": "none (time-based)" + }, + "scroll_morphing": { + "enabled": false + } + }, + "text_effects": { + "type": "gradient-text", + "description": "HeroUI title component supports color='violet' for gradient text; login page 'Web Login' split with violet accent", + "technology": "CSS background-clip-text via HeroUI", + "params": { + "split_strategy": "by-word (Web / Login)", + "animation_per_unit": "none", + "stagger": "none", + "effect_style": "gradient fill" + } + }, + "cursor_effects": { + "enabled": true, + "type": "magnetic-light-blob", + "description": "On HoverEffectCard, a gradient radial blur blob follows cursor position within card bounds", + "technology": "CSS absolute positioned div + React mouse tracking", + "params": { + "shape": "rounded-full", + "size": "150px", + "blend_mode": "normal", + "trail": "opacity transition 300ms", + "interaction_zone": "card bounding box" + } + }, + "image_effects": { + "type": "background-overlay", + "description": "User-uploaded background image rendered full-bleed behind layout with opacity-30 object-contain", + "technology": "CSS background-image on layout root", + "params": { + "filter_pipeline": "opacity-30", + "hover_transform": "none", + "reveal_animation": "none", + "distortion_type": "none" + } + }, + "glassmorphism_neumorphism": { + "enabled": true, + "style": "glass", + "params": { + "blur_radius": "backdrop-blur-sm (4px) to backdrop-blur-xl (24px)", + "transparency": "bg-white/10-70 dark:bg-black/10-40", + "border_treatment": "border border-white/40 dark:border-white/10", + "shadow_type": "shadow-sm to shadow-xl layered", + "light_source_angle": "implied top-left via gradient blobs" + } + }, + "canvas_drawings": { + "enabled": true, + "type": "data-visualization-pie", + "description": "UsagePie component renders CPU/memory donut charts using Canvas 2D with animated sweep", + "technology": "Canvas 2D API", + "params": { + "draw_method": "arc segments with gradient fill", + "animation_loop": "on mount sweep animation", + "color_scheme": "primary/secondary/palette", + "responsiveness": "container-sized", + "interaction": "none (static display)" + } + }, + "svg_animations": { + "enabled": false + }, + "composite_notes": "The design layers: 1) Static gradient mesh background (CSS), 2) Glass cards with backdrop-blur (CSS), 3) 3D tilt cards on hover (CSS 3D + React), 4) Magnetic light blob follows cursor (React + CSS), 5) Spring animations for layout transitions (motion/react), 6) Canvas pie charts for data viz, 7) Themed scrollbars (CSS), 8) Custom background image overlay (CSS). All effects are lightweight — no WebGL, no heavy JS animation libraries beyond motion/react. HeroUI provides accessible component primitives. Dark mode inverts surfaces and adjusts blob colors. Performance is good on modern browsers; fallback is static CSS (disable motion, keep glass)." + } +} \ No newline at end of file