|
|
<template> <div class="login"> <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form"> <!-- 品牌区域 --> <div class="brand-area"> <div class="logo-icon">🐫</div> <h3 class="title">{{ title }}</h3> <p class="subtitle">智慧牧场 · 轻松管理</p> </div>
<el-form-item prop="username"> <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号 / 手机号" class="custom-input" > <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" /> </el-input> </el-form-item>
<el-form-item prop="password"> <el-input v-model="loginForm.password" type="password" auto-complete="off" placeholder="密码" @keyup.enter.native="handleLogin" class="custom-input" > <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" /> </el-input> </el-form-item>
<!-- 优化后的验证码区域:更紧凑、对齐美观 --> <el-form-item prop="code" v-if="captchaEnabled" class="captcha-item"> <div class="captcha-wrapper"> <el-input v-model="loginForm.code" auto-complete="off" placeholder="验证码" @keyup.enter.native="handleLogin" class="captcha-input" > <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" /> </el-input> <div class="captcha-image" @click="getCode"> <img :src="codeUrl" class="captcha-img" alt="验证码" /> <span class="refresh-icon" title="点击刷新">⟳</span> </div> </div> </el-form-item>
<!-- 选项栏:记住密码 + 立即注册 --> <div class="options-bar"> <el-checkbox v-model="loginForm.rememberMe" class="remember-checkbox">记住密码</el-checkbox> <router-link v-if="register" class="register-link" to="/register">立即注册</router-link> </div>
<el-form-item style="width:100%;"> <el-button :loading="loading" size="medium" type="primary" class="login-btn" @click.native.prevent="handleLogin" > <span v-if="!loading">登 录</span> <span v-else>登 录 中...</span> </el-button> </el-form-item> </el-form> </div></template>
<script>import { getCodeImg } from "@/api/login"import Cookies from "js-cookie"import { encrypt, decrypt } from '@/utils/jsencrypt'import defaultSettings from '@/settings'
export default { name: "Login", data() { return { title: '阿右旗阿拉腾敖包镇骆驼产业标准化智慧化示范基地数据中心', footerContent: defaultSettings.footerContent, codeUrl: "", loginForm: { username: "admin", password: "admin123", rememberMe: false, code: "", uuid: "" }, loginRules: { username: [ { required: true, trigger: "blur", message: "请输入您的账号" } ], password: [ { required: true, trigger: "blur", message: "请输入您的密码" } ], code: [{ required: true, trigger: "change", message: "请输入验证码" }] }, loading: false, captchaEnabled: true, register: false, redirect: undefined, showDemoTip: true } }, watch: { $route: { handler: function(route) { this.redirect = route.query && route.query.redirect }, immediate: true } }, created() { this.getCode() this.getCookie() }, methods: { getCode() { getCodeImg().then(res => { this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled if (this.captchaEnabled) { this.codeUrl = "data:image/gif;base64," + res.img this.loginForm.uuid = res.uuid } }) }, getCookie() { const username = Cookies.get("username") const password = Cookies.get("password") const rememberMe = Cookies.get('rememberMe') this.loginForm = { username: username === undefined ? this.loginForm.username : username, password: password === undefined ? this.loginForm.password : decrypt(password), rememberMe: rememberMe === undefined ? false : Boolean(rememberMe) } }, handleLogin() { this.$refs.loginForm.validate(valid => { if (valid) { this.loading = true if (this.loginForm.rememberMe) { Cookies.set("username", this.loginForm.username, { expires: 30 }) Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 }) Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 }) } else { Cookies.remove("username") Cookies.remove("password") Cookies.remove('rememberMe') } this.$store.dispatch("Login", this.loginForm).then(() => { this.$router.push({ path: "/Home" }).catch(() => { }); }).catch(() => { this.loading = false if (this.captchaEnabled) { this.getCode() } }) } }) } }}</script>
<style rel="stylesheet/scss" lang="scss" scoped>// 颜色变量 - 驼场主题色(自然、大地、清新)
$primary-color: #7c9a3e; // 草绿色主色调
$primary-hover: #5c7a2e; // 深草绿
$bg-overlay: rgba(0, 0, 0, 0.3);$text-dark: #2c3a1f;$text-light: #6b7a5a;$card-white: rgba(255, 255, 255, 0.96);$shadow-sm: 0 20px 35px -10px rgba(0, 0, 0, 0.2);$shadow-focus: 0 0 0 3px rgba(124, 154, 62, 0.2);
.login { position: relative; display: flex; justify-content: center; align-items: center; height: 100vh; min-height: 500px; background: linear-gradient(135deg, #2b5e2b 0%, #8cb36b 50%, #d4c9a3 100%); overflow: hidden;
// 登录卡片
.login-form { position: relative; z-index: 2; width: 440px; padding: 40px 35px 35px; background: $card-white; backdrop-filter: blur(2px); border-radius: 32px; box-shadow: $shadow-sm; transition: all 0.3s ease; border: 1px solid rgba(255,255,255,0.5); &:hover { transform: translateY(-3px); box-shadow: 0 25px 40px -12px rgba(0, 0, 0, 0.25); } }
// 品牌区
.brand-area { text-align: center; margin-bottom: 30px; .logo-icon { font-size: 56px; display: inline-block; animation: gentleSwing 2s infinite ease; } .title { margin: 12px 0 6px; font-size: 28px; font-weight: 600; color: $text-dark; letter-spacing: 2px; } .subtitle { font-size: 13px; color: $text-light; margin-bottom: 5px; font-weight: 400; } }
// 输入框样式优化
.custom-input { :deep(.el-input__inner) { height: 48px; border-radius: 60px; border: 1px solid #e2e8e6; background: #fefef7; padding-left: 42px; font-size: 15px; transition: all 0.2s; &:focus { border-color: $primary-color; box-shadow: $shadow-focus; } } :deep(.el-input__prefix) { left: 16px; top: 2px; .input-icon { font-size: 18px; color: $primary-color; } } }
// ========= 优化后的验证码样式 =========
.captcha-item { margin-bottom: 18px; :deep(.el-form-item__content) { line-height: initial; } }
.captcha-wrapper { display: flex; align-items: center; gap: 12px; width: 100%; }
.captcha-input { flex: 1; :deep(.el-input__inner) { height: 48px; border-radius: 60px; border: 1px solid #e2e8e6; background: #fefef7; padding-left: 42px; font-size: 15px; transition: all 0.2s; &:focus { border-color: $primary-color; box-shadow: $shadow-focus; } } :deep(.el-input__prefix) { left: 16px; top: 2px; .input-icon { font-size: 18px; color: $primary-color; } } }
.captcha-image { position: relative; flex-shrink: 0; width: 110px; height: 48px; border-radius: 12px; overflow: hidden; cursor: pointer; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); transition: transform 0.2s, box-shadow 0.2s; &:hover { transform: scale(1.02); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); .refresh-icon { opacity: 1; } } }
.captcha-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.refresh-icon { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 22px; font-weight: bold; color: white; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); opacity: 0; transition: opacity 0.2s; background: rgba(0, 0, 0, 0.5); width: 32px; height: 32px; border-radius: 50%; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(2px); pointer-events: none; }
// 选项栏(记住密码 + 注册)
.options-bar { display: flex; justify-content: space-between; align-items: center; margin: 8px 0 25px 0; .remember-checkbox { :deep(.el-checkbox__inner) { border-radius: 4px; border-color: #cbd5e1; background-color: #fff; } :deep(.el-checkbox__input.is-checked .el-checkbox__inner) { background-color: $primary-color; border-color: $primary-color; } :deep(.el-checkbox__label) { color: $text-light; font-size: 13px; } } .register-link { color: $primary-color; font-size: 13px; text-decoration: none; font-weight: 500; transition: 0.2s; &:hover { color: $primary-hover; text-decoration: underline; } } }
// 登录按钮
.login-btn { width: 100%; height: 48px; background: $primary-color; border: none; border-radius: 60px; font-size: 16px; font-weight: 600; letter-spacing: 2px; box-shadow: 0 8px 18px rgba(124, 154, 62, 0.3); transition: all 0.25s; &:hover, &:focus { background: $primary-hover; transform: scale(1.01); box-shadow: 0 10px 22px rgba(92, 122, 46, 0.4); } }}
// 动画
@keyframes gentleSwing { 0%,100%{ transform: rotate(0deg); } 50%{ transform: rotate(6deg); }}
// 响应式
@media (max-width: 500px) { .login .login-form { width: 88%; padding: 30px 20px; } .captcha-wrapper { gap: 8px; } .captcha-image { width: 95px; height: 44px; } .captcha-input :deep(.el-input__inner) { height: 44px; }}</style>
|