测试环境修改

yfy
严飞永 4 weeks ago
parent 648667b288
commit 98f0335e58

@ -13,7 +13,7 @@ import { governmentGetInfo } from "@/api/login/index";
NProgress.configure({ showSpinner: false });
const whiteList = ["/login", "/entLogin", "/register"]; // 白名单路径
const whiteList = ["/login", "/entLogin", "/register"];
const isWhiteList = (path) => {
return whiteList.some((pattern) => isPathMatch(pattern, path));
@ -25,14 +25,15 @@ router.beforeEach((to, from, next) => {
}
NProgress.start();
const search = window.location.search || window.location.hash.split("?")[1] || "";
const search =
window.location.search || window.location.hash.split("?")[1] || "";
const params = new URLSearchParams(search);
const userToken = params.get("userToken");
const signature = params.get("signature");
const timespan = params.get("timespan");
// =============================
// 🔑 新增:处理 clienttoken 登录逻辑
// 🔑 新增:处理 clienttoken 登录企业单点登录逻辑
// =============================
if (window.location.href.includes("clienttoken=")) {
const reg = /[?&]clienttoken=([^&#]+)/;
@ -41,21 +42,25 @@ router.beforeEach((to, from, next) => {
if (clienttoken) {
// 清除 clienttoken 避免死循环
let modifiedUrl = window.location.href.replace(/[?&]clienttoken=[^&#]+/, '');
if (modifiedUrl.endsWith('?') || modifiedUrl.endsWith('&')) {
modifiedUrl = modifiedUrl.slice(0, -1); // 去掉末尾多余的符号
let modifiedUrl = window.location.href.replace(
/[?&]clienttoken=[^&#]+/,
""
);
if (modifiedUrl.endsWith("?") || modifiedUrl.endsWith("&")) {
modifiedUrl = modifiedUrl.slice(0, -1);
}
// 如果 roles 还未加载,则拉取用户信息
if (store.getters.roles.length === 0) {
isRelogin.show = true;
store.dispatch("SingleSignOnGetInfo", { clientToken: clienttoken })
store
.dispatch("SingleSignOnGetInfo", { clientToken: clienttoken })
.then(() => {
isRelogin.show = false;
// 清除 URL 中的 clienttoken 并刷新页面
window.history.replaceState({}, '', modifiedUrl);
window.history.replaceState({}, "", modifiedUrl);
// 获取用户权限并生成路由
return store.dispatch("GenerateRoutes");
@ -68,7 +73,8 @@ router.beforeEach((to, from, next) => {
// console.error("单点登录失败:", err);
store.dispatch("LogOut").then(() => {
// Message.error("单点登录失败,请重试");
window.location.href = "https://qytt.sipac.gov.cn/ecobrainportal/index.html";
window.location.href =
"https://qytt.sipac.gov.cn/ecobrainportal/index.html";
});
});
@ -85,7 +91,7 @@ router.beforeEach((to, from, next) => {
return;
}
if (userToken && signature && timespan && to.path !== "/login") {
if (userToken && signature && timespan && !isPathMatch("/login", to.path)) {
next({
path: "/login",
query: { userToken, signature, timespan },
@ -150,22 +156,26 @@ router.beforeEach((to, from, next) => {
// =============================
// 🔐 原始本地登录逻辑
// =============================
const token = getToken();
if (token) {
if (getToken()) {
to.meta.title && store.dispatch("settings/setTitle", to.meta.title);
if (to.path === "/login") {
/* has token*/
if (to.path === "/entLogin") {
next({ path: "/" });
NProgress.done();
} else if (isWhiteList(to.path)) {
next();
} else if (whiteList.indexOf(to.path) !== -1) {
next({ path: "/" });
NProgress.done();
// next();
} else {
if (store.getters.roles.length === 0) {
isRelogin.show = true;
// 判断当前用户是否已拉取完user_info信息
store
.dispatch("GetInfo")
.then(() => {
isRelogin.show = false;
store.dispatch("GenerateRoutes").then((accessRoutes) => {
// 根据roles权限生成可访问的路由表
router.addRoutes(accessRoutes);
next({ ...to, replace: true });
});
@ -173,7 +183,7 @@ router.beforeEach((to, from, next) => {
.catch((err) => {
store.dispatch("LogOut").then(() => {
Message.error(err);
next("/");
next({ path: "/" });
});
});
} else {
@ -181,14 +191,16 @@ router.beforeEach((to, from, next) => {
}
}
} else {
if (isWhiteList(to.path)) {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next();
} else {
next(`/login?redirect=${encodeURIComponent(to.fullPath)}`);
next(`/entLogin?redirect=${encodeURIComponent(to.fullPath)}`);
NProgress.done();
}
}
});
router.afterEach(() => {
NProgress.done();
});

@ -48,6 +48,11 @@ export const constantRoutes = [
// 测试
component: () => import("@/views/login_v1"),
hidden: true,
},
{
path: "/entLogin",
component: () => import("@/views/entLogin"),
hidden: true,
},
{
path: "/login_v2",

@ -50,7 +50,6 @@
<!-- <el-button
type="primary"
icon="el-icon-plus"
:loading="exportLoading"
@click="handleExport"
>项目手册导出</el-button
@ -181,7 +180,7 @@
<!-- 步骤1封面设置 -->
<div v-if="activeStep === 1" class="step-content">
<div class="cover-form">
<div class="form-row">
<div class="form-row" style="margin-bottom: 10px">
<div class="form-col">
<label class="form-label">手册名称</label>
<el-input
@ -190,14 +189,30 @@
></el-input>
</div>
<div class="form-col">
<label class="form-label">副标题</label>
<label class="form-label">副标题1</label>
<el-input
v-model="coverForm.subtitle"
v-model="coverForm.subtitle1"
placeholder="请输入"
></el-input>
</div>
</div>
<div class="form-row">
<div class="form-col">
<label class="form-label">副标题2</label>
<el-input
v-model="coverForm.subtitle2"
placeholder="请输入"
></el-input>
</div>
<div class="form-col" style="visibility: hidden">
<label class="form-label">手册名称</label>
<el-input
v-model="coverForm.title"
placeholder="请输入"
></el-input>
</div>
</div>
<!-- <div class="form-row">
<div class="form-col-full">
<label class="form-label">封面图片</label>
<file-upload
@ -207,7 +222,7 @@
:file-type="['png', 'jpg', 'jpeg', 'gif']"
></file-upload>
</div>
</div>
</div> -->
</div>
</div>
@ -337,7 +352,7 @@
<div v-if="activeStep === 3" class="step-content">
<div class="cover-form">
<div class="form-row">
<!-- <div class="form-row">
<div class="form-col-full">
<label class="form-label">封尾图片</label>
<file-upload
@ -347,16 +362,50 @@
:file-type="['png', 'jpg', 'jpeg', 'gif']"
></file-upload>
</div>
</div> -->
<div class="form-row" style="margin-bottom: 10px">
<div class="form-col">
<label class="form-label">单位名称</label>
<el-input
v-model="endForm.dwname"
placeholder="请输入"
></el-input>
</div>
<div class="form-col">
<label class="form-label">联系人</label>
<el-input
v-model="endForm.lxname"
placeholder="请输入"
></el-input>
</div>
</div>
<div class="form-row" style="margin-bottom: 10px">
<div class="form-col">
<label class="form-label">联系方式</label>
<el-input v-model="endForm.phone" placeholder="请输入"></el-input>
</div>
<div class="form-col">
<label class="form-label">时间</label>
<el-date-picker
v-model="endForm.date"
type="date"
placeholder="请选择日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
style="width: 100%"
/>
</div>
</div>
<div class="form-row">
<div class="form-col">
<label class="form-label">副标题</label>
<label class="form-label">地址</label>
<el-input
v-model="endForm.subtitle"
v-model="endForm.address"
placeholder="请输入"
style="width: 60%"
></el-input>
</div>
<div class="form-col">
</div>
</div>
</div>
</div>
@ -430,7 +479,8 @@ export default {
activeStep: 1,
coverForm: {
title: "",
subtitle: "",
subtitle1: "",
subtitle2: "",
imageUrl: "",
},
//
@ -445,7 +495,11 @@ export default {
//
endForm: {
imageUrl: "",
subtitle: "",
dwname: "",
name: "",
phone: "",
lxname: "",
address: "",
},
//
selectedRows: [],
@ -577,13 +631,18 @@ export default {
resetAddForm() {
this.coverForm = {
title: "",
subtitle: "",
subtitle1: "",
subtitle2: "",
imageUrl: "",
};
this.projectSearch = "";
this.endForm = {
imageUrl: "",
subtitle: "",
dwname: "",
date: "",
phone: "",
lxname: "",
address: "",
};
},
nextStep() {
@ -694,9 +753,14 @@ export default {
if (this.coverForm.imageUrl) data.coverImg = this.coverForm.imageUrl;
if (this.coverForm.title) data.name = this.coverForm.title;
if (this.coverForm.subtitle) data.subtitle = this.coverForm.subtitle;
if (this.coverForm.subtitle1) data.subtitle1 = this.coverForm.subtitle1;
if (this.coverForm.subtitle2) data.subtitle2 = this.coverForm.subtitle2;
if (this.endForm.imageUrl) data.tailingImg = this.endForm.imageUrl;
if (this.endForm.subtitle) data.tail = this.endForm.subtitle;
if (this.endForm.dwname) data.dwname = this.endForm.dwname;
if (this.endForm.date) data.date = this.endForm.date;
if (this.endForm.phone) data.phone = this.endForm.phone;
if (this.endForm.lxname) data.lxname = this.endForm.lxname;
if (this.endForm.address) data.address = this.endForm.address;
if (this.selectedProjects && this.selectedProjects.length > 0) {
data.xmId = this.selectedProjects
.map((project) => project.id)
@ -795,12 +859,17 @@ export default {
const detail = res.data;
this.coverForm = {
title: detail.name,
subtitle: detail.subtitle,
subtitle1: detail.subtitle1,
subtitle2: detail.subtitle2,
imageUrl: detail.coverImg,
};
this.endForm = {
imageUrl: detail.tailingImg,
subtitle: detail.tail,
imageUrl: detail.tailingImg || "",
dwname: detail.dwname || "",
lxname: detail.lxname || "",
phone: detail.phone || "",
address: detail.address || "",
date: detail.date || "",
};
//

@ -1,60 +0,0 @@
<template>
<div>
<!-- 显示当前页 -->
<pdf
v-if="show"
:src="pdfUrl"
@num-pages="pageCount = $event"
@link-clicked="gotoPage($event)"
style="border: 1px solid black;"
></pdf>
<!-- 控制按钮 -->
<button @click="prevPage"></button>
{{ currentPage }} / {{ pageCount }}
<button @click="nextPage"></button>
</div>
</template>
<script>
import pdf from "vue-pdf";
export default {
components: {
pdf,
},
data() {
return {
show: false, //
pdfUrl: "", // PDF
currentPage: 1, //
pageCount: 0, //
};
},
mounted() {
this.loadPdf();
},
methods: {
loadPdf() {
// PDF
this.pdfUrl = "pdf/模板.pdf";
this.show = true;
},
gotoPage(pageNumber) {
if (pageNumber >= 1 && pageNumber <= this.pageCount) {
this.currentPage = pageNumber;
}
},
prevPage() {
if (this.currentPage > 1) {
this.currentPage--;
}
},
nextPage() {
if (this.currentPage < this.pageCount) {
this.currentPage++;
}
},
},
};
</script>

@ -155,9 +155,9 @@
</span>
</el-dialog>
<!-- <div class="yuedu">
<div class="yuedu">
<yuedutouzi :xmId="xmId" />
</div> -->
</div>
</div>
</template>

@ -0,0 +1,357 @@
<template>
<div class="login">
<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>
<!-- <el-form-item prop="username" class="loginitem" style="margin-top: 1rem;">
<el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
<svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
</el-input>
</el-form-item>
<el-form-item prop="password" class="loginitem">
<el-input v-model="loginForm.password" type="password" auto-complete="off" placeholder="密码"
@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>
</el-form-item> -->
<!-- <el-checkbox v-model="loginForm.rememberMe" style="margin:1rem 18.6rem 25px 0px;"></el-checkbox> -->
<el-form-item style="width:24rem;;margin-top: 1rem;">
<!-- <el-button :loading="loading" size="medium" type="primary" style="width:100%;background: #2B62F1;"
@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>
</template>
<script>
import { getCodeImg } from '@/api/login'
import Cookies from 'js-cookie'
import { encrypt, decrypt } from '@/utils/jsencrypt'
import forge from 'node-forge'
export default {
name: 'Login',
data() {
return {
codeUrl: '',
activeName: 'second',
loginForm: {
username: '',
password: '',
rememberMe: false,
code: '',
uuid: '',
loginRole: 2
},
loginRules: {
username: [
{ required: true, trigger: 'blur', message: '请输入您的账号' }
],
password: [
{ required: true, trigger: 'blur', message: '请输入您的密码' }
],
code: [{ required: true, trigger: 'change', message: '请输入验证码' }]
},
loading: false,
captchaEnabled: true,
register: false,
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'
},
showEnterpriseLoginButton() {
return this.activeName === 'first'
}
},
created() {
// this.getCode()
// this.getCookie()
location.href = process.env.VUE_APP_BASE_API + "/system/singlelogin/login"
},
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;
}
});
},
getCookie() {
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');
}
// 2048 RSA
const lines = [];
lines.push('-----BEGIN PUBLIC KEY-----');
for (let i = 0; i < this.a1.length; i += 64) {
lines.push(this.a1.slice(i, i + 64));
}
lines.push('-----END PUBLIC KEY-----');
lines.join('\n')
const publicKey = forge.pki.publicKeyFromPem(lines.join('\n'));
//
var dataBytes = forge.util.encodeUtf8(this.loginForm.password);
//
var encryptedBytes = publicKey.encrypt(dataBytes, 'RSA-OAEP', {
md: forge.md.sha256.create(),
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() {
location.href = process.env.VUE_APP_BASE_API + "/system/singlelogin/login";
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
::v-deep .el-tabs__active-bar {
width: 2rem !important;
margin-left: 3rem;
background-color: #216CDC;
height: 0.21rem;
border-radius: 0.16rem;
}
::v-deep .el-tabs__header {
border-bottom: none !important;
}
::v-deep .el-tabs__item {
font-size: 1rem;
padding: 0 20px;
color: #3D424C;
font-family: Alibaba PuHuiTi;
font-weight: 400;
color: #3D424C;
}
::v-deep .el-tabs__item.is-active {
color: #216CDC;
}
::v-deep .el-tabs__nav-wrap::after {
display: none !important;
}
.tongyidenglu {
margin-top: 1rem;
margin-left: 0rem;
}
.login {
display: flex;
justify-content: center;
align-items: center;
border-radius: 6px 0 0 6px;
height: 100%;
background-image: url('../assets/images/loginbackground.png');
background-size: cover;
}
.loginleft {
width: 35rem;
height: 40rem;
background-image: url('../assets/images/loginleft.png');
background-size: 100% 100%;
background-repeat: no-repeat;
}
.title {
width: 29.13rem;
height: 1.94rem;
font-family: Alibaba PuHuiTi;
font-weight: 500;
font-size: 2rem;
color: #292C33;
line-height: 3.5rem;
text-align: center;
margin-top: 1rem;
}
.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;
}
.el-input {
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 {
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>

@ -18,7 +18,7 @@ export default {
this.$router.push({path:"/statistics"})
}else{
//
this.$router.push({path:"/tongjifenxi"})
this.$router.push({path:"/Home"})
}
}
};

@ -93,7 +93,7 @@
>
<span>政务统一身份认证登录</span>
</el-button> -->
<el-button
<!-- <el-button
v-if="showEnterpriseLoginButton"
size="medium"
type="primary"
@ -102,7 +102,7 @@
@click.native.prevent="handleEnterpriseLogin"
>
<span>企业统一身份认证登录</span>
</el-button>
</el-button> -->
</el-form-item>
<div style="font-size: 0.88rem; color: #333">
主办单位苏州工业园区经济发展委员会

@ -112,9 +112,9 @@
<Projectgift :action="action" :xmId="projectId"></Projectgift>
</div>
<!-- 现场实况 -->
<div id="liver">
<!-- <div id="liver">
<Liver :action="action"></Liver>
</div>
</div> -->
<!-- 项目备忘录 -->
<div id="memo">
<Memo :action="action" :xmId="projectId"></Memo>

@ -106,9 +106,9 @@
<Projectgift :action="action" :xmId="projectId"></Projectgift>
</div>
<!-- 现场实况 -->
<div id="liver">
<!-- <div id="liver">
<Liver :action="action"></Liver>
</div>
</div> -->
<!-- 项目备忘录 -->
<div id="memo">
<Memo :action="action" :xmId="projectId"></Memo>

@ -669,6 +669,7 @@ export default {
return deleteBasicInformation(ids);
})
.then(() => {
this.queryParams.current = 1; //
this.getList();
this.$modal.msgSuccess("删除成功");
})

@ -299,6 +299,7 @@ export default {
return deleteBasicInformation(ids);
})
.then(() => {
this.queryParams.current = 1; //
this.getList();
this.$modal.msgSuccess("删除成功");
})

Loading…
Cancel
Save