irc_web/src/views/login/index.vue

804 lines
23 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="login-container">
<div class="login-header">
<!-- <img src="@/assets/login-logo.png" class="login-logo"> -->
</div>
<div class="login-body">
<div class="login-l">
<div class="login-logo">
<img src="@/assets/zzlogo-usa.png" alt="" class="usa-logo" />
</div>
<div
:class="{
'login-image': true,
'login-image-usa': true,
}"
>
<svg-icon icon-class="login-bg" style="width: 90%; height: 90%" />
<!-- <img src="@/assets/login-bg.png" v-else /> -->
</div>
</div>
<div class="login-r">
<div class="title-container">
<!-- IRC Management System -->
<div v-if="NODE_ENV === 'usa'">
<svg-icon
icon-class="login-logo"
style="width: 300px; height: 94px"
/>
</div>
<div class="title" v-else>{{ $t('login:title:system') }}</div>
</div>
<el-form
ref="loginForm"
:model="loginForm"
:rules="loginRules"
class="login-form"
auto-complete="on"
label-position="left"
>
<el-form-item
prop="username"
:rules="[
{
required: true,
message: this.$t('login:formRule:userName'),
trigger: 'blur',
},
]"
>
<span class="svg-container">
<svg-icon icon-class="user" />
</span>
<!-- User Name -->
<el-input
ref="username"
v-model="loginForm.username"
size="small"
:placeholder="$t('login:form:userName')"
name="username"
type="text"
tabindex="1"
/>
</el-form-item>
<el-form-item
prop="password"
:rules="[
{
required: true,
message: this.$t('login:formRule:password'),
trigger: 'blur',
},
]"
>
<span class="svg-container">
<svg-icon icon-class="password" />
</span>
<!-- password -->
<el-input
:key="passwordType"
ref="password"
v-model="loginForm.password"
size="small"
:type="passwordType"
:placeholder="$t('login:form:password')"
name="password"
auto-complete="new-password"
autocomplete="new-password"
tabindex="2"
@keyup.enter.native="handleLogin"
/>
<span class="show-pwd" @click="showPwd">
<svg-icon
:icon-class="passwordType === 'password' ? 'eye' : 'eye-open'"
/>
</span>
<!-- <el-input
:key="passwordType"
ref="password"
v-model="pwdCover"
size="small"
type="text"
:placeholder="$t('login:form:password')"
name="password"
@input="setPassword"
tabindex="2"
@keyup.enter.native="handleLogin"
/>
<span class="show-pwd" @click="hidePassword">
<svg-icon :icon-class="!isShowPassword ? 'eye' : 'eye-open'" />
</span> -->
</el-form-item>
<!-- Login -->
<el-button
:loading="loading"
type="primary"
style="
width: 100%;
margin-bottom: 10px;
background-color: rgb(0, 147, 221);
"
size="medium"
@click.native.prevent="handleLogin"
>
{{ $t('login:button:login') }}
</el-button>
<div style="text-align: right">
<TopLang
v-if="
VUE_APP_OSS_CONFIG_REGION !== 'oss-us-west-1' &&
NODE_ENV !== 'usa'
"
/>
<!-- Forget password? -->
<el-button
type="text"
size="medium"
@click.native.prevent="handleResetPwd"
style="color: rgb(0, 147, 221)"
>
{{ $t('login:button:forgetPassword') }}
</el-button>
</div>
</el-form>
</div>
</div>
<div v-if="language === 'zh'" class="login-footer">
<span
>Copyright © {{ new Date().getFullYear() }} 上海展影医疗科技有限公司
版权所有</span
>
<span> | </span>
<a target="_blank" href="https://beian.miit.gov.cn/">
<span> 沪ICP备2021037850-2 </span>
</a>
<span> | </span>
<a
target="_blank"
href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=31011002005859"
>
<img src="@/assets/filing.png" />
<span>沪公网安备 31011002005859号</span>
</a>
<a @click="openAbout">
<span style="color: #428bca">关于</span>
</a>
</div>
<div v-if="NODE_ENV === 'usa'" class="login-footer">
<span>
© {{ new Date().getFullYear() }} Elevate lmaging Inc. info@{{ host }}
</span>
<a @click="openAbout">
<span style="color: #428bca">About</span>
</a>
</div>
<Vcode
:show="isShow"
:fail-text="$t('login:button:failText')"
:success-text="$t('login:button:successText')"
:slider-text="$t('login:button:sliderText')"
:imgs="[Img1]"
@success="onSuccess"
/>
<el-dialog
v-if="aboutVisible"
:visible.sync="aboutVisible"
width="680px"
style="margin-top: 0"
:close-on-click-modal="false"
size="small"
>
<div
style="
margin: 0 auto;
width: 600px;
line-height: 28px;
text-align: center;
"
>
<h1
style="text-align: center; margin-bottom: 30px"
v-if="NODE_ENV === 'usa'"
>
About
</h1>
<h1 style="text-align: center; margin-bottom: 30px" v-else>关于</h1>
<p style="margin-bottom: 0px" v-if="NODE_ENV === 'usa'">
<!-- {{ $t('login:title:system_title_about') }} -->
<svg-icon
icon-class="login-logo"
style="width: 250px; height: 71px"
/>
</p>
<p style="margin-bottom: 0px" v-else>{{ $t('login:title:system') }}</p>
<p style="margin-bottom: 20px; margin-top: 0">
V{{ $version.IsEnv_US ? $version.Version_US : $version.Version }}
</p>
<p style="margin-bottom: 20px" v-if="language === 'zh'">
Copyright © {{ new Date().getFullYear() }} 上海展影医疗科技有限公司
版权所有
</p>
<p style="margin-bottom: 20px" v-else-if="NODE_ENV === 'usa'">
© {{ new Date().getFullYear() }} Elevate Imaging Inc.
</p>
<p style="margin-bottom: 20px" v-else>
Copyright © {{ new Date().getFullYear() }} Shanghai Extensive Imaging
Inc.
</p>
<div style="margin-bottom: 20px" v-if="NODE_ENV === 'usa'">
<img style="width: 180px" src="@/assets/zzlogo-usa.png" alt="" />
</div>
<div style="margin-bottom: 20px" v-else>
<img style="width: 180px" src="@/assets/zzlogo2.png" alt="" />
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" size="mini" @click="aboutVisible = false">
{{ $t('common:button:close') }}
</el-button>
</div>
</el-dialog>
<browserTip ref="browserTip" />
<toggleRole
v-if="toggleRoleVisible"
:visible.sync="toggleRoleVisible"
:loading="toggleRoleLoading"
@save="loginByRole"
@cancel="cancel"
/>
</div>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex'
import TopLang from './topLang'
// import NoticeMarquee from '../trials/trials-layout/components/noticeMarquee'
import Vcode from 'vue-puzzle-vcode'
import browserTip from '@/views/dictionary/template/browser/tip.vue'
import Img1 from '@/assets/pic-2.png'
import toggleRole from '@/components/toggleRole'
export default {
name: 'Login',
components: { TopLang, Vcode, browserTip, toggleRole },
data() {
return {
NODE_ENV: process.env.NODE_ENV, // process.env.NODE_ENV
VUE_APP_OSS_CONFIG_REGION: process.env.VUE_APP_OSS_CONFIG_REGION,
aboutVisible: false,
loginForm: {
username: '',
password: '',
UserId: null,
},
loginRules: {
username: [
{
required: true,
message: this.$t('login:formRule:userName'),
trigger: 'blur',
},
{ max: 20, message: `${this.$t('common:ruleMessage:maxLength')} 20` },
],
password: [
// {
// required: true,
// trigger: "blur",
// validator: this.$validatePassword
// },
{
required: true,
message: this.$t('login:formRule:password'),
trigger: 'blur',
},
{ max: 20, message: `${this.$t('common:ruleMessage:maxLength')} 20` },
],
},
loading: false,
passwordType: 'password',
pwdCover: null,
isShowPassword: false,
loginType: null,
location: null,
isShow: false,
showCode: false,
Img1,
toggleRoleVisible: false,
toggleRoleLoading: false,
}
},
computed: {
...mapGetters(['asyncRoutes', 'routes', 'language']),
host() {
// return window.location.host
return 'elevateimaging.ai '
},
},
watch: {
'$i18n.locale': {
handler() {
if (this.$refs.browserTip) {
this.$refs.browserTip.open()
}
},
deep: true,
immediate: true,
},
},
mounted() {
let lang = zzSessionStorage.getItem('lang') || 'zh'
zzSessionStorage.clear()
this.loginType = this.$route.query.loginType
this.location = this.$route.query.location
zzSessionStorage.setItem('loginType', this.loginType)
localStorage.setItem('location', this.location)
if (process.env.VUE_APP_OSS_CONFIG_REGION === 'oss-us-west-1') {
this.$i18n.locale = 'en'
this.setLanguage('en')
this.$updateDictionary()
} else {
if (this.location === 'USA' || this.NODE_ENV === 'usa') {
this.$i18n.locale = 'en'
this.setLanguage('en')
this.$updateDictionary()
} else {
this.$i18n.locale = lang
this.setLanguage(lang)
this.$updateDictionary()
}
}
this.$refs.browserTip.open()
},
methods: {
...mapMutations({ setLanguage: 'lang/setLanguage' }),
openAbout() {
this.aboutVisible = true
},
showPwd() {
if (this.passwordType === 'password') {
this.passwordType = ''
} else {
this.passwordType = 'password'
}
this.$nextTick(() => {
this.$refs.password.focus()
})
},
handleLogin() {
this.loginType = this.$route.query.loginType
this.$refs.loginForm.validate((valid) => {
if (valid) {
if (this.showCode) {
this.isShow = true
} else {
this.onSuccess()
}
} else {
// console.log('error submit!!')
return false
}
})
},
loginIn(Id) {
this.loading = true
this.showCode = false
if (Id) this.loginForm.UserId = Id
this.$store
.dispatch('user/login', this.loginForm)
.then((res) => {
if (res.BasicInfo.LoginState === 2) {
this.$message.warning(this.$t('login:message:login4'))
}
if (res.BasicInfo.IsFirstAdd) {
// 当前用户为首次登录,请先修改密码之后再次登录
this.$message.success(this.$t('login:message:login1'))
setTimeout(() => {
this.$router.push({
path: `/recompose?userName=${this.loginForm.username}`,
})
}, 500)
return
} else if (res.BasicInfo.NeedChangePassWord) {
// 请先修改密码后再登录!
this.$alert(
this.$t('login:message:login3'),
this.$t('common:title:warning'),
{
callback: (action) => {
this.$router.push({
path: `/recompose?userName=${this.loginForm.username}`,
})
return
},
}
)
return
} else if (res.IsMFA) {
this.$MFA({
UserId: res.BasicInfo.IdentityUserId,
EMail: res.BasicInfo.EMail,
username: this.loginForm.username,
callBack: this.changeRoleLogin,
cancelBack: () => {
this.loading = false
},
})
return
}
// else if (res.BasicInfo.LoginState === 2) {
// // 本次登录的IP或设备与上次不一致请确认'
// // this.$alert(this.$t('login:message:login4'), this.$t('common:title:warning'))
// this.$message.warning(this.$t('login:message:login4'))
// }
zzSessionStorage.removeItem('userId')
zzSessionStorage.removeItem('identityUserId')
this.changeRoleLogin()
})
.catch(() => {
this.showCode = true
this.loading = false
})
},
loginByRole(userRoleId) {
this.toggleRoleLoading = true
this.$store
.dispatch('user/loginByRole', { userRoleId })
.then((res) => {
this.toggleRoleLoading = false
if (res) {
this.$store
.dispatch('permission/generateRoutes')
.then((res) => {
this.loading = false
if (res && res.length > 0) {
this.$store.dispatch('global/getNoticeList')
this.$router.addRoutes(res)
// if (this.LoginState === 2) {
// this.$message.warning(this.$t('login:message:login4'))
// }
if (this.loginType === 'DevOps') {
this.$router.replace({ path: res[0].path })
return
}
if (this.hasPermi(['role:radmin'])) {
this.$router.replace({ path: res[0].path })
return
}
if (
this.hasPermi([
'role:air',
'role:rpm',
'role:rcrc',
'role:rir',
])
) {
this.$router.replace({ path: '/trials/trials-list' })
} else {
this.$router.replace({ path: '/trials' })
}
} else {
this.toggleRoleLoading = false
// 此账户暂未配置菜单权限,请联系管理员处理后再登录。
this.$message.warning(this.$t('login:message:login2'))
}
})
.catch((err) => {
this.toggleRoleLoading = false
})
} else {
this.toggleRoleLoading = false
}
})
.catch(() => {
this.showCode = true
this.loading = false
this.toggleRoleLoading = false
})
},
changeRoleLogin() {
if (
Array.isArray(this.$store.state.user.roles) &&
this.$store.state.user.roles.length === 1
) {
this.loginByRole(this.$store.state.user.roles[0].Id)
return
}
return (this.toggleRoleVisible = true)
},
cancel() {
this.showCode = true
this.loading = false
this.toggleRoleLoading = false
// this.toggleRoleVisible = false
},
onSuccess() {
this.isShow = false
this.loginIn()
},
handleResetPwd() {
this.$router.push({ name: 'Resetpassword' })
},
// 输入框输入事件
setPassword(val) {
if (this.isShowPassword) {
this.loginForm.password = val
} else {
let reg =
/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[-_.@^+\$!%#*?&\$~])[A-Za-z0-9-~_.@^+\$~!%#*?&]{8,32}$/g // 只允许输入字母和数字
let nDot = /[^●]/g // 非圆点字符
let index = -1 // 新输入的字符位置
let lastChar = void 0 // 新输入的字符
let realArr = this.loginForm.password.split('') // 真实密码数组
let coverArr = val.split('') // 文本框显示密码数组
let coverLen = val.length // 文本框字符串长度
let realLen = this.loginForm.password.length // 真实密码长度
// 找到新输入的字符及位置
coverArr.forEach((el, idx) => {
if (nDot.test(el)) {
index = idx
lastChar = el
}
})
// 判断输入的字符是否符合规范,不符合的话去掉该字符
// if (lastChar && !reg.test(lastChar)) {
// coverArr.splice(index, 1)
// this.pwdCover = coverArr.join('')
// console.log(111111111111111, lastChar)
// // return
// }
if (coverLen - realLen <= 2) {
if (realLen < coverLen) {
// 新增字符
realArr.splice(index, 0, lastChar)
} else if (coverLen <= realLen && index !== -1) {
// 替换字符(选取一个或多个字符直接替换)
realArr.splice(index, realLen - (coverLen - 1), lastChar)
} else {
// 删除字符,因为 val 全是 ● ,没有办法匹配,不知道是从末尾还是中间删除的字符,删除了几个,不好对 password 处理,所以可以通过光标的位置和 val 的长度来判断
let pos = document.getElementById('pwd').selectionEnd // 获取光标位置
realArr.splice(pos, realLen - coverLen)
}
}
// 将 pwdCover 替换成 ●
this.pwdCover = val.replace(/\S/g, '●')
let v = val.replace(/●/g, '')
this.loginForm.password =
coverLen - realLen >= 2 ? realArr.join('') + v : realArr.join('')
}
},
// 点击右侧小眼睛控制显示隐藏
hidePassword() {
if (!this.isShowPassword) {
// console.log("显示");
this.isShowPassword = true
this.pwdCover = this.loginForm.password
} else {
// console.log("隐藏");
this.isShowPassword = false
this.pwdCover = this.pwdCover.replace(/\S/g, '●')
}
},
},
}
</script>
<style lang="scss">
/* input */
$bg: #283443;
$light_gray: #909399;
$cursor: #fff;
// @supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
// .login-container .el-input input {
// // color: #fff;
// }
// }
/* reset element-ui css */
.login-container {
.login-r .el-input {
display: inline-block;
height: 47px;
width: 85%;
input {
background: #f4f4f5;
border: 0px;
-webkit-appearance: none;
border-radius: 0px;
padding: 12px 5px 12px 15px;
// color: $light_gray;
height: 47px;
// caret-color: $cursor;
// &:-webkit-autofill {
// box-shadow: 0 0 0px 1000px $bg inset !important;
// -webkit-text-fill-color: $cursor !important;
// }
}
}
.login-r {
.el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
background: #f4f4f5;
border-radius: 5px;
color: #454545;
}
}
}
</style>
<style lang="scss" scoped>
$bg: #2d3a4b;
$dark_gray: #889aa4;
$light_gray: #606266;
.login-container {
position: relative;
width: 100%;
height: 100%;
overflow: auto;
background: rgb(249, 249, 249);
::v-deep .el-input__inner::placeholder {
color: $dark_gray;
}
.login-header {
margin: 10px 0px 20px 10px;
height: 3rem;
width: 720px;
.login-logo {
height: 100%;
}
}
.login-body {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
// margin-top: -230px;
// margin-left: -400px;
width: 1100px;
height: 600px;
// margin: 30px auto;
box-sizing: border-box;
background: rgb(255, 255, 255);
border-radius: 10px 0px 0px 10px;
.login-l {
position: relative;
float: left;
width: 50%;
height: 100%;
.login-logo {
position: absolute;
top: 35px;
left: 50px;
img {
height: 40px;
}
.usa-logo {
height: 60px;
}
}
.login-image {
position: absolute;
top: 10px;
left: 0px;
// transform: translateY(-50%);
height: 100%;
img {
height: 100%;
}
}
.login-image-usa {
width: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
}
}
.login-r {
position: relative;
float: left;
width: 50%;
height: 100%;
.login-form {
position: absolute;
top: 55%;
// transform: translateY(-50%);
left: 50%;
transform: translate(-50%, -50%);
width: 80%;
padding: 10px;
margin: 0 auto;
overflow: hidden;
}
.title-container {
// margin-bottom: 50px;
text-align: center;
margin-top: 20%;
.title {
font-size: 35px;
color: $light_gray;
text-align: center;
font-weight: bold;
}
.title-logo-message {
font-size: 26px;
color: $light_gray;
text-align: center;
margin-top: 20px;
}
}
.tips {
font-size: 14px;
color: #fff;
margin-bottom: 10px;
span {
&:first-of-type {
margin-right: 16px;
}
}
}
.svg-container {
padding: 6px 5px 6px 15px;
color: $dark_gray;
vertical-align: middle;
width: 30px;
display: inline-block;
}
.show-pwd {
position: absolute;
right: 10px;
top: 7px;
font-size: 16px;
color: $dark_gray;
cursor: pointer;
user-select: none;
}
}
}
.login-footer {
position: absolute;
bottom: 50px;
left: 0px;
width: 100%;
text-align: center;
line-height: 20px;
font-size: 14px;
display: flex;
justify-content: center;
align-items: center;
// color: rgb(180, 190, 199);
color: #909399;
a {
display: inline-block;
text-decoration: none;
height: 20px;
line-height: 20px;
display: flex;
justify-content: center;
}
span {
margin: 0 2px;
}
img {
height: 20px;
line-height: 20px;
}
// p{
// display: inline-block;
// height:20px;
// line-height:20px;
// margin: 0px 0px 0px 5px;
// color:#939393;
// }
}
}
</style>