Become a sponsor

说明
前端工具函数位于 src/utils/ 目录,提供认证管理、本地存储、日期格式化、树结构操作、文件下载等通用能力。
认证与通用工具函数,位于 src/utils/auth.ts:
// 外部链接判断
export function isExternal(path: string) {
return /^(https?:|mailto:|tel:)/.test(path);
}
// 路径规范化
export function getNormalPath(path: string) {
if (path.length === 0 || !path || path == 'undefined') return path;
const newPath = path.replace('//', '/');
return newPath[newPath.length - 1] === '/' ? newPath.slice(0, -1) : newPath;
}
// 确认弹窗封装
export function confirm(msg: string, type: 'warning') {
return ElMessageBox.confirm(msg, '温馨提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: type,
});
}
// 消息提示封装
export function message(msg: string, type = 'success') {
ElMessage[type](msg);
}
// 文件流下载
export function streamFileDownload(file: any, fileName = '文件名称.zip') {
const blob = new Blob([file], { type: 'application/octet-stream;charset=UTF-8' });
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}auth.ts 中还包含树结构转换工具:
// 数组转树
export const arrayToTree = (
data: any[],
props = { id: 'id', parentId: 'pid', children: 'children' },
) => {
data = cloneDeep(data);
const { id, parentId, children } = props;
const result: any[] = [];
const map = new Map();
data.forEach((item) => {
map.set(item[id], item);
const parent = map.get(item[parentId]);
if (parent) {
parent[children] = parent[children] ?? [];
parent[children].push(item);
} else {
result.push(item);
}
});
return result;
};
// 树转数组(广度优先)
export const treeToArray = (data: any[], props = { children: 'children' }) => {
data = cloneDeep(data);
const newData = [];
const queue: any[] = [];
data.forEach((child) => queue.push(child));
while (queue.length) {
const item = queue.shift();
if (item[children]) {
item[children].forEach((child) => queue.push(child));
delete item[children];
}
newData.push(item);
}
return newData;
};
// 递归查找路径
export const findTreeByPath = (tree, path, result = []) => {
for (const node of tree) {
if (node.path === path) result.push(node);
if (node.children?.length) findTreeByPath(node.children, path, result);
}
return result;
};本地存储封装,支持过期时间和 cookie,位于 src/utils/Storage.ts:
const DEFAULT_CACHE_TIME = 7 * 24 * 60 * 60 * 1000; // 7 天
export const createStorage = ({ prefixKey = '', storage = localStorage } = {}) => {
const Storage = class {
private storage = storage;
private prefixKey?: string = prefixKey;
private getKey(key: string) {
return `${this.prefixKey}${key}`.toUpperCase(); // 自动大写
}
// 设置缓存(支持过期时间)
set(key: string, value: any, expire: number | null = DEFAULT_CACHE_TIME) {
const stringData = JSON.stringify({
value,
expire: expire !== null ? Date.now() + expire : null,
});
this.storage.setItem(this.getKey(key), stringData);
}
// 读取缓存(过期自动删除)
get(key: string, def: any = null) {
const item = this.storage.getItem(this.getKey(key));
if (item) {
try {
const data = JSON.parse(item);
const { value, expire } = data;
if (expire === null || expire >= Date.now()) return value;
this.remove(key); // 过期删除
} catch (e) { return def; }
}
return def;
}
remove(key: string) { this.storage.removeItem(this.getKey(key)); }
clear(): void { this.storage.clear(); }
};
return new Storage();
};
export const storage = createStorage();Store mutation-types 定义了存储键名:
// src/store/mutation-types.ts
export const ACCESS_TOKEN = 'ACCESS-TOKEN'; // 用户 token
export const CURRENT_USER = 'CURRENT-USER'; // 当前用户信息
export const IS_LOCKSCREEN = 'IS-LOCKSCREEN'; // 是否锁屏
export const TABS_ROUTES = 'TABS-ROUTES'; // 标签页
export const FIRST_ROUTE = 'FIRST-ROUTE'; // 菜单第一个路由日期格式化工具,基于 dayjs,位于 src/utils/dateUtil.ts:
import dayjs from 'dayjs';
const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm';
const DATE_FORMAT = 'YYYY-MM-DD ';
export function formatToDateTime(date: Date, formatStr = DATE_TIME_FORMAT): string {
return dayjs(date).format(formatStr);
}
export function formatToDate(date: Date, formatStr = DATE_FORMAT): string {
return dayjs(date).format(formatStr);
}dateUtil 也被 vite.config.ts 使用,记录构建时间戳:
// vite.config.ts
import { formatToDateTime } from './src/utils/dateUtil';
const __APP_INFO__ = {
pkg: { dependencies, devDependencies, name, version },
lastBuildTime: formatToDateTime(new Date()),
};HTTP 相关枚举定义,位于 src/enums/httpEnum.ts:
export enum ResultEnum {
SUCCESS = 0, // 业务成功
ERROR = 1, // 业务失败
TIMEOUT = 401, // 登录超时
}
export enum RequestEnum {
GET = 'GET',
POST = 'POST',
PUT = 'PUT',
DELETE = 'DELETE',
}
export enum ContentTypeEnum {
JSON = 'application/json;charset=UTF-8',
FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8',
FORM_DATA = 'multipart/form-data;charset=UTF-8',
}页面路径枚举,位于 src/enums/pageEnum.ts:
export enum PageEnum {
BASE_LOGIN = '/login',
BASE_LOGIN_NAME = 'Login',
REDIRECT = '/redirect',
BASE_HOME = '/dashboard',
BASE_HOME_REDIRECT = '/dashboard/console',
ERROR_PAGE_NAME = 'ErrorPage',
}温馨提示
Storage 工具类自动将键名转为大写(如 access-token → ACCESS-TOKEN),存储时包含过期时间,读取时自动检查是否过期。auth.ts 中的 confirm 和 message 函数是对 ElementPlus 的简封装,在业务组件中直接调用即可。
工具函数库提供了 Storage(本地存储,支持过期)、auth(认证管理、树结构操作、文件下载)、dateUtil(日期格式化)、httpEnum/pageEnum(枚举定义)等通用能力。confirm 和 message 是 ElementPlus 的简封装,arrayToTree/treeToArray 处理菜单数据转换。