|
@@ -22,14 +22,14 @@
|
|
|
</button>
|
|
</button>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
<!-- 背景装饰 -->
|
|
<!-- 背景装饰 -->
|
|
|
<div class="bg-decoration">
|
|
<div class="bg-decoration">
|
|
|
<div class="circle circle-1"></div>
|
|
<div class="circle circle-1"></div>
|
|
|
<div class="circle circle-2"></div>
|
|
<div class="circle circle-2"></div>
|
|
|
<div class="circle circle-3"></div>
|
|
<div class="circle circle-3"></div>
|
|
|
</div>
|
|
</div>
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
<div class="login-card">
|
|
<div class="login-card">
|
|
|
<div class="login-header">
|
|
<div class="login-header">
|
|
|
<div class="logo">
|
|
<div class="logo">
|
|
@@ -38,26 +38,46 @@
|
|
|
<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
|
|
|
- ref="formRef"
|
|
|
|
|
- :model="form"
|
|
|
|
|
- :rules="rules"
|
|
|
|
|
|
|
+ v-if="loginType === 'password'"
|
|
|
|
|
+ ref="passwordFormRef"
|
|
|
|
|
+ :model="passwordForm"
|
|
|
|
|
+ :rules="passwordRules"
|
|
|
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="form.username"
|
|
|
|
|
|
|
+ v-model="passwordForm.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="form.password"
|
|
|
|
|
|
|
+ v-model="passwordForm.password"
|
|
|
type="password"
|
|
type="password"
|
|
|
placeholder="密码"
|
|
placeholder="密码"
|
|
|
size="large"
|
|
size="large"
|
|
@@ -65,11 +85,14 @@
|
|
|
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="form.rememberMe">记住登录状态</el-checkbox>
|
|
|
|
|
|
|
+ <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-form-item>
|
|
<el-form-item>
|
|
|
<el-button
|
|
<el-button
|
|
|
type="primary"
|
|
type="primary"
|
|
@@ -82,14 +105,64 @@
|
|
|
</el-button>
|
|
</el-button>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
</el-form>
|
|
</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-button
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ size="large"
|
|
|
|
|
+ :loading="loading"
|
|
|
|
|
+ class="login-btn"
|
|
|
|
|
+ native-type="submit"
|
|
|
|
|
+ >
|
|
|
|
|
+ 登录
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </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>
|
|
@@ -102,9 +175,9 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
-import { ref, reactive, onMounted } from 'vue';
|
|
|
|
|
|
|
+import { ref, reactive, onMounted, onUnmounted } from 'vue';
|
|
|
import { useRouter } from 'vue-router';
|
|
import { useRouter } from 'vue-router';
|
|
|
-import { User, Lock, Link, VideoPlay } from '@element-plus/icons-vue';
|
|
|
|
|
|
|
+import { User, Lock, Link, VideoPlay, Phone, Message } 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';
|
|
@@ -113,9 +186,13 @@ const router = useRouter();
|
|
|
const authStore = useAuthStore();
|
|
const authStore = useAuthStore();
|
|
|
const serverStore = useServerStore();
|
|
const serverStore = useServerStore();
|
|
|
|
|
|
|
|
-const formRef = ref<FormInstance>();
|
|
|
|
|
|
|
+const passwordFormRef = ref<FormInstance>();
|
|
|
|
|
+const smsFormRef = ref<FormInstance>();
|
|
|
const loading = ref(false);
|
|
const loading = ref(false);
|
|
|
const isMaximized = 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() {
|
|
function handleMinimize() {
|
|
@@ -140,29 +217,53 @@ onMounted(async () => {
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
-const form = reactive({
|
|
|
|
|
|
|
+onUnmounted(() => {
|
|
|
|
|
+ if (cooldownTimer) {
|
|
|
|
|
+ clearInterval(cooldownTimer);
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 密码登录表单
|
|
|
|
|
+const passwordForm = reactive({
|
|
|
username: '',
|
|
username: '',
|
|
|
password: '',
|
|
password: '',
|
|
|
rememberMe: true,
|
|
rememberMe: true,
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
-const rules: FormRules = {
|
|
|
|
|
|
|
+const passwordRules: 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 (!formRef.value) return;
|
|
|
|
|
-
|
|
|
|
|
- const valid = await formRef.value.validate().catch(() => false);
|
|
|
|
|
|
|
+ if (!passwordFormRef.value) return;
|
|
|
|
|
+
|
|
|
|
|
+ const valid = await passwordFormRef.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: form.username,
|
|
|
|
|
- password: form.password,
|
|
|
|
|
- rememberMe: form.rememberMe,
|
|
|
|
|
|
|
+ username: passwordForm.username,
|
|
|
|
|
+ password: passwordForm.password,
|
|
|
|
|
+ rememberMe: passwordForm.rememberMe,
|
|
|
});
|
|
});
|
|
|
ElMessage.success('登录成功');
|
|
ElMessage.success('登录成功');
|
|
|
router.push('/');
|
|
router.push('/');
|
|
@@ -172,6 +273,54 @@ async function handleLogin() {
|
|
|
loading.value = false;
|
|
loading.value = false;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+async function handleSmsLogin() {
|
|
|
|
|
+ if (!smsFormRef.value) return;
|
|
|
|
|
+
|
|
|
|
|
+ const valid = await smsFormRef.value.validate().catch(() => false);
|
|
|
|
|
+ if (!valid) return;
|
|
|
|
|
+
|
|
|
|
|
+ loading.value = true;
|
|
|
|
|
+ try {
|
|
|
|
|
+ await authStore.login({
|
|
|
|
|
+ username: smsForm.phone,
|
|
|
|
|
+ password: smsForm.code,
|
|
|
|
|
+ rememberMe: false,
|
|
|
|
|
+ });
|
|
|
|
|
+ ElMessage.success('登录成功');
|
|
|
|
|
+ router.push('/');
|
|
|
|
|
+ } catch (error: any) {
|
|
|
|
|
+ // 错误已在拦截器中处理
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ 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>
|
|
@@ -205,7 +354,7 @@ async function handleLogin() {
|
|
|
right: 0;
|
|
right: 0;
|
|
|
display: flex;
|
|
display: flex;
|
|
|
-webkit-app-region: no-drag;
|
|
-webkit-app-region: no-drag;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
.window-btn {
|
|
.window-btn {
|
|
|
width: 46px;
|
|
width: 46px;
|
|
|
height: 32px;
|
|
height: 32px;
|
|
@@ -217,16 +366,16 @@ async function handleLogin() {
|
|
|
cursor: pointer;
|
|
cursor: pointer;
|
|
|
transition: background 0.15s;
|
|
transition: background 0.15s;
|
|
|
color: $text-secondary;
|
|
color: $text-secondary;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
svg {
|
|
svg {
|
|
|
width: 12px;
|
|
width: 12px;
|
|
|
height: 12px;
|
|
height: 12px;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
&:hover {
|
|
&:hover {
|
|
|
background: rgba(0, 0, 0, 0.06);
|
|
background: rgba(0, 0, 0, 0.06);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
&.close:hover {
|
|
&.close:hover {
|
|
|
background: #e81123;
|
|
background: #e81123;
|
|
|
color: #fff;
|
|
color: #fff;
|
|
@@ -240,13 +389,13 @@ async function handleLogin() {
|
|
|
inset: 0;
|
|
inset: 0;
|
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
|
pointer-events: none;
|
|
pointer-events: none;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
.circle {
|
|
.circle {
|
|
|
position: absolute;
|
|
position: absolute;
|
|
|
border-radius: 50%;
|
|
border-radius: 50%;
|
|
|
opacity: 0.5;
|
|
opacity: 0.5;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
.circle-1 {
|
|
.circle-1 {
|
|
|
width: 400px;
|
|
width: 400px;
|
|
|
height: 400px;
|
|
height: 400px;
|
|
@@ -254,7 +403,7 @@ async function handleLogin() {
|
|
|
top: -100px;
|
|
top: -100px;
|
|
|
right: -100px;
|
|
right: -100px;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
.circle-2 {
|
|
.circle-2 {
|
|
|
width: 300px;
|
|
width: 300px;
|
|
|
height: 300px;
|
|
height: 300px;
|
|
@@ -262,7 +411,7 @@ async function handleLogin() {
|
|
|
bottom: -80px;
|
|
bottom: -80px;
|
|
|
left: -80px;
|
|
left: -80px;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
.circle-3 {
|
|
.circle-3 {
|
|
|
width: 200px;
|
|
width: 200px;
|
|
|
height: 200px;
|
|
height: 200px;
|
|
@@ -286,8 +435,8 @@ async function handleLogin() {
|
|
|
|
|
|
|
|
.login-header {
|
|
.login-header {
|
|
|
text-align: center;
|
|
text-align: center;
|
|
|
- margin-bottom: 36px;
|
|
|
|
|
-
|
|
|
|
|
|
|
+ margin-bottom: 28px;
|
|
|
|
|
+
|
|
|
.logo {
|
|
.logo {
|
|
|
width: 64px;
|
|
width: 64px;
|
|
|
height: 64px;
|
|
height: 64px;
|
|
@@ -298,20 +447,20 @@ async function handleLogin() {
|
|
|
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;
|
|
@@ -319,38 +468,72 @@ async function handleLogin() {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// 登录方式切换
|
|
|
|
|
+.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;
|
|
@@ -361,16 +544,32 @@ async function handleLogin() {
|
|
|
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 {
|
|
@@ -378,7 +577,7 @@ async function handleLogin() {
|
|
|
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;
|
|
|
}
|
|
}
|
|
@@ -394,7 +593,7 @@ async function handleLogin() {
|
|
|
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;
|
|
|
}
|
|
}
|