@alibarbar/common 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. package/README.md +338 -0
  2. package/dist/algorithm.d.mts +66 -0
  3. package/dist/algorithm.d.ts +66 -0
  4. package/dist/algorithm.js +44 -0
  5. package/dist/algorithm.js.map +1 -0
  6. package/dist/algorithm.mjs +3 -0
  7. package/dist/algorithm.mjs.map +1 -0
  8. package/dist/array.d.mts +139 -0
  9. package/dist/array.d.ts +139 -0
  10. package/dist/array.js +84 -0
  11. package/dist/array.js.map +1 -0
  12. package/dist/array.mjs +3 -0
  13. package/dist/array.mjs.map +1 -0
  14. package/dist/chunk-27UDDVLZ.js +259 -0
  15. package/dist/chunk-27UDDVLZ.js.map +1 -0
  16. package/dist/chunk-2FFSQ573.mjs +138 -0
  17. package/dist/chunk-2FFSQ573.mjs.map +1 -0
  18. package/dist/chunk-4RGXV4SJ.js +106 -0
  19. package/dist/chunk-4RGXV4SJ.js.map +1 -0
  20. package/dist/chunk-56W6YECK.js +374 -0
  21. package/dist/chunk-56W6YECK.js.map +1 -0
  22. package/dist/chunk-5BGSUGTI.mjs +128 -0
  23. package/dist/chunk-5BGSUGTI.mjs.map +1 -0
  24. package/dist/chunk-7E6GELHJ.mjs +302 -0
  25. package/dist/chunk-7E6GELHJ.mjs.map +1 -0
  26. package/dist/chunk-7V5UQXIO.js +89 -0
  27. package/dist/chunk-7V5UQXIO.js.map +1 -0
  28. package/dist/chunk-A4SWQXX7.mjs +484 -0
  29. package/dist/chunk-A4SWQXX7.mjs.map +1 -0
  30. package/dist/chunk-ALDC6LRJ.mjs +85 -0
  31. package/dist/chunk-ALDC6LRJ.mjs.map +1 -0
  32. package/dist/chunk-BHCRFURU.js +491 -0
  33. package/dist/chunk-BHCRFURU.js.map +1 -0
  34. package/dist/chunk-D7CS5EKF.js +110 -0
  35. package/dist/chunk-D7CS5EKF.js.map +1 -0
  36. package/dist/chunk-DYBSRI7V.js +189 -0
  37. package/dist/chunk-DYBSRI7V.js.map +1 -0
  38. package/dist/chunk-F3LAGHPG.js +332 -0
  39. package/dist/chunk-F3LAGHPG.js.map +1 -0
  40. package/dist/chunk-HLDFI7R2.mjs +175 -0
  41. package/dist/chunk-HLDFI7R2.mjs.map +1 -0
  42. package/dist/chunk-HME2N3VY.mjs +354 -0
  43. package/dist/chunk-HME2N3VY.mjs.map +1 -0
  44. package/dist/chunk-I3L42475.js +145 -0
  45. package/dist/chunk-I3L42475.js.map +1 -0
  46. package/dist/chunk-JBLX27WD.mjs +240 -0
  47. package/dist/chunk-JBLX27WD.mjs.map +1 -0
  48. package/dist/chunk-JHZ7M2MR.mjs +133 -0
  49. package/dist/chunk-JHZ7M2MR.mjs.map +1 -0
  50. package/dist/chunk-JK2SE3I2.js +100 -0
  51. package/dist/chunk-JK2SE3I2.js.map +1 -0
  52. package/dist/chunk-JQZBPAPO.js +157 -0
  53. package/dist/chunk-JQZBPAPO.js.map +1 -0
  54. package/dist/chunk-JXYGC2C5.mjs +100 -0
  55. package/dist/chunk-JXYGC2C5.mjs.map +1 -0
  56. package/dist/chunk-KGFTD255.js +104 -0
  57. package/dist/chunk-KGFTD255.js.map +1 -0
  58. package/dist/chunk-LBHBNPNJ.mjs +148 -0
  59. package/dist/chunk-LBHBNPNJ.mjs.map +1 -0
  60. package/dist/chunk-LCXGZISK.js +158 -0
  61. package/dist/chunk-LCXGZISK.js.map +1 -0
  62. package/dist/chunk-LF4CILQS.mjs +87 -0
  63. package/dist/chunk-LF4CILQS.mjs.map +1 -0
  64. package/dist/chunk-MMR6XQNX.js +98 -0
  65. package/dist/chunk-MMR6XQNX.js.map +1 -0
  66. package/dist/chunk-NSSDYX2U.mjs +80 -0
  67. package/dist/chunk-NSSDYX2U.mjs.map +1 -0
  68. package/dist/chunk-O3O67R4I.js +143 -0
  69. package/dist/chunk-O3O67R4I.js.map +1 -0
  70. package/dist/chunk-OX5PLOWB.js +90 -0
  71. package/dist/chunk-OX5PLOWB.js.map +1 -0
  72. package/dist/chunk-PJ7UCTX4.mjs +362 -0
  73. package/dist/chunk-PJ7UCTX4.mjs.map +1 -0
  74. package/dist/chunk-QIBE7GVN.mjs +81 -0
  75. package/dist/chunk-QIBE7GVN.mjs.map +1 -0
  76. package/dist/chunk-QIOC54LQ.mjs +130 -0
  77. package/dist/chunk-QIOC54LQ.mjs.map +1 -0
  78. package/dist/chunk-QV6MIQ7H.mjs +328 -0
  79. package/dist/chunk-QV6MIQ7H.mjs.map +1 -0
  80. package/dist/chunk-TQN37HIN.js +94 -0
  81. package/dist/chunk-TQN37HIN.js.map +1 -0
  82. package/dist/chunk-XJTZDXSR.mjs +94 -0
  83. package/dist/chunk-XJTZDXSR.mjs.map +1 -0
  84. package/dist/chunk-XVUE53T3.js +361 -0
  85. package/dist/chunk-XVUE53T3.js.map +1 -0
  86. package/dist/chunk-Y364QIQH.js +139 -0
  87. package/dist/chunk-Y364QIQH.js.map +1 -0
  88. package/dist/chunk-YXM6Q4JS.mjs +94 -0
  89. package/dist/chunk-YXM6Q4JS.mjs.map +1 -0
  90. package/dist/chunk-ZDMFMUDR.js +309 -0
  91. package/dist/chunk-ZDMFMUDR.js.map +1 -0
  92. package/dist/chunk-ZVJ6NQUM.mjs +82 -0
  93. package/dist/chunk-ZVJ6NQUM.mjs.map +1 -0
  94. package/dist/color.d.mts +74 -0
  95. package/dist/color.d.ts +74 -0
  96. package/dist/color.js +40 -0
  97. package/dist/color.js.map +1 -0
  98. package/dist/color.mjs +3 -0
  99. package/dist/color.mjs.map +1 -0
  100. package/dist/crypto.d.mts +92 -0
  101. package/dist/crypto.d.ts +92 -0
  102. package/dist/crypto.js +60 -0
  103. package/dist/crypto.js.map +1 -0
  104. package/dist/crypto.mjs +3 -0
  105. package/dist/crypto.mjs.map +1 -0
  106. package/dist/data-structure.d.mts +213 -0
  107. package/dist/data-structure.d.ts +213 -0
  108. package/dist/data-structure.js +32 -0
  109. package/dist/data-structure.js.map +1 -0
  110. package/dist/data-structure.mjs +3 -0
  111. package/dist/data-structure.mjs.map +1 -0
  112. package/dist/date.d.mts +108 -0
  113. package/dist/date.d.ts +108 -0
  114. package/dist/date.js +72 -0
  115. package/dist/date.js.map +1 -0
  116. package/dist/date.mjs +3 -0
  117. package/dist/date.mjs.map +1 -0
  118. package/dist/dom.d.mts +92 -0
  119. package/dist/dom.d.ts +92 -0
  120. package/dist/dom.js +56 -0
  121. package/dist/dom.js.map +1 -0
  122. package/dist/dom.mjs +3 -0
  123. package/dist/dom.mjs.map +1 -0
  124. package/dist/file.d.mts +44 -0
  125. package/dist/file.d.ts +44 -0
  126. package/dist/file.js +32 -0
  127. package/dist/file.js.map +1 -0
  128. package/dist/file.mjs +3 -0
  129. package/dist/file.mjs.map +1 -0
  130. package/dist/i18n.d.mts +77 -0
  131. package/dist/i18n.d.ts +77 -0
  132. package/dist/i18n.js +40 -0
  133. package/dist/i18n.js.map +1 -0
  134. package/dist/i18n.mjs +3 -0
  135. package/dist/i18n.mjs.map +1 -0
  136. package/dist/index.d.mts +155 -0
  137. package/dist/index.d.ts +155 -0
  138. package/dist/index.js +839 -0
  139. package/dist/index.js.map +1 -0
  140. package/dist/index.mjs +22 -0
  141. package/dist/index.mjs.map +1 -0
  142. package/dist/network.d.mts +47 -0
  143. package/dist/network.d.ts +47 -0
  144. package/dist/network.js +28 -0
  145. package/dist/network.js.map +1 -0
  146. package/dist/network.mjs +3 -0
  147. package/dist/network.mjs.map +1 -0
  148. package/dist/number.d.mts +100 -0
  149. package/dist/number.d.ts +100 -0
  150. package/dist/number.js +56 -0
  151. package/dist/number.js.map +1 -0
  152. package/dist/number.mjs +3 -0
  153. package/dist/number.mjs.map +1 -0
  154. package/dist/object.d.mts +132 -0
  155. package/dist/object.d.ts +132 -0
  156. package/dist/object.js +80 -0
  157. package/dist/object.js.map +1 -0
  158. package/dist/object.mjs +3 -0
  159. package/dist/object.mjs.map +1 -0
  160. package/dist/performance.d.mts +85 -0
  161. package/dist/performance.d.ts +85 -0
  162. package/dist/performance.js +40 -0
  163. package/dist/performance.js.map +1 -0
  164. package/dist/performance.mjs +3 -0
  165. package/dist/performance.mjs.map +1 -0
  166. package/dist/storage.d.mts +176 -0
  167. package/dist/storage.d.ts +176 -0
  168. package/dist/storage.js +33 -0
  169. package/dist/storage.js.map +1 -0
  170. package/dist/storage.mjs +4 -0
  171. package/dist/storage.mjs.map +1 -0
  172. package/dist/string.d.mts +105 -0
  173. package/dist/string.d.ts +105 -0
  174. package/dist/string.js +68 -0
  175. package/dist/string.js.map +1 -0
  176. package/dist/string.mjs +3 -0
  177. package/dist/string.mjs.map +1 -0
  178. package/dist/tracking.d.mts +182 -0
  179. package/dist/tracking.d.ts +182 -0
  180. package/dist/tracking.js +52 -0
  181. package/dist/tracking.js.map +1 -0
  182. package/dist/tracking.mjs +3 -0
  183. package/dist/tracking.mjs.map +1 -0
  184. package/dist/transform.d.mts +53 -0
  185. package/dist/transform.d.ts +53 -0
  186. package/dist/transform.js +32 -0
  187. package/dist/transform.js.map +1 -0
  188. package/dist/transform.mjs +3 -0
  189. package/dist/transform.mjs.map +1 -0
  190. package/dist/upload-DzlQtUBc.d.mts +202 -0
  191. package/dist/upload-DzlQtUBc.d.ts +202 -0
  192. package/dist/upload.d.mts +1 -0
  193. package/dist/upload.d.ts +1 -0
  194. package/dist/upload.js +17 -0
  195. package/dist/upload.js.map +1 -0
  196. package/dist/upload.mjs +4 -0
  197. package/dist/upload.mjs.map +1 -0
  198. package/dist/url.d.mts +82 -0
  199. package/dist/url.d.ts +82 -0
  200. package/dist/url.js +44 -0
  201. package/dist/url.js.map +1 -0
  202. package/dist/url.mjs +3 -0
  203. package/dist/url.mjs.map +1 -0
  204. package/dist/validation.d.mts +83 -0
  205. package/dist/validation.d.ts +83 -0
  206. package/dist/validation.js +60 -0
  207. package/dist/validation.js.map +1 -0
  208. package/dist/validation.mjs +3 -0
  209. package/dist/validation.mjs.map +1 -0
  210. package/package.json +170 -0
