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

263 lines
5.7 KiB
Vue
Raw Normal View History

2023-11-02 12:12:37 +00:00
<template>
<div
class="login-page"
:style="{
background: `url('/imgs/create/background.webp') no-repeat bottom right`,
2024-05-09 12:34:24 +00:00
'background-size': 'cover'
2023-11-02 12:12:37 +00:00
}"
>
<div class="login-top">
<img src="/imgs/Logo.webp" alt="logo" />
2023-11-02 12:12:37 +00:00
<span>您好请登录</span>
</div>
<div class="login-box">
<el-form
:model="formData"
2023-11-02 12:12:37 +00:00
:rules="rules"
ref="formDataRef"
2023-11-02 12:12:37 +00:00
label-width="100px"
class="login-form"
2024-05-09 12:34:24 +00:00
@submit.prevent
2023-11-02 12:12:37 +00:00
>
<el-form-item label="账号" prop="name">
2024-05-09 12:34:24 +00:00
<el-input v-model="formData.name" size="large"></el-input>
2023-11-02 12:12:37 +00:00
</el-form-item>
<el-form-item label="密码" prop="password">
2024-05-09 12:34:24 +00:00
<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">
2024-05-09 12:34:24 +00:00
<el-input style="width: 150px" v-model="formData.captcha" size="large"></el-input>
<div class="captcha-img" @click="refreshCaptcha" v-html="captchaImgData"></div>
</div>
2023-11-02 12:12:37 +00:00
</el-form-item>
<el-form-item class="button-group">
<el-button
:loading="pending.login"
2023-11-02 12:12:37 +00:00
size="small"
type="primary"
class="button"
@click="submitForm('login')"
2023-11-02 12:12:37 +00:00
>登录</el-button
>
<el-button
:loading="pending.register"
class="button register-button"
@click="submitForm('register')"
2023-11-02 12:12:37 +00:00
>注册</el-button
>
</el-form-item>
</el-form>
</div>
</div>
</template>
2024-05-09 12:34:24 +00:00
<script setup lang="ts">
import { onMounted, ref, reactive } from 'vue'
import { useRoute, useRouter } from 'vue-router'
2024-05-09 12:34:24 +00:00
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'
2024-05-09 12:34:24 +00:00
import { CODE_MAP } from '@/management/api/base'
2024-06-28 10:46:24 +00:00
import { useUserStore } from '@/management/stores/user'
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'
2024-05-09 12:34:24 +00:00
}
],
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) {
2024-01-30 14:19:45 +00:00
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
2024-05-09 12:34:24 +00:00
})
pending[type] = false
if (res.code !== CODE_MAP.SUCCESS) {
ElMessage.error(res.errmsg)
throw new Error('登录/注册失败' + res.errmsg)
2024-01-30 14:19:45 +00:00
}
2024-06-28 10:46:24 +00:00
const userStore = useUserStore()
userStore.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)
2024-01-30 14:19:45 +00:00
} 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
2024-05-09 12:34:24 +00:00
}
} catch (error) {
ElMessage.error('获取验证码失败')
2024-05-09 12:34:24 +00:00
}
}
2023-11-02 12:12:37 +00:00
</script>
2024-05-09 12:34:24 +00:00
2023-11-02 12:12:37 +00:00
<style lang="scss" scoped>
.login-page {
overflow: hidden;
height: 100vh;
2023-11-02 12:12:37 +00:00
.login-top {
color: #4a4c5b;
height: 56px;
background: #fff;
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
2023-11-02 12:12:37 +00:00
img {
width: 90px;
}
}
2023-11-02 12:12:37 +00:00
.login-box {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
}
2023-11-02 12:12:37 +00:00
.login-form {
border-radius: 8px;
padding: 60px 60px 60px 0;
background: #fff;
box-shadow: 4px 0 20px 0 rgba(82, 82, 102, 0.15);
2023-11-02 12:12:37 +00:00
margin-top: -150px;
2023-11-02 12:12:37 +00:00
.button-group {
margin-top: 40px;
}
2023-11-02 12:12:37 +00:00
.button {
width: 160px;
height: 40px;
font-size: 14px;
}
2023-11-02 12:12:37 +00:00
.register-button {
border-color: #faa600;
color: #faa600;
margin-left: 20px;
}
}
2023-11-02 12:12:37 +00:00
.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;
2024-05-09 12:34:24 +00:00
:deep(> svg) {
max-height: 40px;
}
}
}
2023-11-02 12:12:37 +00:00
}
</style>