严飞永 1 month ago
parent a6049d585e
commit d2a44e5fb3

@ -26,76 +26,54 @@ router.beforeEach((to, from, next) => {
NProgress.start() NProgress.start()
//政务登录 const { userToken, signature, timespan } = to.query
const url = window.location.href console.log(userToken, signature, timespan, '参数')
// 检查是否包含政务平台返回的关键参数
const hasUserToken = url.includes('userToken=') if (userToken && signature && timespan) {
const hasSignature = url.includes('signature=') // 政务登录
const hasTimespan = url.includes('timespan=') governmentGetInfo({
userToken,
if (hasUserToken && hasSignature && hasTimespan) { signature,
const regUserToken = /[?&]userToken=([^&#]+)/ timespan
const regSignature = /[?&]signature=([^&#]+)/ }).then(res => {
const regTimespan = /[?&]timespan=([^&#]+)/ const token = res.token
if (token) {
const userTokenMatch = url.match(regUserToken) setToken(token)
const signatureMatch = url.match(regSignature) localStorage.setItem('otherToken', userToken)
const timespanMatch = url.match(regTimespan)
const newQuery = { ...to.query }
const userToken = userTokenMatch ? userTokenMatch[1] : null delete newQuery.userToken
const signature = signatureMatch ? signatureMatch[1] : null delete newQuery.signature
const timespan = timespanMatch ? timespanMatch[1] : null delete newQuery.timespan
const newPath = to.path + '?' + new URLSearchParams(newQuery).toString()
if (userToken && signature && timespan) { window.history.replaceState({}, '', newPath)
// 调用政务系统登录接口
governmentGetInfo({ if (store.getters.roles.length === 0) {
userToken, isRelogin.show = true
signature, store.dispatch('GetInfo').then(() => {
timespan isRelogin.show = false
}).then(res => { store.dispatch('GenerateRoutes').then(accessRoutes => {
const token = res.token router.addRoutes(accessRoutes)
if (token) { next({ ...to, replace: true })
setToken(token) })
localStorage.setItem('otherToken', userToken) }).catch(err => {
store.dispatch('LogOut').then(() => {
const cleanUrl = url Message.error(err)
.replace(regUserToken, '') next({ path: '/' })
.replace(regSignature, '') })
.replace(regTimespan, '') })
.replace(/^&/, '?') } else {
next()
window.history.replaceState({}, '', cleanUrl) }
// 继续路由守卫流程
if (store.getters.roles.length === 0) {
isRelogin.show = true
store.dispatch('GetInfo').then(() => {
isRelogin.show = false
store.dispatch('GenerateRoutes').then(accessRoutes => {
router.addRoutes(accessRoutes)
next({ ...to, replace: true })
})
}).catch(err => {
store.dispatch('LogOut').then(() => {
Message.error(err)
next({ path: '/' })
})
})
} else {
next()
}
}
}).catch(err => {
console.error('政务系统登录失败:', err)
Message.error('政务系统登录失败,请重新登录')
})
} else {
Message.error('缺少必要的登录参数')
next(`/login?redirect=${encodeURIComponent(to.fullPath)}`)
} }
return }).catch(err => {
} console.error('政务系统登录失败:', err)
Message.error('政务系统登录失败,请重新登录')
})
return
}

@ -43,7 +43,10 @@ export const constantRoutes = [
}, },
{ {
path: "/login", path: "/login",
component: () => import("@/views/login"), // 正式环境登录页
// component: () => import("@/views/login"),
// 测试
component: () => import("@/views/login_v1"),
hidden: true, hidden: true,
}, },
{ {
@ -77,7 +80,7 @@ export const constantRoutes = [
component: () => import("@/views/index"), component: () => import("@/views/index"),
name: "Index", name: "Index",
meta: { title: "角色判断", icon: "icon-tjfx-1" }, meta: { title: "角色判断", icon: "icon-tjfx-1" },
hidden:true hidden: true,
}, },
{ {
path: "/user", path: "/user",

@ -203,7 +203,7 @@ export default {
window.location.href = 'https://qyt.sipac.gov.cn/sipsg-enterprise-mobile-manage/#/login' window.location.href = 'https://qyt.sipac.gov.cn/sipsg-enterprise-mobile-manage/#/login'
}, },
handleEnterpriseLogin() { handleEnterpriseLogin() {
window.location.href = 'https://gysl.sipac.gov.cn'; // window.location.href = 'https://gysl.sipac.gov.cn';
} }
} }
} }

@ -1,335 +1,356 @@
<template> <template>
<div class="login"> <div class="login">
<div class="loginleft"> <div class="loginleft">
</div>
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
<img src="@/assets/images/logo@2x.png" alt="">
<div class="title">苏州工业园区工业上楼管理系统</div>
<div class="logintabs">
<el-tabs v-model="activeName" :stretch="true" color="#216CDC">
<el-tab-pane label="企业用户登录" name="first"></el-tab-pane>
<el-tab-pane label="政务人员登录" name="second"></el-tab-pane>
</el-tabs>
</div> </div>
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form"> <el-form-item prop="username" class="loginitem" style="margin-top: 1rem;">
<img src="@/assets/images/logo@2x.png" alt=""> <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
<div class="title">苏州工业园区工业上楼管理系统</div> <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
<div class="logintabs"> </el-input>
<el-tabs v-model="activeName" :stretch="true" color="#216CDC"> </el-form-item>
<el-tab-pane label="企业用户登录" name="first"></el-tab-pane> <el-form-item prop="password" class="loginitem">
<el-tab-pane label="政务人员登录" name="second"></el-tab-pane> <el-input v-model="loginForm.password" type="password" auto-complete="off" placeholder="密码"
</el-tabs> @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" class="loginitem">
<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" style="width: 8.56rem;" />
</div> </div>
<el-form-item prop="username" class="loginitem" style="margin-top: 1rem;"> </el-form-item>
<el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号"> <el-checkbox v-model="loginForm.rememberMe" style="margin:1rem 18.6rem 25px 0px;"></el-checkbox>
<svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" /> <el-form-item style="width:24rem;;margin-top: 1rem;">
</el-input> <el-button :loading="loading" size="medium" type="primary" style="width:100%;background: #2B62F1;"
</el-form-item> @click.native.prevent="handleLogin">
<el-form-item prop="password" class="loginitem"> <span v-if="!loading"> </span>
<el-input v-model="loginForm.password" type="password" auto-complete="off" placeholder="密码" <span v-else> ...</span>
@keyup.enter.native="handleLogin"> </el-button>
<svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" /> <el-button v-if="showGovernmentLoginButton" size="medium" type="primary" class="tongyidenglu"
</el-input> style="width:100%;background: #2B62F1;" @click.native.prevent="handleGovernmentLogin">
</el-form-item> <span>政务统一身份认证登录</span>
<el-form-item prop="code" v-if="captchaEnabled" class="loginitem"> </el-button>
<el-input v-model="loginForm.code" auto-complete="off" placeholder="验证码" style="width: 63%" <el-button v-if="showEnterpriseLoginButton" size="medium" type="primary" class="tongyidenglu"
@keyup.enter.native="handleLogin"> style="width:100%;background: #2B62F1;" @click.native.prevent="handleEnterpriseLogin">
<svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" /> <span>企业统一身份认证登录</span>
</el-input> </el-button>
<div class="login-code">
<img :src="codeUrl" @click="getCode" class="login-code-img" style="width: 8.56rem;" /> </el-form-item>
</div> <div style="font-size: 0.88rem;color: #333;">主办单位苏州工业园区经济发展委员会</div>
</el-form-item> </el-form>
<el-checkbox v-model="loginForm.rememberMe" style="margin:1rem 18.6rem 25px 0px;"></el-checkbox> <!-- 底部 -->
<el-form-item style="width:24rem;;margin-top: 1rem;"> <div class="el-login-footer">
<el-button :loading="loading" size="medium" type="primary" style="width:100%;background: #2B62F1;" <span></span>
@click.native.prevent="handleLogin">
<span v-if="!loading"> </span>
<span v-else> ...</span>
</el-button>
<el-button v-if="showGovernmentLoginButton" size="medium" type="primary" class="tongyidenglu"
style="width:100%;background: #2B62F1;" @click.native.prevent="handleGovernmentLogin">
<span>政务统一身份认证登录</span>
</el-button>
<el-button v-if="showEnterpriseLoginButton" size="medium" type="primary" class="tongyidenglu"
style="width:100%;background: #2B62F1;" @click.native.prevent="handleEnterpriseLogin">
<span>企业统一身份认证登录</span>
</el-button>
</el-form-item>
<div style="font-size: 0.88rem;color: #333;">主办单位苏州工业园区经济发展委员会</div>
</el-form>
<!-- 底部 -->
<div class="el-login-footer">
<span></span>
</div>
</div> </div>
</template> </div>
</template>
<script>
import { getCodeImg } from '@/api/login' <script>
import Cookies from 'js-cookie' import { getCodeImg } from '@/api/login'
import { encrypt, decrypt } from '@/utils/jsencrypt' import Cookies from 'js-cookie'
import { encrypt, decrypt } from '@/utils/jsencrypt'
import forge from 'node-forge'
export default {
name: 'Login', export default {
data() { name: 'Login',
return { data() {
codeUrl: '', return {
activeName: 'second', codeUrl: '',
loginForm: { activeName: 'second',
username: '', loginForm: {
password: '', username: '',
rememberMe: false, password: '',
code: '', rememberMe: false,
uuid: '', code: '',
loginRole: 2 uuid: '',
}, loginRole: 2
loginRules: { },
username: [ loginRules: {
{ required: true, trigger: 'blur', message: '请输入您的账号' } username: [
], { required: true, trigger: 'blur', message: '请输入您的账号' }
password: [ ],
{ required: true, trigger: 'blur', message: '请输入您的密码' } password: [
], { required: true, trigger: 'blur', message: '请输入您的密码' }
code: [{ required: true, trigger: 'change', message: '请输入验证码' }] ],
}, code: [{ required: true, trigger: 'change', message: '请输入验证码' }]
loading: false, },
// loading: false,
captchaEnabled: true, captchaEnabled: true,
// register: false,
register: false, redirect: undefined,
redirect: undefined a1: `MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl8bS1kYTiMhIS5MZU253bc0ukaxrA1lfCziABFxQrC2c09tMrQGjuH6V1x2ofNBMGhOD9uWN/qkAQy/HwOe/NKUqCw6N0ov6guSrqMDW/BdZ3Bl0rmM1/95jTC1xffFFvej7xWNffIbaPI+bJ4WLX9NViNi9HmT0BRNzJ4d2R86LPPCa+bxLaPjsh2R2tBkbLkUot9769aJaPPiwPCZHMkuQenjHSmpWL0okleqMH8EGX7j6A5A/4IUXPMNKMMzkiSRpsIJ65GJmDAbnR3ZXRfC8MzVBBJB6zr5N0F4N9xZfF+JS/Yx726tCu+rA6GDCyTxtQ/wnKpPdwFP5nUWCWQIDAQAB`
}
},
watch: {
$route: {
handler: function (route) {
this.redirect = route.query && route.query.redirect;
},
immediate: true
},
activeName(newVal) {
if (newVal === 'first') {
this.loginForm.loginRole = 2
} else if (newVal === 'second') {
this.loginForm.loginRole = 1
} }
}
},
computed: {
showGovernmentLoginButton() {
return this.activeName === 'second'
}, },
watch: { showEnterpriseLoginButton() {
$route(route) { return this.activeName === 'first'
this.redirect = route.query && route.query.redirect }
}, },
activeName(newVal) { created() {
if (newVal === 'first') { this.getCode()
this.loginForm.loginRole = 2; this.getCookie()
} else if (newVal === 'second') { },
this.loginForm.loginRole = 1; methods: {
getCode() {
getCodeImg().then(res => {
this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled;
if (this.captchaEnabled) {
this.codeUrl = "data:image/gif;base64," + res.img;
this.loginForm.uuid = res.uuid;
} }
} });
}, },
computed: { getCookie() {
showGovernmentLoginButton() { const username = Cookies.get('username')
return this.activeName === 'second'; const password = Cookies.get('password')
}, const rememberMe = Cookies.get('rememberMe')
showEnterpriseLoginButton() { this.loginForm = {
return this.activeName === 'first'; username: username === undefined ? this.loginForm.username : username,
password: password === undefined ? this.loginForm.password : decrypt(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
} }
}, },
created() { handleLogin() {
this.getCode() this.$refs.loginForm.validate(valid => {
this.getCookie()
}, if (valid) {
methods: { this.loading = true;
getCode() { if (this.loginForm.rememberMe) {
getCodeImg().then((res) => { Cookies.set("username", this.loginForm.username, { expires: 30 });
this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 });
if (this.captchaEnabled) { Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 });
this.codeUrl = `data:image/gif;base64,${res.img}` } else {
this.loginForm.uuid = res.uuid Cookies.remove("username");
Cookies.remove("password");
Cookies.remove('rememberMe');
} }
}).catch((error) => { // 2048 RSA
console.error('获取验证码失败:', error) const lines = [];
}) lines.push('-----BEGIN PUBLIC KEY-----');
}, for (let i = 0; i < this.a1.length; i += 64) {
getCookie() { lines.push(this.a1.slice(i, i + 64));
const username = Cookies.get('username')
const password = Cookies.get('password')
const rememberMe = Cookies.get('rememberMe')
this.loginForm = {
username: username === undefined ? this.loginForm.username : username,
password: password === undefined ? this.loginForm.password : decrypt(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
}
},
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');
}
const loginData = {
username: this.loginForm.username,
password: this.loginForm.password,
code: this.loginForm.code,
uuid: this.loginForm.uuid,
loginRole: this.activeName === 'first' ? 2 : 1
};
this.$store.dispatch('Login', loginData)
.then(() => {
this.$router.push({ path: this.redirect || '/' }).catch(() => { });
})
.catch((error) => {
this.loading = false;
if (this.captchaEnabled) {
this.getCode();
}
console.error('登录失败:', error);
});
} }
}); lines.push('-----END PUBLIC KEY-----');
}, lines.join('\n')
handleGovernmentLogin() { const publicKey = forge.pki.publicKeyFromPem(lines.join('\n'));
// //
window.location.href = 'https://qyt.sipac.gov.cn/'; var dataBytes = forge.util.encodeUtf8(this.loginForm.password);
}, //
handleEnterpriseLogin() { var encryptedBytes = publicKey.encrypt(dataBytes, 'RSA-OAEP', {
// md: forge.md.sha256.create(),
// window.location.href = 'https://example.com/enterprise-login'; mgf1: {
} md: forge.md.sha1.create()
}
});
// Base64
var encryptedBase64 = forge.util.encode64(encryptedBytes);
//
const loginData = {
username: this.loginForm.username,
password: encryptedBase64,
code: this.loginForm.code,
uuid: this.loginForm.uuid,
loginRole: this.activeName === 'first' ? 2 : 1
};
this.$store.dispatch('Login', loginData)
.then(() => {
this.$router.push({ path: this.redirect || '/' }).catch(() => { });
})
.catch((error) => {
this.loading = false;
if (this.captchaEnabled) {
this.getCode();
}
console.error('登录失败:', error);
});
}
});
},
handleGovernmentLogin() {
window.location.href = 'https://qyt.sipac.gov.cn/sipsg-enterprise-mobile-manage/#/login'
},
handleEnterpriseLogin() {
window.location.href = 'https://gysl.sipac.gov.cn';
} }
} }
</script> }
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
::v-deep .el-tabs__active-bar { <style rel="stylesheet/scss" lang="scss" scoped>
width: 2rem !important; ::v-deep .el-tabs__active-bar {
margin-left: 3rem; width: 2rem !important;
background-color: #216CDC; margin-left: 3rem;
height: 0.21rem; background-color: #216CDC;
border-radius: 0.16rem; height: 0.21rem;
} border-radius: 0.16rem;
}
::v-deep .el-tabs__header {
border-bottom: none !important; ::v-deep .el-tabs__header {
} border-bottom: none !important;
}
::v-deep .el-tabs__item {
font-size: 1rem; ::v-deep .el-tabs__item {
padding: 0 20px; font-size: 1rem;
color: #3D424C; padding: 0 20px;
font-family: Alibaba PuHuiTi; color: #3D424C;
font-weight: 400; font-family: Alibaba PuHuiTi;
color: #3D424C; font-weight: 400;
} color: #3D424C;
}
::v-deep .el-tabs__item.is-active {
color: #216CDC; ::v-deep .el-tabs__item.is-active {
} color: #216CDC;
}
::v-deep .el-tabs__nav-wrap::after {
display: none !important; ::v-deep .el-tabs__nav-wrap::after {
} display: none !important;
}
.tongyidenglu {
margin-top: 1rem; .tongyidenglu {
margin-left: 0rem; margin-top: 1rem;
} margin-left: 0rem;
}
.login {
display: flex; .login {
justify-content: center; display: flex;
align-items: center; justify-content: center;
border-radius: 6px 0 0 6px; align-items: center;
height: 100%; border-radius: 6px 0 0 6px;
background-image: url('../assets/images/loginbackground.png'); height: 100%;
background-size: cover; background-image: url('../assets/images/loginbackground.png');
} background-size: cover;
}
.loginleft {
width: 35rem; .loginleft {
height: 40rem; width: 35rem;
background-image: url('../assets/images/loginleft.png'); height: 40rem;
background-size: 100% 100%; background-image: url('../assets/images/loginleft.png');
background-repeat: no-repeat; background-size: 100% 100%;
} background-repeat: no-repeat;
}
.title {
width: 29.13rem; .title {
height: 1.94rem; width: 29.13rem;
font-family: Alibaba PuHuiTi; height: 1.94rem;
font-weight: 500; font-family: Alibaba PuHuiTi;
font-size: 2rem; font-weight: 500;
color: #292C33; font-size: 2rem;
line-height: 3.5rem; color: #292C33;
text-align: center; line-height: 3.5rem;
margin-top: 1rem; text-align: center;
} margin-top: 1rem;
}
.loginitem {
width: 24rem; .loginitem {
width: 24rem;
}
.login-form {
border-radius: 0 6px 6px 0;
background: #ffffff;
width: 50rem;
height: 40rem;
padding: 25px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
img {
width: 6.56rem;
height: 3.56rem;
} }
.login-form { .el-input {
border-radius: 0 6px 6px 0; height: 38px;
background: #ffffff;
width: 50rem; input {
height: 40rem;
padding: 25px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
img {
width: 6.56rem;
height: 3.56rem;
}
.el-input {
height: 38px; height: 38px;
input {
height: 38px;
}
}
.input-icon {
height: 39px;
width: 14px;
margin-left: 2px;
}
}
.login-tip {
font-size: 13px;
text-align: center;
color: #bfbfbf;
}
.logintabs {
margin-top: 2.88rem;
width: 18rem;
}
.login-code {
width: 35%;
height: 1.8rem;
float: right;
img {
cursor: pointer;
vertical-align: middle;
} }
} }
.el-login-footer { .input-icon {
height: 40px; height: 39px;
line-height: 40px; width: 14px;
position: fixed; margin-left: 2px;
bottom: 0;
width: 100%;
text-align: center;
color: #333;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
.login-code-img {
height: 38px;
} }
}
.el-tabs__item.is-active {
color: #216CDC; .login-tip {
position: relative; font-size: 13px;
padding-bottom: 0.5rem; text-align: center;
color: #bfbfbf;
}
.logintabs {
margin-top: 2.88rem;
width: 18rem;
}
.login-code {
width: 35%;
height: 1.8rem;
float: right;
img {
cursor: pointer;
vertical-align: middle;
} }
</style> }
.el-login-footer {
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #333;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
.login-code-img {
height: 38px;
}
.el-tabs__item.is-active {
color: #216CDC;
position: relative;
padding-bottom: 0.5rem;
}
</style>
Loading…
Cancel
Save