rax-medical/src/views/login/login.vue
2024-04-23 09:42:25 +08:00

553 lines
14 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">
<div class="left-content move_4"></div>
<div class="right-content">
<!-- <div class="select-hospital-box">
<el-select class="select-hospital" v-model="currentHospital" size="small" @change="selectHospital">
<el-option v-for="item in hospitals" :key="item.id" :label="item.name" :value="item.id"/>
</el-select>
</div>-->
<img v-show="!isShowRegister" class="logo move_2" src="@/assets/imgs/logo.png">
<div v-if="!isShowRegister" class="login-block move_2">
<div class="login-way">
<span :class="passwordLogin && 'active'" @click="passwordLogin = true">密码登录</span>
<span :class="!passwordLogin && 'active'" @click="passwordLogin = false">验证码登录</span>
</div>
<el-form ref="loginFormRef" :model="loginParams" :rules="loginRules" label-width="0" size="small">
<div class="login-form password-login" v-if="passwordLogin">
<el-form-item prop="account">
<el-input v-model="loginParams.account" placeholder="请输入用户名">
<template #prepend>
<el-icon>
<User/>
</el-icon>
</template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginParams.password" type="password" show-password placeholder="请输入密码">
<template #prepend>
<el-icon>
<Lock/>
</el-icon>
</template>
</el-input>
</el-form-item>
<el-button :loading="loading" class="login-btn" type="primary" @click="login('password')">登录</el-button>
<span class="register-btn" @click="getCaptchaCode()">注册账号</span>
</div>
<div class="login-form code-login" v-else>
<el-form-item prop="phone">
<el-input v-model="loginParams.phone" placeholder="请输入手机号">
<template #prepend>
<div @click.stop style="display: flex;align-items: center;">
<el-dropdown @command="selectPhoneArea">
<span style="color: #909399;">{{ loginParams.phoneArea }}<el-icon>
<DCaret/>
</el-icon></span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-for="item in phoneAreas" :command="item">{{
item
}}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
</el-input>
</el-form-item>
<el-form-item prop="code">
<el-input v-model="loginParams.code" placeholder="请输入6位短信验证码">
<template #append>
<span class="send-btn" @click="sendCode">{{ loginParams.sendText }}</span>
</template>
</el-input>
</el-form-item>
<el-button class="login-btn" type="primary" @click="login('code')">登录</el-button>
</div>
</el-form>
</div>
<div v-else class="register-block move_2">
<div class="header-box">
<span class="title">新用户申请</span>
<el-icon @click="isShowRegister = false">
<Close/>
</el-icon>
</div>
<el-form ref="registerFormRef" :model="registerParams" :rules="registerRules" label-width="100">
<el-form-item label="用户名" prop="username">
<el-input v-model="registerParams.username" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="registerParams.password" type="password" show-password
placeholder="请输入密码"></el-input>
</el-form-item>
<el-form-item label="姓名" prop="name">
<el-input v-model="registerParams.name" placeholder="请输入姓名"></el-input>
</el-form-item>
<el-form-item label="手机号" prop="phone">
<el-input v-model="registerParams.phone" placeholder="请输入手机号"></el-input>
</el-form-item>
<el-form-item label="医院" prop="hospital">
<el-select v-model="registerParams.hospital" style="width: 100%;">
<el-option v-for="item in hospitals" :key="item.id" :label="item.name"
:value="item.id"/>
</el-select>
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-radio-group v-model="registerParams.sex">
<el-radio label="男"/>
<el-radio label="女"/>
</el-radio-group>
</el-form-item>
<el-form-item label="验证码" prop="code">
<el-input v-model="registerParams.code" placeholder="请输入验证码"
style="width: calc(100% - 110px);"></el-input>
<img width="100" height="32" style="margin-left: 10px;" :src="captchaImgUrl"/>
<a class="change_img" @click="refreshImg" href="#">看不清?</a>
</el-form-item>
</el-form>
<div class="footer-box">
<el-button type="primary" @click="register">注 册</el-button>
<span @click="isShowRegister = false">已有账号?</span>
</div>
</div>
</div>
</div>
<SliderVerify v-model:isShowSelf="sliderVConf.isShowSelf" :width="sliderVConf.width" :imgUrl="sliderImgUrl"
:height="sliderVConf.height" @success="sliderSuccess" @close="sliderClose"></SliderVerify>
</template>
<script lang='ts' setup>
import {ElMessage, ElMessageBox, ElNotification} from 'element-plus';
//引入获取当前时间的函数
import {getTime} from '@/utils/time';
import {onMounted, reactive, ref} from 'vue'
import {useRoute, useRouter} from 'vue-router'
import {useLoginStore} from '@/stores/user-info-store'
import {getPhoneAreasData} from '@/static-data/core'
import {v4} from "uuid";
import SliderVerify from "@/components/SliderVerify/index.vue";
import * as loginApi from "@/api/login";
import {Session} from "@/utils/storage";
import * as hospitalApi from "@/api/hospital";
//引入用户相关的小仓库
//import useUserStore from "@/stores/user-info-store";
//let useStore = useUserStore();
const router = useRouter()
const hospitals = ref([])
const phoneAreas: any = getPhoneAreasData()
//定义变量控制按钮加载效果
let loading = ref(false);
//自定义校验规则函数
const validatorUserName = (rule: any, value: any, callback: any) => {
//rule:即为校验规则对象
//value:即为表单元素文本内容
//函数:如果符合条件callBack放行通过即为
//如果不符合条件callBack方法,注入错误提示信息
if (/^[a-zA-Z0-9_-]{4,16}$/) {
callback();
} else {
callback(new Error('账号长度4到16位字母数字下划线减号'));
}
}
const validatorPassword = (rule: any, value: any, callback: any) => {
if (/^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/) {
callback();
} else {
callback(new Error('密码最少6位包括至少1个大写字母1个小写字母1个数字1个特殊字符'));
}
}
const validatorPhone = (rule: any, value: any, callback: any) => {
var isPhone = /^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/;
if (value.indexOf('****') >= 0) {
return callback().trim();
}
if (!isPhone.test(value)) {
callback(new Error('请输入合法手机号'));
} else {
callback();
}
}
const loginRules = reactive({
account: [
{required: true, validator: validatorUserName, trigger: 'change'},
],
password: [
{required: true, validator: validatorPassword, trigger: 'change'},
],
phone: [
{required: true, validator: validatorPhone, trigger: 'blur'},
],
code: [
{required: true, message: '请输入验证码', trigger: 'blur'},
]
})
const registerRules = reactive({
username: [
{required: true, validator: validatorUserName, trigger: 'change'},
],
password: [
{required: true, validator: validatorUserName, trigger: 'change'},
],
name: [
{required: true, message: '请输入用户名', trigger: 'blur'},
],
phone: [
{required: true, validator: validatorPhone, trigger: 'change'},
],
hospital: [
{required: true, message: '请选择医院', trigger: 'blur'},
],
code: [
{required: true, message: '请输入验证码', trigger: 'blur'},
]
})
//获取路由器
let $router = useRouter();
//路由对象
let $route = useRoute();
const loginFormRef = ref()
const registerFormRef = ref()
const slideVerifyRef = ref()
const currentHospital = ref(useLoginStore().getlogin().hospital)
const isShowRegister = ref(false)
const passwordLogin = ref(true)
const loginParams = ref({
account: 'admin',
name: '',
password: '123456',
phone: '',
phoneArea: phoneAreas[0],
code: '',
isSendCode: false,
sendTimer: 0,
sendText: '获取短信验证码'
})
const registerParams = ref({
username: '',
password: '',
name: '',
phone: '',
hospital: '',
sex: '',
code: ''
})
const sliderVConf = ref({
isShowSelf: false,
width: 400,
height: 200
})
const captchaImgUrl = ref('')
const sliderImgUrl = ref('')
let randomStr = ""
onMounted(() => {
hospitalApi.getHospitalList().then((res: any) => {
if (res.data) {
hospitals.value = res.data
} else {
hospitals.value.length = 0
}
})
})
const selectHospital = (e: string) => {
// console.log(e)
}
const register = async () => {
await registerFormRef.value.validate((valid: any, fields: any) => {
if (valid) {
loginApi.register({...registerParams.value, randomStr}).then(data => {
ElMessageBox.confirm(
'注册成功,是否登录?',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'success',
draggable: true
}
).then(() => {
loginParams.value.account = registerFormRef.value.account
loginParams.value.name = registerFormRef.value.name
currentHospital.value = registerFormRef.value.hospital
isShowRegister.value = false;
}).catch(() => {
})
})
} else {
// console.log('error submit!', fields)
}
})
}
const selectPhoneArea = (e: string) => {
loginParams.value.phoneArea = e
}
const sendCode = () => {
if (loginParams.value.isSendCode) return
let num = 60
ElMessage.success('发送成功!')
loginParams.value.isSendCode = true
loginParams.value.sendText = '请' + num + '秒后重新发送'
loginParams.value.sendTimer = setInterval(() => {
num--
if (num > 0) {
loginParams.value.sendText = '请' + num + '秒后重新发送'
} else {
loginParams.value.isSendCode = false
loginParams.value.sendText = '重新获取短信验证码'
clearInterval(loginParams.value.sendTimer)
}
}, 1000);
}
const login = async (type: string) => {
//加载效果:开始加载
loading.value = true;
/*if (!currentHospital.value) {
ElMessage.warning('请在右上角选择院区')
return
}*/
//加载效果:开始加载
loading.value = true;
//保证全部表单正常再发请求
await loginFormRef.value.validate((valid: any, fields: any) => {
if (valid) {
sliderVConf.value.isShowSelf = true;
}
})
}
function getCaptchaCode() {
isShowRegister.value = true
refreshImg()
}
function refreshImg() {
randomStr = v4()
captchaImgUrl.value = '/api/admin/code/textImage?randomStr=' + randomStr
}
function sliderSuccess() {
loginApi.login({
username: loginParams.value.account, // 用户名
password: loginParams.value.password, // 密码
randomStr: v4()
}).then((data: any) => {
sliderVConf.value.isShowSelf = false
if (data.code == 1 || data.error) {
ElMessage.error(data.msg ? data.msg : data.error)
loading.value = false
} else {
// 存储token 信息
console.log(data)
ElNotification({
type: 'success',
message: '欢迎回来',
title: `HI,${getTime()}`
});
loginPost(data)
router.push('/home')
}
})
}
function sliderClose() {
loading.value = false
}
const loginPost = (data: any) => {
Session.set('token', data.access_token);
Session.set('refresh_token', data.refresh_token);
useLoginStore().setlogin('account', data.username)
console.log(data)
useLoginStore().setlogin('name', data.user_info.name || '暂未设置姓名')
}
</script>
<style lang='scss' scoped>
.login-page {
width: 100%;
height: 100%;
display: flex;
background-color: #F8F8F8;
.left-content {
width: 50%;
height: 100%;
background: url(@/assets/imgs/login/login_bck.png) no-repeat;
background-size: cover;
}
.right-content {
position: relative;
width: 50%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.select-hospital-box {
position: absolute;
top: 25px;
right: 25px;
}
.logo {
height: 70px;
}
.login-block {
width: 65%;
height: 430px;
min-width: 500px;
min-height: 300px;
padding: 50px;
margin-top: 20px;
background: white;
.login-way {
font-size: 18px;
color: #909399;
span {
cursor: pointer;
margin-right: 10px;
}
.active {
color: $main-color;
font-weight: 600;
}
}
.login-form {
:deep(.el-input) {
font-size: 16px;
margin-top: 20px;
.el-input-group__prepend,
.el-input__wrapper,
.el-input-group__append {
box-shadow: none;
border-bottom: 1px solid $border-color;
background-color: transparent;
padding: 10px 20px;
}
.el-input-group__prepend,
.el-input-group__append {
position: relative;
&::after {
content: '';
position: absolute;
width: 1px;
height: 16px;
top: calc(50% - 8px);
right: 0;
background-color: $border-color;
}
}
.el-input-group__append::after {
right: auto;
left: 0;
}
}
.send-btn {
cursor: pointer;
color: $main-color;
font-weight: 600;
}
}
.login-btn {
width: 100%;
margin-top: 40px;
font-size: 20px;
font-weight: 600;
padding: 25px 0 25px 0.3em;
border-radius: 0px;
letter-spacing: 0.3em;
}
.register-btn {
cursor: pointer;
float: right;
color: $main-color;
margin-top: 20px;
}
}
.register-block {
width: 65%;
min-width: 500px;
min-height: 300px;
padding: 50px;
background: white;
.header-box {
display: flex;
justify-content: space-between;
margin-bottom: 30px;
.title {
font-size: 20px;
color: $main-color;
font-weight: 600;
}
.el-icon {
cursor: pointer;
}
}
.footer-box {
padding-left: 100px;
display: flex;
justify-content: space-between;
align-items: center;
.el-button {
font-size: 16px;
padding: 5px 50px;
}
& > span {
cursor: pointer;
font-size: 18px;
color: #909399;
}
}
}
}
}
</style>