大屏登录页面修改

This commit is contained in:
zzyuan 2024-11-19 09:52:21 +08:00
parent 287691efe7
commit c7c5012d6c
12 changed files with 1386 additions and 178 deletions

View File

@ -1,7 +1,121 @@
// import request from '@/utils/request'
// // 登录方法
// export function login(username, password, loginType, code, uuid, textCode) {
// return request({
// url: '/auth/login',
// headers: {
// isToken: false,
// repeatSubmit: false
// },
// method: 'post',
// timeout: 20000,
// data: { username, password, loginType, code, uuid, textCode }
// })
// }
// // 注册方法
// export function register(data) {
// return request({
// url: '/auth/register',
// headers: {
// isToken: false
// },
// method: 'post',
// data: data
// })
// }
// // 刷新方法
// export function refreshToken() {
// return request({
// url: '/auth/refresh',
// method: 'post'
// })
// }
// // 获取用户详细信息
// export function getInfo() {
// return request({
// url: '/system/user/getInfo',
// method: 'get'
// })
// }
// // 退出方法
// export function logout() {
// return request({
// url: '/auth/logout',
// method: 'post'
// })
// }
// // 获取验证码
// export function getCodeImg() {
// return request({
// url: '/code',
// headers: {
// isToken: false
// },
// method: 'get',
// timeout: 20000
// })
// }
// // 短信验证码
// export function sendCode(data) {
// return request({
// url: '/auth/sendCode',
// headers: {
// isToken: false
// },
// method: 'post',
// data: data
// })
// }
// // 短信验证码--登录
// export function checkCode(data) {
// return request({
// url: '/auth/checkCode',
// headers: {
// isToken: false
// },
// method: 'post',
// data: data
// })
// }
// //南网机具认证中心登录1
// export function SsoLogin(data) {
// return request({
// url: '/auth/onlineApprove',
// headers: {
// isToken: false
// },
// method: 'post',
// data: data
// })
// }
// //南网机具认证中心登录2
// export function loginByMall(data) {
// return request({
// url: '/auth/loginByMall',
// headers: {
// isToken: false
// },
// method: 'post',
// data: data
// })
// }
import request from '@/utils/request'
// 登录方法
export function login(username, password, loginType, code, uuid, textCode) {
export function login(data) {
return request({
url: '/auth/login',
headers: {
@ -9,8 +123,43 @@ export function login(username, password, loginType, code, uuid, textCode) {
repeatSubmit: false
},
method: 'post',
timeout: 20000,
data: { username, password, loginType, code, uuid, textCode }
data: data
})
}
export function isLogin(data) {
return request({
url: '/auth/isLogin',
headers: {
isToken: false,
repeatSubmit: false
},
method: 'post',
data: data
})
}
export function isAdmin(data) {
return request({
url: '/auth/isAdmin',
headers: {
isToken: false,
repeatSubmit: false
},
method: 'post',
data: data
})
}
export function getPhoneCode(payload) {
return request({
url: '/auth/getPhoneCode',
headers: {
isToken: false,
repeatSubmit: false
},
method: 'post',
data: payload
})
}
@ -46,7 +195,7 @@ export function getInfo() {
export function logout() {
return request({
url: '/auth/logout',
method: 'delete'
method: 'post'
})
}
@ -62,55 +211,3 @@ export function getCodeImg() {
})
}
// 短信验证码
export function sendCode(data) {
return request({
url: '/auth/sendCode',
headers: {
isToken: false
},
method: 'post',
data: data
})
}
// 短信验证码--登录
export function checkCode(data) {
return request({
url: '/auth/checkCode',
headers: {
isToken: false
},
method: 'post',
data: data
})
}
//南网机具认证中心登录1
export function SsoLogin(data) {
return request({
url: '/auth/onlineApprove',
headers: {
isToken: false
},
method: 'post',
data: data
})
}
//南网机具认证中心登录2
export function loginByMall(data) {
return request({
url: '/auth/loginByMall',
headers: {
isToken: false
},
method: 'post',
data: data
})
}

BIN
src/assets/images/dp-bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

View File

@ -0,0 +1,291 @@
/**
* 通用css样式布局处理
* Copyright (c) 2019 bonus
*/
/** 基础通用 **/
.pt5 {
padding-top: 5px;
}
.pr5 {
padding-right: 5px;
}
.pb5 {
padding-bottom: 5px;
}
.mt5 {
margin-top: 5px;
}
.mr5 {
margin-right: 5px;
}
.mb5 {
margin-bottom: 5px;
}
.mb8 {
margin-bottom: 8px;
}
.ml5 {
margin-left: 5px;
}
.mt10 {
margin-top: 10px;
}
.mr10 {
margin-right: 10px;
}
.mb10 {
margin-bottom: 10px;
}
.ml10 {
margin-left: 10px;
}
.mt20 {
margin-top: 20px;
}
.mr20 {
margin-right: 20px;
}
.mb20 {
margin-bottom: 20px;
}
.ml20 {
margin-left: 20px;
}
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
font-family: inherit;
font-weight: 500;
line-height: 1.1;
color: inherit;
}
.el-message-box__status + .el-message-box__message{
word-break: break-word;
}
.el-dialog:not(.is-fullscreen) {
margin-top: 6vh !important;
}
.el-dialog__wrapper.scrollbar .el-dialog .el-dialog__body {
overflow: auto;
overflow-x: hidden;
max-height: 70vh;
padding: 10px 20px 0;
}
.el-table {
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
th {
word-break: break-word;
background-color: #f8f8f9;
color: #515a6e;
height: 40px;
font-size: 13px;
}
}
.el-table__body-wrapper {
.el-button [class*="el-icon-"] + span {
margin-left: 1px;
}
}
}
/** 表单布局 **/
.form-header {
font-size: 15px;
color: #6379bb;
border-bottom: 1px solid #ddd;
margin: 8px 10px 25px 10px;
padding-bottom: 5px
}
/** 表格布局 **/
.pagination-container {
position: relative;
height: 25px;
margin-bottom: 10px;
margin-top: 15px;
padding: 10px 20px !important;
}
/* tree border */
.tree-border {
margin-top: 5px;
border: 1px solid #e5e6e7;
background: #FFFFFF none;
border-radius: 4px;
}
.pagination-container .el-pagination {
right: 0;
position: absolute;
}
@media (max-width: 768px) {
.pagination-container .el-pagination > .el-pagination__jump {
display: none !important;
}
.pagination-container .el-pagination > .el-pagination__sizes {
display: none !important;
}
}
.el-table .fixed-width .el-button--mini {
padding-left: 0;
padding-right: 0;
width: inherit;
}
/** 表格更多操作下拉样式 */
.el-table .el-dropdown-link,.el-table .el-dropdown-selfdefine {
cursor: pointer;
margin-left: 5px;
}
.el-table .el-dropdown, .el-icon-arrow-down {
font-size: 12px;
}
.el-tree-node__content > .el-checkbox {
margin-right: 8px;
}
.list-group-striped > .list-group-item {
border-left: 0;
border-right: 0;
border-radius: 0;
padding-left: 0;
padding-right: 0;
}
.list-group {
padding-left: 0px;
list-style: none;
}
.list-group-item {
border-bottom: 1px solid #e7eaec;
border-top: 1px solid #e7eaec;
margin-bottom: -1px;
padding: 11px 0px;
font-size: 13px;
}
.pull-right {
float: right !important;
}
.el-card__header {
padding: 14px 15px 7px;
min-height: 40px;
}
.el-card__body {
padding: 15px 20px 20px 20px;
}
.card-box {
padding-right: 15px;
padding-left: 15px;
margin-bottom: 10px;
}
/* button color */
.el-button--cyan.is-active,
.el-button--cyan:active {
background: #20B2AA;
border-color: #20B2AA;
color: #FFFFFF;
}
.el-button--cyan:focus,
.el-button--cyan:hover {
background: #48D1CC;
border-color: #48D1CC;
color: #FFFFFF;
}
.el-button--cyan {
background-color: #20B2AA;
border-color: #20B2AA;
color: #FFFFFF;
}
/* text color */
.text-navy {
color: #1ab394;
}
.text-primary {
color: inherit;
}
.text-success {
color: #1c84c6;
}
.text-info {
color: #23c6c8;
}
.text-warning {
color: #f8ac59;
}
.text-danger {
color: #ed5565;
}
.text-muted {
color: #888888;
}
/* image */
.img-circle {
border-radius: 50%;
}
.img-lg {
width: 120px;
height: 120px;
}
.avatar-upload-preview {
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
border-radius: 50%;
box-shadow: 0 0 4px #ccc;
overflow: hidden;
}
/* 拖拽列样式 */
.sortable-ghost {
opacity: .8;
color: #fff !important;
background: #42b983 !important;
}
.top-right-btn {
position: relative;
float: right;
}

