| | |
| | | <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 } from "@/utils/auth"; |
| | | import { setToken, removeToken } from "@/utils/auth"; |
| | | |
| | | export default { |
| | | name: "SSORedirect", |
| | |
| | | return { |
| | | errorMessage: "", |
| | | loading: true, |
| | | loadingDetail: "正在处理SSO令牌...", |
| | | }; |
| | | }, |
| | | created() { |
| | | this.handleSSORedirect(); |
| | | }, |
| | | methods: { |
| | | // 匹配orgid |
| | | // 匹配orgid - 优化为对象映射 |
| | | mateOrgid(orgid) { |
| | | if (orgid == "30001002") { |
| | | localStorage.setItem("orgname", "浙江省立同德医院翠苑院区"); |
| | | localStorage.setItem("ZuHuID", "1400361376454545408"); |
| | | localStorage.setItem("deptCode", "1017"); |
| | | } else if (orgid == "30001003") { |
| | | localStorage.setItem("orgname", "浙江省立同德医院之江院区"); |
| | | localStorage.setItem("ZuHuID", "1400360867068907520"); |
| | | localStorage.setItem("deptCode", "01040201"); |
| | | } else if (orgid == "30001004") { |
| | | localStorage.setItem("orgname", "浙江省立同德医院闲林院区"); |
| | | localStorage.setItem("ZuHuID", "1429338802177000002"); |
| | | localStorage.setItem("deptCode", ""); |
| | | } else if (orgid == "30001005") { |
| | | localStorage.setItem("orgname", "浙江省立同德医院天目山路院区"); |
| | | localStorage.setItem("ZuHuID", "1429338802177000003"); |
| | | localStorage.setItem("deptCode", ""); |
| | | } else if (orgid == "30001006") { |
| | | localStorage.setItem("orgname", "浙江省立同德医院青山湖院区"); |
| | | localStorage.setItem("ZuHuID", "1429338802177000004"); |
| | | localStorage.setItem("deptCode", ""); |
| | | } else if (orgid == "30001007") { |
| | | localStorage.setItem("orgname", "测试院区"); |
| | | localStorage.setItem("ZuHuID", "1429338802177000005"); |
| | | localStorage.setItem("deptCode", ""); |
| | | 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(11); |
| | | // 从URL参数中获取token和机构信息 |
| | | let { token, orgid, orgname, ZuHuID, deptCode, redirect } = |
| | | this.$route.query; |
| | | // token = |
| | | // "eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6Ijc5MWVkODNlLWE2MWYtNDI2MS05ZDZlLTNhOTVjYTU2YjZhMiJ9.q6jrRj8fwtb3FOqqwaxIFDr824hf85DW8heCj4qWYgRE55Pn0vkmcujFsYMrz9qqo047Gl7lv3rnok8pk7SKYQ"; // 验证必要参数 |
| | | // orgid = "30001002"; |
| | | if (!token) { |
| | | throw new Error("缺少认证令牌(token)"); |
| | | } |
| | | this.mateOrgid(orgid); |
| | | 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 = "设置用户令牌..."; |
| | | |
| | | // 存储机构信息到localStorage |
| | | // 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); |
| | | this.$store.dispatch("UpdateOrgId", orgid); |
| | | } |
| | | if (orgname) localStorage.setItem("orgname", orgname); |
| | | if (ZuHuID) localStorage.setItem("ZuHuID", ZuHuID); |
| | | if (deptCode) localStorage.setItem("deptCode", deptCode); |
| | | |
| | | // 获取用户信息 |
| | | await this.$store.dispatch("GetInfo"); |
| | | |
| | | // 确定重定向路径 |
| | | let redirectPath = "/index"; |
| | | if (redirect) { |
| | | redirectPath = decodeURIComponent(redirect); |
| | | } else { |
| | | // 根据用户角色决定默认跳转页面 |
| | | const roles = this.$store.state.user.roles; |
| | | const username = this.$store.state.user.name; |
| | | |
| | | if (roles.includes("admin") || username === "admin") { |
| | | redirectPath = "/index"; |
| | | } else { |
| | | redirectPath = "/followvisit/discharge"; |
| | | if (this.$store.dispatch && typeof this.$store.dispatch === "function") { |
| | | await this.$store.dispatch("UpdateOrgId", orgid); |
| | | } |
| | | } |
| | | this.loadingDetail = "设置机构信息..."; |
| | | |
| | | // 跳转到目标页面 |
| | | this.$router.replace({ path: redirectPath }); |
| | | // 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(() => { |
| | |
| | | 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: 20px; |
| | | background: white; |
| | | border-radius: 4px; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | 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: 20px; |
| | | padding: 30px 20px; |
| | | } |
| | | |
| | | .el-icon-loading { |
| | | font-size: 40px; |
| | | font-size: 60px; |
| | | color: #409eff; |
| | | margin-bottom: 10px; |
| | | margin-bottom: 20px; |
| | | animation: spin 1.5s linear infinite; |
| | | } |
| | | |
| | | p { |
| | | @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> |