WholeProcessPlatform/frontend/src/utils/index.ts

180 lines
5.8 KiB
TypeScript
Raw Normal View History

2026-03-25 10:02:19 +08:00
/**
* Check if an element has a class
* @param {HTMLElement} elm
* @param {string} cls
* @returns {boolean}
*/
export function hasClass(ele: HTMLElement, cls: string) {
return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}
/**
* Add class to element
* @param {HTMLElement} elm
* @param {string} cls
*/
export function addClass(ele: HTMLElement, cls: string) {
if (!hasClass(ele, cls)) ele.className += ' ' + cls;
}
/**
* Remove class from element
* @param {HTMLElement} elm
* @param {string} cls
*/
export function removeClass(ele: HTMLElement, cls: string) {
if (hasClass(ele, cls)) {
const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
ele.className = ele.className.replace(reg, ' ');
}
}
export function mix(color1: string, color2: string, weight: number) {
weight = Math.max(Math.min(Number(weight), 1), 0);
const r1 = parseInt(color1.substring(1, 3), 16);
const g1 = parseInt(color1.substring(3, 5), 16);
const b1 = parseInt(color1.substring(5, 7), 16);
const r2 = parseInt(color2.substring(1, 3), 16);
const g2 = parseInt(color2.substring(3, 5), 16);
const b2 = parseInt(color2.substring(5, 7), 16);
const r = Math.round(r1 * (1 - weight) + r2 * weight);
const g = Math.round(g1 * (1 - weight) + g2 * weight);
const b = Math.round(b1 * (1 - weight) + b2 * weight);
const rStr = ('0' + (r || 0).toString(16)).slice(-2);
const gStr = ('0' + (g || 0).toString(16)).slice(-2);
const bStr = ('0' + (b || 0).toString(16)).slice(-2);
return '#' + rStr + gStr + bStr;
}
export function parseTime(time :any, cFormat :any) {
if (arguments.length === 0) {
return null
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'undefined' || time === null || time === 'null') {
return ''
} else if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time)
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
2026-04-22 17:53:20 +08:00
const formatObj:any = {
2026-03-25 10:02:19 +08:00
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result :any, key :any) => {
let value : any = formatObj[key]
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return time_str
}
export function downloadFile(obj: any, name: any, suffix: any) {
try {
const url = window.URL.createObjectURL(new Blob([obj]));
const link = document.createElement('a');
link.style.display = 'none';
link.href = url;
// 优化文件名生成逻辑,避免多余的中横线
const timeStamp = parseTime(new Date(), '{y}{m}{d}{h}{i}{s}') || '';
const separator = timeStamp ? '-' : '';
const fileName = `${timeStamp}${separator}${name}.${suffix}`;
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
// 延迟移除,确保下载触发
setTimeout(() => {
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}, 100);
} catch (error) {
console.error('Download failed:', error);
}
2026-04-03 16:04:16 +08:00
}
/**
* URL
* @param url
* @param fileName URL 使
*/
export function downloadFileByUrl(url: string, fileName?: string) {
if (!url) return;
2026-04-03 16:04:16 +08:00
// 如果没有提供文件名,尝试从 URL 中提取
let name = fileName;
if (!name) {
const urlParts = url.split('/');
name = urlParts[urlParts.length - 1] || 'download_file';
// 去除查询参数
name = name.split('?')[0];
}
// 方法 1: 使用 fetch 获取 Blob (推荐,可重命名且强制下载)
// 注意:如果 URL 跨域且服务器未配置 CORSfetch 会失败
fetch(url)
.then((response) => {
if (!response.ok) throw new Error('Network response was not ok');
return response.blob();
})
.then((blob) => {
const blobUrl = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.style.display = 'none';
link.href = blobUrl;
link.setAttribute('download', name);
document.body.appendChild(link);
link.click();
// 清理
setTimeout(() => {
document.body.removeChild(link);
window.URL.revokeObjectURL(blobUrl);
}, 100);
})
.catch((error) => {
console.warn('Fetch download failed (possibly CORS), falling back to direct link:', error);
// 方法 2: 回退方案 - 直接使用 a 标签跳转
// 这种方式对于 PDF/图片等浏览器支持预览的文件,可能会直接在新标签页打开而不是下载
const link = document.createElement('a');
link.href = url;
link.target = '_blank';
// 如果同源download 属性生效;如果跨域,大多数浏览器会忽略 download 属性并直接打开
if (fileName) {
link.setAttribute('download', fileName);
}
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
}
2026-04-03 16:04:16 +08:00
const modules = import.meta.glob('@/assets/legend/*.svg', { eager: true });
// 图例图标映射
export const iconMap: Record<string, string> = {};
Object.entries(modules).forEach(([path, module]) => {
const fileName = path.match(/\/([^/]+)\.svg$/)?.[1];
if (fileName) {
iconMap[fileName] = (module as any).default;
}
});
// 获取图标路径
export const getIconPath = (icon: string): string => {
return iconMap[icon] || '';
};