diff --git a/src/api/login/index.ts b/src/api/login/index.ts index bc60e8c9..07d08370 100644 --- a/src/api/login/index.ts +++ b/src/api/login/index.ts @@ -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 = {} diff --git a/src/views/Login/Login.vue b/src/views/Login/Login.vue index 4bd9ff90..a0186ab7 100644 --- a/src/views/Login/Login.vue +++ b/src/views/Login/Login.vue @@ -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> diff --git a/src/views/Login/components/LoginForm.vue b/src/views/Login/components/LoginForm.vue index 158cec39..4cc37636 100644 --- a/src/views/Login/components/LoginForm.vue +++ b/src/views/Login/components/LoginForm.vue @@ -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 }, { diff --git a/src/views/Login/components/SSOLogin.vue b/src/views/Login/components/SSOLogin.vue index 56e81fa9..8efd57f9 100644 --- a/src/views/Login/components/SSOLogin.vue +++ b/src/views/Login/components/SSOLogin.vue @@ -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>