174 lines
4.4 KiB
Vue
Raw Normal View History

<script lang="ts" setup>
import { reactive, ref } from "vue"
import { useRouter } from "vue-router"
import { useUserStore } from "@/store/modules/user"
import { User, Lock, Key } from "@element-plus/icons-vue"
import ThemeSwitch from "@/components/ThemeSwitch/index.vue"
2022-08-19 15:25:07 +08:00
import type { FormInstance, FormRules } from "element-plus"
2022-09-14 18:44:32 +08:00
import { getLoginCodeApi } from "@/api/login"
import type { ILoginData } from "@/api/login"
const router = useRouter()
2022-08-19 15:25:07 +08:00
const loginFormRef = ref<FormInstance | null>(null)
2022-04-28 16:10:49 +08:00
2022-08-19 15:25:07 +08:00
/** 登录按钮 Loading */
const loading = ref(false)
/** 验证码图片 URL */
const codeUrl = ref("")
/** 登录表单数据 */
2022-09-14 18:44:32 +08:00
const loginForm: ILoginData = reactive({
2022-08-19 15:25:07 +08:00
username: "admin",
password: "12345678",
2022-09-14 18:44:32 +08:00
code: ""
2022-04-28 16:10:49 +08:00
})
2022-08-19 15:25:07 +08:00
/** 登录表单校验规则 */
const loginFormRules: FormRules = {
username: [{ required: true, message: "请输入用户名", trigger: "blur" }],
password: [
{ required: true, message: "请输入密码", trigger: "blur" },
{ min: 8, max: 16, message: "长度在 8 到 16 个字符", trigger: "blur" }
],
code: [{ required: true, message: "请输入验证码", trigger: "blur" }]
}
/** 登录逻辑 */
const handleLogin = () => {
loginFormRef.value?.validate((valid: boolean) => {
if (valid) {
loading.value = true
useUserStore()
.login({
username: loginForm.username,
2022-09-14 18:44:32 +08:00
password: loginForm.password,
code: loginForm.code
2022-08-19 15:25:07 +08:00
})
.then(() => {
router.push({ path: "/" })
})
.catch(() => {
createCode()
loginForm.password = ""
})
.finally(() => {
loading.value = false
})
} else {
return false
}
})
}
/** 创建验证码 */
const createCode = () => {
// 先清空验证码的输入
loginForm.code = ""
2022-09-14 18:44:32 +08:00
// 获取验证码
getLoginCodeApi().then((res: any) => {
codeUrl.value = res.data
})
2022-08-19 15:25:07 +08:00
}
2022-04-28 16:10:49 +08:00
/** 初始化验证码 */
2022-09-14 18:44:32 +08:00
createCode()
</script>
<template>
<div class="login-container">
<ThemeSwitch class="theme-switch" />
<div class="login-card">
<div class="title">
<img src="@/assets/layout/logo-text-2.png" />
</div>
<div class="content">
2022-08-19 15:25:07 +08:00
<el-form ref="loginFormRef" :model="loginForm" :rules="loginFormRules" @keyup.enter="handleLogin">
<el-form-item prop="username">
<el-input
2022-08-19 15:25:07 +08:00
v-model.trim="loginForm.username"
placeholder="用户名"
type="text"
tabindex="1"
:prefix-icon="User"
size="large"
/>
</el-form-item>
<el-form-item prop="password">
<el-input
2022-08-19 15:25:07 +08:00
v-model.trim="loginForm.password"
placeholder="密码"
type="password"
tabindex="2"
:prefix-icon="Lock"
size="large"
2022-04-28 16:10:49 +08:00
show-password
/>
</el-form-item>
<el-form-item prop="code">
<el-input
2022-08-19 15:25:07 +08:00
v-model.trim="loginForm.code"
placeholder="验证码"
type="text"
tabindex="3"
:prefix-icon="Key"
2022-09-14 18:44:32 +08:00
maxlength="7"
size="large"
/>
<span class="show-code">
2022-08-19 15:25:07 +08:00
<img :src="codeUrl" @click="createCode" />
</span>
</el-form-item>
2022-08-19 15:25:07 +08:00
<el-button :loading="loading" type="primary" size="large" @click.prevent="handleLogin"> </el-button>
</el-form>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.login-container {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 100%;
.theme-switch {
position: fixed;
top: 5%;
right: 5%;
cursor: pointer;
}
.login-card {
width: 480px;
border-radius: 20px;
box-shadow: 0 0 10px #dcdfe6;
background-color: #fff;
overflow: hidden;
.title {
display: flex;
justify-content: center;
align-items: center;
height: 150px;
img {
height: 100%;
}
}
.content {
padding: 20px 50px 50px 50px;
.show-code {
position: absolute;
right: 0px;
top: 0px;
cursor: pointer;
user-select: none;
img {
width: 100px;
2022-05-23 14:30:06 +08:00
height: 40px;
border-radius: 4px;
}
}
.el-button {
width: 100%;
margin-top: 10px;
}
}
}
}
</style>