Files
Aida_Purchaser_Front/src/utils/tools.ts

213 lines
6.3 KiB
TypeScript
Raw Normal View History

2026-04-20 11:21:21 +08:00
import CryptoJS from 'crypto-js'
function getUniversalZoomLevel() {
// 现代浏览器方案
if (window.visualViewport) {
return window.visualViewport.scale;
}
// 备用方案1
if (window.devicePixelRatio) {
return window.devicePixelRatio;
}
// 备用方案2不精确
return window.outerWidth / window.innerWidth;
}
const getMousePosition = (e: any, bor: any) => {
// if(e?.stopPropagation)e.stopPropagation()
// if(e?.preventDefault)e.preventDefault();
let event: any
if (bor) {
const touch = e.changedTouches[0] as any;
event = {
offsetX: touch.clientX - e.target.getBoundingClientRect().left,
offsetY: touch.clientY - e.target.getBoundingClientRect().top,
clientX: touch.clientX,
clientY: touch.clientY,
screenX: touch.screenX,
screenY: touch.screenY,
target: e.target,
}
// if(dom){
// event.offsetX = touch.clientX - dom.getBoundingClientRect().left
// event.offsetY = touch.clientY - dom.getBoundingClientRect().top
// }
} else {
event = {
offsetX: e.offsetX,
offsetY: e.offsetY,
clientX: e.clientX,
clientY: e.clientY,
screenX: e.screenX,
screenY: e.screenY,
target: e.target,
}
}
return event
}
/**
* UUID v4
* @returns UUID v4字符串xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
*/
export function generateUUID(): string {
// 优先使用现代浏览器的crypto.randomUUID()方法
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
return crypto.randomUUID()
}
2026-04-23 14:28:26 +08:00
2026-04-20 11:21:21 +08:00
// 备用方案手动生成UUID v4
2026-04-23 14:28:26 +08:00
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
2026-04-20 11:21:21 +08:00
const r = Math.random() * 16 | 0
const v = c === 'x' ? r : (r & 0x3 | 0x8)
return v.toString(16)
})
}
export {
getUniversalZoomLevel,
getMousePosition,
}
/** -
* @param value ||
2026-04-23 14:28:26 +08:00
* @param format 'YYYY-MM-DD HH:mm:ss'
2026-04-20 11:21:21 +08:00
* @returns
*/
2026-04-23 14:28:26 +08:00
export function FormatDate(value: Date | number | string, format: string = 'YYYY-MM-DD HH:mm:ss') {
const d = new Date(value);
if (!d || isNaN(d.getTime())) return 'Invalid Date';
const pad = (n) => String(n).padStart(2, '0');
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
const tokens = {
YYYY: d.getFullYear(),
YY: String(d.getFullYear()).slice(-2),
MM: pad(d.getMonth() + 1),
M: d.getMonth() + 1,
SM: months[d.getMonth()],
DD: pad(d.getDate()),
D: d.getDate(),
HH: pad(d.getHours()),
H: d.getHours(),
hh: pad(d.getHours() % 12 || 12),
h: d.getHours() % 12 || 12,
mm: pad(d.getMinutes()),
m: d.getMinutes(),
ss: pad(d.getSeconds()),
s: d.getSeconds(),
A: d.getHours() < 12 ? 'AM' : 'PM',
a: d.getHours() < 12 ? 'am' : 'pm'
}
const reg = new RegExp(Object.keys(tokens).join('|'), 'g')
return format.replace(reg, match => tokens[match]);
2026-04-20 11:21:21 +08:00
}
/**
*
* @param list
* @param onProgress
* @param onError
* @param onSuccess
*/
export async function DownloadImages(list: Array<{ url: string, name?: string }>, onProgress?: (count: number, total: number, item: any) => void, onError?: (count: number, total: number, item: any) => void, onSuccess?: (successCount: number, errCount: number) => void) {
const total = list.length;
let count = 0;
let successCount = 0;
let errCount = 0;
for (let i = 0; i < list.length; i++) {
await new Promise((resolve) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", list[i].url);
xhr.responseType = "blob"
xhr.onload = function () {
count++;
if (this.status === 200) {
const blob = this.response;
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = list[i].name || list[i].url.split('/').pop().split('?').shift();
a.click();
successCount++;
typeof onProgress === "function" && onProgress(count, total, list[i]);
resolve(blob);
} else {
errCount++;
typeof onError === "function" && onError(count, total, list[i]);
resolve(true);
}
};
xhr.onerror = function () {
count++;
errCount++;
typeof onError === "function" && onError(count, total, list[i]);
resolve(true);
};
xhr.send();
})
}
typeof onSuccess === "function" && onSuccess(successCount, errCount);
}
/**
* MD5加密密码
* @param password
* @returns MD5加密后的密码
*/
export function encryptPassword(password: string): string {
return CryptoJS.MD5(password).toString()
}
/**
* WhatsApp
* @param url URL
* @returns
*/
2026-04-23 14:28:26 +08:00
export async function shareImageToWhatsapp(url: string) {
2026-04-20 11:21:21 +08:00
// 把图片 URL 转为 Blob
const blob = await fetch(url).then((res) => res.blob())
// 创建文件对象
const file = new File([blob], 'image.jpg', { type: 'image/jpeg' })
// 判断浏览器是否支持文件分享
if (navigator.canShare && navigator.canShare({ files: [file] })) {
await navigator.share({
files: [file]
})
} else {
// 你可以附加一些自定义文本
const message = 'share image ' + url
// 构造WhatsApp链接
const whatsappLink = `https://api.whatsapp.com/send/?text=${encodeURIComponent(message)}`
window.open(whatsappLink, '_blank')
}
2026-04-21 15:57:59 +08:00
}
/**
*
* @param time
* @returns mm:ss
*/
export function CountDown(time: number) {
const mm = String(Math.floor(time / 60)).padStart(2, '0');
const ss = String(time % 60).padStart(2, '0');
return `${mm}:${ss}`;
}
2026-04-23 14:28:26 +08:00
/**
*
* @param {number} bytes -
2026-04-23 17:03:45 +08:00
* @param {number} options -
* @param {number} options.decimals - 2
* @param {boolean} options.unitBig - 使false
2026-04-23 14:28:26 +08:00
* @returns {string}
*/
2026-04-23 17:03:45 +08:00
export function FormatBytes(bytes, options: { decimals?: number, unitBig?: boolean } = {}) {
const { decimals = 2, unitBig = false } = options;
2026-04-24 09:38:24 +08:00
if (!bytes || isNaN(bytes)) return unitBig ? '0 B' : '0 b';
2026-04-23 14:28:26 +08:00
const k = 1024;
2026-04-23 17:03:45 +08:00
const sizes = unitBig ? ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] : ['b', 'kb', 'mb', 'gb', 'tb', 'pb', 'eb', 'zb', 'yb'];
2026-04-23 14:28:26 +08:00
const i = Math.floor(Math.log(bytes) / Math.log(k));
const value = bytes / Math.pow(k, i);
return `${Number(value.toFixed(decimals))} ${sizes[i]}`;
2026-04-23 17:03:45 +08:00
}