mirror of
				https://gitee.com/hhyykk/ipms-sjy-ui.git
				synced 2025-10-30 09:48:44 +08:00 
			
		
		
		
	完善SSO单点登录
This commit is contained in:
		| @@ -76,7 +76,14 @@ export const reqCheckApi = (data) => { | ||||
| } | ||||
|  | ||||
| // ========== OAUTH 2.0 相关 ========== | ||||
|  | ||||
| export type scopesType = string[] | ||||
| export interface paramsType { | ||||
|   responseType: string | ||||
|   clientId: string | ||||
|   redirectUri: string | ||||
|   state: string | ||||
|   scopes: scopesType | ||||
| } | ||||
| export const getAuthorize = (clientId) => { | ||||
|   return request.get({ url: '/system/oauth2/authorize?clientId=' + clientId }) | ||||
| } | ||||
| @@ -87,8 +94,8 @@ export function authorize( | ||||
|   redirectUri: string, | ||||
|   state: string, | ||||
|   autoApprove: boolean, | ||||
|   checkedScopes: any, | ||||
|   uncheckedScopes: any | ||||
|   checkedScopes: scopesType, | ||||
|   uncheckedScopes: scopesType | ||||
| ) { | ||||
|   // 构建 scopes | ||||
|   const scopes = {} | ||||
|   | ||||
| @@ -9,19 +9,19 @@ | ||||
|       > | ||||
|         <!-- 左上角的 logo + 系统标题 --> | ||||
|         <div class="flex items-center relative text-white"> | ||||
|           <img src="@/assets/imgs/logo.png" alt="" class="w-48px h-48px mr-10px" /> | ||||
|           <img alt="" class="w-48px h-48px mr-10px" src="@/assets/imgs/logo.png" /> | ||||
|           <span class="text-20px font-bold">{{ underlineToHump(appStore.getTitle) }}</span> | ||||
|         </div> | ||||
|         <!-- 左边的背景图 + 欢迎语 --> | ||||
|         <div class="flex justify-center items-center h-[calc(100%-60px)]"> | ||||
|           <TransitionGroup | ||||
|             appear | ||||
|             tag="div" | ||||
|             enter-active-class="animate__animated animate__bounceInLeft" | ||||
|             tag="div" | ||||
|           > | ||||
|             <img src="@/assets/svgs/login-box-bg.svg" key="1" alt="" class="w-350px" /> | ||||
|             <div class="text-3xl text-white" key="2">{{ t('login.welcome') }}</div> | ||||
|             <div class="mt-5 font-normal text-white text-14px" key="3"> | ||||
|             <img key="1" alt="" class="w-350px" src="@/assets/svgs/login-box-bg.svg" /> | ||||
|             <div key="2" class="text-3xl text-white">{{ t('login.welcome') }}</div> | ||||
|             <div key="3" class="mt-5 font-normal text-white text-14px"> | ||||
|               {{ t('login.message') }} | ||||
|             </div> | ||||
|           </TransitionGroup> | ||||
| @@ -31,7 +31,7 @@ | ||||
|         <!-- 右上角的主题、语言选择 --> | ||||
|         <div class="flex justify-between items-center text-white @2xl:justify-end @xl:justify-end"> | ||||
|           <div class="flex items-center @2xl:hidden @xl:hidden"> | ||||
|             <img src="@/assets/imgs/logo.png" alt="" class="w-48px h-48px mr-10px" /> | ||||
|             <img alt="" class="w-48px h-48px mr-10px" src="@/assets/imgs/logo.png" /> | ||||
|             <span class="text-20px font-bold">{{ underlineToHump(appStore.getTitle) }}</span> | ||||
|           </div> | ||||
|           <div class="flex justify-end items-center space-x-10px"> | ||||
| @@ -52,18 +52,15 @@ | ||||
|             <QrCodeForm class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" /> | ||||
|             <!-- 注册 --> | ||||
|             <RegisterForm class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" /> | ||||
|             <!-- 三方登录 v-if触发组件初始化 --> | ||||
|             <SSOLoginVue | ||||
|               v-if="isSSO" | ||||
|               class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" | ||||
|             /> | ||||
|             <!-- 三方登录 --> | ||||
|             <SSOLoginVue class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" /> | ||||
|           </div> | ||||
|         </Transition> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| <script setup lang="ts"> | ||||
| <script lang="ts" setup> | ||||
| import { underlineToHump } from '@/utils' | ||||
|  | ||||
| import { useDesign } from '@/hooks/web/useDesign' | ||||
| @@ -72,23 +69,11 @@ import { ThemeSwitch } from '@/layout/components/ThemeSwitch' | ||||
| import { LocaleDropdown } from '@/layout/components/LocaleDropdown' | ||||
|  | ||||
| import { LoginForm, MobileForm, QrCodeForm, RegisterForm, SSOLoginVue } from './components' | ||||
| import { RouteLocationNormalizedLoaded } from 'vue-router' | ||||
|  | ||||
| const { t } = useI18n() | ||||
| const appStore = useAppStore() | ||||
| const { getPrefixCls } = useDesign() | ||||
| const prefixCls = getPrefixCls('login') | ||||
| // =======SSO====== | ||||
| const isSSO = ref(false) | ||||
| const router = useRouter() | ||||
| // 监听当前路由 | ||||
| watch( | ||||
|   () => router.currentRoute.value, | ||||
|   (route: RouteLocationNormalizedLoaded) => { | ||||
|     if (route.name === 'SSOLogin') isSSO.value = true | ||||
|   }, | ||||
|   { immediate: true } | ||||
| ) | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   | ||||
| @@ -279,7 +279,6 @@ const doSocialLogin = async (type: number) => { | ||||
| watch( | ||||
|   () => currentRoute.value, | ||||
|   (route: RouteLocationNormalizedLoaded) => { | ||||
|     if (route.name === 'SSOLogin') setLoginState(LoginStateEnum.SSO) | ||||
|     redirect.value = route?.query?.redirect as string | ||||
|   }, | ||||
|   { | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| <template> | ||||
|   <!-- 表单 --> | ||||
|   <div class="form-cont"> | ||||
|   <div v-show="getShow" class="form-cont"> | ||||
|     <!--    <LoginFormTitle style="width: 100%" />--> | ||||
|     <el-tabs class="form" style="float: none" value="uname"> | ||||
|       <el-tab-pane :label="'三方授权(' + client.name + ')'" name="uname" /> | ||||
|     </el-tabs> | ||||
| @@ -12,8 +13,8 @@ | ||||
|           <el-checkbox-group v-model="loginForm.scopes"> | ||||
|             <el-checkbox | ||||
|               v-for="scope in params.scopes" | ||||
|               :label="scope" | ||||
|               :key="scope" | ||||
|               :label="scope" | ||||
|               style="display: block; margin-bottom: -10px" | ||||
|               >{{ formatScope(scope) }} | ||||
|             </el-checkbox> | ||||
| @@ -24,8 +25,8 @@ | ||||
|           <el-button | ||||
|             :loading="loading" | ||||
|             size="small" | ||||
|             type="primary" | ||||
|             style="width: 60%" | ||||
|             type="primary" | ||||
|             @click.prevent="handleAuthorize(true)" | ||||
|           > | ||||
|             <span v-if="!loading">同意授权</span> | ||||
| @@ -40,19 +41,15 @@ | ||||
|   </div> | ||||
| </template> | ||||
| <script lang="ts" name="SSOLogin" setup> | ||||
| import { authorize, getAuthorize } from '@/api/login' | ||||
| // import LoginFormTitle from './LoginFormTitle.vue' // TODO 艿艿你看看要不要这个表头 | ||||
| import { authorize, getAuthorize, paramsType, scopesType } from '@/api/login' | ||||
| import { LoginStateEnum, useLoginState } from './useLogin' | ||||
| import type { RouteLocationNormalizedLoaded } from 'vue-router' | ||||
|  | ||||
| const { t } = useI18n() | ||||
| const ssoForm = ref() // 表单Ref | ||||
|  | ||||
| type scopesType = string[] | ||||
| interface paramsType { | ||||
|   responseType: string | ||||
|   clientId: string | ||||
|   redirectUri: string | ||||
|   state: string | ||||
|   scopes: scopesType | ||||
| } | ||||
| const { getLoginState, setLoginState } = useLoginState() | ||||
| const getShow = computed(() => unref(getLoginState) === LoginStateEnum.SSO) | ||||
| const loginForm = reactive<{ scopes: scopesType }>({ | ||||
|   scopes: [] // 已选中的 scope 数组 | ||||
| }) | ||||
| @@ -116,6 +113,7 @@ const doAuthorize = (autoApprove, checkedScopes, uncheckedScopes) => { | ||||
| const formatScope = (scope) => { | ||||
|   // 格式化 scope 授权范围,方便用户理解。 | ||||
|   // 这里仅仅是一个 demo,可以考虑录入到字典数据中,例如说字典类型 "system_oauth2_scope",它的每个 scope 都是一条字典数据。 | ||||
|   // TODO 这个之做了中文部分 | ||||
|   return t(`login.sso.${scope}`) | ||||
| } | ||||
| const route = useRoute() | ||||
| @@ -146,7 +144,6 @@ const init = () => { | ||||
|  | ||||
|   // 获取授权页的基本信息 | ||||
|   getAuthorize(params.clientId).then((res) => { | ||||
|     console.log(res) | ||||
|     client.value = res.client | ||||
|     // 解析 scope | ||||
|     let scopes | ||||
| @@ -173,5 +170,18 @@ const init = () => { | ||||
|     } | ||||
|   }) | ||||
| } | ||||
| // =======SSO====== | ||||
| const { currentRoute } = useRouter() | ||||
| // 监听当前路由 | ||||
| watch( | ||||
|   () => currentRoute.value, | ||||
|   (route: RouteLocationNormalizedLoaded) => { | ||||
|     if (route.name === 'SSOLogin') { | ||||
|       setLoginState(LoginStateEnum.SSO) | ||||
|       init() | ||||
|     } | ||||
|   }, | ||||
|   { immediate: true } | ||||
| ) | ||||
| init() | ||||
| </script> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 puhui999
					puhui999