View File

@ -102,7 +102,7 @@
/>
</el-select>
</el-form-item>
<el-form-item label="日期" prop="date" v-if="status > 11">
<el-form-item label="预警时间" prop="date" v-if="status > 11">
<el-date-picker
v-model="queryParams.date"
style="width: 240px"

View File

@ -7,6 +7,7 @@ import './assets/styles/element-variables.scss'
import '@/assets/styles/index.scss' // global css
import '@/assets/styles/ruoyi.scss' // ruoyi css
import '@/assets/styles/bonus.scss' // ruoyi css
import '@/assets/css/global.css'
import '@/assets/iconfont/iconfont.css'
import App from './App'

View File

@ -44,7 +44,8 @@ export const constantRoutes = [
},
{
path: '/login',
component: () => import('@/views/login/index.vue'),
// component: () => import('@/views/login/index.vue'),
component: () => import('@/views/login/login1.vue'),
hidden: true,
},
{

View File

@ -1,7 +1,36 @@
import { login, logout, getInfo, refreshToken, checkCode, loginByMall } from '@/api/login'
import { login, logout, getInfo, refreshToken, getPhoneCode, isLogin,isAdmin} from '@/api/login'
import { getToken, setToken, setExpiresIn, removeToken } from '@/utils/auth'
import { Notification, MessageBox, Message, Loading } from 'element-ui'
import { encrypt } from '@/utils/jsencrypt'
// 更严格的手机号和邮箱正则表达式
const phonePattern = /^(\+86)?1[3-9]\d{9}$/ // 支持前缀 +86
const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
// 构建 payload 函数
const buildPayload = ({ loginMethod, username, password, uuid, code, mobile, verificationCode,phoneUuid }) => {
let loginType = ''
if (loginMethod === 'mobile') {
loginType = phonePattern.test(mobile.trim()) ? 'PHONE_OTP' : emailPattern.test(mobile.trim()) ? 'EMAIL_OTP' : 'PHONE_OTP'
return {
username: mobile.trim(),
verificationCode,
uuid,
code,
loginType,
phoneUuid
}
} else {
loginType = phonePattern.test(username.trim()) ? 'PHONE_PASSWORD' : emailPattern.test(username.trim()) ? 'EMAIL_PASSWORD' : 'USERNAME_PASSWORD'
return {
username: username.trim(),
password,
verificationCode,
uuid,
code,
loginType,
phoneUuid
}
}
}
const user = {
state: {
@ -14,158 +43,112 @@ const user = {
},
mutations: {
SET_TOKEN: (state, token) => {
SET_TOKEN(state, token) {
state.token = token
},
SET_EXPIRES_IN: (state, time) => {
SET_EXPIRES_IN(state, time) {
state.expires_in = time
},
SET_ID: (state, id) => {
SET_ID(state, id) {
state.id = id
},
SET_NAME: (state, name) => {
SET_NAME(state, name) {
state.name = name
},
SET_AVATAR: (state, avatar) => {
SET_AVATAR(state, avatar) {
state.avatar = avatar
},
SET_ROLES: (state, roles) => {
SET_ROLES(state, roles) {
state.roles = roles
},
SET_PERMISSIONS: (state, permissions) => {
SET_PERMISSIONS(state, permissions) {
state.permissions = permissions
}
},
actions: {
// 登录
async Login({ commit }, userInfo) {
const username = userInfo.username.trim()
// const password = encrypt(userInfo.password)
const loginType = userInfo.loginType
const password = userInfo.password
const code = userInfo.code
const uuid = userInfo.uuid
const textCode = userInfo.textCode
return new Promise((resolve, reject) => {
login(username, password, loginType, code, uuid, textCode).then(res => {
let data = res.data
localStorage.setItem('isCode', data.code || '')
setToken(data.access_token)
commit('SET_TOKEN', data.access_token)
localStorage.setItem('token', data.access_token)
setExpiresIn(data.expires_in)
commit('SET_EXPIRES_IN', data.expires_in)
resolve()
}).catch(error => {
reject(error)
})
})
IsLogin({ commit }, userInfo) {
const payload = buildPayload(userInfo)
return isLogin(payload)
.then(res => res)
.catch(error => Promise.reject(error))
},
// 短信验证码 登录
textLogin({ commit }, userInfo) {
console.log(userInfo)
let params = {
phone: userInfo.phone,
code: userInfo.textCode
}
return new Promise((resolve, reject) => {
checkCode(params).then(res => {
console.log(res)
if (res.code == 200) {
let data = res.data
setToken(data.access_token)
commit('SET_TOKEN', data.access_token)
localStorage.setItem('token', data.access_token)
setExpiresIn(data.expires_in)
commit('SET_EXPIRES_IN', data.expires_in)
resolve()
}
}).catch(error => {
reject(error)
})
})
},
//机具租赁平台跳转登录---南网
ssoLogin({ commit }, param) {
return new Promise((resolve, reject) => {
loginByMall(param).then(res => {
console.log(res)
let data = res.data
if (res.code == 200) {
// console.log('登录成功1111111')
setToken(data.access_token)
commit('SET_TOKEN', data.access_token)
localStorage.setItem('token', data.access_token)
setExpiresIn(data.expires_in)
commit('SET_EXPIRES_IN', data.expires_in)
} else {
// console.log('登录失败22222222')
this.$modal.msgError('登录失败');
}
resolve()
}).catch(error => {
reject(error)
})
})
IsAdmin({ commit }, userInfo) {
const payload = buildPayload(userInfo)
return isAdmin(payload)
.then(res => res)
.catch(error => Promise.reject(error))
},
// 登录
Login({ commit }, userInfo) {
const payload = buildPayload(userInfo)
return login(payload)
.then(res => {
const { access_token, expires_in } = res.data
setToken(access_token)
commit('SET_TOKEN', access_token)
setExpiresIn(expires_in)
commit('SET_EXPIRES_IN', expires_in)
return res;
})
.catch(error => Promise.reject(error))
},
// 获取手机验证码
GetPhoneCode({ commit }, userInfo) {
const payload = {
username: userInfo.mobile.trim(),
uuid: userInfo.uuid,
code: userInfo.code,
phoneUuid: userInfo.phoneUuid,
verificationCodeType: userInfo.mobileCodeType
}
return getPhoneCode(payload)
.then(res => res)
.catch(error => Promise.reject(error))
},
// 获取用户信息
GetInfo({ commit, state }) {
return new Promise((resolve, reject) => {
getInfo().then(res => {
GetInfo({ commit }) {
return getInfo()
.then(res => {
const user = res.user
/* 存储当前登录用户的userId */
sessionStorage.setItem('userId', user.userId)
sessionStorage.setItem('deptId', user.deptId)
const avatar = (user.avatar == "" || user.avatar == null) ? require("@/assets/images/profile.jpg") : user.avatar;
if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
commit('SET_ROLES', res.roles)
commit('SET_PERMISSIONS', res.permissions)
} else {
commit('SET_ROLES', ['ROLE_DEFAULT'])
}
const avatar = user.avatar ? user.avatar : require('@/assets/images/profile.jpg')
commit('SET_ROLES', res.roles && res.roles.length > 0 ? res.roles : ['ROLE_DEFAULT'])
commit('SET_PERMISSIONS', res.permissions)
commit('SET_ID', user.userId)
commit('SET_NAME', user.userName)
commit('SET_AVATAR', avatar)
resolve(res)
}).catch(error => {
reject(error)
return res
})
})
.catch(error => Promise.reject(error))
},
// 刷新token
// 刷新 token
RefreshToken({ commit, state }) {
return new Promise((resolve, reject) => {
refreshToken(state.token).then(res => {
setExpiresIn(res.data)
commit('SET_EXPIRES_IN', res.data)
resolve()
}).catch(error => {
reject(error)
return refreshToken(state.token)
.then(res => {
const expiresIn = res.data
setExpiresIn(expiresIn)
commit('SET_EXPIRES_IN', expiresIn)
})
})
.catch(error => Promise.reject(error))
},
// 退出系统
// 退出登录
LogOut({ commit, state }) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
return logout(state.token)
.then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
commit('SET_PERMISSIONS', [])
removeToken()
localStorage.removeItem('isCode')
resolve()
}).catch(error => {
reject(error)
})
})
.catch(error => Promise.reject(error))
},
// 前端
// 前端退
FedLogOut({ commit }) {
return new Promise(resolve => {
commit('SET_TOKEN', '')

View File

@ -0,0 +1,30 @@
import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
// 密钥对生成 http://web.chacuo.net/netrsakeypair
const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' +
'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' +
'7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +
'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +
'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +
'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +
'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +
'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +
'UP8iWi1Qw0Y='
// 加密
export function encrypt(txt) {
const encryptor = new JSEncrypt()
encryptor.setPublicKey(publicKey) // 设置公钥
return encryptor.encrypt(txt) // 对数据进行加密
}
// 解密
export function decrypt(txt) {
const encryptor = new JSEncrypt()
encryptor.setPrivateKey(privateKey) // 设置私钥
return encryptor.decrypt(txt) // 对数据进行解密
}

View File

@ -5,7 +5,7 @@
<!-- -->
<div>
<div :class="['single-sec']" v-if="showProjSec">
<el-input placeholder="请输入内容" suffix-icon="el-icon-search" v-model="searchIpt" />
<el-input placeholder="请输入内容" suffix-icon="el-icon-search" v-model="searchIpt" @input="(v)=>(searchIpt=validForbid(searchIpt))" maxlength="10"/>
</div>
<div
:class="['single-sec', { isActive: !currentProjIndex }]"
@ -273,7 +273,9 @@ export default {
this.showProjSec = true
this.showLefSec = false
this.renderAllProj()
}
},
validForbid(value) { value = value.replace(/[`~!@#$%^&*()_\-+=<>?:"{}|,./;'\\[\]·~@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、]/g, '').replace(/\s/g, ""); return value; }
}
}
</script>

View File

@ -5,7 +5,7 @@
<!-- -->
<div>
<div :class="['single-sec']" v-if="!showLefSec">
<el-input placeholder="请输入内容" suffix-icon="el-icon-search" v-model="searchIpt" />
<el-input placeholder="请输入内容" suffix-icon="el-icon-search" v-model="searchIpt" @input="(v)=>(searchIpt=validForbid(searchIpt))" maxlength="10"/>
</div>
<div
:class="['single-sec', { isActive: showCountrySec }]"
@ -267,7 +267,8 @@ export default {
this.currentProjIndex = undefined
this.currentCountryIndex = undefined
this.getGeoData()
}
},
validForbid(value) { value = value.replace(/[`~!@#$%^&*()_\-+=<>?:"{}|,./;'\\[\]·~@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、]/g, '').replace(/\s/g, ""); return value; }
}
}
</script>

802
src/views/login/login1.vue Normal file
View File

@ -0,0 +1,802 @@
<template>
<div class="container">
<div class="bg-cont">
<div class="bg">
<img src="@/assets/images/dp-bg.png" />
</div>
</div>
<!-- <div class="lef-cont">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="tit">
<span style="padding-bottom: 15px">您好</span>
<span>欢迎来到输变电工程施工现场安全风险预警系统</span>
</div>
<div class="tit-en">
<span style="padding-bottom: 15px">Hello!</span>
<span>Welcome to the Safety Construction Warning System</span>
</div>
<div class="img-cont">
<img src="@/assets/images/warn-bg.png">
</div>
</div> -->
<div class="login">
<h3 class="title" style="font-weight: bold;">输变电工程施工现场安全风险预警系统</h3>
<div class="login-form">
<el-form ref="loginForm" :model="loginForm" :rules="loginRules">
<!-- -->
<template v-if="loginMethod === 'password'">
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
type="text"
auto-complete="off"
:placeholder="`用户名${
config.loginConfig.phonePassword
? '/手机号'
: ''
}${
config.loginConfig.emailPassword
? '/邮箱'
: ''
}`"
>
<svg-icon
slot="prefix"
icon-class="user"
class="el-input__icon input-icon"
/>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
placeholder="密码"
auto-complete="off"
@keyup.enter.native="handleLogin"
>
<svg-icon
slot="prefix"
icon-class="password"
class="el-input__icon input-icon"
/>
</el-input>
</el-form-item>
<el-form-item prop="code" v-if="captchaEnabled">
<el-input
v-model="loginForm.code"
auto-complete="off"
placeholder="验证码"
style="width: 63%"
@keyup.enter.native="handleLogin"
>
<svg-icon
slot="prefix"
icon-class="validCode"
class="el-input__icon input-icon"
/>
</el-input>
<div class="login-code">
<img
:src="codeUrl"
@click="getCode"
class="login-code-img"
/>
</div>
</el-form-item>
<el-form-item v-show="isAdmin" prop="verificationCode">
<el-input
v-model="loginForm.verificationCode"
placeholder="请输入验证码"
>
<template slot="append">
<el-button
type="primary"
@click="sendAdminCode"
:disabled="
isSendingCode || captchaEnabled
? !loginForm.code
: false
"
class="send-code-button"
>
{{
countdown === 0
? '获取验证码'
: `${countdown}s`
}}
</el-button>
</template>
<svg-icon
slot="prefix"
icon-class="message"
class="el-input__icon input-icon"
/>
</el-input>
</el-form-item>
</template>
<template v-else>
<el-form-item prop="mobile">
<el-input
v-model="loginForm.mobile"
type="text"
auto-complete="off"
:placeholder="`${
config.loginConfig.phoneCode
? '手机号'
: '/'
}${config.loginConfig.emailCode ? '邮箱' : ''}`"
>
<svg-icon
slot="prefix"
icon-class="user"
class="el-input__icon input-icon"
/>
</el-input>
</el-form-item>
<el-form-item prop="code" v-if="captchaEnabled">
<el-input
v-model="loginForm.code"
auto-complete="off"
placeholder="验证码"
style="width: 63%"
@keyup.enter.native="handleLogin"
>
<svg-icon
slot="prefix"
icon-class="validCode"
class="el-input__icon input-icon"
/>
</el-input>
<div class="login-code">
<img
:src="codeUrl"
@click="getCode"
class="login-code-img"
/>
</div>
</el-form-item>
<el-form-item prop="verificationCode">
<el-input
v-model="loginForm.verificationCode"
placeholder="请输入验证码"
>
<template slot="append">
<el-button
type="primary"
@click="sendCode"
:disabled="
isSendingCode || captchaEnabled
? !loginForm.code
: false
"
class="send-code-button"
>
{{
countdown === 0
? '获取验证码'
: `${countdown}s`
}}
</el-button>
</template>
<svg-icon
slot="prefix"
icon-class="message"
class="el-input__icon input-icon"
/>
</el-input>
</el-form-item>
</template>
<div class="login-form-center">
<el-link
v-if="
config.loginConfig.emailCode ||
config.loginConfig.phoneCode
"
@click="toggleLoginMethod"
>
{{
loginMethod === 'password'
? '短信登录'
: '密码登录'
}}
</el-link>
<router-link
v-if="
config.registersConfig.emailRegisters ||
config.registersConfig.phoneRegisters
"
to="/register"
>
<!-- <el-link>注册账号</el-link> -->
</router-link>
<!-- <el-checkbox v-model="loginForm.rememberMe">记住密码</el-checkbox> -->
</div>
<el-form-item style="width: 100%">
<el-button
v-if="!isAdmin"
:loading="loading"
size="medium"
type="primary"
style="width: 100%"
@click="
loginMethod === 'password'
? IsAdmin()
: handleLogin()
"
>
<span v-if="!loading"> </span>
<span v-else> 中...</span>
</el-button>
<el-button
v-if="isAdmin"
:loading="loading"
size="medium"
type="primary"
style="width: 100%"
@click="handleLogin()"
>
<span v-if="!loading"> </span>
<span v-else> 中...</span>
</el-button>
</el-form-item>
<!-- <el-form-item>
<div class="login-divider">第三方登录</div>
<div class="login-icons">
<div class="login-icon">
<img :src="dingding" alt="Weibo">
</div>
<div class="login-icon">
<img :src="wx" alt="WeChat">
</div>
<div class="login-icon">
<img :src="qq" alt="QQ">
</div>
</div>
</el-form-item>-->
</el-form>
</div>
</div>
<div class="bottom-info">
版权所有权归国网电力工程技术研究院有限公司
</div>
</div>
</template>
<script>
import { getCodeImg } from '@/api/login'
import Cookies from 'js-cookie'
import { encrypt, decrypt } from '@/utils/jsencrypt'
// import dingding from '@/assets/images/dingding.svg'
// import wx from '@/assets/images/wx.svg'
// import qq from '@/assets/images/QQ.svg'
export default {
name: 'Login',
data() {
return {
// dingding: dingding,
// wx: wx,
// qq: qq,
codeUrl: '',
isAdmin: false,
loginForm: {
username: '',
password: '',
rememberMe: false,
code: '',
mobile: '',
verificationCode: '',
uuid: '',
loginType: '',
phoneUuid: '',
mobileCodeType: 'LOGIN',
},
passwordLoginRules: {
username: [
{
required: true,
trigger: 'blur',
message: '请输入您的账号',
},
],
password: [
{
required: true,
trigger: 'blur',
message: '请输入您的密码',
},
],
code: [
{
required: true,
trigger: 'change',
message: '请输入验证码',
},
],
},
mobileLoginRules: {
mobile: [
{
required: true,
trigger: 'blur',
message: '请输入您的手机号',
},
],
verificationCode: [
{
required: true,
trigger: 'blur',
message: '请输入验证码',
},
],
},
loading: false,
captchaEnabled: true,
redirect: undefined,
isSendingCode: false,
countdown: 0,
loginMethod: 'password', // 'password' or 'mobile'
supportsPhoneLogin: false,
supportsEmailLogin: false,
}
},
computed: {
config() {
return (
JSON.parse(localStorage.getItem('systemConfig')) || {
loginConfig: {
phonePassword: true,
emailPassword: true,
phoneCode: false,
emailCode: false,
},
registersConfig: {
phoneRegisters: true,
emailRegisters: true,
},
}
) // JSON
},
loginRules() {
return this.loginMethod === 'password'
? this.passwordLoginRules
: this.mobileLoginRules
},
},
watch: {
$route: {
handler(route) {
this.redirect = route.query && route.query.redirect
},
immediate: true,
},
},
created() {
this.getCode()
this.getCookie()
},
methods: {
getCode() {
getCodeImg().then((res) => {
this.captchaEnabled =
res.captchaEnabled !== undefined ? res.captchaEnabled : true
console.log(this.captchaEnabled)
if (this.captchaEnabled) {
this.codeUrl = 'data:image/gif;base64,' + res.img
this.loginForm.uuid = res.uuid
}
})
},
getCookie() {
const username = Cookies.get('username')
const password = Cookies.get('password')
const rememberMe = Cookies.get('rememberMe')
this.loginForm.username = username || ''
this.loginForm.password = password ? decrypt(password) : ''
this.loginForm.rememberMe = rememberMe === 'true'
},
handleLogin() {
this.$refs.loginForm.validate((valid) => {
if (valid) {
this.loading = true
if (this.loginForm.rememberMe) {
Cookies.set('username', this.loginForm.username, {
expires: 30,
})
Cookies.set(
'password',
encrypt(this.loginForm.password),
{ expires: 30 },
)
Cookies.set('rememberMe', this.loginForm.rememberMe, {
expires: 30,
})
} else {
Cookies.remove('username')
Cookies.remove('password')
Cookies.remove('rememberMe')
}
this.loginForm.loginMethod = this.loginMethod
this.$store
.dispatch('Login', this.loginForm)
.then((res) => {
console.log(res)
if (res.code === 200) {
if (res.isLogin) {
this.$modal
.confirm(
'账号已在其他地方登录是否继续登录!!!!',
)
.then(function () {
return this.$router.push({
path: this.redirect || '/',
})
})
.then(() => {
this.loading = false
})
.catch(() => {
this.loading = false
})
} else {
this.$router.push({
path: this.redirect || '/',
})
}
}
})
.catch(() => {
this.loading = false
if (this.captchaEnabled) this.getCode()
})
}
})
},
IsAdmin() {
this.loginForm.loginMethod = this.loginMethod
this.$store.dispatch('IsAdmin', this.loginForm).then((res) => {
if (res.data) {
this.isAdmin = res.data
this.$message.success(
'检测到您是超级管理账号,需进行手机检验',
)
} else {
this.handleLogin()
}
})
},
isLogin() {
this.$refs.loginForm.validate((valid) => {
if (valid) {
this.loading = true
let that = this
this.loginForm.loginMethod = this.loginMethod
this.$store
.dispatch('IsLogin', this.loginForm)
.then((res) => {
if (res.data) {
this.$modal
.confirm(
'账号已在其他地方登录是否继续登录!!!!',
)
.then(function () {
return that.handleLogin()
})
.then(() => {
this.loading = false
})
.catch(() => {
this.loading = false
})
} else {
that.handleLogin()
}
})
.catch(() => {
this.loading = false
if (this.captchaEnabled) this.getCode()
})
}
})
},
sendAdminCode() {
this.loginForm.mobile = this.loginForm.username
this.$store
.dispatch('GetPhoneCode', this.loginForm)
.then((res) => {
if (res.code === 200) {
this.loginForm.phoneUuid = res.data
this.$message.success('验证码发送成功')
this.isSendingCode = true
this.countdown = 60
const timer = setInterval(() => {
this.countdown -= 1
if (this.countdown <= 0) {
clearInterval(timer)
this.isSendingCode = false
}
}, 1000)
}
})
.catch(() => {
this.loading = false
//
if (this.captchaEnabled) {
this.getCode()
}
//
this.isSendingCode = false
this.countdown = 0
})
},
sendCode() {
if (this.captchaEnabled ? !this.loginForm.code : false) {
this.$message.error('请先填写验证码')
return
}
if (!this.loginForm.mobile) {
this.$message.error(
'请先填写' + this.config.loginConfig.phoneCode
? '手机号'
: '/' + this.config.loginConfig.emailCode
? '邮箱'
: '',
)
return
}
this.$store
.dispatch('GetPhoneCode', this.loginForm)
.then(() => {
this.isSendingCode = true
this.countdown = 60
const timer = setInterval(() => {
this.countdown -= 1
if (this.countdown <= 0) {
clearInterval(timer)
this.isSendingCode = false
}
}, 1000)
})
.catch(() => {
this.loading = false
//
if (this.captchaEnabled) {
this.getCode()
}
//
this.isSendingCode = false
this.countdown = 0
})
},
toggleLoginMethod() {
this.loginMethod =
this.loginMethod === 'password' ? 'mobile' : 'password'
this.loginForm.username = ''
this.loginForm.password = ''
this.loginForm.code = ''
this.loginForm.verificationCode = ''
this.loginForm.loginMethod = ''
this.isAdmin = false
this.getCode()
},
},
}
</script>
<style lang="scss">
// @font-face {
// font-family: 'titleFont';
// src: url('../assets/iconFont/titleFont.ttf');
// }
.container {
display: flex;
justify-content: flex-end;
align-items: center;
flex-wrap: wrap;
background-color: #eaf0fb;
height: 100%;
}
.bg-cont {
width: 50%;
height: 90%;
display: flex;
justify-content: flex-end;
align-items: center;
.bg {
width: 90%;
height: 70%;
img {
width: 100%;
height: 100%;
}
}
}
.lef-cont {
width: 50%;
height: 100%;
background-color: #7288fa;
box-sizing: border-box;
padding: 5%;
position: relative;
.circle1 {
position: absolute;
top: 8%;
left: 8%;
width: 50px;
height: 50px;
border-radius: 50%;
background-color: #8ea0fb;
}
.circle2 {
position: absolute;
top: calc(8% + 25px);
left: calc(8% + 25px);
width: 30px;
height: 30px;
border-radius: 50%;
background-color: #fff;
}
.tit {
margin-top: 10%;
margin-bottom: 20px;
display: flex;
flex-direction: column;
font-size: 32px;
color: #fff;
}
.tit-en {
display: flex;
flex-direction: column;
font-size: 20px;
color: #fff;
}
.img-cont {
width: 300px;
height: 300px;
margin: 80px auto;
img {
width: 100%;
height: 95%;
}
}
}
.bottom-info {
width: 100%;
height: 10%;
text-align: center;
font-size: 18px;
font-weight: bold;
color: #1e67e7;
}
.login {
width: 50%;
height: 90%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.title {
// font-family: 'titleFont', sans-serif;
margin: 0 auto 50px;
text-align: center;
font-size: 32px;
color: #1e67e7;
}
.login-form {
border-radius: 6px;
background: #ffffff;
width: 60%;
padding: 25px;
.el-input {
height: 38px;
input {
height: 38px;
}
}
.input-icon {
height: 39px;
width: 14px;
margin-left: 2px;
}
.login-form-center {
display: flex;
justify-content: space-between;
align-items: flex-start;
padding: 1%;
margin-bottom: 5%;
}
}
.login-tip {
font-size: 13px;
text-align: center;
color: #bfbfbf;
}
.login-code {
width: 33%;
float: right;
img {
cursor: pointer;
vertical-align: middle;
}
}
.el-login-footer {
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
.login-code-img {
height: 38px;
}
.login-container {
text-align: center;
margin-top: 50px;
}
.login-divider {
display: flex;
align-items: center;
text-align: center;
margin: 20px 0;
}
.login-divider::before,
.login-divider::after {
content: '';
flex: 1;
border-bottom: 1px solid #ccc;
}
.login-divider:not(:empty)::before {
margin-right: 0.25em;
}
.login-divider:not(:empty)::after {
margin-left: 0.25em;
}
.login-icons {
display: flex;
justify-content: center;
gap: 20px;
}
.login-icon {
width: 50px;
height: 50px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.login-icon img {
width: 50px;
height: 50px;
}
</style>

View File

@ -36,8 +36,8 @@ module.exports = {
proxy: {
[process.env.VUE_APP_BASE_API]: {
// target: `https://test-cc.zhgkxt.com`,//线上环境
target: `http://192.168.2.246:18080`, //马
// target: `http://192.168.0.14:19900`, //马
// target: `http://192.168.2.246:18080`, //马
target: `http://192.168.0.14:19900`, //测试
//******** 注意事项 ********* */
// 将 publicPath:'static' 改为 '/gl/',还有env.development和env.production中的VUE_APP_BASE_API改为'/gl/prod-api';
// router/indx.js文件中的base放开