ruoyi-vue-pro 的已经集成了数据大屏模块go-view,并且用vue开发了前端,可以进行拖来拽就能实现一个精美的数据大屏应用,然而点击【报表管理->大屏设计】你却发现需要输入账号密码登陆,这多少有点遗憾。

ruoyi-vue-pro已经支持应用注册并进行oauth2的授权功能,然而最后一公里我们必须自己去走。
1、在【三方授权->应用管理】中注册数据大屏应用report

2、改造yudao-ui-go-view-master项目支持断点登陆
A)新增callback组件。
新增页面src/views/sso/callback.vue,内容如下:
javascript
<template>
<!-- 登录 -->
<div class="go-login-box">
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted } from 'vue'
import { Router, useRoute } from 'vue-router';
import { ssoLoginCallbackApi } from '@/api/path'
import { useSystemStore } from '@/store/modules/systemStore/systemStore'
import { SystemStoreUserInfoEnum, SystemStoreEnum } from '@/store/modules/systemStore/systemStore.d'
import { StorageEnum } from '@/enums/storageEnum';
import { PageEnum, PreviewEnum } from '@/enums/pageEnum'
import { routerTurnByName } from '@/utils'
import {getTenantIdByNameApi, getUserInfoApi, loginApi} from '@/api/path'
const systemStore = useSystemStore()
const t = window['$t']
onMounted(async () => {
const route = useRoute();
const code = route.query.code;
if(!code) {
return;
}
var loginRes = await ssoLoginCallbackApi(code.toString());
if(loginRes && loginRes.data) {
// ① Token 信息(先存储下,保证可以加载个人信息)
const tokenValue = loginRes.data.access_token
const tokenName = 'Authorization'
systemStore.setItem(SystemStoreEnum.TENANT_INFO, {
tenantId: 1
})
systemStore.setItem(SystemStoreEnum.USER_INFO, {
[SystemStoreUserInfoEnum.USER_TOKEN]: tokenValue,
[SystemStoreUserInfoEnum.TOKEN_NAME]: tokenName
})
// 个人信息
const profileRes = await getUserInfoApi();
const id = profileRes?.data?.id;
const username = profileRes?.data?.username;
const nickname = profileRes?.data?.nickname;
if(id && username && nickname){
// 存储到 pinia
systemStore.setItem(SystemStoreEnum.USER_INFO, {
[SystemStoreUserInfoEnum.USER_TOKEN]: tokenValue,
[SystemStoreUserInfoEnum.TOKEN_NAME]: tokenName,
[SystemStoreUserInfoEnum.USER_ID]: id,
[SystemStoreUserInfoEnum.USER_NAME]: username,
[SystemStoreUserInfoEnum.NICK_NAME]: nickname,
})
window['$message'].success(t('login.login_success'))
var sso_url = localStorage.getItem(StorageEnum.GO_SSO_URL);
console.log("sso_url:"+sso_url)
if(sso_url) {
localStorage.removeItem(StorageEnum.GO_SSO_URL);
window.location.href = sso_url;
return;
}
routerTurnByName(sso_url || PageEnum.BASE_HOME_NAME, true)
return;
}
window['$message'].error('登陆失败:'+profileRes.msg)
routerTurnByName(PageEnum.ERROR_PAGE_NAME_403, true)
} else {
window['$message'].success(loginRes.msg);
window['$message'].error('登陆失败:'+loginRes.msg)
routerTurnByName(PageEnum.BASE_LOGIN_NAME, true)
}
})
</script>
B)新增callback路由
在src\router\base.ts中找到LoginRoute,在后面新增代码:
javascript
export const SsoCallbackRoute: RouteRecordRaw = {
path: PageEnum.SSO_CALL_BACK,
name: PageEnum.SSO_CALL_BACK_NAME,
component: () => import('@/views/sso/callback.vue'),
meta: {
title: '单点登录',
},
};
在src\router\index.ts文件中导入

C)新增单点登陆api。
我这里数据大屏的是内网,而且后端使用的是ruoyi-vue-pro,所有appKey, appSecret都是写死在js中的,后期根据需要进行改造配置到后端application.yaml中。

在src\api\path\system.api.ts中,找到logoutApi,在其后新增单点登陆api如下:
javascript
// * SSO登录
// 可以改写成,你的 clientId
const clientId = 'report';
export const ssoLogin = () => {
const redirectUri = encodeURIComponent('http://localhost:3000/callback'); // 注意,需要使用 encodeURIComponent 编码地址
const responseType = 'code'; // 1)授权码模式,对应 code;2)简化模式,对应 token
window.location.href = 'https://192.168.1.222:80/sso?client_id=' + clientId
+ '&redirect_uri=' + redirectUri
+ '&response_type=' + responseType;
}
// * SSO登录
export const ssoLoginCallbackApi = async (code: String) => {
try {
const redirectUri = "http://localhost:3000/callback";
const url = "https://192.168.1.222:80/admin-api/system/oauth2/token?grant_type=authorization_code&code="+ code+"&redirect_uri="+redirectUri;
const params = { }
const headers = {
"Content-Type": ContentTypeEnum.JSON,
"tenant-id": "1",
"Authorization": "Basic " + encode(new TextEncoder().encode(clientId+":datav123"))
};
const config = {
baseURL:'',
headers: headers
};
var res = await axios.post(url, params, config)
console.log(res)
return res.data
} catch (err) {
httpErrorHandle()
}
}
// 单点登陆callback中调用,查询用户个人信息
export const getUserInfoApi = async () => {
try {
const res = await http(RequestHttpEnum.GET)<ProfileVO>(`${ModuleTypeEnum.SYSTEM}/oauth2/user/get`)
return res
} catch (err) {
httpErrorHandle()
}
}
D) 在路由守卫中拦截sso
在src\router\router-guards.ts文件中判断白名单前,新增代码如下:
javascript
if(to && to.query && to.query.sso == 'true'){
localStorage.setItem(StorageEnum.GO_SSO_URL, window.location.href)
// @ts-ignore
if (!routerAllowList.includes(to.name) && !loginCheck()) {
ssoLogin();
return;
}
}
E)处理后端返回未认证(状态码为401)
在src\api\axios.ts中新增代码,如果sso访问但未登陆成功或者token超时则发起单点登陆,代码如下:

3、改造yudao-vue-pro中的【报表管理->大屏设计】中的页面

- 只需要在url上加一个参数sso=true就行了
- 只需要在url上加一个参数sso=true就行了
- 只需要在url上加一个参数sso=true就行了
4、验证访问数据大屏
A)验证单点登录
重新启动yudao-vue-pro,yudao-ui-go-view,或刷新【报表管理->大屏设计】,将会出现授权请求页面如下:

这个页面是yudao-vue-pro中的src\views\sso.vue,这里我只是改了下样式,这个页面应该不需要改动。同意授权后页面会自动跳转到数据大屏的首页,如下图:

- 授权一次以后就可以愉快的访问了
- 授权一次以后就可以愉快的访问了
- 授权一次以后就可以愉快的访问了
B)验证在yudao-vue-pro中配置菜单直接访问数据看板
