|
@@ -1,35 +1,5 @@
|
|
|
<template>
|
|
<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-card">
|
|
|
<div class="login-header">
|
|
<div class="login-header">
|
|
|
<div class="logo">
|
|
<div class="logo">
|
|
@@ -38,46 +8,26 @@
|
|
|
<h1>智媒通</h1>
|
|
<h1>智媒通</h1>
|
|
|
<p>登录您的账号以继续</p>
|
|
<p>登录您的账号以继续</p>
|
|
|
</div>
|
|
</div>
|
|
|
-
|
|
|
|
|
- <!-- 登录方式切换 -->
|
|
|
|
|
- <div class="login-tabs">
|
|
|
|
|
- <button
|
|
|
|
|
- class="tab-btn"
|
|
|
|
|
- :class="{ active: loginType === 'password' }"
|
|
|
|
|
- @click="loginType = 'password'"
|
|
|
|
|
- >
|
|
|
|
|
- 密码登录
|
|
|
|
|
- </button>
|
|
|
|
|
- <button
|
|
|
|
|
- class="tab-btn"
|
|
|
|
|
- :class="{ active: loginType === 'sms' }"
|
|
|
|
|
- @click="loginType = 'sms'"
|
|
|
|
|
- >
|
|
|
|
|
- 手机验证码登录
|
|
|
|
|
- </button>
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 密码登录表单 -->
|
|
|
|
|
|
|
+
|
|
|
<el-form
|
|
<el-form
|
|
|
- v-if="loginType === 'password'"
|
|
|
|
|
- ref="passwordFormRef"
|
|
|
|
|
- :model="passwordForm"
|
|
|
|
|
- :rules="passwordRules"
|
|
|
|
|
|
|
+ ref="formRef"
|
|
|
|
|
+ :model="form"
|
|
|
|
|
+ :rules="rules"
|
|
|
class="login-form"
|
|
class="login-form"
|
|
|
@submit.prevent="handleLogin"
|
|
@submit.prevent="handleLogin"
|
|
|
>
|
|
>
|
|
|
<el-form-item prop="username">
|
|
<el-form-item prop="username">
|
|
|
<el-input
|
|
<el-input
|
|
|
- v-model="passwordForm.username"
|
|
|
|
|
|
|
+ v-model="form.username"
|
|
|
placeholder="用户名或邮箱"
|
|
placeholder="用户名或邮箱"
|
|
|
size="large"
|
|
size="large"
|
|
|
:prefix-icon="User"
|
|
:prefix-icon="User"
|
|
|
/>
|
|
/>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
<el-form-item prop="password">
|
|
<el-form-item prop="password">
|
|
|
<el-input
|
|
<el-input
|
|
|
- v-model="passwordForm.password"
|
|
|
|
|
|
|
+ v-model="form.password"
|
|
|
type="password"
|
|
type="password"
|
|
|
placeholder="密码"
|
|
placeholder="密码"
|
|
|
size="large"
|
|
size="large"
|
|
@@ -85,64 +35,11 @@
|
|
|
show-password
|
|
show-password
|
|
|
/>
|
|
/>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
<el-form-item class="remember-row">
|
|
<el-form-item class="remember-row">
|
|
|
- <el-checkbox v-model="passwordForm.rememberMe">记住登录状态</el-checkbox>
|
|
|
|
|
- <el-button type="primary" link @click="$router.push('/forgot-password')">
|
|
|
|
|
- 忘记密码?
|
|
|
|
|
- </el-button>
|
|
|
|
|
- </el-form-item>
|
|
|
|
|
-
|
|
|
|
|
- <el-form-item>
|
|
|
|
|
- <el-button
|
|
|
|
|
- type="primary"
|
|
|
|
|
- size="large"
|
|
|
|
|
- :loading="loading"
|
|
|
|
|
- class="login-btn"
|
|
|
|
|
- native-type="submit"
|
|
|
|
|
- >
|
|
|
|
|
- 登录
|
|
|
|
|
- </el-button>
|
|
|
|
|
|
|
+ <el-checkbox v-model="form.rememberMe">记住登录状态</el-checkbox>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
- </el-form>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 手机验证码登录表单 -->
|
|
|
|
|
- <el-form
|
|
|
|
|
- v-else
|
|
|
|
|
- ref="smsFormRef"
|
|
|
|
|
- :model="smsForm"
|
|
|
|
|
- :rules="smsRules"
|
|
|
|
|
- class="login-form"
|
|
|
|
|
- @submit.prevent="handleSmsLogin"
|
|
|
|
|
- >
|
|
|
|
|
- <el-form-item prop="phone">
|
|
|
|
|
- <el-input
|
|
|
|
|
- v-model="smsForm.phone"
|
|
|
|
|
- placeholder="手机号"
|
|
|
|
|
- size="large"
|
|
|
|
|
- :prefix-icon="Phone"
|
|
|
|
|
- />
|
|
|
|
|
- </el-form-item>
|
|
|
|
|
-
|
|
|
|
|
- <el-form-item prop="code">
|
|
|
|
|
- <div class="sms-code-row">
|
|
|
|
|
- <el-input
|
|
|
|
|
- v-model="smsForm.code"
|
|
|
|
|
- placeholder="验证码"
|
|
|
|
|
- size="large"
|
|
|
|
|
- :prefix-icon="Message"
|
|
|
|
|
- />
|
|
|
|
|
- <el-button
|
|
|
|
|
- size="large"
|
|
|
|
|
- :disabled="smsCooldown > 0"
|
|
|
|
|
- @click="sendSmsCode"
|
|
|
|
|
- class="sms-code-btn"
|
|
|
|
|
- >
|
|
|
|
|
- {{ smsCooldown > 0 ? `${smsCooldown}s 后重发` : '获取验证码' }}
|
|
|
|
|
- </el-button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-form-item>
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
<el-form-item>
|
|
<el-form-item>
|
|
|
<el-button
|
|
<el-button
|
|
|
type="primary"
|
|
type="primary"
|
|
@@ -155,14 +52,14 @@
|
|
|
</el-button>
|
|
</el-button>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
</el-form>
|
|
</el-form>
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
<div class="login-footer">
|
|
<div class="login-footer">
|
|
|
<span>还没有账号?</span>
|
|
<span>还没有账号?</span>
|
|
|
<el-button type="primary" link @click="$router.push('/register')">
|
|
<el-button type="primary" link @click="$router.push('/register')">
|
|
|
立即注册
|
|
立即注册
|
|
|
</el-button>
|
|
</el-button>
|
|
|
</div>
|
|
</div>
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
<div class="server-info">
|
|
<div class="server-info">
|
|
|
<el-icon><Link /></el-icon>
|
|
<el-icon><Link /></el-icon>
|
|
|
<span>{{ serverStore.currentServer?.name || '未配置服务器' }}</span>
|
|
<span>{{ serverStore.currentServer?.name || '未配置服务器' }}</span>
|
|
@@ -171,121 +68,48 @@
|
|
|
</el-button>
|
|
</el-button>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
|
+ </AuthPageLayout>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
-import { ref, reactive, onMounted, onUnmounted } from 'vue';
|
|
|
|
|
|
|
+import { ref, reactive } from 'vue';
|
|
|
import { useRouter } from 'vue-router';
|
|
import { useRouter } from 'vue-router';
|
|
|
-import { User, Lock, Link, VideoPlay, Phone, Message } from '@element-plus/icons-vue';
|
|
|
|
|
|
|
+import { User, Lock, Link, VideoPlay } from '@element-plus/icons-vue';
|
|
|
import { ElMessage, type FormInstance, type FormRules } from 'element-plus';
|
|
import { ElMessage, type FormInstance, type FormRules } from 'element-plus';
|
|
|
import { useAuthStore } from '@/stores/auth';
|
|
import { useAuthStore } from '@/stores/auth';
|
|
|
import { useServerStore } from '@/stores/server';
|
|
import { useServerStore } from '@/stores/server';
|
|
|
|
|
+import AuthPageLayout from '@/components/AuthPageLayout.vue';
|
|
|
|
|
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
|
const authStore = useAuthStore();
|
|
const authStore = useAuthStore();
|
|
|
const serverStore = useServerStore();
|
|
const serverStore = useServerStore();
|
|
|
|
|
|
|
|
-const passwordFormRef = ref<FormInstance>();
|
|
|
|
|
-const smsFormRef = ref<FormInstance>();
|
|
|
|
|
|
|
+const formRef = ref<FormInstance>();
|
|
|
const loading = ref(false);
|
|
const loading = ref(false);
|
|
|
-const isMaximized = ref(false);
|
|
|
|
|
-const loginType = ref<'password' | 'sms'>('password');
|
|
|
|
|
-const smsCooldown = ref(0);
|
|
|
|
|
-let cooldownTimer: ReturnType<typeof setInterval> | null = null;
|
|
|
|
|
-
|
|
|
|
|
-// 窗口控制
|
|
|
|
|
-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;
|
|
|
|
|
- });
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
-onUnmounted(() => {
|
|
|
|
|
- if (cooldownTimer) {
|
|
|
|
|
- clearInterval(cooldownTimer);
|
|
|
|
|
- }
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
-// 密码登录表单
|
|
|
|
|
-const passwordForm = reactive({
|
|
|
|
|
|
|
+const form = reactive({
|
|
|
username: '',
|
|
username: '',
|
|
|
password: '',
|
|
password: '',
|
|
|
rememberMe: true,
|
|
rememberMe: true,
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
-const passwordRules: FormRules = {
|
|
|
|
|
|
|
+const rules: FormRules = {
|
|
|
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
|
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
|
|
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
|
|
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-// 手机验证码登录表单
|
|
|
|
|
-const smsForm = reactive({
|
|
|
|
|
- phone: '',
|
|
|
|
|
- code: '',
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
-const smsRules: FormRules = {
|
|
|
|
|
- phone: [
|
|
|
|
|
- { required: true, message: '请输入手机号', trigger: 'blur' },
|
|
|
|
|
- { pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确', trigger: 'blur' },
|
|
|
|
|
- ],
|
|
|
|
|
- code: [
|
|
|
|
|
- { required: true, message: '请输入验证码', trigger: 'blur' },
|
|
|
|
|
- { len: 6, message: '验证码为6位', trigger: 'blur' },
|
|
|
|
|
- ],
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
async function handleLogin() {
|
|
async function handleLogin() {
|
|
|
- if (!passwordFormRef.value) return;
|
|
|
|
|
-
|
|
|
|
|
- const valid = await passwordFormRef.value.validate().catch(() => false);
|
|
|
|
|
- if (!valid) return;
|
|
|
|
|
-
|
|
|
|
|
- loading.value = true;
|
|
|
|
|
- try {
|
|
|
|
|
- await authStore.login({
|
|
|
|
|
- username: passwordForm.username,
|
|
|
|
|
- password: passwordForm.password,
|
|
|
|
|
- rememberMe: passwordForm.rememberMe,
|
|
|
|
|
- });
|
|
|
|
|
- ElMessage.success('登录成功');
|
|
|
|
|
- router.push('/');
|
|
|
|
|
- } catch (error: any) {
|
|
|
|
|
- // 错误已在拦截器中处理
|
|
|
|
|
- } finally {
|
|
|
|
|
- loading.value = false;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-async function handleSmsLogin() {
|
|
|
|
|
- if (!smsFormRef.value) return;
|
|
|
|
|
-
|
|
|
|
|
- const valid = await smsFormRef.value.validate().catch(() => false);
|
|
|
|
|
|
|
+ if (!formRef.value) return;
|
|
|
|
|
+
|
|
|
|
|
+ const valid = await formRef.value.validate().catch(() => false);
|
|
|
if (!valid) return;
|
|
if (!valid) return;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
loading.value = true;
|
|
loading.value = true;
|
|
|
try {
|
|
try {
|
|
|
await authStore.login({
|
|
await authStore.login({
|
|
|
- username: smsForm.phone,
|
|
|
|
|
- password: smsForm.code,
|
|
|
|
|
- rememberMe: false,
|
|
|
|
|
|
|
+ username: form.username,
|
|
|
|
|
+ password: form.password,
|
|
|
|
|
+ rememberMe: form.rememberMe,
|
|
|
});
|
|
});
|
|
|
ElMessage.success('登录成功');
|
|
ElMessage.success('登录成功');
|
|
|
router.push('/');
|
|
router.push('/');
|
|
@@ -295,148 +119,24 @@ async function handleSmsLogin() {
|
|
|
loading.value = false;
|
|
loading.value = false;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
-async function sendSmsCode() {
|
|
|
|
|
- if (!smsForm.phone) {
|
|
|
|
|
- ElMessage.warning('请先输入手机号');
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (!/^1[3-9]\d{9}$/.test(smsForm.phone)) {
|
|
|
|
|
- ElMessage.warning('手机号格式不正确');
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- try {
|
|
|
|
|
- // TODO: 调用发送验证码 API
|
|
|
|
|
- ElMessage.success('验证码已发送');
|
|
|
|
|
- smsCooldown.value = 60;
|
|
|
|
|
- cooldownTimer = setInterval(() => {
|
|
|
|
|
- smsCooldown.value--;
|
|
|
|
|
- if (smsCooldown.value <= 0 && cooldownTimer) {
|
|
|
|
|
- clearInterval(cooldownTimer);
|
|
|
|
|
- cooldownTimer = null;
|
|
|
|
|
- }
|
|
|
|
|
- }, 1000);
|
|
|
|
|
- } catch {
|
|
|
|
|
- ElMessage.error('发送验证码失败,请稍后重试');
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
<style lang="scss" scoped>
|
|
|
@use '@/styles/variables.scss' as *;
|
|
@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 {
|
|
.login-card {
|
|
|
width: 420px;
|
|
width: 420px;
|
|
|
padding: 48px 40px;
|
|
padding: 48px 40px;
|
|
|
background: #fff;
|
|
background: #fff;
|
|
|
border-radius: $radius-xl;
|
|
border-radius: $radius-xl;
|
|
|
box-shadow: $shadow-lg;
|
|
box-shadow: $shadow-lg;
|
|
|
- position: relative;
|
|
|
|
|
- z-index: 1;
|
|
|
|
|
border: 1px solid rgba(255, 255, 255, 0.8);
|
|
border: 1px solid rgba(255, 255, 255, 0.8);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.login-header {
|
|
.login-header {
|
|
|
text-align: center;
|
|
text-align: center;
|
|
|
- margin-bottom: 28px;
|
|
|
|
|
-
|
|
|
|
|
|
|
+ margin-bottom: 36px;
|
|
|
|
|
+
|
|
|
.logo {
|
|
.logo {
|
|
|
width: 64px;
|
|
width: 64px;
|
|
|
height: 64px;
|
|
height: 64px;
|
|
@@ -447,20 +147,20 @@ async function sendSmsCode() {
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
justify-content: center;
|
|
|
box-shadow: 0 8px 24px rgba(79, 172, 254, 0.3);
|
|
box-shadow: 0 8px 24px rgba(79, 172, 254, 0.3);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
.el-icon {
|
|
.el-icon {
|
|
|
font-size: 32px;
|
|
font-size: 32px;
|
|
|
color: #fff;
|
|
color: #fff;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
h1 {
|
|
h1 {
|
|
|
margin: 0 0 12px;
|
|
margin: 0 0 12px;
|
|
|
font-size: 24px;
|
|
font-size: 24px;
|
|
|
font-weight: 700;
|
|
font-weight: 700;
|
|
|
color: $text-primary;
|
|
color: $text-primary;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
p {
|
|
p {
|
|
|
margin: 0;
|
|
margin: 0;
|
|
|
color: $text-secondary;
|
|
color: $text-secondary;
|
|
@@ -468,72 +168,38 @@ async function sendSmsCode() {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// 登录方式切换
|
|
|
|
|
-.login-tabs {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- gap: 0;
|
|
|
|
|
- margin-bottom: 24px;
|
|
|
|
|
- border-bottom: 1px solid $border-light;
|
|
|
|
|
-
|
|
|
|
|
- .tab-btn {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- padding: 10px 0;
|
|
|
|
|
- border: none;
|
|
|
|
|
- background: transparent;
|
|
|
|
|
- font-size: 14px;
|
|
|
|
|
- color: $text-secondary;
|
|
|
|
|
- cursor: pointer;
|
|
|
|
|
- transition: all 0.2s;
|
|
|
|
|
- border-bottom: 2px solid transparent;
|
|
|
|
|
- margin-bottom: -1px;
|
|
|
|
|
-
|
|
|
|
|
- &:hover {
|
|
|
|
|
- color: $text-primary;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- &.active {
|
|
|
|
|
- color: $primary-color;
|
|
|
|
|
- border-bottom-color: $primary-color;
|
|
|
|
|
- font-weight: 600;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
.login-form {
|
|
.login-form {
|
|
|
:deep(.el-input__wrapper) {
|
|
:deep(.el-input__wrapper) {
|
|
|
border-radius: $radius-base;
|
|
border-radius: $radius-base;
|
|
|
box-shadow: 0 0 0 1px $border-light inset;
|
|
box-shadow: 0 0 0 1px $border-light inset;
|
|
|
transition: all 0.2s;
|
|
transition: all 0.2s;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
&:hover {
|
|
&:hover {
|
|
|
box-shadow: 0 0 0 1px $primary-color inset;
|
|
box-shadow: 0 0 0 1px $primary-color inset;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
&.is-focus {
|
|
&.is-focus {
|
|
|
box-shadow: 0 0 0 1px $primary-color inset, 0 0 0 3px rgba($primary-color, 0.1);
|
|
box-shadow: 0 0 0 1px $primary-color inset, 0 0 0 3px rgba($primary-color, 0.1);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
:deep(.el-input__inner) {
|
|
:deep(.el-input__inner) {
|
|
|
height: 44px;
|
|
height: 44px;
|
|
|
font-size: 15px;
|
|
font-size: 15px;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
:deep(.el-input__prefix) {
|
|
:deep(.el-input__prefix) {
|
|
|
color: $text-secondary;
|
|
color: $text-secondary;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
.remember-row {
|
|
.remember-row {
|
|
|
margin-bottom: 24px;
|
|
margin-bottom: 24px;
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- justify-content: space-between;
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
:deep(.el-checkbox__label) {
|
|
:deep(.el-checkbox__label) {
|
|
|
color: $text-secondary;
|
|
color: $text-secondary;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
.login-btn {
|
|
.login-btn {
|
|
|
width: 100%;
|
|
width: 100%;
|
|
|
height: 48px;
|
|
height: 48px;
|
|
@@ -544,32 +210,16 @@ async function sendSmsCode() {
|
|
|
border: none;
|
|
border: none;
|
|
|
box-shadow: 0 4px 16px rgba($primary-color, 0.3);
|
|
box-shadow: 0 4px 16px rgba($primary-color, 0.3);
|
|
|
transition: all 0.3s;
|
|
transition: all 0.3s;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
&:hover {
|
|
&:hover {
|
|
|
transform: translateY(-1px);
|
|
transform: translateY(-1px);
|
|
|
box-shadow: 0 6px 20px rgba($primary-color, 0.4);
|
|
box-shadow: 0 6px 20px rgba($primary-color, 0.4);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
&:active {
|
|
&:active {
|
|
|
transform: translateY(0);
|
|
transform: translateY(0);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- .sms-code-row {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- gap: 12px;
|
|
|
|
|
- width: 100%;
|
|
|
|
|
-
|
|
|
|
|
- .el-input {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .sms-code-btn {
|
|
|
|
|
- width: 120px;
|
|
|
|
|
- flex-shrink: 0;
|
|
|
|
|
- font-size: 13px;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.login-footer {
|
|
.login-footer {
|
|
@@ -577,7 +227,7 @@ async function sendSmsCode() {
|
|
|
color: $text-secondary;
|
|
color: $text-secondary;
|
|
|
font-size: 14px;
|
|
font-size: 14px;
|
|
|
margin-top: 8px;
|
|
margin-top: 8px;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
.el-button {
|
|
.el-button {
|
|
|
font-weight: 500;
|
|
font-weight: 500;
|
|
|
}
|
|
}
|
|
@@ -593,7 +243,7 @@ async function sendSmsCode() {
|
|
|
gap: 8px;
|
|
gap: 8px;
|
|
|
color: $text-secondary;
|
|
color: $text-secondary;
|
|
|
font-size: 13px;
|
|
font-size: 13px;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
.el-icon {
|
|
.el-icon {
|
|
|
color: $primary-color;
|
|
color: $primary-color;
|
|
|
}
|
|
}
|