@@ -0,0 +1,100 @@
1
+ 'use strict';
2
+
3
+ // src/browser/dom.ts
4
+ function $(selector, context = document) {
5
+ return context.querySelector(selector);
6
+ }
7
+ function $$(selector, context = document) {
8
+ return Array.from(context.querySelectorAll(selector));
9
+ }
10
+ function addClass(element, className) {
11
+ element.classList.add(className);
12
+ }
13
+ function removeClass(element, className) {
14
+ element.classList.remove(className);
15
+ }
16
+ function toggleClass(element, className) {
17
+ return element.classList.toggle(className);
18
+ }
19
+ function getStyle(element, property) {
20
+ return window.getComputedStyle(element).getPropertyValue(property);
21
+ }
22
+ function setStyle(element, property, value) {
23
+ if (typeof property === "string" && value !== void 0) {
24
+ element.style.setProperty(property, value);
25
+ } else if (typeof property === "object") {
26
+ Object.keys(property).forEach((key) => {
27
+ element.style.setProperty(key, property[key]);
28
+ });
29
+ }
30
+ }
31
+ function scrollTo(target, options = {}) {
32
+ if (typeof window === "undefined") return;
33
+ const { behavior = "smooth", block = "start", inline = "nearest" } = options;
34
+ if (typeof target === "number") {
35
+ window.scrollTo({ top: target, behavior });
36
+ return;
37
+ }
38
+ const element = typeof target === "string" ? $(target) : target;
39
+ if (element) {
40
+ element.scrollIntoView({ behavior, block, inline });
41
+ }
42
+ }
43
+ function getScrollPosition() {
44
+ if (typeof window === "undefined") return { x: 0, y: 0 };
45
+ return {
46
+ x: window.pageXOffset || document.documentElement.scrollLeft || 0,
47
+ y: window.pageYOffset || document.documentElement.scrollTop || 0
48
+ };
49
+ }
50
+ function isInViewport(element, threshold = 0) {
51
+ if (typeof window === "undefined") return false;
52
+ const rect = element.getBoundingClientRect();
53
+ const windowHeight = window.innerHeight || document.documentElement.clientHeight;
54
+ const windowWidth = window.innerWidth || document.documentElement.clientWidth;
55
+ return rect.top >= -threshold * rect.height && rect.left >= -threshold * rect.width && rect.bottom <= windowHeight + threshold * rect.height && rect.right <= windowWidth + threshold * rect.width;
56
+ }
57
+ function getElementOffset(element) {
58
+ const rect = element.getBoundingClientRect();
59
+ return {
60
+ top: rect.top + (window.pageYOffset || document.documentElement.scrollTop),
61
+ left: rect.left + (window.pageXOffset || document.documentElement.scrollLeft)
62
+ };
63
+ }
64
+ async function copyToClipboard(text) {
65
+ if (typeof navigator === "undefined" || !navigator.clipboard) {
66
+ const textArea = document.createElement("textarea");
67
+ textArea.value = text;
68
+ textArea.style.position = "fixed";
69
+ textArea.style.opacity = "0";
70
+ document.body.appendChild(textArea);
71
+ textArea.select();
72
+ try {
73
+ document.execCommand("copy");
74
+ } catch (error) {
75
+ throw new Error("Failed to copy text");
76
+ }
77
+ document.body.removeChild(textArea);
78
+ return;
79
+ }
80
+ try {
81
+ await navigator.clipboard.writeText(text);
82
+ } catch (error) {
83
+ throw new Error("Failed to copy text");
84
+ }
85
+ }
86
+
87
+ exports.$ = $;
88
+ exports.$$ = $$;
89
+ exports.addClass = addClass;
90
+ exports.copyToClipboard = copyToClipboard;
91
+ exports.getElementOffset = getElementOffset;
92
+ exports.getScrollPosition = getScrollPosition;
93
+ exports.getStyle = getStyle;
94
+ exports.isInViewport = isInViewport;
95
+ exports.removeClass = removeClass;
96
+ exports.scrollTo = scrollTo;
97
+ exports.setStyle = setStyle;
98
+ exports.toggleClass = toggleClass;
99
+ //# sourceMappingURL=chunk-JK2SE3I2.js.map
100
+ //# sourceMappingURL=chunk-JK2SE3I2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/browser/dom.ts"],"names":[],"mappings":"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","file":"chunk-JK2SE3I2.js","sourcesContent":["/**\n * DOM工具函数\n */\n\n/**\n * 选择器封装\n * @param selector - CSS选择器\n * @param context - 上下文元素,默认为 document\n * @returns 匹配的元素或元素数组\n */\nexport function $<T extends Element = Element>(\n selector: string,\n context: Document | Element = document\n): T | null {\n return context.querySelector<T>(selector);\n}\n\n/**\n * 选择器封装(返回所有匹配元素)\n * @param selector - CSS选择器\n * @param context - 上下文元素,默认为 document\n * @returns 匹配的元素数组\n */\nexport function $$<T extends Element = Element>(\n selector: string,\n context: Document | Element = document\n): T[] {\n return Array.from(context.querySelectorAll<T>(selector));\n}\n\n/**\n * 添加类名\n * @param element - DOM元素\n * @param className - 类名\n */\nexport function addClass(element: Element, className: string): void {\n element.classList.add(className);\n}\n\n/**\n * 移除类名\n * @param element - DOM元素\n * @param className - 类名\n */\nexport function removeClass(element: Element, className: string): void {\n element.classList.remove(className);\n}\n\n/**\n * 切换类名\n * @param element - DOM元素\n * @param className - 类名\n * @returns 是否包含该类名\n */\nexport function toggleClass(element: Element, className: string): boolean {\n return element.classList.toggle(className);\n}\n\n/**\n * 获取样式\n * @param element - DOM元素\n * @param property - CSS属性名\n * @returns 样式值\n */\nexport function getStyle(element: HTMLElement, property: string): string {\n return window.getComputedStyle(element).getPropertyValue(property);\n}\n\n/**\n * 设置样式\n * @param element - DOM元素\n * @param property - CSS属性名或样式对象\n * @param value - 样式值(当property为字符串时)\n */\nexport function setStyle(\n element: HTMLElement,\n property: string | Record<string, string>,\n value?: string\n): void {\n if (typeof property === 'string' && value !== undefined) {\n element.style.setProperty(property, value);\n } else if (typeof property === 'object') {\n Object.keys(property).forEach(key => {\n element.style.setProperty(key, property[key]);\n });\n }\n}\n\n/**\n * 平滑滚动\n * @param target - 目标位置(元素、选择器或数字)\n * @param options - 滚动选项\n */\nexport function scrollTo(\n target: Element | string | number,\n options: {\n behavior?: ScrollBehavior;\n block?: ScrollLogicalPosition;\n inline?: ScrollLogicalPosition;\n } = {}\n): void {\n if (typeof window === 'undefined') return;\n\n const { behavior = 'smooth', block = 'start', inline = 'nearest' } = options;\n\n if (typeof target === 'number') {\n window.scrollTo({ top: target, behavior });\n return;\n }\n\n const element = typeof target === 'string' ? $(target) : target;\n if (element) {\n element.scrollIntoView({ behavior, block, inline });\n }\n}\n\n/**\n * 获取滚动位置\n * @returns 滚动位置对象\n */\nexport function getScrollPosition(): { x: number; y: number } {\n if (typeof window === 'undefined') return { x: 0, y: 0 };\n return {\n x: window.pageXOffset || document.documentElement.scrollLeft || 0,\n y: window.pageYOffset || document.documentElement.scrollTop || 0,\n };\n}\n\n/**\n * 判断元素是否在视口内\n * @param element - DOM元素\n * @param threshold - 阈值(0-1),默认为 0\n * @returns 是否在视口内\n */\nexport function isInViewport(element: Element, threshold = 0): boolean {\n if (typeof window === 'undefined') return false;\n\n const rect = element.getBoundingClientRect();\n const windowHeight = window.innerHeight || document.documentElement.clientHeight;\n const windowWidth = window.innerWidth || document.documentElement.clientWidth;\n\n return (\n rect.top >= -threshold * rect.height &&\n rect.left >= -threshold * rect.width &&\n rect.bottom <= windowHeight + threshold * rect.height &&\n rect.right <= windowWidth + threshold * rect.width\n );\n}\n\n/**\n * 获取元素偏移量\n * @param element - DOM元素\n * @returns 偏移量对象\n */\nexport function getElementOffset(element: Element): { top: number; left: number } {\n const rect = element.getBoundingClientRect();\n return {\n top: rect.top + (window.pageYOffset || document.documentElement.scrollTop),\n left: rect.left + (window.pageXOffset || document.documentElement.scrollLeft),\n };\n}\n\n/**\n * 复制到剪贴板\n * @param text - 要复制的文本\n * @returns Promise<void>\n */\nexport async function copyToClipboard(text: string): Promise<void> {\n if (typeof navigator === 'undefined' || !navigator.clipboard) {\n // 降级方案\n const textArea = document.createElement('textarea');\n textArea.value = text;\n textArea.style.position = 'fixed';\n textArea.style.opacity = '0';\n document.body.appendChild(textArea);\n textArea.select();\n try {\n document.execCommand('copy');\n } catch (error) {\n throw new Error('Failed to copy text');\n }\n document.body.removeChild(textArea);\n return;\n }\n\n try {\n await navigator.clipboard.writeText(text);\n } catch (error) {\n throw new Error('Failed to copy text');\n }\n}\n"]}
@@ -0,0 +1,157 @@
1
+ 'use strict';
2
+
3
+ // src/helper/performance.ts
4
+ function debounce(fn, delay) {
5
+ let timeoutId = null;
6
+ return function(...args) {
7
+ if (timeoutId) {
8
+ clearTimeout(timeoutId);
9
+ }
10
+ timeoutId = setTimeout(() => {
11
+ fn.apply(this, args);
12
+ timeoutId = null;
13
+ }, delay);
14
+ };
15
+ }
16
+ function throttle(fn, delay) {
17
+ let lastCall = 0;
18
+ let timeoutId = null;
19
+ return function(...args) {
20
+ const now = Date.now();
21
+ const timeSinceLastCall = now - lastCall;
22
+ if (timeSinceLastCall >= delay) {
23
+ lastCall = now;
24
+ fn.apply(this, args);
25
+ } else {
26
+ if (timeoutId) {
27
+ clearTimeout(timeoutId);
28
+ }
29
+ timeoutId = setTimeout(() => {
30
+ lastCall = Date.now();
31
+ fn.apply(this, args);
32
+ timeoutId = null;
33
+ }, delay - timeSinceLastCall);
34
+ }
35
+ };
36
+ }
37
+ function memoize(fn, keyFn) {
38
+ const cache = /* @__PURE__ */ new Map();
39
+ return ((...args) => {
40
+ const key = keyFn ? keyFn(...args) : JSON.stringify(args);
41
+ if (cache.has(key)) {
42
+ return cache.get(key);
43
+ }
44
+ const result = fn(...args);
45
+ cache.set(key, result);
46
+ return result;
47
+ });
48
+ }
49
+ function once(fn) {
50
+ let called = false;
51
+ let result;
52
+ return ((...args) => {
53
+ if (!called) {
54
+ called = true;
55
+ result = fn(...args);
56
+ }
57
+ return result;
58
+ });
59
+ }
60
+ async function retry(fn, retryCount = 3, retryDelay = 1e3) {
61
+ let lastError = null;
62
+ for (let i = 0; i <= retryCount; i++) {
63
+ try {
64
+ return await fn();
65
+ } catch (error) {
66
+ lastError = error instanceof Error ? error : new Error(String(error));
67
+ if (i < retryCount) {
68
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
69
+ }
70
+ }
71
+ }
72
+ throw lastError || new Error("Retry failed");
73
+ }
74
+ async function timeout(fn, timeout2) {
75
+ return Promise.race([
76
+ fn(),
77
+ new Promise((_, reject) => {
78
+ setTimeout(() => reject(new Error(`Operation timeout after ${timeout2}ms`)), timeout2);
79
+ })
80
+ ]);
81
+ }
82
+ async function batch(items, fn, batchSize = 10) {
83
+ const results = [];
84
+ for (let i = 0; i < items.length; i += batchSize) {
85
+ const batch2 = items.slice(i, i + batchSize);
86
+ const batchResults = await Promise.all(batch2.map(fn));
87
+ results.push(...batchResults);
88
+ }
89
+ return results;
90
+ }
91
+ var Queue = class {
92
+ constructor() {
93
+ this.items = [];
94
+ this.processing = false;
95
+ }
96
+ /**
97
+ * 添加项到队列
98
+ * @param item - 要添加的项
99
+ */
100
+ enqueue(item) {
101
+ this.items.push(item);
102
+ if (!this.processing && this.processor) {
103
+ this.processItems();
104
+ }
105
+ }
106
+ /**
107
+ * 设置处理函数并开始处理
108
+ * @param processor - 处理函数
109
+ */
110
+ async start(processor) {
111
+ this.processor = processor;
112
+ if (!this.processing) {
113
+ await this.processItems();
114
+ }
115
+ }
116
+ /**
117
+ * 处理队列
118
+ */
119
+ async processItems() {
120
+ if (!this.processor || this.processing) return;
121
+ this.processing = true;
122
+ while (this.items.length > 0) {
123
+ const item = this.items.shift();
124
+ if (item && this.processor) {
125
+ try {
126
+ await this.processor(item);
127
+ } catch (error) {
128
+ console.error("Queue processing error:", error);
129
+ }
130
+ }
131
+ }
132
+ this.processing = false;
133
+ }
134
+ /**
135
+ * 清空队列
136
+ */
137
+ clear() {
138
+ this.items = [];
139
+ }
140
+ /**
141
+ * 获取队列长度
142
+ */
143
+ get length() {
144
+ return this.items.length;
145
+ }
146
+ };
147
+
148
+ exports.Queue = Queue;
149
+ exports.batch = batch;
150
+ exports.debounce = debounce;
151
+ exports.memoize = memoize;
152
+ exports.once = once;
153
+ exports.retry = retry;
154
+ exports.throttle = throttle;
155
+ exports.timeout = timeout;
156
+ //# sourceMappingURL=chunk-JQZBPAPO.js.map
157
+ //# sourceMappingURL=chunk-JQZBPAPO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/helper/performance.ts"],"names":["timeout","batch"],"mappings":"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","file":"chunk-JQZBPAPO.js","sourcesContent":["/**\n * 性能工具函数\n */\n\n/**\n * 防抖函数\n * @param fn - 要防抖的函数\n * @param delay - 延迟时间(毫秒)\n * @returns 防抖后的函数\n */\nexport function debounce<T extends (...args: unknown[]) => unknown>(\n fn: T,\n delay: number\n): (...args: Parameters<T>) => void {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n return function (this: unknown, ...args: Parameters<T>) {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(() => {\n fn.apply(this, args);\n timeoutId = null;\n }, delay);\n };\n}\n\n/**\n * 节流函数\n * @param fn - 要节流的函数\n * @param delay - 延迟时间(毫秒)\n * @returns 节流后的函数\n */\nexport function throttle<T extends (...args: unknown[]) => unknown>(\n fn: T,\n delay: number\n): (...args: Parameters<T>) => void {\n let lastCall = 0;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n return function (this: unknown, ...args: Parameters<T>) {\n const now = Date.now();\n const timeSinceLastCall = now - lastCall;\n\n if (timeSinceLastCall >= delay) {\n lastCall = now;\n fn.apply(this, args);\n } else {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(() => {\n lastCall = Date.now();\n fn.apply(this, args);\n timeoutId = null;\n }, delay - timeSinceLastCall);\n }\n };\n}\n\n/**\n * 函数记忆化\n * @param fn - 要记忆化的函数\n * @param keyFn - 缓存键生成函数,可选\n * @returns 记忆化后的函数\n */\nexport function memoize<T extends (...args: unknown[]) => unknown>(\n fn: T,\n keyFn?: (...args: Parameters<T>) => string\n): T {\n const cache = new Map<string, ReturnType<T>>();\n\n return ((...args: Parameters<T>): ReturnType<T> => {\n const key = keyFn ? keyFn(...args) : JSON.stringify(args);\n if (cache.has(key)) {\n return cache.get(key)!;\n }\n const result = fn(...args) as ReturnType<T>;\n cache.set(key, result);\n return result;\n }) as T;\n}\n\n/**\n * 只执行一次的函数\n * @param fn - 要执行的函数\n * @returns 包装后的函数\n */\nexport function once<T extends (...args: unknown[]) => unknown>(fn: T): T {\n let called = false;\n let result: ReturnType<T>;\n\n return ((...args: Parameters<T>): ReturnType<T> => {\n if (!called) {\n called = true;\n result = fn(...args) as ReturnType<T>;\n }\n return result;\n }) as T;\n}\n\n/**\n * 重试机制\n * @param fn - 要重试的函数\n * @param retryCount - 重试次数,默认为 3\n * @param retryDelay - 重试延迟(毫秒),默认为 1000\n * @returns Promise<T>\n */\nexport async function retry<T>(\n fn: () => Promise<T>,\n retryCount = 3,\n retryDelay = 1000\n): Promise<T> {\n let lastError: Error | null = null;\n\n for (let i = 0; i <= retryCount; i++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n if (i < retryCount) {\n await new Promise(resolve => setTimeout(resolve, retryDelay));\n }\n }\n }\n\n throw lastError || new Error('Retry failed');\n}\n\n/**\n * 超时控制\n * @param fn - 要执行的函数\n * @param timeout - 超时时间(毫秒)\n * @returns Promise<T>\n */\nexport async function timeout<T>(fn: () => Promise<T>, timeout: number): Promise<T> {\n return Promise.race([\n fn(),\n new Promise<T>((_, reject) => {\n setTimeout(() => reject(new Error(`Operation timeout after ${timeout}ms`)), timeout);\n }),\n ]);\n}\n\n/**\n * 批量处理\n * @param items - 要处理的项数组\n * @param fn - 处理函数\n * @param batchSize - 每批大小,默认为 10\n * @returns Promise<T[]>\n */\nexport async function batch<T, R>(\n items: T[],\n fn: (item: T) => Promise<R>,\n batchSize = 10\n): Promise<R[]> {\n const results: R[] = [];\n\n for (let i = 0; i < items.length; i += batchSize) {\n const batch = items.slice(i, i + batchSize);\n const batchResults = await Promise.all(batch.map(fn));\n results.push(...batchResults);\n }\n\n return results;\n}\n\n/**\n * 队列处理\n */\nexport class Queue<T> {\n private items: T[] = [];\n private processing = false;\n private processor?: (item: T) => Promise<void>;\n\n /**\n * 添加项到队列\n * @param item - 要添加的项\n */\n enqueue(item: T): void {\n this.items.push(item);\n if (!this.processing && this.processor) {\n this.processItems();\n }\n }\n\n /**\n * 设置处理函数并开始处理\n * @param processor - 处理函数\n */\n async start(processor: (item: T) => Promise<void>): Promise<void> {\n this.processor = processor;\n if (!this.processing) {\n await this.processItems();\n }\n }\n\n /**\n * 处理队列\n */\n private async processItems(): Promise<void> {\n if (!this.processor || this.processing) return;\n\n this.processing = true;\n\n while (this.items.length > 0) {\n const item = this.items.shift();\n if (item && this.processor) {\n try {\n await this.processor(item);\n } catch (error) {\n console.error('Queue processing error:', error);\n }\n }\n }\n\n this.processing = false;\n }\n\n /**\n * 清空队列\n */\n clear(): void {\n this.items = [];\n }\n\n /**\n * 获取队列长度\n */\n get length(): number {\n return this.items.length;\n }\n}\n"]}
@@ -0,0 +1,100 @@
1
+ // src/browser/network.ts
2
+ async function fetchWithRetry(url, options = {}, retryCount = 3, retryDelay = 1e3) {
3
+ let lastError = null;
4
+ for (let i = 0; i <= retryCount; i++) {
5
+ try {
6
+ const response = await fetch(url, options);
7
+ if (response.ok) {
8
+ return response;
9
+ }
10
+ if (i < retryCount) {
11
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
12
+ continue;
13
+ }
14
+ return response;
15
+ } catch (error) {
16
+ lastError = error instanceof Error ? error : new Error(String(error));
17
+ if (i < retryCount) {
18
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
19
+ }
20
+ }
21
+ }
22
+ throw lastError || new Error("Fetch failed after retries");
23
+ }
24
+ async function fetchWithTimeout(url, options = {}, timeout = 5e3) {
25
+ const controller = new AbortController();
26
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
27
+ try {
28
+ const response = await fetch(url, {
29
+ ...options,
30
+ signal: controller.signal
31
+ });
32
+ clearTimeout(timeoutId);
33
+ return response;
34
+ } catch (error) {
35
+ clearTimeout(timeoutId);
36
+ if (error instanceof Error && error.name === "AbortError") {
37
+ throw new Error(`Request timeout after ${timeout}ms`);
38
+ }
39
+ throw error;
40
+ }
41
+ }
42
+ async function downloadFile(url, filename) {
43
+ if (typeof window === "undefined") {
44
+ throw new Error("downloadFile is only available in browser environment");
45
+ }
46
+ try {
47
+ const response = await fetch(url);
48
+ if (!response.ok) {
49
+ throw new Error(`Failed to download file: ${response.statusText}`);
50
+ }
51
+ const blob = await response.blob();
52
+ const downloadUrl = window.URL.createObjectURL(blob);
53
+ const link = document.createElement("a");
54
+ link.href = downloadUrl;
55
+ link.download = filename || url.split("/").pop() || "download";
56
+ document.body.appendChild(link);
57
+ link.click();
58
+ document.body.removeChild(link);
59
+ window.URL.revokeObjectURL(downloadUrl);
60
+ } catch (error) {
61
+ throw error instanceof Error ? error : new Error(String(error));
62
+ }
63
+ }
64
+ function checkOnline() {
65
+ if (typeof navigator === "undefined") return true;
66
+ return navigator.onLine;
67
+ }
68
+ async function request(url, options = {}) {
69
+ const { method = "GET", headers = {}, body, timeout, retry = 0 } = options;
70
+ const fetchOptions = {
71
+ method,
72
+ headers: {
73
+ "Content-Type": "application/json",
74
+ ...headers
75
+ }
76
+ };
77
+ if (body) {
78
+ fetchOptions.body = typeof body === "string" ? body : JSON.stringify(body);
79
+ }
80
+ let fetchFn = fetch;
81
+ if (timeout) {
82
+ fetchFn = (url2, opts) => fetchWithTimeout(url2, opts, timeout);
83
+ }
84
+ if (retry > 0) {
85
+ fetchFn = (url2, opts) => fetchWithRetry(url2, opts, retry);
86
+ }
87
+ const response = await fetchFn(url, fetchOptions);
88
+ if (!response.ok) {
89
+ throw new Error(`HTTP error! status: ${response.status}`);
90
+ }
91
+ const contentType = response.headers.get("content-type");
92
+ if (contentType && contentType.includes("application/json")) {
93
+ return response.json();
94
+ }
95
+ return response.text();
96
+ }
97
+
98
+ export { checkOnline, downloadFile, fetchWithRetry, fetchWithTimeout, request };
99
+ //# sourceMappingURL=chunk-JXYGC2C5.mjs.map
100
+ //# sourceMappingURL=chunk-JXYGC2C5.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/browser/network.ts"],"names":["url"],"mappings":"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","file":"chunk-JXYGC2C5.mjs","sourcesContent":["/**\n * 网络工具函数\n */\n\n/**\n * 带重试的fetch\n * @param url - 请求URL\n * @param options - fetch选项\n * @param retryCount - 重试次数,默认为 3\n * @param retryDelay - 重试延迟(毫秒),默认为 1000\n * @returns Promise<Response>\n */\nexport async function fetchWithRetry(\n url: string,\n options: RequestInit = {},\n retryCount = 3,\n retryDelay = 1000\n): Promise<Response> {\n let lastError: Error | null = null;\n\n for (let i = 0; i <= retryCount; i++) {\n try {\n const response = await fetch(url, options);\n if (response.ok) {\n return response;\n }\n // 如果不是最后一次尝试,继续重试\n if (i < retryCount) {\n await new Promise(resolve => setTimeout(resolve, retryDelay));\n continue;\n }\n return response;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n if (i < retryCount) {\n await new Promise(resolve => setTimeout(resolve, retryDelay));\n }\n }\n }\n\n throw lastError || new Error('Fetch failed after retries');\n}\n\n/**\n * 带超时的fetch\n * @param url - 请求URL\n * @param options - fetch选项\n * @param timeout - 超时时间(毫秒),默认为 5000\n * @returns Promise<Response>\n */\nexport async function fetchWithTimeout(\n url: string,\n options: RequestInit = {},\n timeout = 5000\n): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n ...options,\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error instanceof Error && error.name === 'AbortError') {\n throw new Error(`Request timeout after ${timeout}ms`);\n }\n throw error;\n }\n}\n\n/**\n * 文件下载\n * @param url - 文件URL\n * @param filename - 文件名,可选\n * @returns Promise<void>\n */\nexport async function downloadFile(url: string, filename?: string): Promise<void> {\n if (typeof window === 'undefined') {\n throw new Error('downloadFile is only available in browser environment');\n }\n\n try {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to download file: ${response.statusText}`);\n }\n\n const blob = await response.blob();\n const downloadUrl = window.URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = downloadUrl;\n link.download = filename || url.split('/').pop() || 'download';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n window.URL.revokeObjectURL(downloadUrl);\n } catch (error) {\n throw error instanceof Error ? error : new Error(String(error));\n }\n}\n\n/**\n * 检查网络状态\n * @returns 是否在线\n */\nexport function checkOnline(): boolean {\n if (typeof navigator === 'undefined') return true;\n return navigator.onLine;\n}\n\n/**\n * 统一的HTTP请求封装\n * @param url - 请求URL\n * @param options - 请求选项\n * @returns Promise<T>\n */\nexport async function request<T = unknown>(\n url: string,\n options: {\n method?: string;\n headers?: Record<string, string>;\n body?: unknown;\n timeout?: number;\n retry?: number;\n } = {}\n): Promise<T> {\n const { method = 'GET', headers = {}, body, timeout, retry = 0 } = options;\n\n const fetchOptions: RequestInit = {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n };\n\n if (body) {\n fetchOptions.body = typeof body === 'string' ? body : JSON.stringify(body);\n }\n\n let fetchFn: (url: string, options: RequestInit) => Promise<Response> = fetch;\n\n if (timeout) {\n fetchFn = (url, opts) => fetchWithTimeout(url, opts, timeout);\n }\n\n if (retry > 0) {\n fetchFn = (url, opts) => fetchWithRetry(url, opts, retry);\n }\n\n const response = await fetchFn(url, fetchOptions);\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const contentType = response.headers.get('content-type');\n if (contentType && contentType.includes('application/json')) {\n return response.json() as Promise<T>;\n }\n\n return response.text() as Promise<T>;\n}\n"]}
@@ -0,0 +1,104 @@
1
+ 'use strict';
2
+
3
+ // src/format/url.ts
4
+ function parseUrl(url) {
5
+ try {
6
+ const urlObj = new URL(url);
7
+ return {
8
+ protocol: urlObj.protocol,
9
+ host: urlObj.host,
10
+ hostname: urlObj.hostname,
11
+ port: urlObj.port,
12
+ pathname: urlObj.pathname,
13
+ search: urlObj.search,
14
+ hash: urlObj.hash,
15
+ origin: urlObj.origin
16
+ };
17
+ } catch {
18
+ throw new Error(`Invalid URL: ${url}`);
19
+ }
20
+ }
21
+ function buildUrl(parts) {
22
+ const { protocol = "https:", host = "", pathname = "/", search = "", hash = "" } = parts;
23
+ return `${protocol}//${host}${pathname}${search}${hash}`;
24
+ }
25
+ function getQueryParams(url) {
26
+ const searchParams = url ? new URL(url).searchParams : new URLSearchParams(window.location.search);
27
+ const params = {};
28
+ searchParams.forEach((value, key) => {
29
+ params[key] = value;
30
+ });
31
+ return params;
32
+ }
33
+ function setQueryParams(url, params) {
34
+ try {
35
+ const urlObj = new URL(url);
36
+ Object.keys(params).forEach((key) => {
37
+ urlObj.searchParams.set(key, String(params[key]));
38
+ });
39
+ return urlObj.toString();
40
+ } catch {
41
+ throw new Error(`Invalid URL: ${url}`);
42
+ }
43
+ }
44
+ function removeQueryParams(url, keys) {
45
+ try {
46
+ const urlObj = new URL(url);
47
+ keys.forEach((key) => {
48
+ urlObj.searchParams.delete(key);
49
+ });
50
+ return urlObj.toString();
51
+ } catch {
52
+ throw new Error(`Invalid URL: ${url}`);
53
+ }
54
+ }
55
+ function updateQueryParams(url, params) {
56
+ try {
57
+ const urlObj = new URL(url);
58
+ Object.keys(params).forEach((key) => {
59
+ const value = params[key];
60
+ if (value === null) {
61
+ urlObj.searchParams.delete(key);
62
+ } else {
63
+ urlObj.searchParams.set(key, String(value));
64
+ }
65
+ });
66
+ return urlObj.toString();
67
+ } catch {
68
+ throw new Error(`Invalid URL: ${url}`);
69
+ }
70
+ }
71
+ function isAbsoluteUrl(url) {
72
+ try {
73
+ new URL(url);
74
+ return true;
75
+ } catch {
76
+ return /^https?:\/\//i.test(url);
77
+ }
78
+ }
79
+ function joinUrl(baseUrl, ...paths) {
80
+ const base = baseUrl.replace(/\/+$/, "");
81
+ const joinedPaths = paths.map((path) => path.replace(/^\/+|\/+$/g, "")).filter((path) => path.length > 0).join("/");
82
+ return `${base}/${joinedPaths}`;
83
+ }
84
+ function normalizeUrl(url) {
85
+ try {
86
+ const urlObj = new URL(url);
87
+ urlObj.pathname = urlObj.pathname.replace(/\/+/g, "/");
88
+ return urlObj.toString();
89
+ } catch {
90
+ return url;
91
+ }
92
+ }
93
+
94
+ exports.buildUrl = buildUrl;
95
+ exports.getQueryParams = getQueryParams;
96
+ exports.isAbsoluteUrl = isAbsoluteUrl;
97
+ exports.joinUrl = joinUrl;
98
+ exports.normalizeUrl = normalizeUrl;
99
+ exports.parseUrl = parseUrl;
100
+ exports.removeQueryParams = removeQueryParams;
101
+ exports.setQueryParams = setQueryParams;
102
+ exports.updateQueryParams = updateQueryParams;
103
+ //# sourceMappingURL=chunk-KGFTD255.js.map
104
+ //# sourceMappingURL=chunk-KGFTD255.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/format/url.ts"],"names":[],"mappings":";;;AAuBO,SAAS,SAAS,GAAA,EAAwB;AAC/C,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAC1B,IAAA,OAAO;AAAA,MACL,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,QAAQ,MAAA,CAAO;AAAA,KACjB;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,aAAA,EAAgB,GAAG,CAAA,CAAE,CAAA;AAAA,EACvC;AACF;AAOO,SAAS,SAAS,KAAA,EAMd;AACT,EAAA,MAAM,EAAE,QAAA,GAAW,QAAA,EAAU,IAAA,GAAO,EAAA,EAAI,QAAA,GAAW,GAAA,EAAK,MAAA,GAAS,EAAA,EAAI,IAAA,GAAO,EAAA,EAAG,GAAI,KAAA;AACnF,EAAA,OAAO,CAAA,EAAG,QAAQ,CAAA,EAAA,EAAK,IAAI,GAAG,QAAQ,CAAA,EAAG,MAAM,CAAA,EAAG,IAAI,CAAA,CAAA;AACxD;AAOO,SAAS,eAAe,GAAA,EAAsC;AACnE,EAAA,MAAM,YAAA,GAAe,GAAA,GACjB,IAAI,GAAA,CAAI,GAAG,CAAA,CAAE,YAAA,GACb,IAAI,eAAA,CAAgB,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA;AAC9C,EAAA,MAAM,SAAiC,EAAC;AACxC,EAAA,YAAA,CAAa,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAA,KAAQ;AACnC,IAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,EAChB,CAAC,CAAA;AACD,EAAA,OAAO,MAAA;AACT;AAQO,SAAS,cAAA,CACd,KACA,MAAA,EACQ;AACR,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAC1B,IAAA,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,OAAA,CAAQ,CAAA,GAAA,KAAO;AACjC,MAAA,MAAA,CAAO,aAAa,GAAA,CAAI,GAAA,EAAK,OAAO,MAAA,CAAO,GAAG,CAAC,CAAC,CAAA;AAAA,IAClD,CAAC,CAAA;AACD,IAAA,OAAO,OAAO,QAAA,EAAS;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,aAAA,EAAgB,GAAG,CAAA,CAAE,CAAA;AAAA,EACvC;AACF;AAQO,SAAS,iBAAA,CAAkB,KAAa,IAAA,EAAwB;AACrE,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAC1B,IAAA,IAAA,CAAK,QAAQ,CAAA,GAAA,KAAO;AAClB,MAAA,MAAA,CAAO,YAAA,CAAa,OAAO,GAAG,CAAA;AAAA,IAChC,CAAC,CAAA;AACD,IAAA,OAAO,OAAO,QAAA,EAAS;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,aAAA,EAAgB,GAAG,CAAA,CAAE,CAAA;AAAA,EACvC;AACF;AAQO,SAAS,iBAAA,CACd,KACA,MAAA,EACQ;AACR,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAC1B,IAAA,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,OAAA,CAAQ,CAAA,GAAA,KAAO;AACjC,MAAA,MAAM,KAAA,GAAQ,OAAO,GAAG,CAAA;AACxB,MAAA,IAAI,UAAU,IAAA,EAAM;AAClB,QAAA,MAAA,CAAO,YAAA,CAAa,OAAO,GAAG,CAAA;AAAA,MAChC,CAAA,MAAO;AACL,QAAA,MAAA,CAAO,YAAA,CAAa,GAAA,CAAI,GAAA,EAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,MAC5C;AAAA,IACF,CAAC,CAAA;AACD,IAAA,OAAO,OAAO,QAAA,EAAS;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,aAAA,EAAgB,GAAG,CAAA,CAAE,CAAA;AAAA,EACvC;AACF;AAOO,SAAS,cAAc,GAAA,EAAsB;AAClD,EAAA,IAAI;AACF,IAAA,IAAI,IAAI,GAAG,CAAA;AACX,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,eAAA,CAAgB,KAAK,GAAG,CAAA;AAAA,EACjC;AACF;AAQO,SAAS,OAAA,CAAQ,YAAoB,KAAA,EAAyB;AACnE,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AACvC,EAAA,MAAM,cAAc,KAAA,CACjB,GAAA,CAAI,CAAA,IAAA,KAAQ,IAAA,CAAK,QAAQ,YAAA,EAAc,EAAE,CAAC,CAAA,CAC1C,OAAO,CAAA,IAAA,KAAQ,IAAA,CAAK,SAAS,CAAC,CAAA,CAC9B,KAAK,GAAG,CAAA;AACX,EAAA,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA;AAC/B;AAOO,SAAS,aAAa,GAAA,EAAqB;AAChD,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAC1B,IAAA,MAAA,CAAO,QAAA,GAAW,MAAA,CAAO,QAAA,CAAS,OAAA,CAAQ,QAAQ,GAAG,CAAA;AACrD,IAAA,OAAO,OAAO,QAAA,EAAS;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,GAAA;AAAA,EACT;AACF","file":"chunk-KGFTD255.js","sourcesContent":["/**\n * URL工具函数\n */\n\n/**\n * URL解析结果\n */\nexport interface ParsedUrl {\n protocol: string;\n host: string;\n hostname: string;\n port: string;\n pathname: string;\n search: string;\n hash: string;\n origin: string;\n}\n\n/**\n * URL解析\n * @param url - URL字符串\n * @returns 解析后的URL对象\n */\nexport function parseUrl(url: string): ParsedUrl {\n try {\n const urlObj = new URL(url);\n return {\n protocol: urlObj.protocol,\n host: urlObj.host,\n hostname: urlObj.hostname,\n port: urlObj.port,\n pathname: urlObj.pathname,\n search: urlObj.search,\n hash: urlObj.hash,\n origin: urlObj.origin,\n };\n } catch {\n throw new Error(`Invalid URL: ${url}`);\n }\n}\n\n/**\n * URL构建\n * @param parts - URL组成部分\n * @returns 构建后的URL字符串\n */\nexport function buildUrl(parts: {\n protocol?: string;\n host?: string;\n pathname?: string;\n search?: string;\n hash?: string;\n}): string {\n const { protocol = 'https:', host = '', pathname = '/', search = '', hash = '' } = parts;\n return `${protocol}//${host}${pathname}${search}${hash}`;\n}\n\n/**\n * 获取查询参数\n * @param url - URL字符串,默认为当前页面URL\n * @returns 查询参数对象\n */\nexport function getQueryParams(url?: string): Record<string, string> {\n const searchParams = url\n ? new URL(url).searchParams\n : new URLSearchParams(window.location.search);\n const params: Record<string, string> = {};\n searchParams.forEach((value, key) => {\n params[key] = value;\n });\n return params;\n}\n\n/**\n * 设置查询参数\n * @param url - URL字符串\n * @param params - 查询参数对象\n * @returns 设置后的URL字符串\n */\nexport function setQueryParams(\n url: string,\n params: Record<string, string | number | boolean>\n): string {\n try {\n const urlObj = new URL(url);\n Object.keys(params).forEach(key => {\n urlObj.searchParams.set(key, String(params[key]));\n });\n return urlObj.toString();\n } catch {\n throw new Error(`Invalid URL: ${url}`);\n }\n}\n\n/**\n * 移除查询参数\n * @param url - URL字符串\n * @param keys - 要移除的查询参数键数组\n * @returns 移除后的URL字符串\n */\nexport function removeQueryParams(url: string, keys: string[]): string {\n try {\n const urlObj = new URL(url);\n keys.forEach(key => {\n urlObj.searchParams.delete(key);\n });\n return urlObj.toString();\n } catch {\n throw new Error(`Invalid URL: ${url}`);\n }\n}\n\n/**\n * 更新查询参数\n * @param url - URL字符串\n * @param params - 要更新的查询参数对象\n * @returns 更新后的URL字符串\n */\nexport function updateQueryParams(\n url: string,\n params: Record<string, string | number | boolean | null>\n): string {\n try {\n const urlObj = new URL(url);\n Object.keys(params).forEach(key => {\n const value = params[key];\n if (value === null) {\n urlObj.searchParams.delete(key);\n } else {\n urlObj.searchParams.set(key, String(value));\n }\n });\n return urlObj.toString();\n } catch {\n throw new Error(`Invalid URL: ${url}`);\n }\n}\n\n/**\n * 判断是否为绝对URL\n * @param url - URL字符串\n * @returns 是否为绝对URL\n */\nexport function isAbsoluteUrl(url: string): boolean {\n try {\n new URL(url);\n return true;\n } catch {\n return /^https?:\\/\\//i.test(url);\n }\n}\n\n/**\n * URL拼接\n * @param baseUrl - 基础URL\n * @param ...paths - 路径片段\n * @returns 拼接后的URL\n */\nexport function joinUrl(baseUrl: string, ...paths: string[]): string {\n const base = baseUrl.replace(/\\/+$/, '');\n const joinedPaths = paths\n .map(path => path.replace(/^\\/+|\\/+$/g, ''))\n .filter(path => path.length > 0)\n .join('/');\n return `${base}/${joinedPaths}`;\n}\n\n/**\n * URL标准化\n * @param url - URL字符串\n * @returns 标准化后的URL\n */\nexport function normalizeUrl(url: string): string {\n try {\n const urlObj = new URL(url);\n urlObj.pathname = urlObj.pathname.replace(/\\/+/g, '/');\n return urlObj.toString();\n } catch {\n return url;\n }\n}\n"]}