diff --git a/.gitignore b/.gitignore index cddf356..47eed78 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,6 @@ database/*.sqlite3 uploads/ .vscode/ .idea/ +backup/ +*.zip diff --git a/backend/database/dev.sqlite3 b/backend/database/dev.sqlite3 index 8ca0d64..8a29b04 100644 Binary files a/backend/database/dev.sqlite3 and b/backend/database/dev.sqlite3 differ diff --git a/backend/src/routes/index.ts b/backend/src/routes/index.ts index 90404b0..8a8017d 100644 --- a/backend/src/routes/index.ts +++ b/backend/src/routes/index.ts @@ -6,6 +6,11 @@ import settingRoutes from './settings'; const router = new Router(); +// 健康检查端点(用于 Docker 健康检查) +router.get('/api/health', (ctx) => { + ctx.body = { status: 'ok', timestamp: new Date().toISOString() }; +}); + router.use('/api/auth', authRoutes.routes()); router.use('/api/projects', projectRoutes.routes()); router.use('/api/files', fileRoutes.routes()); diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 7a6fd72..e178efa 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -24,20 +24,48 @@ onMounted(async () => { diff --git a/frontend/src/api/auth.ts b/frontend/src/api/auth.ts index f2bca92..9f3f7f7 100644 --- a/frontend/src/api/auth.ts +++ b/frontend/src/api/auth.ts @@ -12,9 +12,9 @@ export interface RegisterData { } export const authApi = { - login: (data: LoginData) => api.post('/auth/login', data), - register: (data: RegisterData) => api.post('/auth/register', data), - logout: () => api.post('/auth/logout'), - getMe: () => api.get('/auth/me') + login: (data: LoginData) => api.post('/auth/login', data) as Promise, + register: (data: RegisterData) => api.post('/auth/register', data) as Promise, + logout: () => api.post('/auth/logout') as Promise, + getMe: () => api.get('/auth/me') as Promise }; diff --git a/frontend/src/components/Drawer.vue b/frontend/src/components/Drawer.vue index 7e73eb5..e9f398b 100644 --- a/frontend/src/components/Drawer.vue +++ b/frontend/src/components/Drawer.vue @@ -3,10 +3,10 @@
-

{{ title }}

+

{{ title }}

-
+
@@ -42,69 +42,110 @@ const handleOverlayClick = () => { left: 0; right: 0; bottom: 0; - background: rgba(0, 0, 0, 0.5); + background: rgba(0, 0, 0, 0.7); + backdrop-filter: blur(8px); z-index: 1000; display: flex; justify-content: flex-end; } .drawer-content { - background: white; - width: 400px; + background: rgba(18, 18, 20, 0.95); + width: 500px; max-width: 90vw; height: 100%; display: flex; flex-direction: column; - box-shadow: -2px 0 10px rgba(0, 0, 0, 0.1); + box-shadow: -10px 0 40px rgba(0, 0, 0, 0.5); + border-left: 1px solid var(--primary); + position: relative; +} + +.drawer-content::before { + content: ''; + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 1px; + background: var(--primary); + box-shadow: 0 0 15px var(--primary); } .drawer-header { - padding: 1.5rem; - border-bottom: 1px solid #eee; + padding: 2rem; + border-bottom: 1px solid rgba(255,255,255,0.1); display: flex; justify-content: space-between; align-items: center; + background: rgba(255,255,255,0.02); } .drawer-header h2 { margin: 0; - font-size: 1.5rem; - color: #333; + font-size: 1.8rem; + font-weight: 800; + color: white; + letter-spacing: -1px; + text-transform: uppercase; } .close-btn { - background: none; - border: none; + background: transparent; + border: 1px solid transparent; font-size: 2rem; - color: #999; + color: var(--color-text-muted); cursor: pointer; line-height: 1; padding: 0; - width: 32px; - height: 32px; + width: 40px; + height: 40px; + border-radius: 50%; display: flex; align-items: center; justify-content: center; + transition: all var(--transition-fast); } .close-btn:hover { - color: #333; + color: var(--primary); + border-color: var(--primary); + box-shadow: 0 0 10px rgba(var(--color-primary-rgb), 0.3); + transform: rotate(90deg); } .drawer-body { flex: 1; overflow-y: auto; - padding: 1.5rem; + padding: 2rem; +} + +.custom-scrollbar::-webkit-scrollbar { + width: 6px; } +.custom-scrollbar::-webkit-scrollbar-track { + background: rgba(0,0,0,0.2); +} + +.custom-scrollbar::-webkit-scrollbar-thumb { + background-color: #333; + border-radius: 3px; +} + +.custom-scrollbar::-webkit-scrollbar-thumb:hover { + background-color: var(--primary); +} + +/* Drawer Transition */ .drawer-enter-active, .drawer-leave-active { - transition: opacity 0.3s; + transition: opacity 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); } .drawer-enter-active .drawer-content, .drawer-leave-active .drawer-content { - transition: transform 0.3s; + transition: transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); } .drawer-enter-from { @@ -122,5 +163,4 @@ const handleOverlayClick = () => { .drawer-leave-to .drawer-content { transform: translateX(100%); } - - + \ No newline at end of file diff --git a/frontend/src/components/NavBar.vue b/frontend/src/components/NavBar.vue index cc16564..4f1c1cb 100644 --- a/frontend/src/components/NavBar.vue +++ b/frontend/src/components/NavBar.vue @@ -2,33 +2,38 @@