<template> <div id="userLayout" :class="['user-layout-wrapper']"> <div class="left-div"> <div id="logo"> <div id="logoImg"> <img src="~@/assets/logo.png" alt="" srcset="" class="imge"> </div> <div id="text">华恒WMS仓储管理系统</div> </div> <div id="backgroundImg"> <img src="~@/assets/beijingtu.jpg" alt="" srcset="" class="imge"/> </div> <div id="copyright"> <div id="company">Copyright © 2024 华恒焊接股份有限公司</div> </div> </div> <div class="right-div"> <a-form-model ref="form" :model="model" :rules="validatorRules"> <div id="welcome">欢迎来到华恒仓储管理系统 !</div> <a-form-model-item required prop="username"> <a-input id="name" v-model="model.username" size="default" autocomplete="off" placeholder="请输入帐户名 / admin" @blur="getWarehouse"> </a-input> </a-form-model-item> <a-form-model-item required prop="password"> <a-input id="password" v-model="model.password" size="default" type="password" autocomplete="new-password" @input="maskPassword" placeholder="请输入密码"> </a-input> </a-form-model-item> <a-form-model-item prop="warehouseCode"> <a-select show-search placeholder="请选择仓库" option-filter-prop="label" v-model="model.warehouseCode" id="warehouseCode"> <a-select-option v-for="item in warehouseList" :key="item.name" :value="item.code">{{ item.name }} </a-select-option> </a-select> </a-form-model-item> <a-form-item> <a-button id="logIn" size="default" type="primary" htmlType="submit" class="login-button" :loading="loginBtn" @click.stop.prevent="handleSubmit" :disabled="loginBtn">登 录</a-button> </a-form-item> </a-form-model> </div> <two-step-captcha v-if="requiredTwoStepCaptcha" :visible="stepCaptchaVisible" @success="stepCaptchaSuccess" @cancel="stepCaptchaCancel"></two-step-captcha> <login-select-tenant ref="loginSelect" @success="loginSelectOk" ></login-select-tenant> </div> </template> <script> import RouteView from '@/components/layouts/RouteView' import { mixinDevice } from '@/utils/mixin.js' import LoginAccount from '@views/user/LoginAccount.vue' import { mapActions } from 'vuex' import { getAction } from '@api/manage' import { getWarehouseByUserCode } from '@api/api' import TwoStepCaptcha from '@comp/tools/TwoStepCaptcha.vue' import LoginSelectTenant from '@views/user/LoginSelectTenant.vue' import { timeFix } from '@/utils/util' export default { name: 'UserLayout', components: { LoginSelectTenant, TwoStepCaptcha }, data() { return { requestCodeSuccess: false, randCodeImage: '', currdatetime: '', requiredTwoStepCaptcha: false, stepCaptchaVisible: false, maskedPassword: '', loginType: 0, loginBtn: false, warehouseList: {}, querySource: {}, model: { username: '', password: '', warehouseCode: '' // inputCode: '' }, validatorRules: { username: [ { required: true, message: <span style="color: red; font-weight: bold; margin-left: 10%; font-size: 0.85vw;">请输入用户名!</span> }, { validator: this.handleUsernameOrEmail } ], password: [ { required: true, message: <span style="color: red; font-weight: bold; margin-left: 10%; font-size: 0.85vw;">请输入密码!</span>, validator: 'click' } ], warehouseCode: [ { required: true, message: <span style="color: red; font-weight: bold; margin-left: 10%; font-size: 0.85vw;">请选择仓库!</span>, trigger: 'change', validator: 'click' } ] } } }, created() { this.handleChangeCheckCode() this.getWarehouse() }, methods: { stepCaptchaCancel() { this.Logout().then(() => { this.loginBtn = false this.stepCaptchaVisible = false }) }, stepCaptchaSuccess() { this.loginSuccess() }, handleSubmit() { this.loginBtn = true // if (this.customActiveKey === 'tab1') { // 使用账户密码登录 this.handleLogin(this.rememberMe) // } else { // //手机号码登录 // this.$refs.plogin.handleLogin(this.rememberMe) // } }, // 校验失败 validateFail() { this.loginBtn = false }, requestSuccess(loginResult) { this.$refs.loginSelect.show(loginResult) }, loginSelectOk() { this.loginSuccess() }, loginSuccess() { this.$router.push({ path: '/dashboard/analysis' }) this.$notification.success({ message: '欢迎', description: `${timeFix()},欢迎回来` }) }, //登录后台失败 requestFailed(err) { let description = ((err.response || {}).data || {}).message || err.message || '请求出现错误,请稍后再试' this.$notification['error']({ message: '登录失败', description: description, duration: 4 }) //账户密码登录错误后更新验证码 if (this.customActiveKey === 'tab1' && description.indexOf('密码错误') > 0) { this.$refs.alogin.handleChangeCheckCode() } this.loginBtn = false }, ...mapActions(['Login']), /**刷新验证码*/ handleChangeCheckCode() { this.currdatetime = new Date().getTime() // this.model.inputCode = '' getAction(`/sys/randomImage/${this.currdatetime}`) .then(res => { if (res.success) { this.randCodeImage = res.result this.requestCodeSuccess = true } else { this.$message.error(res.message) this.requestCodeSuccess = false } }) .catch(() => { this.requestCodeSuccess = false }) }, getWarehouse() { const that = this this.querySource.username = that.model.username let obj = getWarehouseByUserCode(that.querySource) obj.then(res => { that.warehouseList = res.result if (this.warehouseList != null) { this.model.warehouseCode = this.warehouseList[0].code } }) }, maskPassword() { //获取输入框的值 let value = this.model.password if (value != '') { //如果不为空,逐个字符判断是否为圆点 for (let i = 0; i < value.length; i++) { if (value.charAt(i) != '\u25CF') { //如果不是圆点,表示该字符为用户输入的值,放到真实值的对应位置 let char = value.charAt(i) this.maskedPassword = this.maskedPassword.slice(0, i) + char + this.maskedPassword.slice(i) //将该字符替换为圆点 value = value.slice(0, i) + '\u25CF' + value.slice(i + 1) } } //防止真实值和圆点的数量不对应。 this.maskedPassword = this.maskedPassword.slice(0, value.length) //将转换过的字符串显示给用户 this.model.password = value } else { //保持一致性 this.maskedPassword = '' } }, // 判断登录类型 handleUsernameOrEmail(rule, value, callback) { const regex = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$/ if (regex.test(value)) { this.loginType = 0 } else { this.loginType = 1 } callback() }, /** * 验证字段 * @param arr * @param callback */ validateFields(arr, callback) { let promiseArray = [] for (let item of arr) { let p = new Promise((resolve, reject) => { this.$refs['form'].validateField(item, err => { if (!err) { resolve() } else { reject(err) } }) }) promiseArray.push(p) } Promise.all(promiseArray) .then(() => { callback() }) .catch(err => { callback(err) }) }, acceptUsername(username) { this.model['username'] = username }, // 账号密码登录 handleLogin(rememberMe) { this.validateFields(['username', 'password'], err => { if (!err) { let loginParams = { username: this.model.username, password: this.maskedPassword, warehouseCode: this.model.warehouseCode, checkKey: this.currdatetime, remember_me: rememberMe } this.Login(loginParams) .then(res => { this.$emit('success', res.result) this.loginSuccess() }) .catch(err => { this.validateFail() this.requestFailed(err) this.$emit('fail', err) if (err.code == 499) { this.$router.push({ path: '/user/systemTokenModal' }) } }) } else { this.validateFail() this.$emit('validateFail') } }) } } } </script> <style lang="less" scoped> #userLayout { height: 100%; display: flex; /* 设置flex布局 */ width: 100%; /* 容器宽度设置为100% */ } ::v-deep .ant-select-selection { border-width: 1px; border-style: solid; border-radius: 0.6vw; width: 100% !important; height: 100% !important; line-height: 3vw; background-image: url(../../assets/cangku.png); padding-left: 12%; /* 留出图片的空间 */ background-repeat: no-repeat; background-position: 0.6vw center; background-size: 1.6vw 1.6vw; font-size: 1vw; color: #333333; box-shadow: 2px 5px 5px #c3c3c3; } /deep/ .ant-select-selection__rendered { margin-top: 0.6vw; } /deep/ .ant-form { width: 100%; } ///deep/ .ant-select-dropdown-menu-item-selected{ // font-size: 18px; // height: 30px; //} .left-div { flex: 0 0 68%; /* 左侧div宽度为容器的70% */ } .right-div { display: flex; flex: 0 0 32%; background-color: #fafafa; display: flex; /* 使用 flex 布局 */ flex-direction: column; /* 垂直排列子元素 */ justify-content: center; /* 垂直居中 */ align-items: center; /* 水平居中 */ height: 100%; /* 使 div 占满父容器高度 */ } #logo { height: 10%; width: 100%; //background-color: red; //margin-left: 150px; //margin-left: 11%; //margin-top: -3%; display: flex; // margin-top: 0; } #backgroundImg { height: 80%; display: flex; justify-content: center; align-items: center; .imge { height: 75%; background-size: contain; background-repeat: no-repeat; position: relative; } } #copyright { height: 10%; /* 高度为视口的 10% */ width: 100%; /* 确保宽度不超出容器 */ position: fixed; /* 固定定位 */ bottom: 0; /* 靠底部对齐 */ display: flex; align-items: flex-end; /* 垂直方向上靠下对齐 */ padding: 10px; /* 添加内边距 */ } #logoImg { width: 22%; height: 100%; float: right; position: relative; //background-color: yellow; .imge { width: 83%; height: 30%; position: absolute; right: 5%; /* 水平居右 */ top: 20%; /* 从顶部偏移50% */ // transform: translateY(-50%); /* 向上移动自身高度的50%,实现垂直居中 */ //object-fit: contain; //top: 39%; //left: 45%; //object-fit: cover; /* 或 contain、fill、none、scale-down */ //object-position: center; } } #text { height: 69%; width: 100%; font-size: 1.1vw; align-content: center; color: #333333; //margin-left: 5px; font-family: 'Microsoft YaHei', 'SimSun', sans-serif; font-weight: bold; //background-color: blue; } #form-container { width: 200px; /* 设置宽度 */ height: 50px; /* 设置高度 */ //margin-left: 820px; //margin-top: 100px; } #company { text-align: center; /* 水平居中对齐 */ // color: #ac1e2b; /* 字体颜色 */ font-size: 0.9vw; /* 字体大小 */ font-family: 'Microsoft YaHei', 'SimSun', sans-serif; /* 字体系列 */ width: 100%; /* 宽度 100% */ } #welcome { margin-top: 20px; color: #333333; font-size: 1.5vw; align-content: end; font-family: 'Microsoft YaHei', 'SimSun', sans-serif; text-align: center; margin-left: 1vw; } #name { border-width: 1px; border-style: solid; border-radius: 0.6vw; width: 85%; height: 3vw; line-height: 3vw; margin-top: 3vw; margin-left: 8%; margin-bottom: 0.5vw; background-image: url(../../assets/huiyuan.png); padding-left: 12%; /* 留出图片的空间 */ background-repeat: no-repeat; background-position: 0.6vw center; background-size: 1.6vw 1.6vw; font-size: 1vw; color: #333333; box-shadow: 2px 5px 5px #c3c3c3; } #name::after { content: ''; display: inline-block; width: 0; height: 0; overflow: hidden; } #name::placeholder { font-size: 1vw; color: #999999; padding-left: 0px; } #password { border-width: 1px; border-style: solid; border-radius: 0.6vw; width: 85%; height: 3vw; line-height: 3vw; margin-left: 8%; margin-bottom: 0.5vw; background-image: url(../../assets/mima.png); padding-left: 12%; /* 留出图片的空间 */ background-repeat: no-repeat; background-position: 0.6vw center; background-size: 1.6vw 1.6vw; font-size: 1vw; color: #333333; box-shadow: 2px 5px 5px #c3c3c3; } #warehouseCode { border-color: #ebf3fd; border-width: 1px; border-style: solid; border-radius: 0.6vw; width: 85%; height: 3vw; line-height: 3vw; margin-left: 8%; margin-bottom: 2.5vw; font-size: 1vw; text-align: center; //color: #333333; } #password::after { content: ''; display: inline-block; width: 0; height: 0; overflow: hidden; } #password::placeholder { font-size: 1vw; color: #999999; padding-left: 0px; } /deep/ .ant-form-item-control { line-height: 3vw; } /deep/ .ant-select-selection__rendered { line-height: 1.5vw; } a-select { width: 100%; height: 100%; font-size: 16px; color: #333; background-color: #fff; border: 1px solid #ccc; border-radius: 0.6vw; } #logIn { border-color: #ac1e2b; border-width: 1px; border-style: solid; border-radius: 0.6vw; width: 85%; height: 3vw; line-height: 3vw; margin-left: 8%; font-size: 1.2vw; align-items: center; justify-content: center; display: flex; color: #ebf3fd; background-color: red; box-shadow: 2px 5px 5px #c3c3c3; } </style>