Browse Source

refactor: 重构 Login 和 Register 页面使用 AuthPageLayout 组件

- 移除重复的窗口控制代码(isMaximized 状态、minimize/maximize/close 处理器)
- 移除重复的背景装饰代码(.bg-decoration 和 .circle 样式)
- 复用已有的 AuthPageLayout.vue 组件
- 减少约 200 行重复代码,提升可维护性
ethanfly 2 weeks ago
parent
commit
51c4a9e1a2
2 changed files with 8 additions and 310 deletions
  1. 4 155
      client/src/views/Login/index.vue
  2. 4 155
      client/src/views/Register/index.vue

+ 4 - 155
client/src/views/Login/index.vue

@@ -1,35 +1,5 @@
 <template>
-  <div class="login-container">
-    <!-- 顶部可拖动标题栏 -->
-    <div class="drag-region">
-      <div class="window-controls">
-        <button class="window-btn minimize" @click="handleMinimize" title="最小化">
-          <svg viewBox="0 0 12 12"><rect y="5" width="12" height="2" fill="currentColor"/></svg>
-        </button>
-        <button class="window-btn maximize" @click="handleMaximize" :title="isMaximized ? '还原' : '最大化'">
-          <svg v-if="isMaximized" viewBox="0 0 12 12">
-            <rect x="1.5" y="3" width="7" height="7" stroke="currentColor" stroke-width="1.5" fill="none"/>
-            <path d="M3.5 3V1.5H11V9H9.5" stroke="currentColor" stroke-width="1.5" fill="none"/>
-          </svg>
-          <svg v-else viewBox="0 0 12 12">
-            <rect x="1" y="1" width="10" height="10" stroke="currentColor" stroke-width="1.5" fill="none"/>
-          </svg>
-        </button>
-        <button class="window-btn close" @click="handleClose" title="关闭">
-          <svg viewBox="0 0 12 12">
-            <path d="M1 1L11 11M1 11L11 1" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
-          </svg>
-        </button>
-      </div>
-    </div>
-    
-    <!-- 背景装饰 -->
-    <div class="bg-decoration">
-      <div class="circle circle-1"></div>
-      <div class="circle circle-2"></div>
-      <div class="circle circle-3"></div>
-    </div>
-    
+  <AuthPageLayout>
     <div class="login-card">
       <div class="login-header">
         <div class="logo">
@@ -98,16 +68,17 @@
         </el-button>
       </div>
     </div>
-  </div>
+  </AuthPageLayout>
 </template>
 
 <script setup lang="ts">
-import { ref, reactive, onMounted } from 'vue';
+import { ref, reactive } from 'vue';
 import { useRouter } from 'vue-router';
 import { User, Lock, Link, VideoPlay } from '@element-plus/icons-vue';
 import { ElMessage, type FormInstance, type FormRules } from 'element-plus';
 import { useAuthStore } from '@/stores/auth';
 import { useServerStore } from '@/stores/server';
+import AuthPageLayout from '@/components/AuthPageLayout.vue';
 
 const router = useRouter();
 const authStore = useAuthStore();
@@ -115,30 +86,6 @@ const serverStore = useServerStore();
 
 const formRef = ref<FormInstance>();
 const loading = ref(false);
