<template>
|
<div class="sso-redirect">
|
<div class="loading-container">
|
<el-alert
|
v-if="errorMessage"
|
:title="errorMessage"
|
type="error"
|
:closable="false"
|
show-icon
|
></el-alert>
|
<div v-else class="loading-content">
|
<i class="el-icon-loading"></i>
|
<p>单点登录中,请稍候...</p>
|
<p class="loading-detail">{{ loadingDetail }}</p>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
import { setToken, removeToken } from "@/utils/auth";
|
|
export default {
|
name: "SSORedirect",
|
data() {
|
return {
|
errorMessage: "",
|
loading: true,
|
loadingDetail: "正在处理SSO令牌...",
|
};
|
},
|
created() {
|
this.handleSSORedirect();
|
},
|
methods: {
|
// 匹配orgid - 优化为对象映射
|
mateOrgid(orgid) {
|
const orgMap = {
|
"30001002": {
|
orgname: "省立同德翠苑院区",
|
ZuHuID: "1400361376454545408",
|
deptCode: "1017",
|
},
|
"30001003": {
|
orgname: "省立同德之江院区",
|
ZuHuID: "1400360867068907520",
|
deptCode: "01040201",
|
},
|
"30001004": {
|
orgname: "省立同德闲林院区",
|
ZuHuID: "1429338802177000002",
|
deptCode: "",
|
},
|
"30001005": {
|
orgname: "省立同德天目山路院区",
|
ZuHuID: "1429338802177000003",
|
deptCode: "",
|
},
|
"30001006": {
|
orgname: "省立同德青山湖院区",
|
ZuHuID: "1429338802177000004",
|
deptCode: "",
|
},
|
"30001007": {
|
orgname: "测试院区",
|
ZuHuID: "1429338802177000005",
|
deptCode: "",
|
},
|
};
|
|
const orgInfo = orgMap[orgid];
|
if (orgInfo) {
|
localStorage.setItem("orgname", orgInfo.orgname);
|
localStorage.setItem("ZuHuID", orgInfo.ZuHuID);
|
localStorage.setItem("deptCode", orgInfo.deptCode);
|
return orgInfo;
|
}
|
return null;
|
},
|
|
// 清理旧系统的本地存储
|
clearOldSystemData() {
|
// 清理可能冲突的旧系统数据
|
const oldKeys = ["old-token", "old-user-info", "old-session"];
|
oldKeys.forEach((key) => {
|
localStorage.removeItem(key);
|
sessionStorage.removeItem(key);
|
});
|
|
// 清理特定前缀的存储
|
Object.keys(localStorage).forEach((key) => {
|
if (key.startsWith("old-system-") || key.startsWith("legacy-")) {
|
localStorage.removeItem(key);
|
}
|
});
|
},
|
|
// 获取默认重定向路径
|
getDefaultRedirectPath() {
|
try {
|
const roles = this.$store.state.user?.roles || [];
|
const username = this.$store.state.user?.name || "";
|
|
if (roles.includes("admin") || username === "admin") {
|
return "/index";
|
}
|
return "/followvisit/discharge";
|
} catch (error) {
|
console.warn("获取默认重定向路径失败:", error);
|
return "/followvisit/discharge";
|
}
|
},
|
|
// 验证SSO参数
|
validateSSOParams(params) {
|
const { token, orgid } = params;
|
|
if (!token) {
|
throw new Error("缺少认证令牌(token)");
|
}
|
|
if (!orgid) {
|
console.warn("SSO登录缺少orgid参数");
|
}
|
|
// 验证token格式(简单验证)
|
if (token.length < 10) {
|
throw new Error("令牌格式无效");
|
}
|
|
return true;
|
},
|
|
// 主处理函数
|
async handleSSORedirect() {
|
try {
|
console.log("SSO重定向开始处理...");
|
|
// 1. 获取URL参数
|
const params = this.$route.query;
|
console.log("SSO参数:", params);
|
|
// 2. 验证必要参数
|
this.validateSSOParams(params);
|
this.loadingDetail = "验证令牌中...";
|
|
// 3. 清理旧系统数据
|
this.clearOldSystemData();
|
|
const { token, orgid, orgname, ZuHuID, deptCode, redirect } = params;
|
|
// 4. 存储token
|
setToken(token);
|
this.$store.commit("SET_TOKEN", token);
|
this.loadingDetail = "设置用户令牌...";
|
|
// 5. 处理机构信息
|
if (orgid) {
|
// 优先使用mateOrgid映射
|
const orgInfo = this.mateOrgid(orgid);
|
if (!orgInfo) {
|
// 如果没有映射,使用传入的参数
|
if (orgname) localStorage.setItem("orgname", orgname);
|
if (ZuHuID) localStorage.setItem("ZuHuID", ZuHuID);
|
if (deptCode) localStorage.setItem("deptCode", deptCode);
|
}
|
|
localStorage.setItem("orgid", orgid);
|
if (this.$store.dispatch && typeof this.$store.dispatch === "function") {
|
await this.$store.dispatch("UpdateOrgId", orgid);
|
}
|
}
|
this.loadingDetail = "设置机构信息...";
|
|
// 6. 获取用户信息
|
if (this.$store.dispatch && typeof this.$store.dispatch === "function") {
|
await this.$store.dispatch("GetInfo");
|
}
|
this.loadingDetail = "获取用户信息...";
|
|
// 7. 处理重定向路径
|
let redirectPath = "/followvisit/discharge";
|
|
if (redirect) {
|
// 解码传入的重定向路径
|
try {
|
redirectPath = decodeURIComponent(redirect);
|
console.log("使用传入的重定向路径:", redirectPath);
|
} catch (e) {
|
console.error("解码重定向路径失败:", e);
|
redirectPath = this.getDefaultRedirectPath();
|
}
|
} else {
|
redirectPath = this.getDefaultRedirectPath();
|
}
|
|
// 8. 移除URL中的token参数(安全考虑)
|
this.$router.replace({ query: {} });
|
|
// 9. 延迟跳转,确保状态已更新
|
setTimeout(() => {
|
this.loadingDetail = "跳转到目标页面...";
|
console.log("准备跳转到:", redirectPath);
|
|
// ✅ 使用 push 而不是 replace,保留历史记录
|
this.$router.push({ path: redirectPath }).then(() => {
|
console.log("SSO登录成功,跳转完成");
|
}).catch((error) => {
|
console.error("路由跳转失败:", error);
|
// 回退到默认页面
|
this.$router.push({ path: "/followvisit/discharge" });
|
});
|
}, 500);
|
|
} catch (error) {
|
console.error("SSO登录失败:", error);
|
this.errorMessage = `单点登录失败: ${error.message || "未知错误"}`;
|
this.loading = false;
|
|
// 清理token
|
removeToken();
|
this.$store.commit("SET_TOKEN", "");
|
|
// 显示错误详情(开发环境)
|
if (process.env.NODE_ENV === "development") {
|
this.errorMessage += ` (详情: ${error.toString()})`;
|
}
|
|
// 5秒后跳转到普通登录页
|
setTimeout(() => {
|
this.$router.replace("/login");
|
}, 5000);
|
}
|
},
|
},
|
};
|
</script>
|
|
<style scoped>
|
.sso-redirect {
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
height: 100vh;
|
min-height: 500px;
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
background-color: #f5f7fa;
|
padding: 20px;
|
box-sizing: border-box;
|
}
|
|
.loading-container {
|
text-align: center;
|
padding: 40px 60px;
|
background: rgba(255, 255, 255, 0.95);
|
border-radius: 12px;
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
min-width: 400px;
|
max-width: 500px;
|
backdrop-filter: blur(10px);
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
}
|
|
.loading-content {
|
padding: 30px 20px;
|
}
|
|
.el-icon-loading {
|
font-size: 60px;
|
color: #409eff;
|
margin-bottom: 20px;
|
animation: spin 1.5s linear infinite;
|
}
|
|
@keyframes spin {
|
0% { transform: rotate(0deg); }
|
100% { transform: rotate(360deg); }
|
}
|
|
.loading-content p {
|
margin: 0;
|
color: #606266;
|
font-size: 16px;
|
line-height: 1.6;
|
}
|
|
.loading-detail {
|
margin-top: 10px !important;
|
font-size: 14px !important;
|
color: #909399 !important;
|
opacity: 0.8;
|
}
|
|
/* 响应式设计 */
|
@media (max-width: 768px) {
|
.sso-redirect {
|
padding: 10px;
|
}
|
|
.loading-container {
|
padding: 30px 20px;
|
min-width: 300px;
|
max-width: 90vw;
|
}
|
|
.el-icon-loading {
|
font-size: 50px;
|
}
|
|
.loading-content p {
|
font-size: 15px;
|
}
|
}
|
</style>
|