| | |
| | | <script setup> |
| | | import { onLaunch } from '@dcloudio/uni-app'; |
| | | import { getToken } from '@/utils/auth'; |
| | | import { useUserStore } from '@/stores/user'; |
| | | import { onLaunch } from "@dcloudio/uni-app"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import { useUserStore } from "@/stores/user"; |
| | | |
| | | // 定义页面白名单 |
| | | const pageWhiteList = [ |
| | | 'pages/login/Login', |
| | | 'pages/login/DingTalkLogin' |
| | | ]; |
| | | const pageWhiteList = ["pages/login/Login", "pages/login/DingTalkLogin"]; |
| | | const isPageInWhiteList = (currentPage) => |
| | | pageWhiteList.some((path) => currentPage.includes(path)); |
| | | |
| | | // 白名单检查 |
| | | const isPageInWhiteList = (currentPage) => { |
| | | return pageWhiteList.some(path => currentPage.includes(path)); |
| | | } |
| | | |
| | | // 全局标记 |
| | | let isProcessingSSO = false; |
| | | |
| | | onLaunch(() => { |
| | | console.log('App Launch'); |
| | | |
| | | console.log("App Launch"); |
| | | const launchOptions = uni.getLaunchOptionsSync(); |
| | | const currentPage = launchOptions.path || ''; |
| | | const currentPage = launchOptions.path || ""; |
| | | const query = launchOptions.query || {}; |
| | | console.log('启动参数:', { currentPage, query, launchOptions }); |
| | | console.log("启动参数:", { currentPage, query }); |
| | | |
| | | // ✅ 第一步:检查是否SSO链接 |
| | | if (query.userName && query.passWord) { |
| | | console.log('检测到SSO参数,处理中...'); |
| | | |
| | | // 如果已经在登录页,直接处理 |
| | | // ✅ 改为检测 code 参数 |
| | | if (query.code) { |
| | | console.log('检测到免登码(code),准备跳转登录页'); |
| | | if (currentPage.includes('login/Login')) { |
| | | console.log('当前已在登录页,等待login.vue处理SSO'); |
| | | console.log('当前已在登录页,等待login.vue处理'); |
| | | return; |
| | | } |
| | | |
| | | // 防止重复处理 |
| | | if (isProcessingSSO) { |
| | | console.log('正在处理SSO中,跳过'); |
| | | return; |
| | | } |
| | | |
| | | if (isProcessingSSO) return; |
| | | isProcessingSSO = true; |
| | | uni.__isSSOHandling = true; |
| | | |
| | | // ✅ 构建登录页URL,携带所有原始参数 |
| | | const queryParams = []; |
| | | |
| | | // 携带原始页面路径 |
| | | if (currentPage) { |
| | | queryParams.push(`redirect=${encodeURIComponent('/' + currentPage)}`); |
| | | } |
| | | |
| | | // 携带所有查询参数 |
| | | for (const key in query) { |
| | | if (query[key]) { |
| | | queryParams.push(`${key}=${encodeURIComponent(query[key])}`); |
| | | } |
| | | } |
| | | // 携带 code 参数 |
| | | queryParams.push(`code=${encodeURIComponent(query.code)}`); |
| | | // 注意:其他业务参数(如 fcid)已不在 URL 上,不需要携带 |
| | | |
| | | console.log('跳转到登录页,参数:', queryParams); |
| | | |
| | | // 延迟跳转,避免冲突 |
| | | setTimeout(() => { |
| | | uni.redirectTo({ |
| | | url: `/pages/login/Login?${queryParams.join('&')}`, |
| | | success: () => { |
| | | console.log('SSO跳转成功'); |
| | | setTimeout(() => { |
| | | uni.__isSSOHandling = false; |
| | | isProcessingSSO = false; |
| | | }, 500); |
| | | }, |
| | | fail: () => { |
| | | console.log('SSO跳转失败'); |
| | | uni.__isSSOHandling = false; |
| | | isProcessingSSO = false; |
| | | } |
| | | }); |
| | | }, 200); |
| | | |
| | | return; |
| | | } |
| | | |
| | | // 第二步:正常token检查 |
| | | // 原有 token 检查逻辑不变(但注意去掉 SSO 参数判断) |
| | | handleTokenCheck(); |
| | | }); |
| | | |
| | | // token检查函数 |
| | | const handleTokenCheck = async () => { |
| | | const userStore = useUserStore(); |
| | | const token = getToken(); |
| | | const launchOptions = uni.getLaunchOptionsSync(); |
| | | const currentPage = launchOptions.path || ''; |
| | | const currentPage = launchOptions.path || ""; |
| | | const query = launchOptions.query || {}; |
| | | |
| | | console.log('token检查:', { |
| | | hasToken: !!token, |
| | | currentPage, |
| | | query |
| | | }); |
| | | console.log("token检查:", { hasToken: !!token, currentPage }); |
| | | |
| | | // 如果有SSO参数,已在上一步处理 |
| | | if (query.userName && query.passWord) { |
| | | return; |
| | | } |
| | | |
| | | if (!token) { |
| | | if (!isPageInWhiteList(currentPage)) { |
| | | console.log('无token且不在白名单,跳转登录页'); |
| | | |
| | | // 构建跳转URL,携带当前页面信息 |
| | | let loginUrl = '/pages/login/Login'; |
| | | console.log("无token且不在白名单,跳转登录页"); |
| | | let loginUrl = "/pages/login/Login"; |
| | | if (currentPage) { |
| | | const queryParams = []; |
| | | queryParams.push(`redirect=${encodeURIComponent('/' + currentPage)}`); |
| | | |
| | | // 携带其他参数 |
| | | queryParams.push(`redirect=${encodeURIComponent("/" + currentPage)}`); |
| | | for (const key in query) { |
| | | if (query[key]) { |
| | | queryParams.push(`${key}=${encodeURIComponent(query[key])}`); |
| | | } |
| | | } |
| | | |
| | | if (queryParams.length > 0) { |
| | | loginUrl += `?${queryParams.join('&')}`; |
| | | loginUrl += `?${queryParams.join("&")}`; |
| | | } |
| | | } |
| | | |
| | | setTimeout(() => { |
| | | uni.redirectTo({ url: loginUrl }); |
| | | }, 100); |
| | |
| | | |
| | | try { |
| | | const current = await uni.$uapi.get("/getInfo"); |
| | | |
| | | if (current && current.user) { |
| | | userStore.setUserInfo(current.user); |
| | | if (current.roles) { |
| | | userStore.setroleKey(current.roles); |
| | | } |
| | | |
| | | if (current.roles) userStore.setroleKey(current.roles); |
| | | if (isPageInWhiteList(currentPage)) { |
| | | uni.switchTab({ url: '/pages/index/index' }); |
| | | uni.switchTab({ url: "/pages/index/index" }); |
| | | } |
| | | } else { |
| | | console.error('token无效'); |
| | | console.error("token无效"); |
| | | userStore.clearUser(); |
| | | if (!isPageInWhiteList(currentPage)) { |
| | | uni.redirectTo({ url: '/pages/login/Login' }); |
| | | uni.redirectTo({ url: "/pages/login/Login" }); |
| | | } |
| | | } |
| | | } catch (error) { |
| | | console.error('初始化失败:', error); |
| | | console.error("初始化失败:", error); |
| | | userStore.clearUser(); |
| | | if (!isPageInWhiteList(currentPage)) { |
| | | uni.redirectTo({ url: '/pages/login/Login' }); |
| | | uni.redirectTo({ url: "/pages/login/Login" }); |
| | | } |
| | | } |
| | | }; |
| | |
| | | |
| | | <style lang="scss"> |
| | | @import "@/uni_modules/uview-plus/index.scss"; |
| | | // 主题颜色 |
| | | $primary-color: #67AFAB; |
| | | $primary-light: rgba($primary-color, 0.1); |
| | | $primary-gradient: linear-gradient(135deg, #67AFAB, #89C4C1); |
| | | |
| | | // 文字颜色 |
| | | $primary-color: #67afab; |
| | | $primary-light: rgba($primary-color, 0.1); |
| | | $primary-gradient: linear-gradient(135deg, #67afab, #89c4c1); |
| | | $text-primary: #333333; |
| | | $text-regular: #666666; |
| | | $text-secondary: #999999; |
| | | |
| | | // 背景颜色 |
| | | $bg-color: #F5F6FA; |
| | | $card-bg: #FFFFFF; |
| | | |
| | | // 功能色 |
| | | $success: #67C23A; |
| | | $warning: #E6A23C; |
| | | $danger: #F56C6C; |
| | | $bg-color: #f5f6fa; |
| | | $card-bg: #ffffff; |
| | | $success: #67c23a; |
| | | $warning: #e6a23c; |
| | | $danger: #f56c6c; |
| | | $info: #909399; |
| | | |
| | | // 圆角 |
| | | $radius-sm: 4rpx; |
| | | $radius-md: 12rpx; |
| | | $radius-lg: 24rpx; |
| | | $radius-xl: 36rpx; |
| | | |
| | | // 阴影 |
| | | $shadow-sm: 0 2rpx 8rpx rgba(0, 0, 0, 0.05); |
| | | $shadow-md: 0 4rpx 16rpx rgba(0, 0, 0, 0.08); |
| | | $shadow-lg: 0 8rpx 24rpx rgba(0, 0, 0, 0.12); |
| | | |
| | | // 混入 |
| | | @mixin flex-center { |
| | | display: flex; |
| | | align-items: center; |
| | |
| | | overflow: hidden; |
| | | } |
| | | |
| | | // 通用样式类 |
| | | .primary-btn { |
| | | background: $primary-gradient; |
| | | color: #fff; |
| | |
| | | line-height: 80rpx; |
| | | text-align: center; |
| | | box-shadow: 0 4rpx 12rpx rgba($primary-color, 0.3); |
| | | |
| | | &[disabled] { |
| | | opacity: 0.6; |
| | | } |
| | | |
| | | &:active { |
| | | transform: scale(0.95); |
| | | } |
| | |
| | | position: relative; |
| | | padding-left: 20rpx; |
| | | margin-bottom: 30rpx; |
| | | |
| | | &::before { |
| | | content: ''; |
| | | content: ""; |
| | | position: absolute; |
| | | left: 0; |
| | | top: 50%; |
| | |
| | | font-size: 32rpx; |
| | | color: $danger; |
| | | font-weight: bold; |
| | | |
| | | &.free { |
| | | color: $success; |
| | | } |
| | | |
| | | &.original { |
| | | font-size: 24rpx; |
| | | color: $text-secondary; |
| | |
| | | border-radius: $radius-xl; |
| | | padding: 0 30rpx; |
| | | box-shadow: $shadow-md; |
| | | |
| | | .icon-search { |
| | | width: 32rpx; |
| | | height: 32rpx; |
| | | margin-right: 20rpx; |
| | | color: $primary-color; |
| | | } |
| | | |
| | | input { |
| | | flex: 1; |
| | | font-size: 28rpx; |
| | |
| | | } |
| | | } |
| | | |
| | | @import '@/static/style/iconfont.scss'; |
| | | // @import "@/static/style/iconfont.scss"; |
| | | |
| | | page { |
| | | background-color: $bg-color; |