-const isMaximized = ref(false);
-
-// 窗口控制
-function handleMinimize() {
-  window.electronAPI?.minimizeWindow?.();
-}
-
-function handleMaximize() {
-  window.electronAPI?.maximizeWindow?.();
-}
-
-function handleClose() {
-  window.electronAPI?.closeWindow?.();
-}
-
-// 监听窗口最大化状态
-onMounted(async () => {
-  if (window.electronAPI?.isMaximized) {
-    isMaximized.value = await window.electronAPI.isMaximized();
-  }
-  window.electronAPI?.onMaximizedChange?.((maximized: boolean) => {
-    isMaximized.value = maximized;
-  });
-});
 
 const form = reactive({
   username: '',
@@ -177,110 +124,12 @@ async function handleLogin() {
 <style lang="scss" scoped>
 @use '@/styles/variables.scss' as *;
 
-.login-container {
-  min-height: 100vh;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  background: linear-gradient(135deg, #f5f7fa 0%, #e4e8eb 100%);
-  position: relative;
-  overflow: hidden;
-}
-
-// 顶部可拖动区域
-.drag-region {
-  position: fixed;
-  top: 0;
-  left: 0;
-  right: 0;
-  height: 32px;
-  -webkit-app-region: drag;
-  z-index: 999;
-}
-
-// 窗口控制按钮
-.window-controls {
-  position: absolute;
-  top: 0;
-  right: 0;
-  display: flex;
-  -webkit-app-region: no-drag;
-  
-  .window-btn {
-    width: 46px;
-    height: 32px;
-    border: none;
-    background: transparent;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    cursor: pointer;
-    transition: background 0.15s;
-    color: $text-secondary;
-    
-    svg {
-      width: 12px;
-      height: 12px;
-    }
-    
-    &:hover {
-      background: rgba(0, 0, 0, 0.06);
-    }
-    
-    &.close:hover {
-      background: #e81123;
-      color: #fff;
-    }
-  }
-}
-
-// 背景装饰
-.bg-decoration {
-  position: absolute;
-  inset: 0;
-  overflow: hidden;
-  pointer-events: none;
-  
-  .circle {
-    position: absolute;
-    border-radius: 50%;
-    opacity: 0.5;
-  }
-  
-  .circle-1 {
-    width: 400px;
-    height: 400px;
-    background: linear-gradient(135deg, rgba(79, 140, 255, 0.2), rgba(79, 140, 255, 0.05));
-    top: -100px;
-    right: -100px;
-  }
-  
-  .circle-2 {
-    width: 300px;
-    height: 300px;
-    background: linear-gradient(135deg, rgba(250, 112, 154, 0.15), rgba(254, 225, 64, 0.1));
-    bottom: -80px;
-    left: -80px;
-  }
-  
-  .circle-3 {
-    width: 200px;
-    height: 200px;
-    background: linear-gradient(135deg, rgba(102, 126, 234, 0.15), rgba(118, 75, 162, 0.1));
-    top: 50%;
-    left: 10%;
-    transform: translateY(-50%);
-  }
-}
-
 .login-card {
   width: 420px;
   padding: 48px 40px;
   background: #fff;
   border-radius: $radius-xl;
   box-shadow: $shadow-lg;
-  position: relative;
-  z-index: 1;
   border: 1px solid rgba(255, 255, 255, 0.8);
 }
 

+ 4 - 155
client/src/views/Register/index.vue

@@ -1,35 +1,5 @@
 <template>
-  <div class="register-container">
-    <!-- 顶部可拖动标题栏 -->
-    <div class="drag-region">
-      <div class="window-controls">
-        <button class="window-btn minimize" @click="handleMinimize" title="最小化">
-          <svg viewBox="0 0 12 12"><rect y="5" width="12" height="2" fill="currentColor"/></svg>
-        </button>
-        <button class="window-btn maximize" @click="handleMaximize" :title="isMaximized ? '还原' : '最大化'">
-          <svg v-if="isMaximized" viewBox="0 0 12 12">
-            <rect x="1.5" y="3" width="7" height="7" stroke="currentColor" stroke-width="1.5" fill="none"/>
-            <path d="M3.5 3V1.5H11V9H9.5" stroke="currentColor" stroke-width="1.5" fill="none"/>
-          </svg>
-          <svg v-else viewBox="0 0 12 12">
-            <rect x="1" y="1" width="10" height="10" stroke="currentColor" stroke-width="1.5" fill="none"/>
-          </svg>
-        </button>
-        <button class="window-btn close" @click="handleClose" title="关闭">
-          <svg viewBox="0 0 12 12">
-            <path d="M1 1L11 11M1 11L11 1" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
-          </svg>
-        </button>
-      </div>
-    </div>
-    
-    <!-- 背景装饰 -->
-    <div class="bg-decoration">
-      <div class="circle circle-1"></div>
-      <div class="circle circle-2"></div>
-      <div class="circle circle-3"></div>
-    </div>
-    
+  <AuthPageLayout>
     <div class="register-card">
       <div class="register-header">
         <div class="logo">
@@ -106,45 +76,22 @@
         </el-button>
       </div>
     </div>
-  </div>
+  </AuthPageLayout>
 </template>
 
 <script setup lang="ts">
-import { ref, reactive, onMounted } from 'vue';
+import { ref, reactive } from 'vue';
 import { useRouter } from 'vue-router';
 import { User, Lock, Message, UserFilled } from '@element-plus/icons-vue';
 import { ElMessage, type FormInstance, type FormRules } from 'element-plus';
 import { useAuthStore } from '@/stores/auth';
+import AuthPageLayout from '@/components/AuthPageLayout.vue';
 
 const router = useRouter();
 const authStore = useAuthStore();
 
 const formRef = ref<FormInstance>();
 const loading = ref(false);
-const isMaximized = ref(false);
-
-// 窗口控制
-function handleMinimize() {
-  window.electronAPI?.minimizeWindow?.();
-}
-
-function handleMaximize() {
-  window.electronAPI?.maximizeWindow?.();
-}
-
-function handleClose() {
-  window.electronAPI?.closeWindow?.();
-}
-
-// 监听窗口最大化状态
-onMounted(async () => {
-  if (window.electronAPI?.isMaximized) {
-    isMaximized.value = await window.electronAPI.isMaximized();
-  }
-  window.electronAPI?.onMaximizedChange?.((maximized: boolean) => {
-    isMaximized.value = maximized;
-  });
-});
 
 const form = reactive({
   username: '',
@@ -205,110 +152,12 @@ async function handleRegister() {
 <style lang="scss" scoped>
 @use '@/styles/variables.scss' as *;
 
-.register-container {
-  min-height: 100vh;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  background: linear-gradient(135deg, #f5f7fa 0%, #e4e8eb 100%);
-  position: relative;
-  overflow: hidden;
-}
-
-// 顶部可拖动区域
-.drag-region {
-  position: fixed;
-  top: 0;
-  left: 0;
-  right: 0;
-  height: 32px;
-  -webkit-app-region: drag;
-  z-index: 999;
-}
-
-// 窗口控制按钮
-.window-controls {
-  position: absolute;
-  top: 0;
-  right: 0;
-  display: flex;
-  -webkit-app-region: no-drag;
-  
-  .window-btn {
-    width: 46px;
-    height: 32px;
-    border: none;
-    background: transparent;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    cursor: pointer;
-    transition: background 0.15s;
-    color: $text-secondary;
-    
-    svg {
-      width: 12px;
-      height: 12px;
-    }
-    
-    &:hover {
-      background: rgba(0, 0, 0, 0.06);
-    }
-    
-    &.close:hover {
-      background: #e81123;
-      color: #fff;
-    }
-  }
-}
-
-// 背景装饰
-.bg-decoration {
-  position: absolute;
-  inset: 0;
-  overflow: hidden;
-  pointer-events: none;
-  
-  .circle {
-    position: absolute;
-    border-radius: 50%;
-    opacity: 0.5;
-  }
-  
-  .circle-1 {
-    width: 400px;
-    height: 400px;
-    background: linear-gradient(135deg, rgba(79, 140, 255, 0.2), rgba(79, 140, 255, 0.05));
-    top: -100px;
-    right: -100px;
-  }
-  
-  .circle-2 {
-    width: 300px;
-    height: 300px;
-    background: linear-gradient(135deg, rgba(250, 112, 154, 0.15), rgba(254, 225, 64, 0.1));
-    bottom: -80px;
-    left: -80px;
-  }
-  
-  .circle-3 {
-    width: 200px;
-    height: 200px;
-    background: linear-gradient(135deg, rgba(102, 126, 234, 0.15), rgba(118, 75, 162, 0.1));
-    top: 50%;
-    left: 10%;
-    transform: translateY(-50%);
-  }
-}
-
 .register-card {
   width: 420px;
   padding: 48px 40px;
   background: #fff;
   border-radius: $radius-xl;
   box-shadow: $shadow-lg;
-  position: relative;
-  z-index: 1;
   border: 1px solid rgba(255, 255, 255, 0.8);
 }