/** * 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) } const formatObj:any = { 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); } } /** * 通过 URL 下载文件 * @param url 文件地址 * @param fileName 文件名(可选,如果不传则尝试从 URL 解析或使用默认名) */ export function downloadFileByUrl(url: string, fileName?: string) { if (!url) return; // 如果没有提供文件名,尝试从 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 跨域且服务器未配置 CORS,fetch 会失败 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); }); } const modules = import.meta.glob('@/assets/legend/*.svg', { eager: true }); // 图例图标映射 export const iconMap: Record = {}; 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] || ''; };