|
|
|
<template>
|
|
|
|
<div class="main">
|
|
|
|
<div class="header">
|
|
|
|
<img :src="Logo" class="icon" />
|
|
|
|
<div class="sys-title">
|
|
|
|
<span class="title-cn">比特电科-设备管理系统</span>
|
|
|
|
<span class="title-en">BTDK-Equipment Management System</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="body">
|
|
|
|
<img :src="bg" class="bg" alt="" />
|
|
|
|
<div class="form">
|
|
|
|
<div class="title">账号登录</div>
|
|
|
|
<el-form label-position="top" :model="account">
|
|
|
|
<el-form-item class="label">
|
|
|
|
<el-input v-model="account.username" class="input" placeholder="请输入账号" />
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item class="label">
|
|
|
|
<el-input
|
|
|
|
type="password"
|
|
|
|
v-model="account.password"
|
|
|
|
class="input"
|
|
|
|
placeholder="请输入密码"
|
|
|
|
/>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form>
|
|
|
|
<el-button color="#08a4f0" class="login-btn" @click="onLogin" :loading="isLoading"
|
|
|
|
>登录</el-button
|
|
|
|
>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
import {
|
|
|
|
login,
|
|
|
|
getTenantId,
|
|
|
|
sendSmsCode,
|
|
|
|
smsLogin,
|
|
|
|
type LoginRequestData,
|
|
|
|
} from '@/api/module/system/login'
|
|
|
|
import Logo from '@/assets/image/dashboard/login/logo.png'
|
|
|
|
import bg from '@/assets/image/dashboard/login/bg.png'
|
|
|
|
import { setRefreshToken, setTenantId } from '@/utils/auth'
|
|
|
|
import { setToken } from '@/utils/auth'
|
|
|
|
import { isResError } from '@/hooks/useMessage'
|
|
|
|
import { useIcon } from '@/utils/useIcon'
|
|
|
|
import message from 'element-plus/es/components/message/index.mjs'
|
|
|
|
import { useWindowKeyEnter } from '@/tools/common/hooks'
|
|
|
|
import { useRouter } from 'vue-router'
|
|
|
|
|
|
|
|
const isLoading = ref(false)
|
|
|
|
const router = useRouter()
|
|
|
|
|
|
|
|
const activeName = ref('account')
|
|
|
|
const account = reactive<LoginRequestData>({
|
|
|
|
username: '',
|
|
|
|
password: '',
|
|
|
|
})
|
|
|
|
|
|
|
|
const mobile = reactive({
|
|
|
|
tenantName: '',
|
|
|
|
number: '',
|
|
|
|
code: '',
|
|
|
|
captchaVerification: '',
|
|
|
|
rememberMe: true,
|
|
|
|
})
|
|
|
|
|
|
|
|
async function onLogin() {
|
|
|
|
isLoading.value = true
|
|
|
|
try {
|
|
|
|
switch (activeName.value) {
|
|
|
|
case 'account':
|
|
|
|
await loginByAccount()
|
|
|
|
break
|
|
|
|
case 'mobile':
|
|
|
|
await loginByMobile()
|
|
|
|
break
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
isLoading.value = false
|
|
|
|
router.push('/file/document')
|
|
|
|
}
|
|
|
|
|
|
|
|
async function loginByAccount() {
|
|
|
|
if (!account.username || !account.password) {
|
|
|
|
message.error('用户名或密码不能为空')
|
|
|
|
isLoading.value = false
|
|
|
|
return Promise.reject()
|
|
|
|
}
|
|
|
|
|
|
|
|
const loginRes = await login({
|
|
|
|
username: account.username,
|
|
|
|
password: account.password,
|
|
|
|
})
|
|
|
|
|
|
|
|
if (isResError(loginRes)) {
|
|
|
|
isLoading.value = false
|
|
|
|
return Promise.reject(loginRes)
|
|
|
|
}
|
|
|
|
|
|
|
|
setToken(loginRes.data.accessToken)
|
|
|
|
setRefreshToken(loginRes.data.refreshToken)
|
|
|
|
}
|
|
|
|
|
|
|
|
const smsVO = reactive({
|
|
|
|
smsCode: {
|
|
|
|
mobile: '',
|
|
|
|
scene: 21,
|
|
|
|
},
|
|
|
|
loginSms: {
|
|
|
|
mobile: '',
|
|
|
|
code: '',
|
|
|
|
},
|
|
|
|
})
|
|
|
|
const mobileCodeTimer = ref(0)
|
|
|
|
const getSmsCode = async () => {
|
|
|
|
const tenantRes = await getTenantId(mobile.tenantName)
|
|
|
|
if (isResError(tenantRes)) {
|
|
|
|
isLoading.value = false
|
|
|
|
return
|
|
|
|
}
|
|
|
|
smsVO.smsCode.mobile = mobile.number
|
|
|
|
|
|
|
|
const res = await sendSmsCode(smsVO.smsCode)
|
|
|
|
|
|
|
|
if (isResError(res)) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
message.success('验证码已发送')
|
|
|
|
mobileCodeTimer.value = 60
|
|
|
|
let msgTimer = setInterval(() => {
|
|
|
|
mobileCodeTimer.value = mobileCodeTimer.value - 1
|
|
|
|
if (mobileCodeTimer.value <= 0) {
|
|
|
|
clearInterval(msgTimer)
|
|
|
|
}
|
|
|
|
}, 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
async function loginByMobile() {
|
|
|
|
smsVO.loginSms.mobile = mobile.number
|
|
|
|
smsVO.loginSms.code = mobile.code
|
|
|
|
|
|
|
|
const res = await smsLogin(smsVO.loginSms)
|
|
|
|
if (isResError(res)) {
|
|
|
|
isLoading.value = false
|
|
|
|
return Promise.reject(res)
|
|
|
|
}
|
|
|
|
setToken(res.data.accessToken)
|
|
|
|
setRefreshToken(res.data.refreshToken)
|
|
|
|
}
|
|
|
|
|
|
|
|
async function settingTenantId(tenantName: string) {
|
|
|
|
const tenantRes = await getTenantId(tenantName)
|
|
|
|
if (isResError(tenantRes)) {
|
|
|
|
isLoading.value = false
|
|
|
|
return Promise.reject()
|
|
|
|
}
|
|
|
|
setTenantId(tenantRes.data)
|
|
|
|
}
|
|
|
|
|
|
|
|
useWindowKeyEnter(onLogin)
|
|
|
|
onMounted(() => {
|
|
|
|
// verifyCode.value.showCode()
|
|
|
|
// getVerCode()
|
|
|
|
})
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
.main {
|
|
|
|
position: relative;
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
background: linear-gradient(to bottom right, #08a4f0, #7f80fe);
|
|
|
|
.header {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
height: 110px;
|
|
|
|
padding-left: 26px;
|
|
|
|
.icon {
|
|
|
|
width: 52px;
|
|
|
|
height: 52px;
|
|
|
|
margin-right: 12px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.sys-title {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
font-size: 26px;
|
|
|
|
color: #ffffff;
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
|
|
.title-cn {
|
|
|
|
margin-bottom: 8px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.title-en {
|
|
|
|
font-size: 16px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.body {
|
|
|
|
height: calc(100% - 110px);
|
|
|
|
display: flex;
|
|
|
|
justify-content: space-around;
|
|
|
|
.bg {
|
|
|
|
// max-width: 1010px;
|
|
|
|
// max-height: 1010px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.form {
|
|
|
|
width: 440px;
|
|
|
|
padding: 64px 44px;
|
|
|
|
background-color: #ffffff;
|
|
|
|
border-radius: 3px;
|
|
|
|
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
|
|
|
|
margin: auto 0;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
box-sizing: border-box;
|
|
|
|
.title {
|
|
|
|
font-size: 24px;
|
|
|
|
font-weight: 600;
|
|
|
|
text-align: center;
|
|
|
|
color: #333333;
|
|
|
|
margin-bottom: 48px;
|
|
|
|
}
|
|
|
|
:deep(.el-form-item) {
|
|
|
|
margin-bottom: 26px;
|
|
|
|
}
|
|
|
|
:deep(.el-input) {
|
|
|
|
height: 40px;
|
|
|
|
}
|
|
|
|
:deep(.el-button) {
|
|
|
|
height: 40px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|