diff --git a/static/style.css b/static/style.css index cf94adb..c696204 100644 --- a/static/style.css +++ b/static/style.css @@ -1,1047 +1,372 @@ /** - * STP模具几何分析中心 - 暖白色主题设计系统 - * 版本: 4.0.0 - 现代化暖色系UI + * STP模具几何分析中心 - 现代简约设计系统 + * 版本: 5.0.0 - Modern Minimal UI + * 设计灵感: Linear, Notion, Vercel, Stripe */ /* ================================ - 设计系统变量 - 暖白色主题 + 设计系统变量 - 现代简约风格 ================================ */ :root { - /* 主色调 - 温暖的琥珀/橙色系 */ - --primary-color: #e67e22; - --primary-hover: #d35400; - --primary-light: #fdebd0; - --primary-dark: #ba4a00; + /* 主色调 - 现代蓝紫渐变系 */ + --primary-50: #f0f5ff; + --primary-100: #e0eaff; + --primary-200: #c7d7fe; + --primary-300: #a4bcfd; + --primary-400: #7c96fb; + --primary-500: #5a6ff5; + --primary-600: #4a4ee0; + --primary-700: #3d3dc7; + --primary-800: #3535a5; + --primary-900: #2e2e87; - /* 辅助色 */ - --secondary-color: #8e6d4a; - --accent-color: #c0392b; + /* 中性灰色系 - 现代冷灰 */ + --gray-50: #fafafa; + --gray-100: #f4f4f5; + --gray-200: #e4e4e7; + --gray-300: #d4d4d8; + --gray-400: #a1a1aa; + --gray-500: #71717a; + --gray-600: #52525b; + --gray-700: #3f3f46; + --gray-800: #27272a; + --gray-900: #18181b; + + /* 强调色 - 翡翠绿 */ + --accent-50: #ecfdf5; + --accent-100: #d1fae5; + --accent-200: #a7f3d0; + --accent-300: #6ee7b7; + --accent-400: #34d399; + --accent-500: #10b981; + --accent-600: #059669; + --accent-700: #047857; /* 状态色 */ - --success-color: #27ae60; - --success-light: #d5f4e6; - --warning-color: #f39c12; - --warning-light: #fef9e7; - --error-color: #e74c3c; - --error-light: #fdedec; - --info-color: #3498db; - --info-light: #ebf5fb; - - /* 暖白色系 */ - --warm-white: #faf8f5; - --cream: #fdf9f3; - --ivory: #fffff0; - --linen: #faf0e6; - --seashell: #fff5ee; - - /* 暖灰色系 */ - --warm-gray-50: #faf9f7; - --warm-gray-100: #f5f3f0; - --warm-gray-200: #e8e4de; - --warm-gray-300: #d4cfc6; - --warm-gray-400: #a69f94; - --warm-gray-500: #7a7267; - --warm-gray-600: #5c564d; - --warm-gray-700: #3d3832; - --warm-gray-800: #2c2824; - --warm-gray-900: #1a1816; + --success: #10b981; + --success-bg: #ecfdf5; + --warning: #f59e0b; + --warning-bg: #fffbeb; + --error: #ef4444; + --error-bg: #fef2f2; + --info: #3b82f6; + --info-bg: #eff6ff; /* 文字颜色 */ - --text-primary: #3d3832; - --text-secondary: #5c564d; - --text-muted: #7a7267; - --text-light: #a69f94; + --text-primary: #18181b; + --text-secondary: #3f3f46; + --text-tertiary: #71717a; + --text-muted: #a1a1aa; + --text-inverse: #fafafa; + + /* 背景色 */ + --bg-primary: #ffffff; + --bg-secondary: #fafafa; + --bg-tertiary: #f4f4f5; + --bg-elevated: #ffffff; + --bg-overlay: rgba(0, 0, 0, 0.5); + + /* 边框 */ + --border-light: #e4e4e7; + --border-default: #d4d4d8; + --border-strong: #a1a1aa; + + /* 渐变 */ + --gradient-primary: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + --gradient-accent: linear-gradient(135deg, #10b981 0%, #059669 100%); + --gradient-hero: linear-gradient(135deg, #f5f7fa 0%, #e4e8f0 100%); + --gradient-card: linear-gradient(180deg, #ffffff 0%, #fafafa 100%); + --gradient-shine: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent); /* 间距系统 */ - --space-xs: 0.25rem; - --space-sm: 0.5rem; - --space-md: 1rem; - --space-lg: 1.5rem; - --space-xl: 2rem; - --space-2xl: 3rem; - --space-3xl: 4rem; + --space-1: 0.25rem; + --space-2: 0.5rem; + --space-3: 0.75rem; + --space-4: 1rem; + --space-5: 1.25rem; + --space-6: 1.5rem; + --space-8: 2rem; + --space-10: 2.5rem; + --space-12: 3rem; + --space-16: 4rem; - /* 字体系统 */ - --font-family: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', system-ui, sans-serif; - --font-size-xs: 0.75rem; - --font-size-sm: 0.875rem; - --font-size-base: 1rem; - --font-size-lg: 1.125rem; - --font-size-xl: 1.25rem; - --font-size-2xl: 1.5rem; - --font-size-3xl: 1.875rem; - --font-size-4xl: 2.25rem; + /* 字体 */ + --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + --font-mono: 'JetBrains Mono', 'Fira Code', Consolas, monospace; - /* 阴影系统 - 温暖阴影 */ - --shadow-xs: 0 1px 2px rgba(58, 45, 35, 0.05); - --shadow-sm: 0 2px 4px rgba(58, 45, 35, 0.08); - --shadow-md: 0 4px 12px rgba(58, 45, 35, 0.1); - --shadow-lg: 0 8px 24px rgba(58, 45, 35, 0.12); - --shadow-xl: 0 16px 48px rgba(58, 45, 35, 0.15); - --shadow-warm: 0 4px 20px rgba(230, 126, 34, 0.15); + /* 字号 */ + --text-xs: 0.75rem; + --text-sm: 0.875rem; + --text-base: 1rem; + --text-lg: 1.125rem; + --text-xl: 1.25rem; + --text-2xl: 1.5rem; + --text-3xl: 1.875rem; + --text-4xl: 2.25rem; + --text-5xl: 3rem; - /* 圆角系统 */ + /* 字重 */ + --font-normal: 400; + --font-medium: 500; + --font-semibold: 600; + --font-bold: 700; + + /* 行高 */ + --leading-tight: 1.25; + --leading-normal: 1.5; + --leading-relaxed: 1.625; + + /* 阴影 - 现代柔和阴影 */ + --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.05); + --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06); + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); + --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); + --shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25); + --shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, 0.06); + --shadow-glow: 0 0 40px rgba(99, 102, 241, 0.15); + + /* 圆角 */ --radius-sm: 0.375rem; - --radius-md: 0.625rem; - --radius-lg: 0.875rem; - --radius-xl: 1.25rem; - --radius-2xl: 1.5rem; + --radius-md: 0.5rem; + --radius-lg: 0.75rem; + --radius-xl: 1rem; + --radius-2xl: 1.25rem; + --radius-3xl: 1.5rem; --radius-full: 9999px; - /* 过渡动画 */ - --transition-fast: 0.15s ease; - --transition-base: 0.25s ease; - --transition-slow: 0.4s ease; - --transition-bounce: 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55); + /* 动画 */ + --ease-default: cubic-bezier(0.4, 0, 0.2, 1); + --ease-in: cubic-bezier(0.4, 0, 1, 1); + --ease-out: cubic-bezier(0, 0, 0.2, 1); + --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1); + --ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55); + --duration-fast: 150ms; + --duration-normal: 200ms; + --duration-slow: 300ms; } /* ================================ - 基础重置与全局样式 + CSS Reset & Base ================================ */ -* { +*, *::before, *::after { + box-sizing: border-box; margin: 0; padding: 0; - box-sizing: border-box; } html { - scroll-behavior: smooth; font-size: 16px; -} - -body { - font-family: var(--font-family); - background: linear-gradient(135deg, var(--warm-white) 0%, var(--cream) 50%, var(--linen) 100%); - background-attachment: fixed; - min-height: 100vh; - padding: var(--space-lg); - color: var(--text-primary); - line-height: 1.7; + scroll-behavior: smooth; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } -/* 背景装饰 */ -body::before { - content: ''; - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-image: - radial-gradient(circle at 20% 80%, rgba(230, 126, 34, 0.05) 0%, transparent 50%), - radial-gradient(circle at 80% 20%, rgba(243, 156, 18, 0.05) 0%, transparent 50%), - radial-gradient(circle at 40% 40%, rgba(39, 174, 96, 0.03) 0%, transparent 40%); - pointer-events: none; - z-index: -1; +body { + font-family: var(--font-sans); + font-size: var(--text-base); + line-height: var(--leading-normal); + color: var(--text-primary); + background: var(--bg-secondary); + min-height: 100vh; } /* ================================ - 应用外壳 + 排版 ================================ */ -.app-shell { +h1, h2, h3, h4, h5, h6 { + font-weight: var(--font-semibold); + line-height: var(--leading-tight); + color: var(--text-primary); +} + +h1 { font-size: var(--text-4xl); } +h2 { font-size: var(--text-3xl); } +h3 { font-size: var(--text-2xl); } +h4 { font-size: var(--text-xl); } +h5 { font-size: var(--text-lg); } +h6 { font-size: var(--text-base); } + +p { + color: var(--text-secondary); + line-height: var(--leading-relaxed); +} + +a { + color: var(--primary-600); + text-decoration: none; + transition: color var(--duration-fast) var(--ease-default); +} + +a:hover { + color: var(--primary-700); +} + +/* ================================ + 主布局容器 + ================================ */ +.app-container { + min-height: 100vh; + background: var(--bg-secondary); +} + +.main-content { max-width: 1400px; margin: 0 auto; - min-height: calc(100vh - 2 * var(--space-lg)); - display: flex; - flex-direction: column; - animation: fadeInUp 0.6s ease-out; + padding: var(--space-6); } -@keyframes fadeInUp { - from { - opacity: 0; - transform: translateY(20px); - } - to { - opacity: 1; - transform: translateY(0); +@media (min-width: 768px) { + .main-content { + padding: var(--space-8); } } /* ================================ - 通知系统 + 头部导航 ================================ */ -.notification-container { - position: fixed; - top: var(--space-lg); - right: var(--space-lg); - z-index: 1000; - max-width: 420px; - display: flex; - flex-direction: column; - gap: var(--space-sm); +.app-header { + background: rgba(255, 255, 255, 0.8); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border-bottom: 1px solid var(--border-light); + position: sticky; + top: 0; + z-index: 100; } -.notification { - background: white; - border-radius: var(--radius-lg); - padding: var(--space-md) var(--space-lg); - box-shadow: var(--shadow-lg); - border-left: 4px solid var(--info-color); - animation: slideInRight 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55); +.header-content { + max-width: 1400px; + margin: 0 auto; + padding: var(--space-4) var(--space-6); display: flex; align-items: center; justify-content: space-between; - backdrop-filter: blur(10px); - transition: transform var(--transition-base), box-shadow var(--transition-base); -} - -.notification:hover { - transform: translateX(-4px); - box-shadow: var(--shadow-xl); -} - -.notification-success { - border-left-color: var(--success-color); - background: linear-gradient(135deg, white 0%, var(--success-light) 100%); -} - -.notification-error { - border-left-color: var(--error-color); - background: linear-gradient(135deg, white 0%, var(--error-light) 100%); -} - -.notification-warning { - border-left-color: var(--warning-color); - background: linear-gradient(135deg, white 0%, var(--warning-light) 100%); -} - -.notification-message { - flex: 1; - color: var(--text-primary); - font-weight: 500; -} - -.notification-close { - background: var(--warm-gray-100); - border: none; - font-size: var(--font-size-lg); - color: var(--text-muted); - cursor: pointer; - padding: var(--space-xs); - margin-left: var(--space-md); - border-radius: var(--radius-full); - width: 28px; - height: 28px; - display: flex; - align-items: center; - justify-content: center; - transition: all var(--transition-fast); -} - -.notification-close:hover { - background: var(--error-light); - color: var(--error-color); - transform: rotate(90deg); -} - -@keyframes slideInRight { - from { - transform: translateX(100%); - opacity: 0; - } - to { - transform: translateX(0); - opacity: 1; - } -} - -/* ================================ - 应用头部 - ================================ */ -.app-header { - background: linear-gradient(135deg, white 0%, var(--cream) 100%); - border-radius: var(--radius-2xl) var(--radius-2xl) 0 0; - padding: var(--space-2xl) var(--space-3xl); - box-shadow: var(--shadow-md); - margin-bottom: var(--space-lg); - border: 1px solid var(--warm-gray-200); - border-bottom: none; - position: relative; - overflow: hidden; -} - -.app-header::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - height: 4px; - background: linear-gradient(90deg, var(--primary-color), var(--warning-color), var(--success-color)); -} - -.app-title { - display: flex; - align-items: center; - gap: var(--space-xl); - margin-bottom: var(--space-xl); } .logo { - font-size: var(--font-size-4xl); - background: linear-gradient(135deg, var(--primary-color), var(--warning-color)); + display: flex; + align-items: center; + gap: var(--space-3); +} + +.logo-icon { + width: 40px; + height: 40px; + background: var(--gradient-primary); + border-radius: var(--radius-lg); + display: flex; + align-items: center; + justify-content: center; + font-size: 1.25rem; + color: white; + box-shadow: var(--shadow-md); +} + +.logo-text { + font-size: var(--text-xl); + font-weight: var(--font-bold); + background: var(--gradient-primary); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; - filter: drop-shadow(0 2px 4px rgba(230, 126, 34, 0.3)); - animation: float 3s ease-in-out infinite; } -@keyframes float { - 0%, 100% { transform: translateY(0); } - 50% { transform: translateY(-5px); } -} - -.app-title h1 { - font-size: var(--font-size-3xl); - color: var(--text-primary); - margin-bottom: var(--space-xs); - font-weight: 700; - letter-spacing: -0.02em; -} - -.app-subtitle { - color: var(--text-secondary); - font-size: var(--font-size-base); - font-weight: 400; -} - -.app-nav { - display: flex; - gap: var(--space-sm); - border-top: 1px solid var(--warm-gray-200); - padding-top: var(--space-lg); -} - -.nav-link { - padding: var(--space-sm) var(--space-lg); - text-decoration: none; - color: var(--text-secondary); - border-radius: var(--radius-full); - transition: all var(--transition-base); - font-weight: 500; - display: flex; - align-items: center; - gap: var(--space-sm); - position: relative; - overflow: hidden; -} - -.nav-link::before { - content: ''; - position: absolute; - bottom: 0; - left: 50%; - width: 0; - height: 2px; - background: var(--primary-color); - transition: all var(--transition-base); - transform: translateX(-50%); -} - -.nav-link:hover { - color: var(--primary-color); - background: var(--primary-light); -} - -.nav-link:hover::before { - width: 60%; -} - -.nav-link.active { - color: white; - background: linear-gradient(135deg, var(--primary-color), var(--primary-hover)); - box-shadow: var(--shadow-warm); -} - -.nav-link.active::before { - display: none; -} - -/* ================================ - 主要内容区域 - ================================ */ -.app-main { - flex: 1; - background: white; - border-radius: 0 0 var(--radius-2xl) var(--radius-2xl); - padding: var(--space-2xl) var(--space-3xl); - box-shadow: var(--shadow-md); - border: 1px solid var(--warm-gray-200); - border-top: none; -} - -/* ================================ - 应用底部 - ================================ */ -.app-footer { - background: linear-gradient(135deg, var(--warm-gray-100) 0%, var(--warm-gray-200) 100%); - color: var(--text-secondary); - padding: var(--space-lg) var(--space-xl); - border-radius: var(--radius-xl); - margin-top: var(--space-lg); - display: flex; - justify-content: space-between; - align-items: center; - font-size: var(--font-size-sm); - border: 1px solid var(--warm-gray-200); -} - -.footer-left, .footer-right { - display: flex; - align-items: center; - gap: var(--space-md); -} - -.status-success { - color: var(--success-color); - font-weight: 600; -} - -.status-error { - color: var(--error-color); - font-weight: 600; -} - -/* ================================ - 上传区域 - ================================ */ -.upload-section { - margin-bottom: var(--space-2xl); -} - -.upload-area { - border: 2px dashed var(--warm-gray-300); - border-radius: var(--radius-xl); - padding: var(--space-3xl); - text-align: center; - transition: all var(--transition-base); - background: linear-gradient(135deg, var(--warm-gray-50) 0%, white 100%); - cursor: pointer; - position: relative; - overflow: hidden; -} - -.upload-area::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: linear-gradient(135deg, var(--primary-light) 0%, transparent 100%); - opacity: 0; - transition: opacity var(--transition-base); -} - -.upload-area:hover, -.upload-area.drag-over { - border-color: var(--primary-color); - background: var(--cream); - transform: translateY(-2px); - box-shadow: var(--shadow-lg); -} - -.upload-area:hover::before, -.upload-area.drag-over::before { - opacity: 1; -} - -.upload-icon { - font-size: 4rem; - margin-bottom: var(--space-lg); - display: block; - animation: bounce 2s ease-in-out infinite; -} - -@keyframes bounce { - 0%, 100% { transform: translateY(0); } - 50% { transform: translateY(-10px); } -} - -.upload-area h3 { - color: var(--text-primary); - font-size: var(--font-size-xl); - margin-bottom: var(--space-sm); -} - -.upload-area p { - color: var(--text-muted); - margin-bottom: var(--space-md); -} - -.file-input { - display: none; -} - -.btn { - display: inline-flex; - align-items: center; - justify-content: center; - gap: var(--space-sm); - padding: var(--space-sm) var(--space-lg); - border-radius: var(--radius-full); - font-weight: 600; - font-size: var(--font-size-sm); - cursor: pointer; - transition: all var(--transition-base); - border: none; - text-decoration: none; -} - -.btn-primary { - background: linear-gradient(135deg, var(--primary-color), var(--primary-hover)); - color: white; - box-shadow: var(--shadow-sm), 0 4px 12px rgba(230, 126, 34, 0.3); -} - -.btn-primary:hover { - transform: translateY(-2px); - box-shadow: var(--shadow-md), 0 6px 20px rgba(230, 126, 34, 0.4); -} - -.btn-primary:active { - transform: translateY(0); -} - -.btn-secondary { - background: white; - color: var(--text-primary); - border: 2px solid var(--warm-gray-300); -} - -.btn-secondary:hover { - border-color: var(--primary-color); - color: var(--primary-color); - background: var(--primary-light); -} - -.btn-success { - background: linear-gradient(135deg, var(--success-color), #219a52); - color: white; - box-shadow: 0 4px 12px rgba(39, 174, 96, 0.3); -} - -.btn-success:hover { - transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(39, 174, 96, 0.4); -} - -.btn:disabled { - opacity: 0.6; - cursor: not-allowed; - transform: none !important; -} - -/* ================================ - 文件信息卡片 - ================================ */ -.file-info { - background: linear-gradient(135deg, var(--primary-light) 0%, white 100%); - border-radius: var(--radius-lg); - padding: var(--space-lg); - margin-top: var(--space-lg); - border: 1px solid var(--primary-color); - animation: scaleIn 0.3s ease-out; -} - -@keyframes scaleIn { - from { - opacity: 0; - transform: scale(0.95); - } - to { - opacity: 1; - transform: scale(1); - } -} - -.file-info h4 { - color: var(--primary-color); - margin-bottom: var(--space-sm); - display: flex; - align-items: center; - gap: var(--space-sm); -} - -.file-info p { - color: var(--text-secondary); - font-size: var(--font-size-sm); -} - -/* ================================ - 进度条 - ================================ */ -.progress-container { - margin: var(--space-xl) 0; -} - -.progress-bar { - height: 8px; - background: var(--warm-gray-200); - border-radius: var(--radius-full); - overflow: hidden; - position: relative; -} - -.progress-fill { - height: 100%; - background: linear-gradient(90deg, var(--primary-color), var(--warning-color), var(--success-color)); - background-size: 200% 100%; - border-radius: var(--radius-full); - transition: width var(--transition-slow); - animation: shimmer 2s linear infinite; -} - -@keyframes shimmer { - 0% { background-position: 200% 0; } - 100% { background-position: -200% 0; } -} - -.progress-text { - text-align: center; - margin-top: var(--space-sm); - color: var(--text-secondary); - font-size: var(--font-size-sm); -} - -/* ================================ - 结果展示区域 - ================================ */ -.results-section { - padding: var(--space-lg) 0; -} - -.result-card { - background: white; - border-radius: var(--radius-xl); - padding: var(--space-xl); - margin: var(--space-lg) 0; - border: 1px solid var(--warm-gray-200); - box-shadow: var(--shadow-sm); - transition: all var(--transition-base); -} - -.result-card:hover { - box-shadow: var(--shadow-lg); - transform: translateY(-2px); -} - -.result-card h3 { - color: var(--text-primary); - margin-bottom: var(--space-lg); - display: flex; - align-items: center; - gap: var(--space-sm); - font-size: var(--font-size-xl); - padding-bottom: var(--space-md); - border-bottom: 2px solid var(--warm-gray-100); -} - -/* 数据网格 */ -.task-info, -.geometry-data, -.bounding-box-data, -.topology-data, -.features-data, -.recommendations-data, -.metrics-data, -.analysis-info { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); - gap: var(--space-md); -} - -/* 数据项 */ -.data-item { - background: linear-gradient(135deg, var(--warm-gray-50) 0%, white 100%); - padding: var(--space-lg); - border-radius: var(--radius-lg); - border: 1px solid var(--warm-gray-200); - transition: all var(--transition-base); -} - -.data-item:hover { - transform: translateY(-3px); - box-shadow: var(--shadow-md); - border-color: var(--primary-light); -} - -.data-label { - font-weight: 600; - color: var(--text-secondary); - margin-bottom: var(--space-sm); - font-size: var(--font-size-sm); - display: flex; - align-items: center; - gap: var(--space-sm); - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.data-value { - color: var(--text-primary); - font-family: 'SF Mono', 'Consolas', monospace; - font-size: var(--font-size-lg); - font-weight: 700; -} - -.data-unit { - color: var(--text-muted); - font-size: var(--font-size-sm); - margin-left: var(--space-xs); - font-weight: 400; -} - -/* 坐标项 */ -.coordinate-item { - background: linear-gradient(135deg, var(--info-light) 0%, white 100%); - padding: var(--space-md); - border-radius: var(--radius-md); - border: 1px solid var(--info-color); -} - -.coordinate-label { - font-weight: 600; - color: var(--info-color); - margin-bottom: var(--space-xs); - font-size: var(--font-size-sm); -} - -.coordinate-value { - font-family: 'SF Mono', 'Consolas', monospace; - color: var(--text-primary); - font-weight: 600; -} - -/* ================================ - 状态徽章 - ================================ */ -.status-badge { - padding: var(--space-xs) var(--space-md); - border-radius: var(--radius-full); - font-size: var(--font-size-sm); - font-weight: 600; - display: inline-flex; - align-items: center; - gap: var(--space-xs); -} - -.status-pending { - background: var(--warning-light); - color: #8b6914; - border: 1px solid var(--warning-color); -} - -.status-processing { - background: var(--info-light); - color: #1a5276; - border: 1px solid var(--info-color); - animation: pulse 2s ease-in-out infinite; -} - -@keyframes pulse { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.7; } -} - -.status-completed { - background: var(--success-light); - color: #1e8449; - border: 1px solid var(--success-color); -} - -.status-failed { - background: var(--error-light); - color: #922b21; - border: 1px solid var(--error-color); -} - -/* ================================ - 特征和建议卡片 - ================================ */ -.feature-item { - background: linear-gradient(135deg, var(--info-light) 0%, white 100%); - padding: var(--space-lg); - border-radius: var(--radius-lg); - border-left: 4px solid var(--info-color); - transition: all var(--transition-base); -} - -.feature-item:hover { - transform: translateX(4px); - box-shadow: var(--shadow-md); -} - -.recommendation-item { - background: linear-gradient(135deg, var(--warning-light) 0%, white 100%); - padding: var(--space-lg); - border-radius: var(--radius-lg); - border-left: 4px solid var(--warning-color); - transition: all var(--transition-base); -} - -.recommendation-item:hover { - transform: translateX(4px); - box-shadow: var(--shadow-md); -} - -.recommendation-high { - border-left-color: var(--error-color); - background: linear-gradient(135deg, var(--error-light) 0%, white 100%); -} - -.recommendation-medium { - border-left-color: var(--warning-color); - background: linear-gradient(135deg, var(--warning-light) 0%, white 100%); -} - -.recommendation-low { - border-left-color: var(--success-color); - background: linear-gradient(135deg, var(--success-light) 0%, white 100%); -} - -.feature-header, -.recommendation-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: var(--space-md); -} - -.feature-type { - font-weight: 700; - color: var(--text-primary); - font-size: var(--font-size-lg); -} - -.confidence-badge { - background: linear-gradient(135deg, var(--info-color), #2980b9); - color: white; - padding: var(--space-xs) var(--space-md); - border-radius: var(--radius-full); - font-size: var(--font-size-sm); - font-weight: 600; -} - -.priority-badge { - padding: var(--space-xs) var(--space-md); - border-radius: var(--radius-full); - font-size: var(--font-size-sm); - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.priority-high { - background: linear-gradient(135deg, var(--error-color), #c0392b); - color: white; -} - -.priority-medium { - background: linear-gradient(135deg, var(--warning-color), #d68910); - color: white; -} - -.priority-low { - background: linear-gradient(135deg, var(--success-color), #219a52); - color: white; -} - -.recommendation-list { - list-style: none; - padding: 0; - margin: var(--space-md) 0 0; -} - -.recommendation-list li { - padding: var(--space-sm) 0; - border-bottom: 1px solid var(--warm-gray-200); - display: flex; - align-items: flex-start; - gap: var(--space-sm); - color: var(--text-secondary); -} - -.recommendation-list li:last-child { - border-bottom: none; -} - -.recommendation-list li::before { - content: "💡"; - font-size: 1.1em; - flex-shrink: 0; -} - -/* ================================ - 指标卡片 - ================================ */ -.metric-item { - background: white; - padding: var(--space-xl); - border-radius: var(--radius-xl); - box-shadow: var(--shadow-sm); - text-align: center; - border: 1px solid var(--warm-gray-200); - transition: all var(--transition-base); -} - -.metric-item:hover { - transform: translateY(-4px); - box-shadow: var(--shadow-lg); -} - -.metric-value { - font-size: var(--font-size-3xl); - font-weight: 800; - color: var(--text-primary); - margin: var(--space-md) 0; - line-height: 1; -} - -.metric-label { - color: var(--text-muted); - font-size: var(--font-size-sm); +.logo-subtitle { + font-size: var(--text-xs); + color: var(--text-tertiary); text-transform: uppercase; letter-spacing: 0.1em; + margin-top: 2px; } -.metric-good { - color: var(--success-color); +/* 导航菜单 */ +.nav-menu { + display: flex; + gap: var(--space-2); } -.metric-warning { - color: var(--warning-color); -} - -.metric-poor { - color: var(--error-color); -} - -/* ================================ - 加载动画 - ================================ */ -.loading { - text-align: center; - padding: var(--space-2xl); -} - -.spinner { - width: 50px; - height: 50px; - border: 4px solid var(--warm-gray-200); - border-top-color: var(--primary-color); - border-radius: 50%; - animation: spin 1s linear infinite; - margin: 0 auto var(--space-lg); -} - -@keyframes spin { - to { transform: rotate(360deg); } -} - -.loading-text { +.nav-item { + padding: var(--space-2) var(--space-4); + border-radius: var(--radius-md); + font-size: var(--text-sm); + font-weight: var(--font-medium); color: var(--text-secondary); - font-size: var(--font-size-lg); + cursor: pointer; + transition: all var(--duration-fast) var(--ease-default); + border: none; + background: transparent; } -/* ================================ - 错误消息 - ================================ */ -.error-message { - background: linear-gradient(135deg, var(--error-light) 0%, white 100%); - color: var(--error-color); - padding: var(--space-lg); - border-radius: var(--radius-lg); - margin: var(--space-lg) 0; - border-left: 4px solid var(--error-color); +.nav-item:hover { + background: var(--gray-100); + color: var(--text-primary); +} + +.nav-item.active { + background: var(--primary-50); + color: var(--primary-600); +} + +/* 用户信息 */ +.user-section { display: flex; align-items: center; - gap: var(--space-md); + gap: var(--space-4); } -.error-message::before { - content: "⚠️"; - font-size: 1.5em; +.status-badge { + display: flex; + align-items: center; + gap: var(--space-2); + padding: var(--space-2) var(--space-3); + background: var(--accent-50); + border-radius: var(--radius-full); + font-size: var(--text-sm); + color: var(--accent-700); +} + +.status-dot { + width: 8px; + height: 8px; + background: var(--accent-500); + border-radius: 50%; + animation: pulse-dot 2s infinite; +} + +@keyframes pulse-dot { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.7; transform: scale(1.2); } } /* ================================ - 历史记录表格 - ================================ */ -.history-table { - width: 100%; - border-collapse: collapse; - margin-top: var(--space-lg); - background: white; - border-radius: var(--radius-lg); - overflow: hidden; - box-shadow: var(--shadow-sm); -} - -.history-table th, -.history-table td { - padding: var(--space-md) var(--space-lg); - text-align: left; - border-bottom: 1px solid var(--warm-gray-200); -} - -.history-table th { - background: linear-gradient(135deg, var(--warm-gray-100) 0%, var(--warm-gray-50) 100%); - color: var(--text-secondary); - font-weight: 600; - font-size: var(--font-size-sm); - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.history-table tr:hover td { - background: var(--warm-gray-50); -} - -.history-table tr:last-child td { - border-bottom: none; -} - -/* ================================ - 空状态 - ================================ */ -.empty-state { - text-align: center; - padding: var(--space-3xl); - color: var(--text-muted); -} - -.empty-state-icon { - font-size: 4rem; - margin-bottom: var(--space-lg); - opacity: 0.5; -} - -.empty-state h3 { - color: var(--text-secondary); - margin-bottom: var(--space-sm); -} - -/* ================================ - 统计卡片 + 统计卡片区域 ================================ */ .stats-grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); - gap: var(--space-lg); - margin-bottom: var(--space-2xl); + grid-template-columns: repeat(4, 1fr); + gap: var(--space-4); + margin-bottom: var(--space-8); +} + +@media (max-width: 1024px) { + .stats-grid { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (max-width: 640px) { + .stats-grid { + grid-template-columns: 1fr; + } } .stat-card { - background: white; + background: var(--bg-primary); border-radius: var(--radius-xl); - padding: var(--space-xl); - text-align: center; - border: 1px solid var(--warm-gray-200); - transition: all var(--transition-base); + padding: var(--space-5); + border: 1px solid var(--border-light); + transition: all var(--duration-normal) var(--ease-default); position: relative; overflow: hidden; } @@ -1052,136 +377,833 @@ body::before { top: 0; left: 0; right: 0; - height: 4px; - background: linear-gradient(90deg, var(--primary-color), var(--warning-color)); + height: 3px; + background: var(--gradient-primary); + opacity: 0; + transition: opacity var(--duration-normal) var(--ease-default); } .stat-card:hover { - transform: translateY(-4px); + border-color: var(--primary-200); box-shadow: var(--shadow-lg); + transform: translateY(-2px); +} + +.stat-card:hover::before { + opacity: 1; } .stat-icon { - font-size: 2.5rem; - margin-bottom: var(--space-md); + width: 44px; + height: 44px; + border-radius: var(--radius-lg); + display: flex; + align-items: center; + justify-content: center; + font-size: 1.25rem; + margin-bottom: var(--space-3); +} + +.stat-card:nth-child(1) .stat-icon { + background: var(--primary-50); + color: var(--primary-600); +} + +.stat-card:nth-child(2) .stat-icon { + background: var(--accent-50); + color: var(--accent-600); +} + +.stat-card:nth-child(3) .stat-icon { + background: var(--warning-bg); + color: var(--warning); +} + +.stat-card:nth-child(4) .stat-icon { + background: var(--info-bg); + color: var(--info); } .stat-value { - font-size: var(--font-size-3xl); - font-weight: 800; + font-size: var(--text-3xl); + font-weight: var(--font-bold); color: var(--text-primary); line-height: 1; + margin-bottom: var(--space-1); } .stat-label { - color: var(--text-muted); - font-size: var(--font-size-sm); - margin-top: var(--space-sm); + font-size: var(--text-sm); + color: var(--text-tertiary); +} + +/* ================================ + 主内容区域布局 + ================================ */ +.content-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--space-6); +} + +@media (max-width: 1024px) { + .content-grid { + grid-template-columns: 1fr; + } +} + +/* ================================ + 卡片组件 + ================================ */ +.card { + background: var(--bg-primary); + border-radius: var(--radius-xl); + border: 1px solid var(--border-light); + overflow: hidden; + transition: all var(--duration-normal) var(--ease-default); +} + +.card:hover { + box-shadow: var(--shadow-lg); +} + +.card-header { + padding: var(--space-5) var(--space-6); + border-bottom: 1px solid var(--border-light); + display: flex; + align-items: center; + justify-content: space-between; +} + +.card-title { + display: flex; + align-items: center; + gap: var(--space-3); + font-size: var(--text-lg); + font-weight: var(--font-semibold); + color: var(--text-primary); +} + +.card-title-icon { + width: 32px; + height: 32px; + background: var(--gray-100); + border-radius: var(--radius-md); + display: flex; + align-items: center; + justify-content: center; + font-size: 1rem; +} + +.card-body { + padding: var(--space-6); +} + +/* ================================ + 上传区域 + ================================ */ +.upload-zone { + border: 2px dashed var(--border-default); + border-radius: var(--radius-xl); + padding: var(--space-10); + text-align: center; + transition: all var(--duration-normal) var(--ease-default); + cursor: pointer; + background: var(--bg-secondary); +} + +.upload-zone:hover, +.upload-zone.drag-over { + border-color: var(--primary-400); + background: var(--primary-50); +} + +.upload-zone.drag-over { + transform: scale(1.02); +} + +.upload-icon { + width: 64px; + height: 64px; + margin: 0 auto var(--space-4); + background: var(--gradient-primary); + border-radius: var(--radius-xl); + display: flex; + align-items: center; + justify-content: center; + font-size: 2rem; + color: white; + box-shadow: var(--shadow-lg); +} + +.upload-title { + font-size: var(--text-lg); + font-weight: var(--font-semibold); + color: var(--text-primary); + margin-bottom: var(--space-2); +} + +.upload-hint { + font-size: var(--text-sm); + color: var(--text-tertiary); + margin-bottom: var(--space-4); +} + +.upload-formats { + display: flex; + justify-content: center; + gap: var(--space-2); + flex-wrap: wrap; +} + +.format-tag { + padding: var(--space-1) var(--space-3); + background: var(--gray-100); + border-radius: var(--radius-full); + font-size: var(--text-xs); + font-weight: var(--font-medium); + color: var(--text-secondary); +} + +/* ================================ + 按钮样式 + ================================ */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--space-2); + padding: var(--space-3) var(--space-5); + font-size: var(--text-sm); + font-weight: var(--font-medium); + border-radius: var(--radius-lg); + border: none; + cursor: pointer; + transition: all var(--duration-fast) var(--ease-default); + white-space: nowrap; +} + +.btn-primary { + background: var(--gradient-primary); + color: white; + box-shadow: var(--shadow-md); +} + +.btn-primary:hover { + transform: translateY(-1px); + box-shadow: var(--shadow-lg); +} + +.btn-primary:active { + transform: translateY(0); +} + +.btn-secondary { + background: var(--bg-primary); + color: var(--text-primary); + border: 1px solid var(--border-default); +} + +.btn-secondary:hover { + background: var(--gray-50); + border-color: var(--border-strong); +} + +.btn-ghost { + background: transparent; + color: var(--text-secondary); +} + +.btn-ghost:hover { + background: var(--gray-100); + color: var(--text-primary); +} + +.btn-lg { + padding: var(--space-4) var(--space-8); + font-size: var(--text-base); +} + +.btn-full { + width: 100%; +} + +.btn:disabled { + opacity: 0.5; + cursor: not-allowed; + transform: none !important; +} + +/* ================================ + 文件列表 + ================================ */ +.file-list { + display: flex; + flex-direction: column; + gap: var(--space-3); +} + +.file-item { + display: flex; + align-items: center; + gap: var(--space-4); + padding: var(--space-4); + background: var(--bg-secondary); + border-radius: var(--radius-lg); + border: 1px solid transparent; + cursor: pointer; + transition: all var(--duration-fast) var(--ease-default); +} + +.file-item:hover { + background: var(--bg-primary); + border-color: var(--primary-200); + box-shadow: var(--shadow-sm); +} + +.file-icon { + width: 44px; + height: 44px; + background: var(--primary-50); + border-radius: var(--radius-lg); + display: flex; + align-items: center; + justify-content: center; + font-size: 1.25rem; + color: var(--primary-600); + flex-shrink: 0; +} + +.file-info { + flex: 1; + min-width: 0; +} + +.file-name { + font-weight: var(--font-medium); + color: var(--text-primary); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.file-meta { + display: flex; + gap: var(--space-4); + font-size: var(--text-sm); + color: var(--text-tertiary); + margin-top: var(--space-1); +} + +.file-actions { + display: flex; + gap: var(--space-2); +} + +/* ================================ + 分析结果区域 + ================================ */ +.result-section { + margin-top: var(--space-8); +} + +.result-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: var(--space-6); +} + +.result-title { + display: flex; + align-items: center; + gap: var(--space-3); + font-size: var(--text-2xl); + font-weight: var(--font-bold); +} + +.result-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: var(--space-4); +} + +.result-card { + background: var(--bg-primary); + border-radius: var(--radius-xl); + padding: var(--space-5); + border: 1px solid var(--border-light); + transition: all var(--duration-normal) var(--ease-default); +} + +.result-card:hover { + box-shadow: var(--shadow-md); + border-color: var(--primary-200); +} + +.result-card-header { + display: flex; + align-items: center; + gap: var(--space-3); + margin-bottom: var(--space-4); +} + +.result-card-icon { + width: 40px; + height: 40px; + border-radius: var(--radius-lg); + display: flex; + align-items: center; + justify-content: center; + font-size: 1.125rem; +} + +.result-card-title { + font-size: var(--text-sm); + font-weight: var(--font-medium); + color: var(--text-secondary); +} + +.result-card-value { + font-size: var(--text-2xl); + font-weight: var(--font-bold); + color: var(--text-primary); +} + +/* ================================ + 数据表格 + ================================ */ +.data-table { + width: 100%; + border-collapse: collapse; +} + +.data-table th, +.data-table td { + padding: var(--space-3) var(--space-4); + text-align: left; + border-bottom: 1px solid var(--border-light); +} + +.data-table th { + font-size: var(--text-sm); + font-weight: var(--font-medium); + color: var(--text-tertiary); + background: var(--bg-secondary); text-transform: uppercase; letter-spacing: 0.05em; } +.data-table td { + font-size: var(--text-sm); + color: var(--text-primary); +} + +.data-table tbody tr { + transition: background var(--duration-fast) var(--ease-default); +} + +.data-table tbody tr:hover { + background: var(--gray-50); +} + /* ================================ - 响应式设计 + 标签和徽章 ================================ */ -@media (max-width: 1024px) { - .app-header { - padding: var(--space-xl); +.badge { + display: inline-flex; + align-items: center; + gap: var(--space-1); + padding: var(--space-1) var(--space-3); + font-size: var(--text-xs); + font-weight: var(--font-medium); + border-radius: var(--radius-full); +} + +.badge-success { + background: var(--success-bg); + color: var(--success); +} + +.badge-warning { + background: var(--warning-bg); + color: var(--warning); +} + +.badge-error { + background: var(--error-bg); + color: var(--error); +} + +.badge-info { + background: var(--info-bg); + color: var(--info); +} + +.badge-neutral { + background: var(--gray-100); + color: var(--text-secondary); +} + +/* ================================ + 进度条 + ================================ */ +.progress-bar { + height: 8px; + background: var(--gray-200); + border-radius: var(--radius-full); + overflow: hidden; +} + +.progress-fill { + height: 100%; + background: var(--gradient-primary); + border-radius: var(--radius-full); + transition: width var(--duration-slow) var(--ease-default); + position: relative; +} + +.progress-fill::after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: var(--gradient-shine); + animation: shimmer 2s infinite; +} + +@keyframes shimmer { + 0% { transform: translateX(-100%); } + 100% { transform: translateX(100%); } +} + +/* ================================ + 通知消息 + ================================ */ +.notification-container { + position: fixed; + top: var(--space-6); + right: var(--space-6); + z-index: 1000; + display: flex; + flex-direction: column; + gap: var(--space-3); + pointer-events: none; +} + +.notification { + display: flex; + align-items: flex-start; + gap: var(--space-3); + padding: var(--space-4); + background: var(--bg-primary); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-xl); + border: 1px solid var(--border-light); + min-width: 320px; + max-width: 420px; + pointer-events: auto; + animation: slideIn var(--duration-normal) var(--ease-out); +} + +@keyframes slideIn { + from { + opacity: 0; + transform: translateX(100%); } - - .app-main { - padding: var(--space-xl); - } - - .app-title { - flex-direction: column; - align-items: flex-start; - gap: var(--space-md); + to { + opacity: 1; + transform: translateX(0); } } +.notification-icon { + width: 24px; + height: 24px; + border-radius: var(--radius-full); + display: flex; + align-items: center; + justify-content: center; + font-size: 0.875rem; + flex-shrink: 0; +} + +.notification-success .notification-icon { + background: var(--success-bg); + color: var(--success); +} + +.notification-error .notification-icon { + background: var(--error-bg); + color: var(--error); +} + +.notification-warning .notification-icon { + background: var(--warning-bg); + color: var(--warning); +} + +.notification-info .notification-icon { + background: var(--info-bg); + color: var(--info); +} + +.notification-content { + flex: 1; +} + +.notification-title { + font-weight: var(--font-medium); + color: var(--text-primary); + margin-bottom: var(--space-1); +} + +.notification-message { + font-size: var(--text-sm); + color: var(--text-secondary); +} + +.notification-close { + width: 24px; + height: 24px; + border-radius: var(--radius-md); + border: none; + background: transparent; + color: var(--text-muted); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all var(--duration-fast) var(--ease-default); +} + +.notification-close:hover { + background: var(--gray-100); + color: var(--text-primary); +} + +/* ================================ + 加载状态 + ================================ */ +.loading-spinner { + width: 24px; + height: 24px; + border: 2px solid var(--gray-200); + border-top-color: var(--primary-500); + border-radius: 50%; + animation: spin 0.8s linear infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + +.skeleton { + background: linear-gradient(90deg, var(--gray-100) 25%, var(--gray-50) 50%, var(--gray-100) 75%); + background-size: 200% 100%; + animation: skeleton-loading 1.5s infinite; + border-radius: var(--radius-md); +} + +@keyframes skeleton-loading { + 0% { background-position: 200% 0; } + 100% { background-position: -200% 0; } +} + +/* ================================ + 空状态 + ================================ */ +.empty-state { + text-align: center; + padding: var(--space-12); +} + +.empty-icon { + width: 80px; + height: 80px; + margin: 0 auto var(--space-4); + background: var(--gray-100); + border-radius: var(--radius-2xl); + display: flex; + align-items: center; + justify-content: center; + font-size: 2rem; + color: var(--text-muted); +} + +.empty-title { + font-size: var(--text-lg); + font-weight: var(--font-semibold); + color: var(--text-primary); + margin-bottom: var(--space-2); +} + +.empty-description { + font-size: var(--text-sm); + color: var(--text-tertiary); + max-width: 320px; + margin: 0 auto; +} + +/* ================================ + 页脚 + ================================ */ +.app-footer { + margin-top: var(--space-12); + padding: var(--space-6); + border-top: 1px solid var(--border-light); + text-align: center; +} + +.footer-content { + display: flex; + align-items: center; + justify-content: center; + gap: var(--space-6); + font-size: var(--text-sm); + color: var(--text-tertiary); +} + +.footer-divider { + width: 4px; + height: 4px; + background: var(--gray-300); + border-radius: 50%; +} + +/* ================================ + Vue 过渡动画 + ================================ */ +.fade-enter-active, +.fade-leave-active { + transition: opacity var(--duration-normal) var(--ease-default); +} + +.fade-enter-from, +.fade-leave-to { + opacity: 0; +} + +.slide-up-enter-active, +.slide-up-leave-active { + transition: all var(--duration-normal) var(--ease-out); +} + +.slide-up-enter-from { + opacity: 0; + transform: translateY(20px); +} + +.slide-up-leave-to { + opacity: 0; + transform: translateY(-10px); +} + +.scale-enter-active, +.scale-leave-active { + transition: all var(--duration-normal) var(--ease-bounce); +} + +.scale-enter-from, +.scale-leave-to { + opacity: 0; + transform: scale(0.95); +} + +.list-enter-active, +.list-leave-active { + transition: all var(--duration-slow) var(--ease-out); +} + +.list-enter-from { + opacity: 0; + transform: translateX(-20px); +} + +.list-leave-to { + opacity: 0; + transform: translateX(20px); +} + +.list-move { + transition: transform var(--duration-slow) var(--ease-default); +} + +/* ================================ + 响应式调整 + ================================ */ @media (max-width: 768px) { - body { - padding: var(--space-md); + .main-content { + padding: var(--space-4); } - .app-header { - padding: var(--space-lg); - border-radius: var(--radius-xl) var(--radius-xl) 0 0; + .header-content { + padding: var(--space-3) var(--space-4); } - .app-main { - padding: var(--space-lg); - border-radius: 0 0 var(--radius-xl) var(--radius-xl); + .logo-text { + font-size: var(--text-lg); } - .app-title h1 { - font-size: var(--font-size-2xl); + .nav-menu { + display: none; } - .app-nav { - flex-wrap: wrap; + .card-body { + padding: var(--space-4); } - .nav-link { - padding: var(--space-sm) var(--space-md); - font-size: var(--font-size-sm); - } - - .upload-area { - padding: var(--space-xl); - } - - .upload-icon { - font-size: 3rem; - } - - .task-info, - .geometry-data, - .bounding-box-data, - .topology-data, - .features-data, - .recommendations-data, - .metrics-data, - .analysis-info { - grid-template-columns: 1fr; - } - - .app-footer { - flex-direction: column; - gap: var(--space-md); - text-align: center; - } - - .footer-left, - .footer-right { - flex-wrap: wrap; - justify-content: center; - } - - .stats-grid { - grid-template-columns: 1fr 1fr; - } -} - -@media (max-width: 480px) { - .stats-grid { - grid-template-columns: 1fr; + .upload-zone { + padding: var(--space-6); } .notification-container { - left: var(--space-md); - right: var(--space-md); + top: var(--space-4); + right: var(--space-4); + left: var(--space-4); + } + + .notification { + min-width: auto; max-width: none; } - - .history-table { - font-size: var(--font-size-sm); +} + +/* ================================ + 深色模式支持 + ================================ */ +@media (prefers-color-scheme: dark) { + :root { + --bg-primary: #18181b; + --bg-secondary: #0f0f12; + --bg-tertiary: #27272a; + --bg-elevated: #27272a; + + --border-light: #27272a; + --border-default: #3f3f46; + + --text-primary: #fafafa; + --text-secondary: #d4d4d8; + --text-tertiary: #a1a1aa; + --text-muted: #71717a; } - .history-table th, - .history-table td { - padding: var(--space-sm); + .stat-card, + .card, + .result-card, + .notification { + background: var(--bg-elevated); + } + + .upload-zone { + background: var(--bg-tertiary); + } + + .upload-zone:hover, + .upload-zone.drag-over { + background: rgba(99, 102, 241, 0.1); } } @@ -1189,415 +1211,74 @@ body::before { 打印样式 ================================ */ @media print { - body { - background: white; - padding: 0; - } - .app-header, - .app-footer, + .nav-menu, .notification-container, - .upload-section, - .nav-link { - display: none; + .btn { + display: none !important; } - .app-main { - box-shadow: none; - border: none; - padding: 0; + .app-container { + background: white; } + .card, + .stat-card, .result-card { - break-inside: avoid; box-shadow: none; border: 1px solid #ddd; } } /* ================================ - 深色模式支持(可选) + 工具类 ================================ */ -@media (prefers-color-scheme: dark) { - :root { - --warm-white: #1a1816; - --cream: #2c2824; - --text-primary: #f5f3f0; - --text-secondary: #d4cfc6; - --text-muted: #a69f94; - } -} +.text-center { text-align: center; } +.text-left { text-align: left; } +.text-right { text-align: right; } -/* ================================ - Vue 过渡动画 - ================================ */ -.fade-slide-enter-active, -.fade-slide-leave-active { - transition: all 0.3s ease; -} +.font-mono { font-family: var(--font-mono); } +.font-bold { font-weight: var(--font-bold); } +.font-medium { font-weight: var(--font-medium); } -.fade-slide-enter-from { - opacity: 0; - transform: translateY(10px); -} +.text-primary { color: var(--text-primary); } +.text-secondary { color: var(--text-secondary); } +.text-muted { color: var(--text-muted); } -.fade-slide-leave-to { - opacity: 0; - transform: translateY(-10px); -} +.mt-2 { margin-top: var(--space-2); } +.mt-4 { margin-top: var(--space-4); } +.mt-6 { margin-top: var(--space-6); } +.mb-2 { margin-bottom: var(--space-2); } +.mb-4 { margin-bottom: var(--space-4); } +.mb-6 { margin-bottom: var(--space-6); } -.notification-enter-active, -.notification-leave-active { - transition: all 0.3s ease; -} +.flex { display: flex; } +.flex-col { flex-direction: column; } +.items-center { align-items: center; } +.justify-center { justify-content: center; } +.justify-between { justify-content: space-between; } +.gap-2 { gap: var(--space-2); } +.gap-4 { gap: var(--space-4); } +.gap-6 { gap: var(--space-6); } -.notification-enter-from { - opacity: 0; - transform: translateX(100%); -} +.hidden { display: none; } +.visible { visibility: visible; } +.invisible { visibility: hidden; } -.notification-leave-to { - opacity: 0; - transform: translateX(100%); -} - -.notification-hidden { - opacity: 0; - transform: translateX(20px); -} - -.list-enter-active, -.list-leave-active { - transition: all 0.4s ease; -} - -.list-enter-from { - opacity: 0; - transform: translateY(20px); -} - -.list-leave-to { - opacity: 0; - transform: translateY(-20px); -} - -.list-move { - transition: transform 0.4s ease; -} - -.expand-enter-active, -.expand-leave-active { - transition: all 0.3s ease; +.truncate { overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } -.expand-enter-from, -.expand-leave-to { - opacity: 0; - max-height: 0; -} - -.expand-enter-to, -.expand-leave-from { - max-height: 1000px; -} - -/* ================================ - 卡片和布局组件 - ================================ */ -.card { - background: white; - border-radius: var(--radius-xl); - padding: var(--space-xl); - border: 1px solid var(--warm-gray-200); - box-shadow: var(--shadow-sm); - transition: all var(--transition-base); -} - -.card:hover { - box-shadow: var(--shadow-md); -} - -.card h2 { - display: flex; - align-items: center; - gap: var(--space-sm); - color: var(--text-primary); - font-size: var(--font-size-xl); - margin-bottom: var(--space-md); -} - -.card-icon { - font-size: 1.5em; -} - -.card-subtitle { - color: var(--text-muted); - font-size: var(--font-size-sm); - margin-bottom: var(--space-lg); -} - -.grid-2 { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: var(--space-lg); -} - -.grid-3 { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: var(--space-lg); -} - -@media (max-width: 1024px) { - .grid-2, - .grid-3 { - grid-template-columns: 1fr; - } -} - -/* ================================ - 上传卡片 - ================================ */ -.upload-card { - min-height: 400px; -} - -.upload-btn { - width: 100%; - margin-top: var(--space-lg); - padding: var(--space-md) var(--space-xl); - font-size: var(--font-size-lg); -} - -.clear-btn { - margin-top: var(--space-sm); -} - -.current-task-card { - background: linear-gradient(135deg, var(--warm-gray-50) 0%, white 100%); - border-radius: var(--radius-lg); - padding: var(--space-lg); - margin-top: var(--space-xl); - border: 1px solid var(--warm-gray-200); -} - -.current-task-card h4 { - color: var(--text-primary); - margin-bottom: var(--space-md); -} - -/* ================================ - 文件预览 - ================================ */ -.latest-file { - margin-bottom: var(--space-lg); -} - -.latest-file h4 { - color: var(--text-secondary); - font-size: var(--font-size-sm); - text-transform: uppercase; - letter-spacing: 0.05em; - margin-bottom: var(--space-md); -} - -.file-preview { - display: flex; - align-items: center; - gap: var(--space-md); - padding: var(--space-md); - background: var(--warm-gray-50); - border-radius: var(--radius-lg); -} - -.file-preview .file-icon { - font-size: 2rem; -} - -.file-preview .file-name { - font-weight: 600; - color: var(--text-primary); - margin-bottom: var(--space-xs); -} - -.file-preview .file-meta { - display: flex; - gap: var(--space-md); - color: var(--text-muted); - font-size: var(--font-size-sm); -} - -.link-btn { - display: inline-flex; - margin-top: var(--space-lg); -} - -/* ================================ - 历史记录视图 - ================================ */ -.history-view h2 { - display: flex; - align-items: center; - gap: var(--space-sm); - color: var(--text-primary); - margin-bottom: var(--space-sm); -} - -.file-list { - display: flex; - flex-direction: column; - gap: var(--space-md); - margin-top: var(--space-xl); -} - -.file-card { - background: white; - border-radius: var(--radius-lg); - border: 1px solid var(--warm-gray-200); +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; overflow: hidden; - transition: all var(--transition-base); -} - -.file-card:hover { - box-shadow: var(--shadow-md); -} - -.file-card.expanded { - box-shadow: var(--shadow-lg); -} - -.file-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: var(--space-lg); - cursor: pointer; - transition: background var(--transition-fast); -} - -.file-header:hover { - background: var(--warm-gray-50); -} - -.file-info .file-name { - font-weight: 600; - color: var(--text-primary); - margin-bottom: var(--space-xs); -} - -.file-info .file-meta { - color: var(--text-muted); - font-size: var(--font-size-sm); -} - -.expand-btn { - flex-shrink: 0; -} - -.record-list { - padding: 0 var(--space-lg) var(--space-lg); -} - -.record-item { - padding: var(--space-md); - background: var(--warm-gray-50); - border-radius: var(--radius-md); - margin-bottom: var(--space-sm); - cursor: pointer; - transition: all var(--transition-fast); -} - -.record-item:hover { - background: var(--primary-light); - transform: translateX(4px); -} - -.record-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: var(--space-sm); -} - -.record-date { - color: var(--text-secondary); - font-size: var(--font-size-sm); -} - -.record-meta { - display: flex; - flex-wrap: wrap; - gap: var(--space-md); - color: var(--text-muted); - font-size: var(--font-size-sm); -} - -/* ================================ - 结果视图 - ================================ */ -.result-view h2 { - display: flex; - align-items: center; - gap: var(--space-sm); - color: var(--text-primary); - margin-bottom: var(--space-xl); -} - -.result-layout { - display: flex; - flex-direction: column; - gap: var(--space-xl); -} - -/* ================================ - 通知图标 - ================================ */ -.notification-icon { - width: 24px; - height: 24px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - font-size: 12px; - font-weight: bold; - flex-shrink: 0; -} - -.notification-success .notification-icon { - background: var(--success-color); - color: white; -} - -.notification-error .notification-icon { - background: var(--error-color); - color: white; -} - -.notification-warning .notification-icon { - background: var(--warning-color); - color: white; -} - -.notification-info .notification-icon { - background: var(--info-color); - color: white; -} - -/* ================================ - 页脚增强 - ================================ */ -.footer-item { - display: inline-flex; - align-items: center; - gap: var(--space-xs); -} - -.footer-label { - color: var(--text-muted); -} - -.footer-divider { - color: var(--warm-gray-400); + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; } diff --git a/static/vue-app.js b/static/vue-app.js index a313941..76b43c2 100644 --- a/static/vue-app.js +++ b/static/vue-app.js @@ -1,24 +1,23 @@ /** * STP模具几何分析中心 - Vue3单页应用 - * 版本: 4.0.0 - 暖白色主题 + 增强动画效果 + * 版本: 5.0.0 - Modern Minimal UI + * 设计灵感: Linear, Notion, Vercel, Stripe */ const { createApp, ref, computed, onMounted, reactive, watch, nextTick } = Vue; const { createRouter, createWebHistory, useRoute, useRouter } = VueRouter; -// 全局状态管理 const appState = reactive({ health: null, loading: false, notifications: [], - theme: 'warm' + theme: 'modern' }); -// 通用工具函数 function formatFileSize(bytes) { - if (!bytes || bytes === 0) return "0 Bytes"; + if (!bytes || bytes === 0) return "0 B"; const k = 1024; - const sizes = ["Bytes", "KB", "MB", "GB"]; + const sizes = ["B", "KB", "MB", "GB"]; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; } @@ -51,12 +50,12 @@ function statusText(status) { function getStatusClass(status) { const classMap = { - pending: "status-pending", - processing: "status-processing", - completed: "status-completed", - failed: "status-failed" + pending: "badge-warning", + processing: "badge-info", + completed: "badge-success", + failed: "badge-error" }; - return classMap[status] || "status-pending"; + return classMap[status] || "badge-neutral"; } let notificationId = 0; @@ -93,7 +92,6 @@ function handleApiError(error, context = '') { return message; } -// 顶部导航 + 布局 const App = { setup() { const route = useRoute(); @@ -110,7 +108,6 @@ const App = { } } catch (error) { appState.health = null; - handleApiError(error, '健康检查'); } }; @@ -143,77 +140,80 @@ const App = { }; }, template: ` -
专业模具几何分析,支持型腔自动生成与工艺参数计算
+