/** * 节流函数 * @param {Function} func 要执行的函数 * @param {number} delay 节流时间间隔(毫秒) * @returns {Function} 经过节流处理的函数 */ export function throttle (func, delay) { let lastExecTime = 0; let timerId = null; return function (...args) { const context = this; const now = Date.now(); const timeSinceLastExec = now - lastExecTime; // 如果距离上次执行时间已经超过delay,立即执行 if (timeSinceLastExec >= delay) { lastExecTime = now; func.apply(context, args); } // 否则设置定时器,在剩余时间后执行 else if (!timerId) { timerId = setTimeout(() => { lastExecTime = Date.now(); timerId = null; func.apply(context, args); }, delay - timeSinceLastExec); } }; } /** * 防抖函数 * @param {Function} func 要执行的函数 * @param {number} wait 等待时间(毫秒) * @returns {Function} 经过防抖处理的函数 */ export function debounce (func, wait) { let timeoutId; return function (...args) { const context = this; // 清除之前的定时器 clearTimeout(timeoutId); // 设置新的定时器 timeoutId = setTimeout(() => { func.apply(context, args); }, wait); }; } export function generateRandomDigits (length = 6) { let result = ''; for (let i = 0; i < length; i++) { result += Math.floor(Math.random() * 10); } return result; } // 新增:生成头像渐变背景色 export function getAvatarGradient (name) { const colors = [ 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)', 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)', 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)', 'linear-gradient(135deg, #fa709a 0%, #fee140 100%)', 'linear-gradient(135deg, #a8edea 0%, #fed6e3 100%)', 'linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%)', 'linear-gradient(135deg, #ff8a80 0%, #ff5722 100%)', 'linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%)', 'linear-gradient(135deg, #a18cd1 0%, #fbc2eb 100%)' ]; if (!name) return colors[ 0 ]; // 根据名字生成一个索引 let hash = 0; for (let i = 0; i < name.length; i++) { hash = name.charCodeAt(i) + ((hash << 5) - hash); } const index = Math.abs(hash) % colors.length; return colors[ index ]; } export const bufferConverter = { // 字符串转ArrayBuffer(UTF-8编码) stringToBase64(str) { let length = 0; for (let i = 0; i < str.length; i++) { const code = str.charCodeAt(i); if (code < 0x80) { length += 1; } else if (code < 0x800) { length += 2; } else { length += 3; } } const buffer = new ArrayBuffer(length); const view = new Uint8Array(buffer); let offset = 0; for (let i = 0; i < str.length; i++) { const code = str.charCodeAt(i); if (code < 0x80) { view[offset++] = code; } else if (code < 0x800) { view[offset++] = 0xC0 | (code >> 6); view[offset++] = 0x80 | (code & 0x3F); } else { view[offset++] = 0xE0 | (code >> 12); view[offset++] = 0x80 | ((code >> 6) & 0x3F); view[offset++] = 0x80 | (code & 0x3F); } } return uni.arrayBufferToBase64(buffer) }, // ArrayBuffer转字符串(UTF-8解码) base64ToString(base64) { const buffer = uni.base64ToArrayBuffer(base64) const bytes = new Uint8Array(buffer); let result = ''; let i = 0; while (i < bytes.length) { const byte1 = bytes[i++]; if (byte1 < 0x80) { result += String.fromCharCode(byte1); } else if (byte1 < 0xE0) { const byte2 = bytes[i++]; if (i > bytes.length) break; result += String.fromCharCode( ((byte1 & 0x1F) << 6) | (byte2 & 0x3F) ); } else if (byte1 < 0xF0) { const byte2 = bytes[i++]; const byte3 = bytes[i++]; if (i > bytes.length) break; result += String.fromCharCode( ((byte1 & 0x0F) << 12) | ((byte2 & 0x3F) << 6) | (byte3 & 0x3F) ); } else { // 处理四字节UTF-8字符(代理对) i += 3; result += '�'; } } return result; } } export function isInRangeOptimized (current, center, radius) { console.log(current, center); const R = 6371e3; // 地球半径 米 const radLat1 = (current.latitude * Math.PI) / 180; const radLat2 = (center.latitude * Math.PI) / 180; const deltaLat = ((center.latitude - current.latitude) * Math.PI) / 180; const deltaLon = ((center.longitude - current.longitude) * Math.PI) / 180; const a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2); return a <= Math.pow(radius / R, 2); } /** * WGS-84 转 GCJ-02(火星坐标系) * @param {number} wgsLat - WGS-84 纬度 * @param {number} wgsLon - WGS-84 经度 * @returns {[number, number]} [gcjLat, gcjLon] */ export function wgs84ToGcj02(wgsLat, wgsLon) { const a = 6378245.0; // 长半轴(GCJ-02 椭球参数) const ee = 0.00669342162296594323; // 扁率(GCJ-02 椭球参数) // 判断是否在国内(不在国内则直接返回原坐标) if (outOfChina(wgsLat, wgsLon)) { return [wgsLat, wgsLon]; } // 计算偏移量 let dLat = transformLat(wgsLon - 105.0, wgsLat - 35.0); let dLon = transformLon(wgsLon - 105.0, wgsLat - 35.0); const radLat = (wgsLat * Math.PI) / 180.0; let magic = Math.sin(radLat); magic = 1 - ee * magic * magic; const sqrtMagic = Math.sqrt(magic); dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * Math.PI); dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * Math.PI); // 返回 GCJ-02 坐标 return [wgsLat + dLat, wgsLon + dLon]; } // 辅助函数:判断坐标是否在国外(无需偏移) function outOfChina(lat, lon) { return lon < 72.004 || lon > 137.8347 || lat < 0.8293 || lat > 55.8271; } // 辅助函数:计算纬度偏移 function transformLat(x, y) { let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x)); ret += ((20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0) / 3.0; ret += ((20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin((y / 3.0) * Math.PI)) * 2.0) / 3.0; ret += ((160.0 * Math.sin((y / 12.0) * Math.PI) + 320 * Math.sin((y * Math.PI) / 30.0)) * 2.0) / 3.0; return ret; } // 辅助函数:计算经度偏移 function transformLon(x, y) { let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x)); ret += ((20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0) / 3.0; ret += ((20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin((x / 3.0) * Math.PI)) * 2.0) / 3.0; ret += ((150.0 * Math.sin((x / 12.0) * Math.PI) + 300.0 * Math.sin((x / 30.0) * Math.PI)) * 2.0) / 3.0; return ret; }