You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

353 lines
11 KiB

<template>
<div class="site-wrapper site-page--login">
<div class="site-content__wrapper">
<div class="site-content">
<div class="login-main">
<div class="login-language-wrapper">
<el-select
v-model="selectedLanguage"
class="login-language-select"
:placeholder="$t('login.selectLanguagePlaceholder')"
@change="switchLoginLanguage">
<el-option
v-for="(item, index) in languageList"
:key="'login-language-' + index"
:label="item.languageName"
:value="item.languageCode">
</el-option>
</el-select>
</div>
<h3 class="login-title">{{ $t('login.title') }}</h3>
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()" status-icon>
<el-form-item prop="userName">
<el-input v-model="dataForm.userName" :placeholder="$t('login.accountPlaceholder')" @blur="handleUsernameBlur"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input v-model="dataForm.password" type="password" :placeholder="$t('login.passwordPlaceholder')"></el-input>
</el-form-item>
<el-form-item >
<el-select v-model="selectedSite" :placeholder="$t('login.selectSitePlaceholder')" style="width: 100%;">
<el-option
v-for="item in siteList"
:key="item.siteCode"
:label="item.siteName"
:value="item.siteCode">
</el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button class="login-btn-submit" type="primary" @click="dataFormSubmit()">{{ $t('button.login') }}</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
</div>
</template>
<script>
import { getUUID } from '@/utils'
import {getConfigParams} from '@/api/sysConfig.js'
import {getUserAuthorizedSites} from '@/api/factory/accessSite.js'
import {searchSysLanguage} from '@/api/sysLanguage.js'
export default {
data () {
return {
src: 'http://192.168.1.83/upload/ifs.png',
dataForm: {
userName: '',
password: '',
uuid: '',
captcha: ''
},
siteList: [],
selectedSite: '',
selectedLanguage: 'cn',
languageList: [],
captchaPath: ''
}
},
computed: {
dataRule() {
return {
userName: [
{ required: true, message: this.$t('login.accountRequired'), trigger: 'blur' }
],
password: [
{ required: true, message: this.$t('login.passwordRequired'), trigger: 'blur' }
]
}
},
multiLanguage: {
get() {
return this.$store.state.user.multiLanguage
},
set(val) {
this.$store.commit('user/updateMultiLanguage', val)
}
},
authControl: {
get() {
return this.$store.state.user.authControl
},
set(val) {
this.$store.commit('user/updateAuthControl', val)
}
}
},
created () {
this.initLoginLanguage()
this.getLanguageList()
this.userName();
},
methods: {
normalizeLanguageCode(languageCode) {
const locale = (languageCode || '').toLowerCase()
return (locale === 'en' || locale === 'en-us') ? 'en' : 'cn'
},
// 登录页默认中文,但保留用户上一次选择的语言
initLoginLanguage() {
const locale = this.normalizeLanguageCode(localStorage.getItem('locale') || 'cn')
this.applyLoginLanguage(locale)
},
// 登录页多语言下拉兜底选项,避免接口异常时无法切换
buildFallbackLanguageList() {
return [
{ languageCode: 'cn', languageName: this.$t('login.languageOptionCn') },
{ languageCode: 'en', languageName: this.$t('login.languageOptionEn') }
]
},
// 获取多语言列表,接口异常时保留默认中英文选项
getLanguageList() {
this.languageList = this.buildFallbackLanguageList()
searchSysLanguage({ languageCode: this.$i18n.locale }).then(({data}) => {
const rows = (data && data.rows) ? data.rows : []
if (rows.length > 0) {
this.languageList = rows
if (!this.languageList.find(item => this.normalizeLanguageCode(item.languageCode) === this.selectedLanguage)) {
this.selectedLanguage = this.languageList[0].languageCode
}
this.selectedLanguage = this.normalizeLanguageCode(this.selectedLanguage)
}
}).catch(() => {
})
},
// 统一处理登录页语言生效,保证请求头与页面语言一致
applyLoginLanguage(languageCode) {
const locale = this.normalizeLanguageCode(languageCode)
this.selectedLanguage = locale
this.$i18n.locale = locale
localStorage.setItem('locale', locale)
},
switchLoginLanguage(languageCode) {
this.applyLoginLanguage(languageCode)
this.getLanguageList()
},
// 获取上次登陆的用户名
userName(){
this.dataForm.userName = localStorage.getItem('userName')
this.handleUsernameBlur()
this.dataForm.selectedSite = localStorage.getItem('site')
},
// 用户名失焦时获取工厂列表
handleUsernameBlur() {
if (this.dataForm.userName && this.dataForm.userName.trim()) {
this.getUserSiteList(this.dataForm.userName);
} else {
this.siteList = [];
this.selectedSite = '';
}
},
// 根据用户名获取授权的工厂列表
getUserSiteList(userName) {
if (!userName || !userName.trim()) {
this.siteList = [];
this.selectedSite = '';
return;
}
getUserAuthorizedSites({ userName: userName.trim() }).then(({data}) => {
if (data && data.code === 0) {
this.siteList = data.data || data.list || [];
// 清空之前选择的工厂
this.selectedSite = '';
// 如果只有一个工厂,自动选中
if (this.siteList.length === 1) {
this.selectedSite = this.siteList[0].siteCode;
}
} else {
this.siteList = [];
this.selectedSite = '';
this.$message.error(data.msg || this.$t('login.getSiteListFailed'));
}
}).catch(error => {
this.siteList = [];
this.selectedSite = '';
console.error('获取工厂列表失败:', error);
this.$message.error(this.$t('login.getSiteListFailed'));
})
},
// 提交表单
dataFormSubmit () {
// 如果有工厂列表但未选择工厂,提示用户
if (this.siteList.length > 0 && !this.selectedSite) {
this.$message.error(this.$t('login.siteRequired'));
return;
}
this.$refs['dataForm'].validate((valid) => {
if (valid) {
this.$http({
url: this.$http.adornUrl('/sys/login'),
method: 'post',
data: this.$http.adornData({
'username': this.dataForm.userName,
'password': this.dataForm.password,
'uuid': this.dataForm.uuid,
'site': this.selectedSite
})
}).then(({data}) => {
if (data && data.code === 0) {
// 设置Cookie过期时间为8小时,与后端token同步 - rqrq
this.$cookie.set('token_wms', data.token, { expires: '8h' })
this.$router.replace({ name: 'home' })
const loginLanguage = this.normalizeLanguageCode(this.selectedLanguage || data.language || 'cn')
this.applyLoginLanguage(loginLanguage)
localStorage.setItem('refresh', "0")
localStorage.setItem('userName', this.dataForm.userName)
localStorage.setItem('site', this.selectedSite) // 保存选择的工厂
this.getConfigParams()
} else {
this.$message.error(data.msg)
}
})
}
})
},
// 获取全局参数变量
getConfigParams() {
getConfigParams().then(({data}) => {
if (data && data.code == 0) {
localStorage.setItem('configParams', JSON.stringify(data.data))
// this.multiLanguage = JSON.parse(localStorage.getItem('configParams')).multiLanguage
// this.authControl = JSON.parse(localStorage.getItem('configParams')).authControl
}
})
}
}
}
</script>
<style lang="scss" scoped>
.site-wrapper.site-page--login {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(38, 50, 56, 0);
overflow: hidden;
&:before {
position: fixed;
top: 0;
left: 0;
z-index: -1;
width: 80%;
height: 100%;
content: "";
background-image: url(~@/assets/img/login_bg.jpg);
background-size: cover;
}
.site-content__wrapper {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: 0;
margin: 0;
overflow-x: hidden;
overflow-y: auto;
background-color: transparent;
}
.site-content {
min-height: 100%;
padding: 15% 500px 30px 30px;
}
.brand-info {
margin: 220px 100px 0 90px;
color: #fff;
}
.brand-info__text {
margin: 0 0 22px 0;
font-size: 48px;
font-weight: 400;
text-transform : uppercase;
}
.brand-info__intro {
margin: 10px 0;
font-size: 16px;
line-height: 1.58;
opacity: .6;
}
.login-main {
position: absolute;
top: 0;
right: 0;
padding: 15% 60px 180px;
width: 350px;
min-height: 100%;
background-color: #fff;
box-sizing: border-box;
}
.login-title {
font-size: 30px;
margin: 0 0 18px 0;
text-align: center;
}
.login-language-wrapper {
position: absolute;
top: 24px;
right: 24px;
z-index: 2;
}
.login-language-select {
width: 140px;
.el-input__inner {
margin-top: 0 !important;
height: 32px;
line-height: 32px;
}
}
.login-captcha {
overflow: hidden;
> img {
width: 100%;
cursor: pointer;
}
}
.login-btn-submit {
width: 100%;
}
.login-main .el-input__inner{
margin-top: 10px;
height: 45px;
}
.el-button--medium {
margin-top: 0px;
padding: 5px 11px;
font-size: 16px;
border-radius: 4px;
}
.el-form-item {
margin-bottom: 5px;
}
}
</style>