-
e.stopPropagation()}
- >
- {children}
+
{site.name}
+ {site.description &&
{site.description}
}
+ {site.category &&
{site.category.name}}
+
+
+
+
)
diff --git a/frontend/src/index.css b/frontend/src/index.css
index 67b7224..f534499 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -1,95 +1,761 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
-
-:root {
- --bg-primary: #0d0f12;
- --bg-secondary: #15181f;
- --bg-card: #1a1d24;
- --bg-hover: #1e293b;
- --text-primary: #f1f5f9;
- --text-secondary: #94a3b8;
- --text-muted: #64748b;
- --border-color: #2a2f3a;
- --accent: #6366f1;
- --accent-hover: #818cf8;
-}
-
-* {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
-}
-
-html {
- font-family: 'Inter', system-ui, -apple-system, sans-serif;
-}
+/* ===== 精致美观导航网站 v3 ===== */
+* { margin: 0; padding: 0; box-sizing: border-box; }
+html, body, #root { height: 100%; }
body {
- background: var(--bg-primary);
- color: var(--text-primary);
+ font-family: 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', -apple-system, sans-serif;
+ font-size: 14px;
+ line-height: 1.6;
+ color: #333;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ min-height: 100vh;
+ -webkit-font-smoothing: antialiased;
+}
+
+/* ===== 整体布局 ===== */
+.app {
+ display: flex;
min-height: 100vh;
}
-/* Glass effect */
-.glass {
- background: rgba(26, 29, 36, 0.8);
- backdrop-filter: blur(12px);
- border: 1px solid var(--border-color);
+/* ===== 左侧边栏 ===== */
+.sidebar {
+ width: 240px;
+ background: rgba(255, 255, 255, 0.95);
+ backdrop-filter: blur(20px);
+ border-right: 1px solid rgba(255, 255, 255, 0.2);
+ display: flex;
+ flex-direction: column;
+ flex-shrink: 0;
}
-/* Card hover effect */
-.card-hover {
+.sidebar-header {
+ padding: 20px;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.05);
+}
+
+.logo {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.logo-icon {
+ width: 36px;
+ height: 36px;
+ background: linear-gradient(135deg, #667eea, #764ba2);
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: white;
+ font-size: 16px;
+}
+
+.logo-text {
+ font-size: 16px;
+ font-weight: 600;
+ background: linear-gradient(135deg, #667eea, #764ba2);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+/* 分类列表 */
+.categories-section {
+ flex: 1;
+ overflow-y: auto;
+ padding: 16px 12px;
+}
+
+.categories-title {
+ font-size: 11px;
+ font-weight: 600;
+ color: #999;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+ padding: 0 8px;
+ margin-bottom: 8px;
+}
+
+.category-item {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 10px 12px;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ margin-bottom: 4px;
+ color: #666;
+ font-size: 13px;
+}
+
+.category-item:hover {
+ background: rgba(102, 126, 234, 0.08);
+ color: #667eea;
+}
+
+.category-item.active {
+ background: linear-gradient(135deg, #667eea, #764ba2);
+ color: white;
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
+}
+
+.category-icon {
+ width: 24px;
+ height: 24px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 6px;
+ background: rgba(0, 0, 0, 0.04);
+ font-size: 14px;
+}
+
+.category-item.active .category-icon {
+ background: rgba(255, 255, 255, 0.2);
+}
+
+.category-name {
+ flex: 1;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.category-count {
+ font-size: 11px;
+ padding: 2px 6px;
+ background: rgba(0, 0, 0, 0.06);
+ border-radius: 10px;
+}
+
+.category-item.active .category-count {
+ background: rgba(255, 255, 255, 0.2);
+}
+
+/* 侧边栏底部 */
+.sidebar-footer {
+ padding: 16px;
+ border-top: 1px solid rgba(0, 0, 0, 0.05);
+}
+
+.add-btn {
+ width: 100%;
+ height: 40px;
+ background: linear-gradient(135deg, #667eea, #764ba2);
+ color: white;
+ border: none;
+ border-radius: 10px;
+ font-size: 13px;
+ font-weight: 500;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 6px;
+ transition: all 0.2s ease;
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
+}
+
+.add-btn:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
+}
+
+/* ===== 主内容区 ===== */
+.main-content {
+ flex: 1;
+ padding: 32px;
+ overflow-y: auto;
+}
+
+/* 搜索栏 */
+.search-bar {
+ max-width: 600px;
+ margin-bottom: 32px;
+ position: relative;
+}
+
+.search-input {
+ width: 100%;
+ height: 48px;
+ padding: 0 20px 0 48px;
+ background: rgba(255, 255, 255, 0.95);
+ border: 2px solid transparent;
+ border-radius: 24px;
+ font-size: 14px;
+ color: #333;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
transition: all 0.2s ease;
}
-.card-hover:hover {
- transform: translateY(-4px);
- box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
- border-color: var(--accent);
+.search-input:focus {
+ outline: none;
+ border-color: rgba(102, 126, 234, 0.5);
+ box-shadow: 0 4px 25px rgba(102, 126, 234, 0.2);
}
-/* Scrollbar */
+.search-icon {
+ position: absolute;
+ left: 18px;
+ top: 50%;
+ transform: translateY(-50%);
+ color: #999;
+}
+
+/* 区块标题 */
+.section-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 20px;
+}
+
+.section-title {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ font-size: 16px;
+ font-weight: 600;
+ color: white;
+ text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
+}
+
+.section-count {
+ font-size: 13px;
+ font-weight: 400;
+ opacity: 0.8;
+}
+
+/* 网站网格 */
+.website-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
+ gap: 20px;
+}
+
+/* 网站卡片 */
+.site-card {
+ position: relative;
+ background: white;
+ border-radius: 16px;
+ padding: 24px 20px;
+ cursor: pointer;
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
+ overflow: hidden;
+}
+
+.site-card::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 4px;
+ background: linear-gradient(90deg, #667eea, #764ba2);
+ opacity: 0;
+ transition: opacity 0.3s ease;
+}
+
+.site-card:hover {
+ transform: translateY(-6px);
+ box-shadow: 0 16px 50px rgba(102, 126, 234, 0.25);
+}
+
+.site-card:hover::before {
+ opacity: 1;
+}
+
+.site-card:hover .card-bottom-actions {
+ opacity: 1;
+}
+
+.card-bottom-actions {
+ position: absolute;
+ bottom: 12px;
+ left: 12px;
+ right: 12px;
+ display: flex;
+ gap: 6px;
+ justify-content: flex-end;
+ align-items: center;
+}
+
+.site-card:hover .external-icon {
+ opacity: 0;
+}
+
+/* 卡片图标 */
+.card-icon {
+ width: 52px;
+ height: 52px;
+ background: linear-gradient(135deg, #f5f7fa, #e4e8ec);
+ border-radius: 14px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 16px;
+ transition: all 0.3s ease;
+}
+
+.site-card:hover .card-icon {
+ transform: scale(1.05);
+ background: linear-gradient(135deg, #667eea15, #764ba215);
+}
+
+.card-icon img {
+ width: 28px;
+ height: 28px;
+ object-fit: contain;
+}
+
+.card-icon svg {
+ width: 26px;
+ height: 26px;
+ color: #667eea;
+}
+
+.card-name {
+ font-size: 14px;
+ font-weight: 600;
+ color: #1a1a1a;
+ margin-bottom: 4px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.card-desc {
+ font-size: 12px;
+ color: #888;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.card-category {
+ display: inline-block;
+ margin-top: 12px;
+ padding: 4px 10px;
+ background: linear-gradient(135deg, #667eea10, #764ba210);
+ border-radius: 6px;
+ font-size: 11px;
+ font-weight: 500;
+ color: #667eea;
+}
+
+/* 收藏星星 */
+.card-favorite {
+ width: 32px;
+ height: 32px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border: none;
+ background: #f5f5f5;
+ color: #ccc;
+ cursor: pointer;
+ border-radius: 8px;
+ padding: 0;
+ transition: all 0.2s ease;
+}
+
+.card-favorite:hover,
+.card-favorite.active {
+ color: #fbbf24;
+ background: #fef3c7;
+}
+
+/* 操作按钮 */
+.card-actions {
+ position: absolute;
+ bottom: 12px;
+ right: 12px;
+ display: flex;
+ gap: 4px;
+ padding: 4px;
+ background: rgba(255, 255, 255, 0.95);
+ border-radius: 10px;
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+ opacity: 0;
+ transition: all 0.2s ease;
+}
+
+.action-btn {
+ width: 32px;
+ height: 32px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border: none;
+ background: #f5f5f5;
+ color: #888;
+ cursor: pointer;
+ border-radius: 8px;
+ transition: all 0.2s ease;
+}
+
+.action-btn:hover {
+ border-color: #667eea;
+ color: #667eea;
+ transform: scale(1.05);
+}
+
+.action-btn.delete:hover {
+ border-color: #ef4444;
+ color: #ef4444;
+ background: #fef2f2;
+}
+
+/* 外部链接图标 */
+.external-icon {
+ position: absolute;
+ bottom: 14px;
+ right: 14px;
+ color: #ccc;
+ opacity: 0;
+ transition: all 0.2s ease;
+}
+
+/* 空状态 */
+.empty-state {
+ text-align: center;
+ padding: 80px 40px;
+ background: rgba(255, 255, 255, 0.95);
+ border-radius: 24px;
+ box-shadow: 0 8px 40px rgba(0, 0, 0, 0.1);
+}
+
+.empty-icon {
+ width: 100px;
+ height: 100px;
+ margin: 0 auto 24px;
+ background: linear-gradient(135deg, #667eea15, #764ba215);
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.empty-icon svg {
+ width: 44px;
+ height: 44px;
+ color: #667eea;
+}
+
+.empty-title {
+ font-size: 20px;
+ font-weight: 600;
+ color: #1a1a1a;
+ margin-bottom: 8px;
+}
+
+.empty-desc {
+ font-size: 14px;
+ color: #888;
+ margin-bottom: 28px;
+}
+
+/* ===== 弹窗 ===== */
+.modal-overlay {
+ position: fixed;
+ inset: 0;
+ background: rgba(0, 0, 0, 0.5);
+ backdrop-filter: blur(4px);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 1000;
+ padding: 24px;
+}
+
+.modal {
+ background: white;
+ border-radius: 20px;
+ padding: 28px;
+ width: 100%;
+ max-width: 420px;
+ box-shadow: 0 25px 80px rgba(0, 0, 0, 0.25);
+}
+
+.modal-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 24px;
+}
+
+.modal-title {
+ font-size: 18px;
+ font-weight: 600;
+ color: #1a1a1a;
+}
+
+.modal-close {
+ width: 32px;
+ height: 32px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border: none;
+ background: #f5f5f5;
+ color: #888;
+ cursor: pointer;
+ border-radius: 8px;
+ transition: all 0.2s ease;
+}
+
+.modal-close:hover {
+ background: #eee;
+ color: #333;
+}
+
+/* ===== 表单 ===== */
+.form-group {
+ margin-bottom: 18px;
+}
+
+.form-label {
+ display: block;
+ font-size: 13px;
+ font-weight: 500;
+ color: #555;
+ margin-bottom: 8px;
+}
+
+.form-input {
+ width: 100%;
+ height: 44px;
+ padding: 0 14px;
+ border: 2px solid #f0f0f0;
+ border-radius: 10px;
+ font-size: 14px;
+ color: #333;
+ transition: all 0.2s ease;
+}
+
+.form-input:focus {
+ outline: none;
+ border-color: #667eea;
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
+}
+
+.form-select {
+ width: 100%;
+ height: 44px;
+ padding: 0 14px;
+ border: 2px solid #f0f0f0;
+ border-radius: 10px;
+ font-size: 14px;
+ color: #333;
+ background: white;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.form-select:focus {
+ outline: none;
+ border-color: #667eea;
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
+}
+
+.form-checkbox {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ font-size: 14px;
+ color: #555;
+ cursor: pointer;
+}
+
+.form-checkbox input {
+ width: 18px;
+ height: 18px;
+ accent-color: #667eea;
+}
+
+.color-picker {
+ width: 100%;
+ height: 44px;
+ padding: 4px;
+ border: 2px solid #f0f0f0;
+ border-radius: 10px;
+ cursor: pointer;
+ background: white;
+}
+
+.icon-picker {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+
+.icon-option {
+ width: 40px;
+ height: 40px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border: 2px solid #f0f0f0;
+ border-radius: 10px;
+ background: white;
+ color: #666;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.icon-option:hover {
+ border-color: #667eea;
+ color: #667eea;
+}
+
+.icon-option.selected {
+ border-color: #667eea;
+ background: linear-gradient(135deg, #667eea10, #764ba210);
+ color: #667eea;
+}
+
+.form-actions {
+ display: flex;
+ gap: 12px;
+ margin-top: 28px;
+}
+
+.form-actions .btn {
+ flex: 1;
+ height: 46px;
+ border-radius: 12px;
+ font-size: 15px;
+ font-weight: 500;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.btn-cancel {
+ background: #f5f5f5;
+ border: none;
+ color: #666;
+}
+
+.btn-cancel:hover {
+ background: #eee;
+}
+
+.btn-submit {
+ background: linear-gradient(135deg, #667eea, #764ba2);
+ border: none;
+ color: white;
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
+}
+
+.btn-submit:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
+}
+
+/* ===== 加载 ===== */
+.loading {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-height: 300px;
+}
+
+.spinner {
+ width: 32px;
+ height: 32px;
+ border: 3px solid rgba(255, 255, 255, 0.3);
+ border-top-color: white;
+ border-radius: 50%;
+ animation: spin 0.8s linear infinite;
+}
+
+@keyframes spin {
+ to { transform: rotate(360deg); }
+}
+
+/* ===== 响应式 ===== */
+@media (max-width: 768px) {
+ .app {
+ flex-direction: column;
+ }
+
+ .sidebar {
+ width: 100%;
+ max-height: 40vh;
+ border-right: none;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.2);
+ }
+
+ .categories-section {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ padding: 12px;
+ }
+
+ .categories-title {
+ display: none;
+ }
+
+ .category-item {
+ margin: 0;
+ padding: 8px 12px;
+ background: rgba(0, 0, 0, 0.04);
+ border-radius: 8px;
+ }
+
+ .category-count {
+ display: none;
+ }
+
+ .sidebar-footer {
+ padding: 12px;
+ }
+
+ .add-btn span {
+ display: none;
+ }
+
+ .main-content {
+ padding: 20px;
+ }
+
+ .search-bar {
+ margin-bottom: 20px;
+ }
+
+ .search-input {
+ height: 42px;
+ }
+
+ .website-grid {
+ grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
+ gap: 14px;
+ }
+
+ .site-card {
+ padding: 18px 16px;
+ }
+}
+
+/* ===== 滚动条 ===== */
::-webkit-scrollbar {
- width: 8px;
- height: 8px;
+ width: 6px;
+ height: 6px;
}
::-webkit-scrollbar-track {
- background: var(--bg-secondary);
+ background: transparent;
}
::-webkit-scrollbar-thumb {
- background: var(--bg-hover);
- border-radius: 4px;
+ background: rgba(0, 0, 0, 0.15);
+ border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
- background: #334155;
-}
-
-/* Input focus */
-input:focus, textarea:focus, select:focus {
- outline: none;
- border-color: var(--accent);
- box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);
-}
-
-/* Button press effect */
-.btn-press:active {
- transform: scale(0.97);
-}
-
-/* Modal backdrop */
-.modal-backdrop {
- background: rgba(0, 0, 0, 0.7);
- backdrop-filter: blur(4px);
-}
-
-/* Gradient text */
-.gradient-text {
- background: linear-gradient(135deg, #6366f1 0%, #a855f7 50%, #ec4899 100%);
- -webkit-background-clip: text;
- -webkit-text-fill-color: transparent;
- background-clip: text;
+ background: rgba(0, 0, 0, 0.25);
}
diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js
index ede1a58..7aaedcc 100644
--- a/frontend/tailwind.config.js
+++ b/frontend/tailwind.config.js
@@ -8,23 +8,28 @@ export default {
extend: {
colors: {
primary: {
- 50: '#f0f9ff',
- 100: '#e0f2fe',
- 200: '#bae6fd',
- 300: '#7dd3fc',
- 400: '#38bdf8',
- 500: '#0ea5e9',
- 600: '#0284c7',
- 700: '#0369a1',
- 800: '#075985',
- 900: '#0c4a6e',
+ 50: '#faf5ff',
+ 100: '#f3e8ff',
+ 200: '#e9d5ff',
+ 300: '#d8b4fe',
+ 400: '#c084fc',
+ 500: '#a855f7',
+ 600: '#9333ea',
+ 700: '#7e22ce',
+ 800: '#6b21a8',
+ 900: '#581c87',
},
- dark: {
- 100: '#1e293b',
- 200: '#1a1d24',
- 300: '#15181f',
- 400: '#111318',
- 500: '#0d0f12',
+ surface: {
+ 50: '#ffffff',
+ 100: '#fafafa',
+ 200: '#f4f4f5',
+ 300: '#e4e4e7',
+ 400: '#a1a1aa',
+ 500: '#71717a',
+ 600: '#52525b',
+ 700: '#3f3f46',
+ 800: '#27272a',
+ 900: '#18181b',
}
},
fontFamily: {
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
index 13dbe22..c25aa9d 100644
--- a/frontend/vite.config.js
+++ b/frontend/vite.config.js
@@ -6,6 +6,7 @@ export default defineConfig({
server: {
host: '0.0.0.0',
port: 5173,
+ allowedHosts: ['nav.pags.cn', 'localhost', '127.0.0.1'],
proxy: {
'/api': {
target: 'http://localhost:5003',