Pārlūkot izejas kodu

refactor(样式): 重构样式系统并替换旧API实现

- 引入CSS变量支持暗色模式
- 删除旧的lazyapi.ts实现,替换为新的axios.ts API模块
- 更新BlogMenu组件样式以使用新的CSS变量
- 修改路由组件类型定义提高类型安全性

这些更改改善了代码的可维护性和可扩展性,同时为暗色模式提供了支持。
Sakulin 2 mēneši atpakaļ
vecāks
revīzija
fb2515b0e6
5 mainītis faili ar 174 papildinājumiem un 71 dzēšanām
  1. 41 9
      src/assets/main.css
  2. 22 13
      src/components/BlogMenu.vue
  3. 2 1
      src/router/index.ts
  4. 109 0
      src/utils/axios.ts
  5. 0 48
      src/utils/lazyapi.ts

+ 41 - 9
src/assets/main.css

@@ -1,9 +1,41 @@
+:root {
+  --background-color: #ffffff;
+  --secondary-background-color: #f0f0f0;
+  --text-color: #474747;
+  --primary-text-color: #474747;
+  --secondary-text-color: #6c757d;
+  --muted-text-color: #999;
+  --highlight-text-color: #dc3545;
+  --link-color: blue;
+  --success-color: #28a745;
+  --warning-color: #ffc107;
+  --danger-color: #dc3545;
+  --info-color: #17a2b8;
+}
+
+@media (prefers-color-scheme: dark) {
+  :root {
+    --background-color: #343a40;
+    --secondary-background-color: #495057;
+    --text-color: #f8f9fa;
+    --primary-text-color: #f8f9fa;
+    --secondary-text-color: #adb5bd;
+    --muted-text-color: #6c757d;
+    --highlight-text-color: #ff6b6b;
+    --link-color: #66d9ef;
+    --success-color: #4caf50;
+    --warning-color: #ffd700;
+    --danger-color: #ff6b6b;
+    --info-color: #1abc9c;
+  }
+}
+
 body {
     margin: 0;
     font-size: 16px;
     box-sizing: border-box;
-    background: #f0f0f0;
-    color: #474747;
+    background: var(--secondary-background-color);
+    color: var(--primary-text-color);
 }
 
 p, h1, h2, h3, h4, h5, h6, blockquote, ul, ol, li, pre, code {
@@ -13,7 +45,7 @@ p, h1, h2, h3, h4, h5, h6, blockquote, ul, ol, li, pre, code {
 
 a {
     text-decoration: none;
-    color: blue;
+    color: var(--link-color);
 }
 
 ::-webkit-scrollbar {
@@ -75,7 +107,7 @@ a {
     width: 200px;
     align-self: flex-start;
     height: max-content;
-    background: #fff;
+    background: var(--background-color);
     padding: 20px;
     border-radius: 12px;
     transition: all .3s;
@@ -88,7 +120,7 @@ a {
     flex-direction: column;
     align-items: center;
     margin-bottom: 20px;
-    background: #f0f0f0;
+    background: var(--secondary-background-color);
     padding: 20px;
     line-height: 25px;
     border-radius: 12px;
@@ -100,7 +132,7 @@ a {
     height: 100px;
     border-radius: 50%;
     margin-bottom: 10px;
-    background: #fff;
+    background: var(--background-color);
     transition: all .3s;
 }
 
@@ -133,7 +165,7 @@ a {
 .post-item {
     margin-bottom: 20px;
     padding: 30px;
-    background: #fff;
+    background: var(--background-color);
     line-height: 30px;
     border-radius: 12px;
 }
@@ -185,7 +217,7 @@ a {
 .footer {
     padding: 20px;
     margin: 20px 0;
-    background: #fff;
+    background: var(--background-color);
     border-radius: 12px;
 }
 
@@ -256,5 +288,5 @@ a {
     .footer {
         border-radius: 0;
     }
-    
+
 }

+ 22 - 13
src/components/BlogMenu.vue

@@ -12,7 +12,7 @@ const currentRouteName = computed(() => router.currentRoute.value.name);
 <div class="nav" >
     <div class="module-wrapper" v-for="m of blogModules" :key="m.routeName" @click="router.push(m.routeUrl)">
         <div :class="(currentRouteName == m.routeName) ? ['module-active-icon-wrapper'] : ['icon-wrapper']">
-            <div v-html="m.iconTemplate" class="module-icon"/>
+            <div v-html="m.iconTemplate" class="module-icon-svg"/>
         </div>
         <div class="module-item">{{ m.title }}</div>
     </div>
@@ -22,12 +22,6 @@ const currentRouteName = computed(() => router.currentRoute.value.name);
 
 <style scoped>
 
-.module-icon {
-    width: 16px;
-    height: 16px;
-    display: flex
-}
-
 .nav {
     display: flex;
     flex-direction: column;
@@ -41,18 +35,18 @@ const currentRouteName = computed(() => router.currentRoute.value.name);
     cursor: pointer;
     border-radius: 12px;
     background: transparent;
-    padding: 0 0 0 12px;
+    padding: 0 8px 0 8px;
     transition: all .3s;
 }
 
 .module-wrapper:hover {
-    background: #f0f0f0;
+    background: var(--secondary-background-color);
 }
 
 .module-item {
     display: flex;
     text-decoration: none;
-    color: #333;
+    color: var(--secondary-text-color);
     padding: 10px 12px;
     transition: all .3s;
 }
@@ -67,10 +61,18 @@ const currentRouteName = computed(() => router.currentRoute.value.name);
     }
 
     .module-item {
-        line-height: 50px;
-        padding: 0 20px 0 12px;
+        /* line-height: 50px;
+        padding: 0 20px 0 12px; */
+        display: none;
+    }
+
+    .module-wrapper:hover {
+        background: none;
     }
 
+    .module-wrapper:hover .icon-wrapper {
+      background: var(--secondary-background-color);
+    }
 }
 
 .icon-wrapper {
@@ -84,7 +86,7 @@ const currentRouteName = computed(() => router.currentRoute.value.name);
 }
 
 .module-active-icon-wrapper {
-    background: #F0F0F0;
+    background: var(--secondary-background-color);
     border-radius: 12px;
     width: 32px;
     height: 32px;
@@ -94,4 +96,11 @@ const currentRouteName = computed(() => router.currentRoute.value.name);
     transition: .3s all;
 }
 
+.module-icon-svg {
+    width: 16px;
+    height: 16px;
+    display: flex;
+    fill: var(--text-color);
+}
+
 </style>

+ 2 - 1
src/router/index.ts

@@ -1,5 +1,6 @@
 import { aboutIcon, homeIcon, friendIcon, archiveIcon } from '@/assets/icons';
 import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
+import type { RouteComponent } from 'vue-router';
 
 interface BlogModule {
   routeName: string;
@@ -7,7 +8,7 @@ interface BlogModule {
   title: string;
   iconTemplate?: string;
   description?: string;
-  component: any;
+  component: RouteComponent;
 }
 
 export const modules: BlogModule[] = [

+ 109 - 0
src/utils/axios.ts

@@ -0,0 +1,109 @@
+import axios from 'axios'
+
+let token = ''
+
+const baseServer = axios.create({
+  baseURL: 'http://localhost:3000/',
+  headers: {
+    Authorization: `Bearer ${token}`,
+  },
+})
+
+interface AuthSuccess {
+  code: 200
+  token: string
+}
+
+interface AuthFailed {
+  code: 401
+  msg: string
+}
+
+interface PostListSuccess {
+  code: number
+  data: Datum[]
+}
+
+interface Datum {
+  id: number
+  title: string
+  createdAt: string
+  updatedAt: string
+  tags: Tag[]
+}
+
+interface Tag {
+  name: string
+  id: number
+  color: string
+}
+
+interface TagList {
+  code: number
+  data: Tag[]
+}
+
+interface PostGetSuccess {
+  code: number
+  data: PostDetail
+}
+
+interface PostDetail {
+  id: number
+  title: string
+  content: string
+  createdAt: string
+  updatedAt: string
+  tags: Tag[]
+}
+
+interface DefaultFailedResponse {
+  code: 404
+  msg: string
+}
+
+interface PostBody {
+  title: string
+  content: string
+  tags: string[]
+}
+
+interface PushSuccess {
+  code: number
+  msg: string
+  data: {
+    id: number
+  }
+}
+
+interface UpdateSuccess {
+  code: 200,
+  msg: string
+}
+
+
+export const api = {
+  auth(password: string) {
+    return (baseServer.post('/auth/', { password }) as Promise<AuthSuccess | AuthFailed>).then(
+      (data) => {
+        if (data.code == 200) token = data.token
+        return data
+      },
+    )
+  },
+  postList(length: number = 10, start: number = 10) {
+    return baseServer.get(`/post/list?length=${length}&start=${start}`) as Promise<PostListSuccess>
+  },
+  postGet(id: number = 2) {
+    return baseServer.get(`/post/get/${id}`) as Promise<PostGetSuccess | DefaultFailedResponse>
+  },
+  tagList() {
+    return baseServer.get('/tag/list') as Promise<TagList>
+  },
+  postPush(body: PostBody) {
+    return baseServer.post('/post/push', body) as Promise<PushSuccess | AuthFailed>
+  },
+  postEdit(id: number, body: PostBody) {
+    return baseServer.post(`/post/edit/${id}`, body) as Promise<UpdateSuccess | AuthFailed>
+  }
+}

+ 0 - 48
src/utils/lazyapi.ts

@@ -1,48 +0,0 @@
-import axios from "axios";
-
-const baseServer = axios.create({
-  baseURL: 'http://8.130.126.103:3000/'
-});
-
-interface LazyItem<T> {
-    get(hard?: boolean): Promise<T>;
-}
-
-export function lazyItem<T, R = T>(url: string, defaultValue: T, middleware: ((base: R) => T) | null = null): LazyItem<T> {
-
-   let value = defaultValue;
-   let available = false;
-   let promiseInstance: Promise<T> | null = null;
-
-   function get(hard = false) {
-
-       if (hard) {
-           promiseInstance = null;
-           available = false;
-       }
-
-       if (!promiseInstance) {
-           promiseInstance = new Promise((resolve, reject) => {
-               if (available) {
-                   resolve(value);
-                   return;
-               }
-
-               baseServer.get(url)
-                   .then(response => {
-                       value = middleware ? middleware(response.data) : response.data;
-                       available = true;
-                       resolve(value);
-                   })
-                   .catch(err => {
-                       promiseInstance = null;
-                       reject(err);
-                   });
-           }) as Promise<T>;
-       }
-
-       return promiseInstance;
-   }
-
-   return {get};
-}