|
|
@@ -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);
|
|
|
}
|
|
|
|