handler.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /**
  2. * 节流函数
  3. * @param {Function} func 要执行的函数
  4. * @param {number} delay 节流时间间隔(毫秒)
  5. * @returns {Function} 经过节流处理的函数
  6. */
  7. export function throttle (func, delay) {
  8. let lastExecTime = 0;
  9. let timerId = null;
  10. return function (...args) {
  11. const context = this;
  12. const now = Date.now();
  13. const timeSinceLastExec = now - lastExecTime;
  14. // 如果距离上次执行时间已经超过delay,立即执行
  15. if (timeSinceLastExec >= delay) {
  16. lastExecTime = now;
  17. func.apply(context, args);
  18. }
  19. // 否则设置定时器,在剩余时间后执行
  20. else if (!timerId) {
  21. timerId = setTimeout(() => {
  22. lastExecTime = Date.now();
  23. timerId = null;
  24. func.apply(context, args);
  25. }, delay - timeSinceLastExec);
  26. }
  27. };
  28. }
  29. /**
  30. * 防抖函数
  31. * @param {Function} func 要执行的函数
  32. * @param {number} wait 等待时间(毫秒)
  33. * @returns {Function} 经过防抖处理的函数
  34. */
  35. export function debounce (func, wait) {
  36. let timeoutId;
  37. return function (...args) {
  38. const context = this;
  39. // 清除之前的定时器
  40. clearTimeout(timeoutId);
  41. // 设置新的定时器
  42. timeoutId = setTimeout(() => {
  43. func.apply(context, args);
  44. }, wait);
  45. };
  46. }
  47. export function generateRandomDigits (length = 6) {
  48. let result = '';
  49. for (let i = 0; i < length; i++) {
  50. result += Math.floor(Math.random() * 10);
  51. }
  52. return result;
  53. }
  54. // 新增:生成头像渐变背景色
  55. export function getAvatarGradient (name) {
  56. const colors = [
  57. 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
  58. 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
  59. 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)',
  60. 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)',
  61. 'linear-gradient(135deg, #fa709a 0%, #fee140 100%)',
  62. 'linear-gradient(135deg, #a8edea 0%, #fed6e3 100%)',
  63. 'linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%)',
  64. 'linear-gradient(135deg, #ff8a80 0%, #ff5722 100%)',
  65. 'linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%)',
  66. 'linear-gradient(135deg, #a18cd1 0%, #fbc2eb 100%)'
  67. ];
  68. if (!name) return colors[ 0 ];
  69. // 根据名字生成一个索引
  70. let hash = 0;
  71. for (let i = 0; i < name.length; i++) {
  72. hash = name.charCodeAt(i) + ((hash << 5) - hash);
  73. }
  74. const index = Math.abs(hash) % colors.length;
  75. return colors[ index ];
  76. }
  77. export const bufferConverter = {
  78. // 字符串转ArrayBuffer(UTF-8编码)
  79. stringToBase64(str) {
  80. let length = 0;
  81. for (let i = 0; i < str.length; i++) {
  82. const code = str.charCodeAt(i);
  83. if (code < 0x80) {
  84. length += 1;
  85. } else if (code < 0x800) {
  86. length += 2;
  87. } else {
  88. length += 3;
  89. }
  90. }
  91. const buffer = new ArrayBuffer(length);
  92. const view = new Uint8Array(buffer);
  93. let offset = 0;
  94. for (let i = 0; i < str.length; i++) {
  95. const code = str.charCodeAt(i);
  96. if (code < 0x80) {
  97. view[offset++] = code;
  98. } else if (code < 0x800) {
  99. view[offset++] = 0xC0 | (code >> 6);
  100. view[offset++] = 0x80 | (code & 0x3F);
  101. } else {
  102. view[offset++] = 0xE0 | (code >> 12);
  103. view[offset++] = 0x80 | ((code >> 6) & 0x3F);
  104. view[offset++] = 0x80 | (code & 0x3F);
  105. }
  106. }
  107. return uni.arrayBufferToBase64(buffer)
  108. },
  109. // ArrayBuffer转字符串(UTF-8解码)
  110. base64ToString(base64) {
  111. const buffer = uni.base64ToArrayBuffer(base64)
  112. const bytes = new Uint8Array(buffer);
  113. let result = '';
  114. let i = 0;
  115. while (i < bytes.length) {
  116. const byte1 = bytes[i++];
  117. if (byte1 < 0x80) {
  118. result += String.fromCharCode(byte1);
  119. } else if (byte1 < 0xE0) {
  120. const byte2 = bytes[i++];
  121. if (i > bytes.length) break;
  122. result += String.fromCharCode(
  123. ((byte1 & 0x1F) << 6) | (byte2 & 0x3F)
  124. );
  125. } else if (byte1 < 0xF0) {
  126. const byte2 = bytes[i++];
  127. const byte3 = bytes[i++];
  128. if (i > bytes.length) break;
  129. result += String.fromCharCode(
  130. ((byte1 & 0x0F) << 12) | ((byte2 & 0x3F) << 6) | (byte3 & 0x3F)
  131. );
  132. } else {
  133. // 处理四字节UTF-8字符(代理对)
  134. i += 3;
  135. result += '�';
  136. }
  137. }
  138. return result;
  139. }
  140. }
  141. export function isInRangeOptimized (current, center, radius) {
  142. console.log(current, center);
  143. const R = 6371e3; // 地球半径 米
  144. const radLat1 = (current.latitude * Math.PI) / 180;
  145. const radLat2 = (center.latitude * Math.PI) / 180;
  146. const deltaLat = ((center.latitude - current.latitude) * Math.PI) / 180;
  147. const deltaLon = ((center.longitude - current.longitude) * Math.PI) / 180;
  148. const a =
  149. Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
  150. Math.cos(radLat1) * Math.cos(radLat2) * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);
  151. return a <= Math.pow(radius / R, 2);
  152. }
  153. /**
  154. * WGS-84 转 GCJ-02(火星坐标系)
  155. * @param {number} wgsLat - WGS-84 纬度
  156. * @param {number} wgsLon - WGS-84 经度
  157. * @returns {[number, number]} [gcjLat, gcjLon]
  158. */
  159. export function wgs84ToGcj02(wgsLat, wgsLon) {
  160. const a = 6378245.0; // 长半轴(GCJ-02 椭球参数)
  161. const ee = 0.00669342162296594323; // 扁率(GCJ-02 椭球参数)
  162. // 判断是否在国内(不在国内则直接返回原坐标)
  163. if (outOfChina(wgsLat, wgsLon)) {
  164. return [wgsLat, wgsLon];
  165. }
  166. // 计算偏移量
  167. let dLat = transformLat(wgsLon - 105.0, wgsLat - 35.0);
  168. let dLon = transformLon(wgsLon - 105.0, wgsLat - 35.0);
  169. const radLat = (wgsLat * Math.PI) / 180.0;
  170. let magic = Math.sin(radLat);
  171. magic = 1 - ee * magic * magic;
  172. const sqrtMagic = Math.sqrt(magic);
  173. dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * Math.PI);
  174. dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * Math.PI);
  175. // 返回 GCJ-02 坐标
  176. return [wgsLat + dLat, wgsLon + dLon];
  177. }
  178. // 辅助函数:判断坐标是否在国外(无需偏移)
  179. function outOfChina(lat, lon) {
  180. return lon < 72.004 || lon > 137.8347 || lat < 0.8293 || lat > 55.8271;
  181. }
  182. // 辅助函数:计算纬度偏移
  183. function transformLat(x, y) {
  184. let ret =
  185. -100.0 +
  186. 2.0 * x +
  187. 3.0 * y +
  188. 0.2 * y * y +
  189. 0.1 * x * y +
  190. 0.2 * Math.sqrt(Math.abs(x));
  191. ret +=
  192. ((20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) *
  193. 2.0) /
  194. 3.0;
  195. ret +=
  196. ((20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin((y / 3.0) * Math.PI)) *
  197. 2.0) /
  198. 3.0;
  199. ret +=
  200. ((160.0 * Math.sin((y / 12.0) * Math.PI) + 320 * Math.sin((y * Math.PI) / 30.0)) *
  201. 2.0) /
  202. 3.0;
  203. return ret;
  204. }
  205. // 辅助函数:计算经度偏移
  206. function transformLon(x, y) {
  207. let ret =
  208. 300.0 +
  209. x +
  210. 2.0 * y +
  211. 0.1 * x * x +
  212. 0.1 * x * y +
  213. 0.1 * Math.sqrt(Math.abs(x));
  214. ret +=
  215. ((20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) *
  216. 2.0) /
  217. 3.0;
  218. ret +=
  219. ((20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin((x / 3.0) * Math.PI)) *
  220. 2.0) /
  221. 3.0;
  222. ret +=
  223. ((150.0 * Math.sin((x / 12.0) * Math.PI) + 300.0 * Math.sin((x / 30.0) * Math.PI)) *
  224. 2.0) /
  225. 3.0;
  226. return ret;
  227. }