xiaoju-survey/web/src/management/pages/login/LoginPage.vue

263 lines
5.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div
class="login-page"
:style="{
background: `url('/imgs/create/background.webp') no-repeat bottom right`,
'background-size': 'cover'
}"
>
<div class="login-top">
<img src="/imgs/Logo.webp" alt="logo" />
<span>您好请登录</span>
</div>
<div class="login-box">
<el-form
:model="formData"
:rules="rules"
ref="formDataRef"
label-width="100px"
class="login-form"
@submit.prevent
>
<el-form-item label="账号" prop="name">
<el-input v-model="formData.name" size="large"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" v-model="formData.password" size="large"></el-input>
</el-form-item>
<el-form-item label="验证码" prop="captcha">
<div class="captcha-wrapper">
<el-input style="width: 150px" v-model="formData.captcha" size="large"></el-input>
<div class="captcha-img" @click="refreshCaptcha" v-html="captchaImgData"></div>
</div>
</el-form-item>
<el-form-item class="button-group">
<el-button
:loading="pending.login"
size="small"
type="primary"
class="button"
@click="submitForm('login')"
>登录</el-button
>
<el-button
:loading="pending.register"
class="button register-button"
@click="submitForm('register')"
>注册</el-button
>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, reactive } from 'vue'
import { useStore } from 'vuex'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import 'element-plus/theme-chalk/src/message.scss'
import { login, register } from '@/management/api/auth'
import { refreshCaptcha as refreshCaptchaApi } from '@/management/api/captcha'
import { CODE_MAP } from '@/management/api/base'
const store = useStore()
const route = useRoute()
const router = useRouter()
interface FormData {
name: string
password: string
captcha: string
captchaId: string
}
interface Pending {
login: boolean
register: boolean
}
const formData = reactive<FormData>({
name: '',
password: '',
captcha: '',
captchaId: ''
})
const rules = {
name: [
{ required: true, message: '请输入账号', trigger: 'blur' },
{
min: 3,
max: 10,
message: '长度在 3 到 10 个字符',
trigger: 'blur'
}
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{
min: 8,
max: 16,
message: '长度在 8 到 16 个字符',
trigger: 'blur'
}
],
captcha: [
{
required: true,
message: '请输入验证码',
trigger: 'blur'
}
]
}
onMounted(() => {
refreshCaptcha()
})
const pending = reactive<Pending>({
login: false,
register: false
})
const captchaImgData = ref<string>('')
const formDataRef = ref<any>(null)
const submitForm = (type: 'login' | 'register') => {
formDataRef.value.validate(async (valid: boolean) => {
if (valid) {
try {
const submitTypes = {
login,
register
}
pending[type] = true
const res: any = await submitTypes[type]({
username: formData.name,
password: formData.password,
captcha: formData.captcha,
captchaId: formData.captchaId
})
pending[type] = false
if (res.code !== CODE_MAP.SUCCESS) {
ElMessage.error(res.errmsg)
throw new Error('登录/注册失败' + res.errmsg)
}
store.dispatch('user/login', {
username: res.data.username,
token: res.data.token
})
let redirect: any = {
name: 'survey'
}
if (route.query.redirect) {
redirect = decodeURIComponent(route.query.redirect as string)
}
router.replace(redirect)
} catch (error) {
pending[type] = false
}
return true
} else {
return false
}
})
}
const refreshCaptcha = async () => {
try {
const res: any = await refreshCaptchaApi({
captchaId: formData.captchaId
})
if (res.code === 200) {
const { id, img } = res.data
formData.captchaId = id
captchaImgData.value = img
}
} catch (error) {
ElMessage.error('获取验证码失败')
}
}
</script>
<style lang="scss" scoped>
.login-page {
overflow: hidden;
height: 100vh;
.login-top {
color: #4a4c5b;
height: 56px;
background: #fff;
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
img {
width: 90px;
}
}
.login-box {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
}
.login-form {
border-radius: 8px;
padding: 60px 60px 60px 0;
background: #fff;
box-shadow: 4px 0 20px 0 rgba(82, 82, 102, 0.15);
margin-top: -150px;
.button-group {
margin-top: 40px;
}
.button {
width: 160px;
height: 40px;
font-size: 14px;
}
.register-button {
border-color: #faa600;
color: #faa600;
margin-left: 20px;
}
}
.tips {
color: #999;
position: fixed;
bottom: 15px;
text-align: center;
margin-left: 50%;
transform: translateX(-50%);
}
.captcha-wrapper {
display: flex;
align-items: center;
.captcha-img {
height: 40px;
cursor: pointer;
:deep(> svg) {
max-height: 40px;
}
}
}
}
</style>