方便接入upm的前端项目,快速集成相关鉴权功能。
如果你使用的是 npm 作为包管理工具,可以通过以下命令来安装 SDK:
npm i xhumanoid-upm-js
https://git.x-humanoid-cloud.com/cloud/front-project/upmauth-demo
import './assets/scss/main.scss'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import { installComponents } from 'xhumanoid-upm-js'
import { setupPermission } from './permission'
import App from './App.vue'
import router from './router'
const app = createApp(App)
//引入全部icon
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.use(createPinia())
app.use(router)
app.use(installComponents)
setupPermission().then(() => {
app.mount('#app')
})
./permission.js
import { UpmAuth } from 'xhumanoid-upm-js'
import { useGlobalStore } from "@/stores/global";
import { addRoute } from '@/router/addRoute'
export async function setupPermission() {
const upmAuth = new UpmAuth({
authType: 'cookie',
clientId: import.meta.env.VITE_APP_UPM_CLIENTID, //应用clientid
env: import.meta.env.VITE_APP_ENV === 'production' ? 'prod' : 'sit', //'prod'-生产,'sit'-sit环境
loginUrl: import.meta.env.VITE_APP_DATA_API + '/v1/login', //登录
logoutUrl: import.meta.env.VITE_APP_DATA_API + '/v1/logout', //退出登录
userInfoUrl: import.meta.env.VITE_APP_DATA_API + '/v1/userInfo', //获取用户信息
permissionUrl: import.meta.env.VITE_APP_DATA_API + '/v1/user/permissions', //获取用户权限
refreshTokenUrl: import.meta.env.VITE_APP_DATA_API + '/v1/refreshToken', //刷新token
})
let userInfo = await upmAuth.checkAuth()
window.$UpmAuth = upmAuth
if (userInfo) {
useGlobalStore().setLoginUser(userInfo) //设置登录用户信息
//动态添加路由信息
if (userInfo.menuTree) {
await addRoute(userInfo.menuTree)
}
} else {
return Promise.reject('获取用户信息失败')
}
}
// ./router/addRoute
import router from "@/router/index";
//路由信息映射
const routeInfo = {};
const pages = import.meta.glob("@/views/**/*.vue");
for (const componentPath in pages) {
let lastIndex = componentPath.lastIndexOf("/");
let name = componentPath.slice(lastIndex + 1, -4);
name = name.charAt(0).toLocaleLowerCase() + name.slice(1);
let routerPath = componentPath.slice(10, lastIndex) + "/" + name;
let routeName = routerPath.slice(1).replace("/", "-");
routeInfo[routerPath] = {
routeName,
componentPath,
};
}
//生成router树
function generateRoutes(routes) {
const newRoutes = routes.map((route) => {
let { routeName, componentPath } = routeInfo[route.path] || {};
const newRoute = {
path: route.path,
name: routeName,
component: routeName && componentPath ? pages[componentPath] : "",
meta: {
title: route.name,
},
};
if (route.children) {
newRoute.children = generateRoutes(route.children);
}
return newRoute;
});
return newRoutes;
}
export async function addRoute(menuTree) {
if (menuTree && menuTree.length > 0) {
let routes = generateRoutes(menuTree);
router.addRoute({
name: "",
path: "",
redirect:routes[0].path,
component: pages["/src/views/Laylout.vue"],
meta: {
title: "管理端",
},
children: routes,
});
}
console.log("zzp", router.getRoutes());
await router.replace(router.currentRoute.value.fullPath); //等待路由加载成功
}
window.$UpmAuth.logOut();
<template>
<el-menu :default-active="$route.path" router :collapse="isCollapse">
<menu-items :items="menuTree"></menu-items>
</el-menu>
</template>
<script setup>
import { useGlobalStore } from "@/stores/global";
const globalStore = useGlobalStore();
const isCollapse = ref(false);
const menuTree = globalStore.loginUser.menuTree;
</script>
service.interceptors.request.use(
async (config) => {
config.headers = {
...config.headers,
Authorization: window.$UpmAuth.getAuthorization(),//字段名可以跟后端确定一下
};
return config;
},
(err) => {
console.log("service.interceptors.request.use", err);
return Promise.reject(err);
}
);
service.interceptors.response.use(
(response) => {
if (response.status === 200) {
let res = response?.data;
if (res.code === 0) {
return res.data;
} else {
if (res.code === 40006) {
//尝试鉴权续期
window.$UpmAuth.refreshAuth();
}
return Promise.reject(res);
}
} else {
return Promise.reject("network error..");
}
}
);
//Menu.vue
<template>
<el-menu
:default-active="$route.path"
router
:collapse="isCollapse"
>
<menu-items :items="menuTree" :iconNames="iconNames"></menu-items>
</el-menu>
</template>
<script setup>
import { useGlobalStore } from "@/stores/global";
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
const globalStore = useGlobalStore();
const menuTree = globalStore.userInfo.menuTree;//权限菜单树
const iconNames = Object.keys(ElementPlusIconsVue)//icon name 列表
</script>