123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476 |
- // +---------------------------------------------------------------------
- // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
- // +---------------------------------------------------------------------
- // | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
- // +---------------------------------------------------------------------
- // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
- // +---------------------------------------------------------------------
- // | Author: CRMEB Team <admin@crmeb.com>
- // +---------------------------------------------------------------------
- import Cookies from 'js-cookie';
- // cookie保存的天数
- import config from '@/config';
- import { forEach, hasOneOf, objEqual } from '@/libs/tools';
- import { cloneDeep } from 'lodash';
- const { title, useI18n } = config;
- import { Local } from '@/utils/storage.js';
- // 设置setCookies;
- // setToken
- export const setCookies = (key, val, cookieExpires) => {
- Cookies.set(key, val, { expires: cookieExpires || 1 });
- };
- // 获取getCookies;
- // getToken
- export const getCookies = (key) => {
- return Cookies.get(key);
- };
- export const removeCookies = (key) => {
- return Cookies.remove(key);
- };
- export const hasChild = (item) => {
- return item.children && item.children.length !== 0;
- };
- const showThisMenuEle = (item, access) => {
- if (item.meta && item.meta.access && item.meta.access.length) {
- if (hasOneOf(item.meta.access, access)) return true;
- else return false;
- } else return true;
- };
- /**
- * @param {Array} list 通过路由列表得到菜单列表
- * @returns {Array}
- */
- export const getMenuByRouter = (list, access) => {
- let res = [];
- forEach(list, (item) => {
- if (!item.meta || (item.meta && !item.meta.hideInMenu)) {
- let obj = {
- icon: (item.meta && item.meta.icon) || '',
- name: item.name,
- meta: item.meta,
- };
- if ((hasChild(item) || (item.meta && item.meta.showAlways)) && showThisMenuEle(item, access)) {
- obj.children = getMenuByRouter(item.children, access);
- }
- if (item.meta && item.meta.href) obj.href = item.meta.href;
- if (showThisMenuEle(item, access)) res.push(obj);
- }
- });
- return res;
- };
- /**
- * @param {Array} routeMetched 当前路由metched
- * @returns {Array}
- */
- export const getBreadCrumbList = (route, homeRoute) => {
- let homeItem = { ...homeRoute, icon: homeRoute.meta?.icon };
- let routeMetched = route.matched;
- if (routeMetched.some((item) => item.name === homeRoute.name)) return [homeItem];
- let res = routeMetched
- .filter((item) => {
- return item.meta === undefined || !item.meta.hideInBread;
- })
- .map((item) => {
- let meta = { ...item.meta };
- if (meta.title && typeof meta.title === 'function') {
- meta.__titleIsFunction__ = true;
- meta.title = meta.title(route);
- }
- let obj = {
- icon: (item.meta && item.meta.icon) || '',
- name: item.name,
- meta: meta,
- };
- return obj;
- });
- res = res.filter((item) => {
- return !item.meta.hideInMenu;
- });
- return [{ ...homeItem, to: homeRoute.path }, ...res];
- };
- export const getRouteTitleHandled = (route) => {
- let router = { ...route };
- let meta = { ...route.meta };
- let title = '';
- if (meta.title) {
- if (typeof meta.title === 'function') {
- meta.__titleIsFunction__ = true;
- title = meta.title(router);
- } else title = meta.title;
- }
- meta.title = title;
- router.meta = meta;
- return router;
- };
- export const showTitle = (item, vm) => {
- let { title, __titleIsFunction__ } = item.meta;
- if (!title) return;
- if (useI18n) {
- if (title.includes('{{') && title.includes('}}') && useI18n)
- title = title.replace(/({{[\s\S]+?}})/, (m, str) => str.replace(/{{([\s\S]*)}}/, (m, _) => vm.$t(_.trim())));
- else if (__titleIsFunction__) title = item.meta.title;
- else title = vm.$t(item.name);
- } else title = (item.meta && item.meta.title) || item.name;
- return title;
- };
- /**
- * @description 本地存储和获取标签导航列表
- */
- export const setTagNavListInLocalstorage = (list) => {
- Local.set('tagNaveListJavaPlat', JSON.stringify(list));
- };
- /**
- * @returns {Array} 其中的每个元素只包含路由原信息中的name, path, meta三项
- */
- export const getTagNavListFromLocalstorage = () => {
- const list = Local.get('tagNaveListJavaPlat');
- return list ? JSON.parse(list) : [];
- };
- /**
- * @param {Array} routers 路由列表数组
- * @description 用于找到路由列表中name为home的对象
- */
- export const getHomeRoute = (routers, homeName = 'home') => {
- let i = -1;
- let len = routers.length;
- let homeRoute = {};
- while (++i < len) {
- let item = routers[i];
- if (item.children && item.children.length) {
- let res = getHomeRoute(item.children, homeName);
- if (res.name) return res;
- } else {
- if (item.name === homeName) homeRoute = item;
- }
- }
- return homeRoute;
- };
- /**
- * @param {*} list 现有标签导航列表
- * @param {*} newRoute 新添加的路由原信息对象
- * @description 如果该newRoute已经存在则不再添加
- */
- export const getNewTagList = (list, newRoute) => {
- const { name, path, meta } = newRoute;
- let newList = [...list];
- if (newList.findIndex((item) => item.path === path) >= 0) return newList;
- else newList.push({ name, path, meta });
- return newList;
- };
- /**
- * @param {*} access 用户权限数组,如 ['super_admin', 'admin']
- * @param {*} route 路由列表
- */
- const hasAccess = (access, route) => {
- if (route.meta && route.meta.access) return hasOneOf(access, route.meta.access);
- else return true;
- };
- /**
- * 权鉴
- * @param {*} name 即将跳转的路由name
- * @param {*} access 用户权限数组
- * @param {*} routes 路由列表
- * @description 用户是否可跳转到该页
- */
- export const canTurnTo = (name, access, routes) => {
- const routePermissionJudge = (list) => {
- return list.some((item) => {
- if (item.children && item.children.length) {
- return routePermissionJudge(item.children);
- } else if (item.name === name) {
- return hasAccess(access, item);
- }
- });
- };
- return routePermissionJudge(routes);
- };
- /**
- * @param {String} url
- * @description 从URL中解析参数
- */
- export const getParams = (url) => {
- const keyValueArr = url.split('?')[1].split('&');
- let paramObj = {};
- keyValueArr.forEach((item) => {
- const keyValue = item.split('=');
- paramObj[keyValue[0]] = keyValue[1];
- });
- return paramObj;
- };
- /**
- * @param {Array} list 标签列表
- * @param {String} name 当前关闭的标签的name
- */
- export const getNextRoute = (list, route) => {
- let res = {};
- if (list.length === 2) {
- res = getHomeRoute(list);
- } else {
- const index = list.findIndex((item) => routeEqual(item, route));
- if (index === list.length - 1) res = list[list.length - 2];
- else res = list[index + 1];
- }
- return res;
- };
- /**
- * @param {Number} times 回调函数需要执行的次数
- * @param {Function} callback 回调函数
- */
- export const doCustomTimes = (times, callback) => {
- let i = -1;
- while (++i < times) {
- callback(i);
- }
- };
- /**
- * @param {Object} file 从上传组件得到的文件对象
- * @returns {Promise} resolve参数是解析后的二维数组
- * @description 从Csv文件中解析出表格,解析成二维数组
- */
- export const getArrayFromFile = (file) => {
- let nameSplit = file.name.split('.');
- let format = nameSplit[nameSplit.length - 1];
- return new Promise((resolve, reject) => {
- let reader = new FileReader();
- reader.readAsText(file); // 以文本格式读取
- let arr = [];
- reader.onload = function (evt) {
- let data = evt.target.result; // 读到的数据
- let pasteData = data.trim();
- arr = pasteData
- .split(/[\n\u0085\u2028\u2029]|\r\n?/g)
- .map((row) => {
- return row.split('\t');
- })
- .map((item) => {
- return item[0].split(',');
- });
- if (format === 'csv') resolve(arr);
- else reject(new Error('[Format Error]:你上传的不是Csv文件'));
- };
- });
- };
- /**
- * @param {Array} array 表格数据二维数组
- * @returns {Object} { columns, tableData }
- * @description 从二维数组中获取表头和表格数据,将第一行作为表头,用于在表格中展示数据
- */
- export const getTableDataFromArray = (array) => {
- let columns = [];
- let tableData = [];
- if (array.length > 1) {
- let titles = array.shift();
- columns = titles.map((item) => {
- return {
- title: item,
- key: item,
- };
- });
- tableData = array.map((item) => {
- let res = {};
- item.forEach((col, i) => {
- res[titles[i]] = col;
- });
- return res;
- });
- }
- return {
- columns,
- tableData,
- };
- };
- export const findNodeUpper = (ele, tag) => {
- if (ele.parentNode) {
- if (ele.parentNode.tagName === tag.toUpperCase()) {
- return ele.parentNode;
- } else {
- return findNodeUpper(ele.parentNode, tag);
- }
- }
- };
- export const findNodeUpperByClasses = (ele, classes) => {
- let parentNode = ele.parentNode;
- if (parentNode) {
- let classList = parentNode.classList;
- if (classList && classes.every((className) => classList.contains(className))) {
- return parentNode;
- } else {
- return findNodeUpperByClasses(parentNode, classes);
- }
- }
- };
- export const findNodeDownward = (ele, tag) => {
- const tagName = tag.toUpperCase();
- if (ele.childNodes.length) {
- let i = -1;
- let len = ele.childNodes.length;
- while (++i < len) {
- let child = ele.childNodes[i];
- if (child.tagName === tagName) return child;
- else return findNodeDownward(child, tag);
- }
- }
- };
- export const showByAccess = (access, canViewAccess) => {
- return hasOneOf(canViewAccess, access);
- };
- /**
- * @description 根据name/params/query判断两个路由对象是否相等
- * @param {*} route1 路由对象
- * @param {*} route2 路由对象
- */
- export const routeEqual = (route1, route2) => {
- const params1 = route1.params || {};
- const params2 = route2.params || {};
- const query1 = route1.query || {};
- const query2 = route2.query || {};
- return route1.name === route2.name && objEqual(params1, params2) && objEqual(query1, query2);
- };
- /**
- * 判断打开的标签列表里是否已存在这个新添加的路由对象
- */
- export const routeHasExist = (tagNavList, routeItem) => {
- let len = tagNavList.length;
- let res = false;
- doCustomTimes(len, (index) => {
- if (routeEqual(tagNavList[index], routeItem)) res = true;
- });
- return res;
- };
- export const localSave = (key, value) => {
- localStorage.setItem(key, value);
- };
- export const localRead = (key) => {
- return localStorage.getItem(key) || '';
- };
- // scrollTop animation
- export const scrollTop = (el, from = 0, to, duration = 500, endCallback) => {
- if (!window.requestAnimationFrame) {
- window.requestAnimationFrame =
- window.webkitRequestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- window.msRequestAnimationFrame ||
- function (callback) {
- return window.setTimeout(callback, 1000 / 60);
- };
- }
- const difference = Math.abs(from - to);
- const step = Math.ceil((difference / duration) * 50);
- const scroll = (start, end, step) => {
- if (start === end) {
- endCallback && endCallback();
- return;
- }
- let d = start + step > end ? end : start + step;
- if (start > end) {
- d = start - step < end ? end : start - step;
- }
- if (el === window) {
- window.scrollTo(d, d);
- } else {
- el.scrollTop = d;
- }
- window.requestAnimationFrame(() => scroll(d, end, step));
- };
- scroll(from, to, step);
- };
- /**
- * @description 根据当前跳转的路由设置显示在浏览器标签的title
- * @param {Object} routeItem 路由对象
- * @param {Object} vm Vue实例
- */
- export const setTitle = (routeItem, vm) => {
- let winTitle = localStorage.getItem('ADMIN_TITLE') || title;
- const handledRoute = getRouteTitleHandled(routeItem);
- const pageTitle = showTitle(handledRoute, vm);
- const resTitle = pageTitle ? `${winTitle} - ${pageTitle}` : winTitle;
- window.document.title = resTitle;
- };
- export const R = (menuList, newOpenMenus) => {
- menuList.forEach((item) => {
- let newMenu = {};
- for (let i in item) {
- if (i !== 'children') newMenu[i] = cloneDeep(item[i]);
- }
- newOpenMenus.push(newMenu);
- item.children && R(item.children, newOpenMenus);
- });
- return newOpenMenus;
- };
- export function getMenuopen(to, menuList) {
- const allMenus = [];
- menuList.forEach((menu) => {
- const menus = transMenu(menu, []);
- allMenus.push({
- path: menu.path,
- openNames: [],
- });
- menus.forEach((item) => allMenus.push(item));
- });
- const currentMenu = allMenus.find((item) => item.path === to.path);
- return currentMenu ? currentMenu.openNames : [];
- }
- function transMenu(menu, openNames) {
- if (menu.children && menu.children.length) {
- const itemOpenNames = openNames.concat([menu.path]);
- return menu.children.reduce((all, item) => {
- all.push({
- path: item.path,
- openNames: itemOpenNames,
- });
- const foundChildren = transMenu(item, itemOpenNames);
- return all.concat(foundChildren);
- }, []);
- } else {
- return [menu].map((item) => {
- return {
- path: item.path,
- openNames: openNames,
- };
- });
- }
- }
- export function wss(wsSocketUrl) {
- let ishttps = document.location.protocol == 'https:';
- if (ishttps) {
- return wsSocketUrl.replace('ws:', 'wss:');
- } else {
- return wsSocketUrl.replace('wss:', 'ws:');
- }
- }
|