yxuse
v2.0.34
Published
## 更新日志
Downloads
995
Readme
yxuse
更新日志
2024 4-15 (Vue2.x--> 2.0.15 Vue3.x--->3.0.21)
- 新增 icon 的自动加载功能,以及 icon 的管理
import yxIcon from "yxuse/yxIcon";
2024 4-01 (Vue2.x--> 2.0.11 Vue3.x--->3.0.18)
- 悬浮球新增语言切换的入口
- 新增翻译的模块 translate
export interface YxuseOptions { ...之前的配置 /** 系统标识,isRenderLang为true时必传 */ systemKey?: string; } translate 模块方法说明 /** * @description:初始化语言包 * @param {*} lang 语言包标识 * @param {*} systemKey 系统标识 */ initTranslate /** * @description:语言切换 * @param {*} lang 语言包标识 */ changeLang /** * @description:获取当前语言 */ getLang
2024 3-18 (Vue2.x--> 2.0.3 Vue3.x--->3.0.10)
theme
- 主题初始化 install 方法新增配置,主要有当前开发的环境,在开发环境下无 token 会进行弹窗提示,进行自动登录,生产环境登录失效自动跳转至 loginUrl 地址(已内置)
export interface YxuseOptions { /** 是否渲染悬浮球*/ isRenderToolbar?: boolean; /** 是否加载工单*/ isRenderIssue?: boolean; /** 是否加载语言切换*/ isRenderLang?: boolean; /** 登录页地址,非运管系统项目使用*/ loginUrl?: string; /** 自定义登录api,非运管系统项目使用*/ loginApiUrl?: string; /** 翻译Api地址,非运管系统项目使用*/ translateApiUrl?: string; /** 主题列表接口,非运管系统项目使用*/ themeApiUrl: string; /** 首页地址,非运管系统项目使用*/ homeUrl?: string; /** 系统默认语言*/ lang?: string; /** 当前环境*/ environment: "development" | "production"; }
- 新增判断当前色值是否在当前主题中的方法 findColorByTheme(key: string, color: string)
auth
- 新增获取系统配置的方法 getSystemConfig(key: string)
utils
- 新增判断该色值是否是深色的方法 isDarkColor(color: string)
起步
低版本适配为1.0.100
//npm
npm install yxuse@latest
//pnpm
pnpm install yxuse@latest
//最新淘宝镜像地址为 https://registry.npmmirror.com
//速度慢或者版本更新不及时 请使用npm源镜像下载
// npm set registry https://registry.npmjs.org
// //或
// pnpm set registry https://registry.npmjs.org
npm publish
权限相关
import { auth } from "yxuse/api";
数据权限
- 在综合管理-用户管理中操作栏编辑数据权限,给对应账户添加对应的星和站即可。管理员账户无需配置,默认有所有的星和站
系统权限
系统权限
- 此层级的权限决定在运管系统入口处是否显示。目前有综合管理(integrated-management)、轨道控制系统(orbit)、任务计划(traceplan)、遥控分系统(telecommand)、遥测分系统(telemetry)、站控分系统(station-control)。
- 配置步骤:
- 在综合管理系统-权限配置模块新增分系统
- 在综合管理-用户管理中操作栏(系统权限)给对应用户分配系统权限
分系统菜单权限
- 此层级的权限决定在各分系统的菜单栏是否显示。
- 配置步骤:
- 在综合管理系统-权限配置模块中各分系统下添加分系统路由
- 表单配置说明:路由名称(左侧菜单名称),路由标识(分系统名称.前端路由名称),路由类型选择页面,前端路由(前端页面路由),接口路由(可以不填)
- 在综合管理-用户管理中操作栏(系统权限)给对应用户分配当前系统权限
分系统按钮权限
此层级的权限决定在各分系统中某按钮的是否显示
配置步骤:
在综合管理系统-权限配置模块中各分系统下添加分系统路由
表单配置说明:路由名称(左侧菜单名称),路由标识(前端页面路由名称.按钮含义),路由类型选择按钮类型,前端路由(前端页面路由名称.按钮含义),接口路由(可以不填)
yxuse 内置方法
/** * @description:获取token */ getToken; /** * @description:移除token */ removeToken; /** * 获取当前用户的权限(通用权限) * @param systemName 系统名称 * @description 综合管理分系统->integrated * @description 站控分系统->station * @description 综合管理->integrated * @description 轨道分系统->orbit * @description 任务计划分系统->traceplan * @description 遥控分系统->telecommand * @description 遥测分系统->telemetry * @returns 当前分系统的用户菜单列表 userMenuList * @returns 当前分系统的用户按钮列表 userBtnList */ getUserPermissions; /** * * @param userMenuList 用户路由数据 * @param viewModules 页面文件 * @param viewConfig 页面配置项 * @returns UserRouter 用户动态路由 * @description 综合管理分系统->integrated * @description 站控分系统->station * 此方法适用于Vue3+Vite项目 */ getUserRouter;
代码参考
Vue3.0+Vite+Ts+pinia
//Vue3.0+Vite+Ts+pinia // router/index.ts router.beforeEach(async (to, from, next) => { const globalStore = GlobalStore(); NProgress.start(); // await getBaseConfig(); //权限校验 // 2.动态设置标题 const title = import.meta.env.VITE_GLOB_APP_TITLE; document.title = to.meta.title ? `${to.meta.title} - ${title}` : title; // 3.判断是访问登陆页,有 Token 就在当前页面,没有 Token 重置路由并放行到登陆页 const URL = [LOGIN_URL]; if (URL.includes(to.path.toLocaleLowerCase())) { if (globalStore.token) return next(from.fullPath); return next(); } // 4.判断访问页面是否在路由白名单地址中,如果存在直接放行 if (ROUTER_WHITE_LIST.includes(to.path)) return next(); // 5.判断是否有 Token,没有重定向到 login if (!globalStore.token) return next({ path: LOGIN_URL, replace: true }); // 6.如果没有菜单列表,或者系统列表,就重新请求菜单列表并添加动态路由 const authStore = AuthStore(); authStore.setRouteName(to.name as string); if (!authStore.authMenuList.length) { //监测是当前用户是否有权限 const isEmptyPower = await initDynamicRouter(to.path); if (!isEmptyPower) return next({ ...to, replace: true }); } next(); }); //router/modules/dynamicRouter.ts export const initDynamicRouter = async path => { const authStore = AuthStore(); const globalStore = GlobalStore(); const configStore = ConfigStore(); const baseConfig = configStore.baseConfigMapGet; if (Object.keys(baseConfig).length === 0) { await configStore.getBaseConfig(); } try { // 1.获取菜单列表 && 按钮权限(可合并到一个接口获取,根据后端不同可自行改造) await authStore.getUserRouteListApi(); //2.判断当前用户有没有系统权限 if (!authStore.authMenuListGet.length) { //用户无权限且当前路由不在系统入口页面 默认跳转至系统入口 if (path !== SYSTEM_ENTRY) { router.replace(SYSTEM_ENTRY); } else { ElNotification({ title: "无权限访问", message: "当前账号无任何系统权限,请联系系统管理员!", type: "warning", duration: 3000 }); } return true; } // 3.添加动态路由 //页面文件 const modules = import.meta.glob("@/views/**/*.vue"); //页面配置项 const viewConfig = import.meta.glob("@/views/**/config.ts", { import: "viewConfig", eager: true }); const userRouterList = auth.getUserRouter(authStore.authMenuList, modules, viewConfig); console.log(authStore.authMenuList); userRouterList.forEach(route => { router.addRoute("layout", route); }); authStore.setLayoutMenuList(userRouterList); return false; } catch (error) { // 💢 当按钮 || 菜单请求出错时,重定向到登陆页 // globalStore.setToken(""); // router.replace(LOGIN_URL); return Promise.reject(error); } };
Vue2+Vuex+Webpack+Vue
//router/index.js router.beforeEach(async (to, from, next) => { NProgress.start(); document.title = to.query.name ? `${to.query.name + "-"}` : "" + `${to.meta.title ?? ""}`; // 1.判断是访问登陆页,有 Token 就在当前页面,没有 Token 重置路由并放行到登陆页 const URL = [LOGIN_ROUTER]; const token = auth.getToken(); if (URL.includes(to.path.toLocaleLowerCase())) { if (token) return next(from.fullPath); return next(); } //2.判断是否有无token,没有重定向到 login if (!token) return next({ path: LOGIN_ROUTER, replace: true }); //3.判断用户是否有菜单列表 if (!store.getters.authMenuListGet.length) { //监测是当前用户是否有权限,并同步菜单 const isEmptyPower = await initDynamicRouter(to.path); if (!isEmptyPower) return next({ ...to, replace: true }); } else { //动态设置菜单 setNavList(to.path, permission); } return next(); }); //router/dynamicRouter.js let userStationRouter = []; /** * 初始化动态路由 */ export const initDynamicRouter = async path => { try { // 1.获取菜单列表 && 按钮权限(可合并到一个接口获取,根据后端不同可自行改造) // await store.dispatch('getUserRouteListApi'); // console.log(store.getters.authMenuListGet); const authMenuList = await fetchUserRouteList(); //2.判断当前用户有没有系统权限 if (!authMenuList.length) { handleNoPermission(); return true; } // 3.添加动态路由,生成菜单栏 userStationRouter = generateUserStationRouter(authMenuList); addRoutesToRouter(userStationRouter); addRoutesToRouter(permission); setNavList(path, permission); return false; } catch (error) { // 💢 当按钮 || 菜单请求出错时,重定向到登陆页 // globalStore.setToken(""); // router.replace(LOGIN_URL); handleRequestError(error); return Promise.reject(error); } }; //错误处理 function handleRequestError(error) { auth.removeToken(); } //无权限处理 function handleNoPermission() { Notification({ title: "无权限访问", message: "当前账号无任何系统权限,请联系系统管理员!", type: "warning", duration: 3000 }); } //动态用户菜单 async function fetchUserRouteList() { await store.dispatch("getUserRouteListApi"); return store.getters.authMenuListGet.map(item => item.routeView); } //过滤路由 function generateUserStationRouter(authMenuList) { return stationRouter .map(item => { if (item.children.length === 1 && authMenuList.includes(item.path)) { return item; } else if (item.children.length > 1) { item.children = item.children.filter(child => authMenuList.includes(child.path)); return item.children.length ? item : null; } return null; }) .filter(item => item !== null); } //动态添加路由 function addRoutesToRouter(routes) { for (let route of routes) { router.addRoute(route); } }
404 页面配置
Vue2+VueRouter3.x
//静态路由下添加 { path: '*', component: () => import('@/components/ErrorPage/404.vue'), },
Vue3+VueRouter4.x
//静态路由下添加 { path: "/:pathMatch(.*)*", component: () => import("@/components/ErrorMessage/404.vue") }
按钮级别权限处理(自定义指令)
import store from "@/store"; const auth = { inserted(el, binding) { controlShowByUserPower(el, binding); } }; function controlShowByUserPower(el, binding) { const value = binding.value; const authButtonList = store.getters.authButtonListGet; return !authButtonList.includes(value) ? el.parentNode.removeChild(el) : ""; } export default auth; //如何使用,“stationController.addStation标识需要与按钮权限标识匹配” <div v-auth="'stationController.addStation'"> </div>;
主题
使用方式
//在项目入口文件 main.js/main.ts中,在webpack5/vite项目中请使用以下方式按需导入 import { install } from "yxuse/theme"; install(); //在webpack4或其他低版本语法 import yxuse from "yxuse"; const { install } = yxuse.theme; install();
内置方法
/** * @description:注册主题下的css变量 */ install; /** * @description:修改主题 * @param themeName 主题名称 */ changeTheme; /** * @description:获取当前主题 */ getCurTheme; /** * @description:获取当前主题下的系统配置 * @param systemName 系统名称 */ getSystemThemeConfig; /** * @description:获取当前主题下的某个组/模块配置颜色 * @param groupName 名称 */ getGroupColor; /** * @description:注册当前系统私有css变量 * @param systemName 系统名称 */ installSystemTheme;
css 变量 json 配置
下方各类组件颜色变量配置,需要大家一起丰富
green: {
common: {
//公用颜色
color: {
//主题色
"main-100": "rgba(80, 165, 122, 1)",
"main-50": "rgba(80, 165, 122, 0.5)",
"main-25": "rgba(80, 165, 122, 0.25)",
"main-15": "rgba(80, 165, 122, 0.15)",
"main-5": "rgba(80, 165, 122, 0.05)",
//故障色
"error-100": "rgba(255, 152, 146, 1)",
"error-50": "rgba(255, 152, 146, 0.5)",
"error-25": "rgba(255, 152, 146, 0.25)",
"error-15": "rgba(255, 152, 146, 0.15)",
"error-5": "rgba(255, 152, 146, 0.05)",
//预警色
"warning-100": "rgba(249, 162, 33, 1)",
"warning-50": "rgba(249, 162, 33, 0.5)",
"warning-25": "rgba(249, 162, 33, 0.25)",
"warning-15": "rgba(249, 162, 33, 0.15)",
"warning-5": "rgba(249, 162, 33, 0.05)",
//信息色
"info-100": "rgba(133, 233, 183, 1)",
"info-50": "rgba(133, 233, 183, 0.5)",
"info-25": "rgba(133, 233, 183, 0.25)",
"info-15": "rgba(133, 233, 183, 0.15)",
"info-5": "rgba(133, 233, 183, 0.05)",
//中性色
"neutral-100": "rgba(85, 221, 221, 1)",
"neutral-50": "rgba(85, 221, 221, 0.5)",
"neutral-25": "rgba(85, 221, 221, 0.25)",
"neutral-15": "rgba(85, 221, 221, 0.15)",
"neutral-5": "rgba(85, 221, 221, 0.05)"
},
//背景色类
background: {
"error-gradual": "linear-gradient(90deg, #FFCECB 0%, rgba(255,235,233,0.35) 100%)",
"warning-gradual": "linear-gradient(90deg, #FFE4BC 0%, rgba(255,250,233,0.35) 100%)",
"success-gradual": "linear-gradient(90deg, #D5ECBE 0%, rgba(234,255,233,0.35) 100%)"
},
//按钮类
button: {
background: "rgba(103, 186, 145, 0.10)",
"border-color": "rgba(80, 165, 122, 1)",
"text-color": "rgba(80, 165, 122, 1)",
"active-background-color": "rgba(80, 165, 122, 1)",
"active-border-color": "rgba(154, 209, 162, 1)",
"active-text-color": "#fff"
},
checkbox: {
background: "rgba(216, 233, 219, 1)",
"icon-color": "rgba(80, 165, 122, 0)",
"border-color": "rgba(154, 209, 162, 1)",
"checked-background": "rgba(216, 233, 219, 1)",
"checked-icon-color": "rgba(80, 165, 122, 1)",
"checked-border-color": "rgba(154, 209, 162, 1)"
},
//input
input: {
background: "rgba(237, 246, 239, 1)",
"border-color": "rgba(80, 165, 122, 1)",
color: "rgba(29, 75, 52, 1)",
"placeholder-color": "rgba(80, 165, 122, 1)",
"hover-background": "rgba(237, 246, 239, 0.30)",
"hover-border-color": "rgba(80, 165, 122, 1)",
"hover-color": "rgba(80, 165, 122, 1)",
"active-background": "rgba(237, 246, 239, 0.30)",
"active-border-color": "rgba(80, 165, 122, 1)",
"active-color": "rgba(80, 165, 122, 1)",
"disabled-background": "rgba(237, 246, 239, 1)",
"disabled-border-color": "rgba(237, 246, 239, 1)",
"disabled-color": "rgba(83, 83, 83, 1)"
},
// select
select: {
"dropdown-background": "rgba(237, 246, 239, 1)",
"dropdown-border-color": "rgba(80, 165, 122, 1)",
"dropdown-item-color": "rgba(80, 165, 122, 1)",
"dropdown-item-hover-background": "rgba(178, 220, 198, 1)",
"dropdown-item-hover-color": "rgba(29, 75, 52, 1)",
"dropdown-item-selected-background": "rgba(178, 220, 198, 1)",
"dropdown-item-selected-color": "rgba(29, 75, 52, 1)"
},
//文字颜色
text: {
main: "#50A57A",
deep: "#1D4B34",
light: "rgba(80, 165, 122, 0.50)",
paler: "#637B6B",
warning: "#F8B85A"
},
tree:{},
//布局类
layout: {},
//表格类
table: {},
//曲线类
chart: {},
//提示类
message: {}
},
//各系统个性化配置
cloud: {},//运管系统
"station-control-center": {}, //站控
"traceplan-client":{} //任务计划
...
},