@alibarbar/common 1.0.9 → 1.1.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 (185) hide show
  1. package/dist/{chunk-O3O67R4I.js → algorithm.cjs} +1 -3
  2. package/dist/algorithm.js +130 -44
  3. package/dist/{chunk-LOAZSPGQ.js → array.cjs} +1 -3
  4. package/dist/array.js +135 -84
  5. package/dist/{chunk-Y364QIQH.js → color.cjs} +1 -3
  6. package/dist/color.js +127 -40
  7. package/dist/{chunk-DYBSRI7V.js → crypto.cjs} +109 -3
  8. package/dist/crypto.d.mts +48 -1
  9. package/dist/crypto.d.ts +48 -1
  10. package/dist/crypto.js +274 -60
  11. package/dist/{chunk-BHCRFURU.js → data-structure.cjs} +1 -3
  12. package/dist/data-structure.js +481 -32
  13. package/dist/{chunk-I3L42475.js → date.cjs} +1 -3
  14. package/dist/date.js +125 -72
  15. package/dist/{chunk-JK2SE3I2.js → dom.cjs} +1 -3
  16. package/dist/dom.js +84 -56
  17. package/dist/{chunk-7V5UQXIO.js → file.cjs} +1 -3
  18. package/dist/file.js +79 -32
  19. package/dist/{chunk-OX5PLOWB.js → i18n.cjs} +1 -3
  20. package/dist/i18n.js +78 -40
  21. package/dist/index.cjs +4543 -0
  22. package/dist/index.d.mts +6 -162
  23. package/dist/index.d.ts +6 -162
  24. package/dist/index.js +3712 -17374
  25. package/dist/{chunk-4RGXV4SJ.js → network.cjs} +1 -3
  26. package/dist/network.js +97 -28
  27. package/dist/{chunk-3FRYJPHG.js → number.cjs} +1 -3
  28. package/dist/number.js +77 -56
  29. package/dist/{chunk-27UDDVLZ.js → object.cjs} +1 -3
  30. package/dist/object.js +237 -80
  31. package/dist/{chunk-JQZBPAPO.js → performance.cjs} +1 -3
  32. package/dist/performance.js +145 -40
  33. package/dist/services.cjs +291 -0
  34. package/dist/services.d.mts +161 -0
  35. package/dist/services.d.ts +161 -0
  36. package/dist/services.js +281 -0
  37. package/dist/storage.cjs +943 -0
  38. package/dist/storage.d.mts +46 -1
  39. package/dist/storage.d.ts +46 -1
  40. package/dist/storage.js +930 -32
  41. package/dist/{chunk-D7CS5EKF.js → string.cjs} +1 -3
  42. package/dist/string.js +91 -68
  43. package/dist/{chunk-56W6YECK.js → tracking.cjs} +1 -3
  44. package/dist/tracking.js +359 -52
  45. package/dist/{chunk-ZDMFMUDR.js → transform.cjs} +1 -3
  46. package/dist/transform.js +299 -32
  47. package/dist/{chunk-NJARVI6X.mjs → upload.cjs} +42 -15
  48. package/dist/upload.d.mts +1 -1
  49. package/dist/upload.d.ts +1 -1
  50. package/dist/upload.js +402 -20
  51. package/dist/{chunk-KGFTD255.js → url.cjs} +1 -3
  52. package/dist/url.js +91 -44
  53. package/dist/{chunk-TQN37HIN.js → validation.cjs} +1 -3
  54. package/dist/validation.js +77 -60
  55. package/package.json +7 -2
  56. package/dist/algorithm.js.map +0 -1
  57. package/dist/algorithm.mjs +0 -4
  58. package/dist/algorithm.mjs.map +0 -1
  59. package/dist/array.js.map +0 -1
  60. package/dist/array.mjs +0 -4
  61. package/dist/array.mjs.map +0 -1
  62. package/dist/chunk-27UDDVLZ.js.map +0 -1
  63. package/dist/chunk-2R2QWFJC.mjs +0 -138
  64. package/dist/chunk-2R2QWFJC.mjs.map +0 -1
  65. package/dist/chunk-3FRYJPHG.js.map +0 -1
  66. package/dist/chunk-4RGXV4SJ.js.map +0 -1
  67. package/dist/chunk-56W6YECK.js.map +0 -1
  68. package/dist/chunk-5BGSUGTI.mjs +0 -128
  69. package/dist/chunk-5BGSUGTI.mjs.map +0 -1
  70. package/dist/chunk-7E6GELHJ.mjs +0 -302
  71. package/dist/chunk-7E6GELHJ.mjs.map +0 -1
  72. package/dist/chunk-7V5UQXIO.js.map +0 -1
  73. package/dist/chunk-A4SWQXX7.mjs +0 -484
  74. package/dist/chunk-A4SWQXX7.mjs.map +0 -1
  75. package/dist/chunk-BHCRFURU.js.map +0 -1
  76. package/dist/chunk-CDSGEAOK.mjs +0 -80
  77. package/dist/chunk-CDSGEAOK.mjs.map +0 -1
  78. package/dist/chunk-D7CS5EKF.js.map +0 -1
  79. package/dist/chunk-DYBSRI7V.js.map +0 -1
  80. package/dist/chunk-FEBKPX5A.js +0 -386
  81. package/dist/chunk-FEBKPX5A.js.map +0 -1
  82. package/dist/chunk-FJ6ZGZIA.mjs +0 -39
  83. package/dist/chunk-FJ6ZGZIA.mjs.map +0 -1
  84. package/dist/chunk-HLDFI7R2.mjs +0 -175
  85. package/dist/chunk-HLDFI7R2.mjs.map +0 -1
  86. package/dist/chunk-I3L42475.js.map +0 -1
  87. package/dist/chunk-JBLX27WD.mjs +0 -240
  88. package/dist/chunk-JBLX27WD.mjs.map +0 -1
  89. package/dist/chunk-JHZ7M2MR.mjs +0 -133
  90. package/dist/chunk-JHZ7M2MR.mjs.map +0 -1
  91. package/dist/chunk-JK2SE3I2.js.map +0 -1
  92. package/dist/chunk-JQZBPAPO.js.map +0 -1
  93. package/dist/chunk-JXYGC2C5.mjs +0 -100
  94. package/dist/chunk-JXYGC2C5.mjs.map +0 -1
  95. package/dist/chunk-KGFTD255.js.map +0 -1
  96. package/dist/chunk-LBHBNPNJ.mjs +0 -148
  97. package/dist/chunk-LBHBNPNJ.mjs.map +0 -1
  98. package/dist/chunk-LF4CILQS.mjs +0 -87
  99. package/dist/chunk-LF4CILQS.mjs.map +0 -1
  100. package/dist/chunk-LOAZSPGQ.js.map +0 -1
  101. package/dist/chunk-NJARVI6X.mjs.map +0 -1
  102. package/dist/chunk-NSSDYX2U.mjs +0 -80
  103. package/dist/chunk-NSSDYX2U.mjs.map +0 -1
  104. package/dist/chunk-O3O67R4I.js.map +0 -1
  105. package/dist/chunk-OIXQ3E6W.mjs +0 -354
  106. package/dist/chunk-OIXQ3E6W.mjs.map +0 -1
  107. package/dist/chunk-OX5PLOWB.js.map +0 -1
  108. package/dist/chunk-PJ7UCTX4.mjs +0 -362
  109. package/dist/chunk-PJ7UCTX4.mjs.map +0 -1
  110. package/dist/chunk-PR4QN5HX.js +0 -44
  111. package/dist/chunk-PR4QN5HX.js.map +0 -1
  112. package/dist/chunk-QIBE7GVN.mjs +0 -81
  113. package/dist/chunk-QIBE7GVN.mjs.map +0 -1
  114. package/dist/chunk-QIOC54LQ.mjs +0 -130
  115. package/dist/chunk-QIOC54LQ.mjs.map +0 -1
  116. package/dist/chunk-TQN37HIN.js.map +0 -1
  117. package/dist/chunk-WZDOPUJW.js +0 -361
  118. package/dist/chunk-WZDOPUJW.js.map +0 -1
  119. package/dist/chunk-XJTZDXSR.mjs +0 -94
  120. package/dist/chunk-XJTZDXSR.mjs.map +0 -1
  121. package/dist/chunk-Y364QIQH.js.map +0 -1
  122. package/dist/chunk-YXM6Q4JS.mjs +0 -94
  123. package/dist/chunk-YXM6Q4JS.mjs.map +0 -1
  124. package/dist/chunk-ZDMFMUDR.js.map +0 -1
  125. package/dist/chunk-ZVJ6NQUM.mjs +0 -82
  126. package/dist/chunk-ZVJ6NQUM.mjs.map +0 -1
  127. package/dist/color.js.map +0 -1
  128. package/dist/color.mjs +0 -4
  129. package/dist/color.mjs.map +0 -1
  130. package/dist/crypto.js.map +0 -1
  131. package/dist/crypto.mjs +0 -4
  132. package/dist/crypto.mjs.map +0 -1
  133. package/dist/data-structure.js.map +0 -1
  134. package/dist/data-structure.mjs +0 -4
  135. package/dist/data-structure.mjs.map +0 -1
  136. package/dist/date.js.map +0 -1
  137. package/dist/date.mjs +0 -4
  138. package/dist/date.mjs.map +0 -1
  139. package/dist/dom.js.map +0 -1
  140. package/dist/dom.mjs +0 -4
  141. package/dist/dom.mjs.map +0 -1
  142. package/dist/file.js.map +0 -1
  143. package/dist/file.mjs +0 -4
  144. package/dist/file.mjs.map +0 -1
  145. package/dist/i18n.js.map +0 -1
  146. package/dist/i18n.mjs +0 -4
  147. package/dist/i18n.mjs.map +0 -1
  148. package/dist/index.js.map +0 -1
  149. package/dist/index.mjs +0 -17155
  150. package/dist/index.mjs.map +0 -1
  151. package/dist/network.js.map +0 -1
  152. package/dist/network.mjs +0 -4
  153. package/dist/network.mjs.map +0 -1
  154. package/dist/number.js.map +0 -1
  155. package/dist/number.mjs +0 -4
  156. package/dist/number.mjs.map +0 -1
  157. package/dist/object.js.map +0 -1
  158. package/dist/object.mjs +0 -4
  159. package/dist/object.mjs.map +0 -1
  160. package/dist/performance.js.map +0 -1
  161. package/dist/performance.mjs +0 -4
  162. package/dist/performance.mjs.map +0 -1
  163. package/dist/storage.js.map +0 -1
  164. package/dist/storage.mjs +0 -5
  165. package/dist/storage.mjs.map +0 -1
  166. package/dist/string.js.map +0 -1
  167. package/dist/string.mjs +0 -4
  168. package/dist/string.mjs.map +0 -1
  169. package/dist/tracking.js.map +0 -1
  170. package/dist/tracking.mjs +0 -4
  171. package/dist/tracking.mjs.map +0 -1
  172. package/dist/transform.js.map +0 -1
  173. package/dist/transform.mjs +0 -4
  174. package/dist/transform.mjs.map +0 -1
  175. package/dist/upload.js.map +0 -1
  176. package/dist/upload.mjs +0 -5
  177. package/dist/upload.mjs.map +0 -1
  178. package/dist/url.js.map +0 -1
  179. package/dist/url.mjs +0 -4
  180. package/dist/url.mjs.map +0 -1
  181. package/dist/validation.js.map +0 -1
  182. package/dist/validation.mjs +0 -4
  183. package/dist/validation.mjs.map +0 -1
  184. /package/dist/{upload-DchqyDBQ.d.mts → index-DchqyDBQ.d.mts} +0 -0
  185. /package/dist/{upload-DchqyDBQ.d.ts → index-DchqyDBQ.d.ts} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/string.ts"],"names":["template"],"mappings":"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","file":"chunk-D7CS5EKF.js","sourcesContent":["/**\n * 字符串工具函数\n */\n\n/**\n * 首字母大写\n * @param str - 输入字符串\n * @returns 首字母大写的字符串\n */\nexport function capitalize(str: string): string {\n if (!str) return str;\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n}\n\n/**\n * 驼峰命名转换\n * @param str - 输入字符串(支持 kebab-case, snake_case, space separated)\n * @returns 驼峰命名字符串\n */\nexport function camelCase(str: string): string {\n if (!str) return str;\n\n // 先转换为小写,然后按空格、短横线、下划线分割\n const words = str\n .replace(/[A-Z]/g, letter => ` ${letter.toLowerCase()}`)\n .split(/[\\s\\-_]+/)\n .filter(word => word.length > 0);\n\n if (words.length === 0) return '';\n\n // 第一个单词全小写,后续单词首字母大写\n return (\n words[0].toLowerCase() +\n words\n .slice(1)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('')\n );\n}\n\n/**\n * 短横线命名转换\n * @param str - 输入字符串\n * @returns kebab-case 字符串\n */\nexport function kebabCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/[\\s_]+/g, '-')\n .toLowerCase();\n}\n\n/**\n * 截断字符串\n * @param str - 输入字符串\n * @param length - 最大长度\n * @param suffix - 后缀,默认为 '...'\n * @returns 截断后的字符串\n */\nexport function truncate(str: string, length: number, suffix = '...'): string {\n if (str.length <= length) return str;\n return str.slice(0, length - suffix.length) + suffix;\n}\n\n/**\n * 下划线命名转换\n * @param str - 输入字符串\n * @returns snake_case 字符串\n */\nexport function snakeCase(str: string): string {\n if (!str) return str;\n return str\n .replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`)\n .replace(/[\\s-]+/g, '_')\n .replace(/^_+|_+$/g, '')\n .toLowerCase();\n}\n\n/**\n * 帕斯卡命名转换\n * @param str - 输入字符串(支持 kebab-case, snake_case, space separated)\n * @returns PascalCase 字符串\n */\nexport function pascalCase(str: string): string {\n if (!str) return str;\n const camel = camelCase(str);\n return camel.charAt(0).toUpperCase() + camel.slice(1);\n}\n\n/**\n * 字符串脱敏\n * @param str - 输入字符串\n * @param options - 脱敏选项\n * @returns 脱敏后的字符串\n */\nexport function mask(\n str: string,\n options: {\n start?: number;\n end?: number;\n maskChar?: string;\n } = {}\n): string {\n if (!str) return str;\n const { start = 0, end = str.length, maskChar = '*' } = options;\n const startIndex = Math.max(0, start);\n const endIndex = Math.min(str.length, end);\n if (startIndex >= endIndex) return str;\n return str.slice(0, startIndex) + maskChar.repeat(endIndex - startIndex) + str.slice(endIndex);\n}\n\n/**\n * 手机号脱敏(默认显示前3位和后4位)\n * @param phone - 手机号\n * @returns 脱敏后的手机号\n */\nexport function maskPhone(phone: string): string {\n if (!phone || phone.length < 7) return phone;\n return mask(phone, { start: 3, end: phone.length - 4 });\n}\n\n/**\n * 邮箱脱敏(默认显示前2位和@后的域名)\n * @param email - 邮箱地址\n * @returns 脱敏后的邮箱\n */\nexport function maskEmail(email: string): string {\n if (!email || !email.includes('@')) return email;\n const [local, domain] = email.split('@');\n if (local.length <= 2) return email;\n return `${local.slice(0, 2)}***@${domain}`;\n}\n\n/**\n * URL友好的字符串转换(slugify)\n * @param str - 输入字符串\n * @returns URL友好的字符串\n */\nexport function slugify(str: string): string {\n if (!str) return '';\n return str\n .toLowerCase()\n .trim()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/[\\s_-]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n\n/**\n * 移除重音符号\n * @param str - 输入字符串\n * @returns 移除重音后的字符串\n */\nexport function removeAccents(str: string): string {\n if (!str) return str;\n return str.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '');\n}\n\n/**\n * HTML转义\n * @param str - 输入字符串\n * @returns 转义后的字符串\n */\nexport function escapeHtml(str: string): string {\n if (!str) return str;\n const map: Record<string, string> = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;',\n };\n return str.replace(/[&<>\"']/g, char => map[char]);\n}\n\n/**\n * HTML反转义\n * @param str - 输入字符串\n * @returns 反转义后的字符串\n */\nexport function unescapeHtml(str: string): string {\n if (!str) return str;\n const map: Record<string, string> = {\n '&amp;': '&',\n '&lt;': '<',\n '&gt;': '>',\n '&quot;': '\"',\n '&#39;': \"'\",\n };\n return str.replace(/&amp;|&lt;|&gt;|&quot;|&#39;/g, char => map[char]);\n}\n\n/**\n * 模板字符串替换\n * @param template - 模板字符串,使用 {{key}} 作为占位符\n * @param data - 替换数据对象\n * @returns 替换后的字符串\n */\nexport function template(template: string, data: Record<string, unknown>): string {\n if (!template) return template;\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (match, key) => {\n const value = data[key];\n return value !== undefined && value !== null ? String(value) : match;\n });\n}\n\n/**\n * 关键词高亮\n * @param text - 文本内容\n * @param keyword - 关键词\n * @param tag - 高亮标签,默认为 'mark'\n * @returns 高亮后的HTML字符串\n */\nexport function highlight(text: string, keyword: string, tag = 'mark'): string {\n if (!text || !keyword) return text;\n const regex = new RegExp(`(${escapeRegex(keyword)})`, 'gi');\n return text.replace(regex, `<${tag}>$1</${tag}>`);\n}\n\n/**\n * 转义正则表达式特殊字符\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/helper/crypto.ts"],"names":[],"mappings":"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","file":"chunk-DYBSRI7V.js","sourcesContent":["/**\n * 加密工具函数\n */\n\n/**\n * SHA256加密\n * @param data - 要加密的数据(字符串或ArrayBuffer)\n * @returns Promise<string> 加密后的十六进制字符串\n */\nexport async function sha256(data: string | ArrayBuffer): Promise<string> {\n const buffer = typeof data === 'string' ? new TextEncoder().encode(data) : data;\n const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\n}\n\n/**\n * Base64编码\n * @param data - 要编码的数据(字符串或ArrayBuffer)\n * @returns Base64编码字符串\n */\nexport function base64Encode(data: string | ArrayBuffer): string {\n if (typeof data === 'string') {\n return btoa(unescape(encodeURIComponent(data)));\n }\n const bytes = new Uint8Array(data);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n/**\n * Base64解码\n * @param data - Base64编码字符串\n * @returns 解码后的字符串\n */\nexport function base64Decode(data: string): string {\n try {\n return decodeURIComponent(escape(atob(data)));\n } catch {\n throw new Error('Invalid Base64 string');\n }\n}\n\n/**\n * 生成UUID v4\n * @returns UUID字符串\n */\nexport function generateUUID(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n // 降级方案\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n/**\n * 生成随机字符串\n * @param length - 字符串长度\n * @param charset - 字符集,默认为 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'\n * @returns 随机字符串\n */\nexport function generateRandomString(\n length: number,\n charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'\n): string {\n let result = '';\n for (let i = 0; i < length; i++) {\n result += charset.charAt(Math.floor(Math.random() * charset.length));\n }\n return result;\n}\n\n/**\n * 通用哈希函数(简单实现)\n * @param data - 要哈希的数据\n * @returns 哈希值\n */\nexport function hash(data: string): number {\n let hashValue = 0;\n for (let i = 0; i < data.length; i++) {\n const char = data.charCodeAt(i);\n hashValue = (hashValue << 5) - hashValue + char;\n hashValue = hashValue & hashValue; // 转换为32位整数\n }\n return Math.abs(hashValue);\n}\n\n/**\n * RSA密钥对类型\n */\nexport interface RSAKeyPair {\n publicKey: CryptoKey;\n privateKey: CryptoKey;\n}\n\n/**\n * 生成RSA密钥对\n * @param modulusLength - 密钥长度,默认为 2048\n * @returns Promise<RSAKeyPair> RSA密钥对\n */\nexport async function generateRSAKeyPair(modulusLength = 2048): Promise<RSAKeyPair> {\n if (typeof crypto === 'undefined' || !crypto.subtle) {\n throw new Error('Web Crypto API is not available');\n }\n\n const keyPair = await crypto.subtle.generateKey(\n {\n name: 'RSA-OAEP',\n modulusLength,\n publicExponent: new Uint8Array([1, 0, 1]),\n hash: 'SHA-256',\n },\n true,\n ['encrypt', 'decrypt']\n );\n\n return {\n publicKey: keyPair.publicKey,\n privateKey: keyPair.privateKey,\n };\n}\n\n/**\n * RSA加密\n * @param data - 要加密的数据(字符串)\n * @param publicKey - 公钥\n * @returns Promise<string> Base64编码的加密数据\n */\nexport async function rsaEncrypt(data: string, publicKey: CryptoKey): Promise<string> {\n if (typeof crypto === 'undefined' || !crypto.subtle) {\n throw new Error('Web Crypto API is not available');\n }\n\n const encoder = new TextEncoder();\n const dataBuffer = encoder.encode(data);\n\n // RSA-OAEP 最大加密长度受密钥长度限制\n // 2048位密钥最多加密245字节,需要分块处理\n const maxChunkSize = 245;\n const chunks: ArrayBuffer[] = [];\n\n for (let i = 0; i < dataBuffer.length; i += maxChunkSize) {\n const chunk = dataBuffer.slice(i, i + maxChunkSize);\n const encrypted = await crypto.subtle.encrypt(\n {\n name: 'RSA-OAEP',\n },\n publicKey,\n chunk\n );\n chunks.push(encrypted);\n }\n\n // 将所有加密块合并并转换为Base64\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);\n const merged = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n merged.set(new Uint8Array(chunk), offset);\n offset += chunk.byteLength;\n }\n\n return base64Encode(merged.buffer);\n}\n\n/**\n * RSA解密\n * @param encryptedData - Base64编码的加密数据\n * @param privateKey - 私钥\n * @returns Promise<string> 解密后的字符串\n */\nexport async function rsaDecrypt(encryptedData: string, privateKey: CryptoKey): Promise<string> {\n if (typeof crypto === 'undefined' || !crypto.subtle) {\n throw new Error('Web Crypto API is not available');\n }\n\n // Base64解码为ArrayBuffer\n const binaryString = atob(encryptedData);\n const encryptedArray = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n encryptedArray[i] = binaryString.charCodeAt(i);\n }\n\n // RSA-OAEP 解密块大小(256字节对于2048位密钥)\n const chunkSize = 256;\n const chunks: string[] = [];\n\n for (let i = 0; i < encryptedArray.length; i += chunkSize) {\n const chunk = encryptedArray.slice(i, i + chunkSize);\n const decrypted = await crypto.subtle.decrypt(\n {\n name: 'RSA-OAEP',\n },\n privateKey,\n chunk\n );\n const decoder = new TextDecoder();\n chunks.push(decoder.decode(decrypted));\n }\n\n return chunks.join('');\n}\n\n/**\n * 导出公钥为Base64字符串\n * @param publicKey - 公钥\n * @returns Promise<string> Base64编码的公钥\n */\nexport async function exportPublicKey(publicKey: CryptoKey): Promise<string> {\n if (typeof crypto === 'undefined' || !crypto.subtle) {\n throw new Error('Web Crypto API is not available');\n }\n\n const exported = await crypto.subtle.exportKey('spki', publicKey);\n return base64Encode(exported);\n}\n\n/**\n * 导出私钥为Base64字符串\n * @param privateKey - 私钥\n * @returns Promise<string> Base64编码的私钥\n */\nexport async function exportPrivateKey(privateKey: CryptoKey): Promise<string> {\n if (typeof crypto === 'undefined' || !crypto.subtle) {\n throw new Error('Web Crypto API is not available');\n }\n\n const exported = await crypto.subtle.exportKey('pkcs8', privateKey);\n return base64Encode(exported);\n}\n\n/**\n * 从Base64字符串导入公钥\n * @param keyData - Base64编码的公钥\n * @returns Promise<CryptoKey> 公钥对象\n */\nexport async function importPublicKey(keyData: string): Promise<CryptoKey> {\n if (typeof crypto === 'undefined' || !crypto.subtle) {\n throw new Error('Web Crypto API is not available');\n }\n\n const keyBuffer = base64Decode(keyData);\n const keyArray = new Uint8Array(keyBuffer.split('').map(char => char.charCodeAt(0)));\n\n return crypto.subtle.importKey(\n 'spki',\n keyArray.buffer,\n {\n name: 'RSA-OAEP',\n hash: 'SHA-256',\n },\n true,\n ['encrypt']\n );\n}\n\n/**\n * 从Base64字符串导入私钥\n * @param keyData - Base64编码的私钥\n * @returns Promise<CryptoKey> 私钥对象\n */\nexport async function importPrivateKey(keyData: string): Promise<CryptoKey> {\n if (typeof crypto === 'undefined' || !crypto.subtle) {\n throw new Error('Web Crypto API is not available');\n }\n\n const keyBuffer = base64Decode(keyData);\n const keyArray = new Uint8Array(keyBuffer.split('').map(char => char.charCodeAt(0)));\n\n return crypto.subtle.importKey(\n 'pkcs8',\n keyArray.buffer,\n {\n name: 'RSA-OAEP',\n hash: 'SHA-256',\n },\n true,\n ['decrypt']\n );\n}\n"]}
@@ -1,386 +0,0 @@
1
- 'use strict';
2
-
3
- var chunk7V5UQXIO_js = require('./chunk-7V5UQXIO.js');
4
-
5
- // src/types/upload.ts
6
- var UploadStatus = /* @__PURE__ */ ((UploadStatus2) => {
7
- UploadStatus2["PENDING"] = "pending";
8
- UploadStatus2["UPLOADING"] = "uploading";
9
- UploadStatus2["PAUSED"] = "paused";
10
- UploadStatus2["COMPLETED"] = "completed";
11
- UploadStatus2["FAILED"] = "failed";
12
- UploadStatus2["CANCELLED"] = "cancelled";
13
- return UploadStatus2;
14
- })(UploadStatus || {});
15
-
16
- // src/browser/upload.ts
17
- var ChunkUploader = class {
18
- constructor(file, options = {}) {
19
- this.taskId = null;
20
- this.chunks = [];
21
- this.uploadedChunks = /* @__PURE__ */ new Set();
22
- this.status = "pending" /* PENDING */;
23
- this.abortController = null;
24
- this.file = file;
25
- this.options = {
26
- chunkSize: options.chunkSize || 2 * 1024 * 1024,
27
- // 默认2MB
28
- concurrency: options.concurrency || 3,
29
- retryCount: options.retryCount || 3,
30
- retryDelay: options.retryDelay || 1e3,
31
- baseURL: options.baseURL || "",
32
- headers: options.headers || {},
33
- onProgress: options.onProgress || (() => {
34
- }),
35
- onComplete: options.onComplete || (() => {
36
- }),
37
- onError: options.onError || (() => {
38
- })
39
- };
40
- }
41
- /**
42
- * 初始化上传
43
- */
44
- async initUpload() {
45
- const fileMd5 = await this.calculateFileMD5();
46
- const request = {
47
- fileName: this.file.name,
48
- fileSize: this.file.size,
49
- fileMd5,
50
- chunkSize: this.options.chunkSize
51
- };
52
- const response = await this.request("/api/files/common/init", {
53
- method: "POST",
54
- headers: {
55
- "Content-Type": "application/json",
56
- ...this.options.headers
57
- },
58
- body: JSON.stringify(request)
59
- });
60
- if (response.code !== 200) {
61
- throw new Error(response.message || "\u521D\u59CB\u5316\u4E0A\u4F20\u5931\u8D25");
62
- }
63
- return response.data;
64
- }
65
- /**
66
- * 计算文件MD5
67
- */
68
- async calculateFileMD5() {
69
- const chunks = chunk7V5UQXIO_js.splitFileIntoChunks(this.file, this.options.chunkSize);
70
- const md5Promises = chunks.map(
71
- (chunk, index) => chunk7V5UQXIO_js.calculateBlobMD5(chunk).then((md5) => ({ index, md5 }))
72
- );
73
- const md5Results = await Promise.all(md5Promises);
74
- return md5Results.map((r) => r.md5).join("");
75
- }
76
- /**
77
- * 准备分片
78
- */
79
- prepareChunks() {
80
- const blobChunks = chunk7V5UQXIO_js.splitFileIntoChunks(this.file, this.options.chunkSize);
81
- this.chunks = blobChunks.map((blob, index) => ({
82
- index,
83
- start: index * this.options.chunkSize,
84
- end: Math.min((index + 1) * this.options.chunkSize, this.file.size),
85
- blob
86
- }));
87
- }
88
- /**
89
- * 获取已上传的分片列表(用于断点续传)
90
- */
91
- async getUploadedChunks() {
92
- if (!this.taskId) return [];
93
- try {
94
- const response = await this.request(
95
- `/api/files/common/chunks/${this.taskId}`,
96
- {
97
- method: "GET",
98
- headers: this.options.headers
99
- }
100
- );
101
- if (response.code === 200) {
102
- return response.data || [];
103
- }
104
- } catch (error) {
105
- console.warn("\u83B7\u53D6\u5DF2\u4E0A\u4F20\u5206\u7247\u5931\u8D25:", error);
106
- }
107
- return [];
108
- }
109
- /**
110
- * 上传单个分片
111
- */
112
- async uploadChunk(chunkInfo, retryCount = 0) {
113
- if (!this.taskId) {
114
- throw new Error("\u4EFB\u52A1ID\u4E0D\u5B58\u5728");
115
- }
116
- if (this.uploadedChunks.has(chunkInfo.index)) {
117
- return;
118
- }
119
- try {
120
- const chunkMd5 = await chunk7V5UQXIO_js.calculateBlobMD5(chunkInfo.blob);
121
- const formData = new FormData();
122
- formData.append("file", chunkInfo.blob, this.file.name);
123
- const url = `/api/files/common/chunk?taskId=${this.taskId}&chunkIndex=${chunkInfo.index}&chunkMd5=${chunkMd5}`;
124
- const response = await this.request(url, {
125
- method: "POST",
126
- headers: this.options.headers,
127
- body: formData
128
- });
129
- if (response.code === 200 && response.data.success) {
130
- this.uploadedChunks.add(chunkInfo.index);
131
- await this.updateProgress();
132
- } else {
133
- throw new Error(response.message || "\u5206\u7247\u4E0A\u4F20\u5931\u8D25");
134
- }
135
- } catch (error) {
136
- if (retryCount < this.options.retryCount) {
137
- await this.delay(this.options.retryDelay);
138
- return this.uploadChunk(chunkInfo, retryCount + 1);
139
- }
140
- throw error;
141
- }
142
- }
143
- /**
144
- * 并发上传分片
145
- */
146
- async uploadChunksConcurrently() {
147
- const chunksToUpload = this.chunks.filter((chunk) => !this.uploadedChunks.has(chunk.index));
148
- if (chunksToUpload.length === 0) {
149
- return;
150
- }
151
- let currentIndex = 0;
152
- const uploadNext = async () => {
153
- while (this.status === "uploading" /* UPLOADING */) {
154
- const chunkIndex = currentIndex++;
155
- if (chunkIndex >= chunksToUpload.length) {
156
- break;
157
- }
158
- const chunk = chunksToUpload[chunkIndex];
159
- await this.uploadChunk(chunk);
160
- }
161
- };
162
- const tasks = Array(this.options.concurrency).fill(null).map(() => uploadNext());
163
- await Promise.all(tasks);
164
- }
165
- /**
166
- * 更新上传进度(仅用于回调前端显示)
167
- */
168
- async updateProgress() {
169
- if (!this.taskId) return;
170
- try {
171
- const response = await this.request(
172
- `/api/files/common/progress/${this.taskId}`,
173
- {
174
- method: "GET",
175
- headers: this.options.headers
176
- }
177
- );
178
- if (response.code === 200 && response.data) {
179
- this.options.onProgress(response.data);
180
- }
181
- } catch (error) {
182
- console.warn("\u83B7\u53D6\u4E0A\u4F20\u8FDB\u5EA6\u5931\u8D25:", error);
183
- }
184
- }
185
- /**
186
- * 获取上传进度
187
- */
188
- async getUploadProgress() {
189
- if (!this.taskId) {
190
- return null;
191
- }
192
- try {
193
- const response = await this.request(
194
- `/api/files/common/progress/${this.taskId}`,
195
- {
196
- method: "GET",
197
- headers: this.options.headers
198
- }
199
- );
200
- if (response.code === 200 && response.data) {
201
- console.log("[\u83B7\u53D6\u8FDB\u5EA6]", response.data);
202
- return response.data;
203
- }
204
- } catch (error) {
205
- console.warn("\u83B7\u53D6\u4E0A\u4F20\u8FDB\u5EA6\u5931\u8D25:", error);
206
- }
207
- return null;
208
- }
209
- /**
210
- * 完成上传(调用后端合并分片接口)
211
- */
212
- async completeUpload() {
213
- if (!this.taskId) {
214
- throw new Error("\u4EFB\u52A1ID\u4E0D\u5B58\u5728");
215
- }
216
- console.log("[\u5B8C\u6210\u4E0A\u4F20] \u8C03\u7528\u5B8C\u6210\u63A5\u53E3:", `/api/files/common/complete/${this.taskId}`);
217
- const response = await this.request(
218
- `/api/files/common/complete/${this.taskId}`,
219
- {
220
- method: "POST",
221
- headers: this.options.headers
222
- }
223
- );
224
- console.log("[\u5B8C\u6210\u4E0A\u4F20] \u63A5\u53E3\u54CD\u5E94:", response);
225
- if (response.code !== 200) {
226
- throw new Error(response.message || "\u5B8C\u6210\u4E0A\u4F20\u5931\u8D25");
227
- }
228
- return response.data;
229
- }
230
- /**
231
- * 开始上传
232
- */
233
- async upload() {
234
- try {
235
- this.status = "uploading" /* UPLOADING */;
236
- this.abortController = new AbortController();
237
- console.log("[\u4E0A\u4F20\u6D41\u7A0B] 1. \u521D\u59CB\u5316\u4E0A\u4F20");
238
- const initResponse = await this.initUpload();
239
- this.taskId = initResponse.taskId;
240
- if (initResponse.instantUpload && initResponse.fileUrl) {
241
- console.log("[\u4E0A\u4F20\u6D41\u7A0B] \u79D2\u4F20\u6210\u529F");
242
- this.status = "completed" /* COMPLETED */;
243
- const result = {
244
- taskId: this.taskId,
245
- fileUrl: initResponse.fileUrl,
246
- fileName: this.file.name,
247
- fileSize: this.file.size,
248
- fileMd5: "",
249
- success: true,
250
- message: "\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u79D2\u4F20\u6210\u529F"
251
- };
252
- this.options.onComplete(result);
253
- return result;
254
- }
255
- console.log("[\u4E0A\u4F20\u6D41\u7A0B] 2. \u51C6\u5907\u5206\u7247");
256
- this.prepareChunks();
257
- const totalChunks = this.chunks.length;
258
- console.log(`[\u4E0A\u4F20\u6D41\u7A0B] \u5171 ${totalChunks} \u4E2A\u5206\u7247`);
259
- console.log("[\u4E0A\u4F20\u6D41\u7A0B] 3. \u68C0\u67E5\u5DF2\u4E0A\u4F20\u5206\u7247");
260
- const existingChunks = await this.getUploadedChunks();
261
- existingChunks.forEach((index) => this.uploadedChunks.add(index));
262
- console.log(
263
- `[\u4E0A\u4F20\u6D41\u7A0B] \u5DF2\u4E0A\u4F20 ${existingChunks.length} \u4E2A\u5206\u7247\uFF0C\u8FD8\u9700\u4E0A\u4F20 ${totalChunks - existingChunks.length} \u4E2A`
264
- );
265
- console.log("[\u4E0A\u4F20\u6D41\u7A0B] 4. \u5F00\u59CB\u4E0A\u4F20\u5206\u7247");
266
- await this.uploadChunksConcurrently();
267
- console.log("[\u4E0A\u4F20\u6D41\u7A0B] 5. \u6240\u6709\u5206\u7247\u4E0A\u4F20\u5B8C\u6210");
268
- const uploadedCount = this.uploadedChunks.size;
269
- if (uploadedCount < totalChunks) {
270
- throw new Error(`\u4E0A\u4F20\u9A8C\u8BC1\u5931\u8D25\uFF1A\u5DF2\u4E0A\u4F20 ${uploadedCount}/${totalChunks} \u4E2A\u5206\u7247`);
271
- }
272
- console.log(`[\u4E0A\u4F20\u6D41\u7A0B] 6. \u9A8C\u8BC1\u901A\u8FC7\uFF1A${uploadedCount}/${totalChunks} \u4E2A\u5206\u7247\u5DF2\u4E0A\u4F20`);
273
- const localPercentage = Math.round(uploadedCount / totalChunks * 100);
274
- console.log(`[\u4E0A\u4F20\u6D41\u7A0B] 7. \u672C\u5730\u8FDB\u5EA6\uFF1A${localPercentage}%`);
275
- console.log("[\u4E0A\u4F20\u6D41\u7A0B] 8. \u83B7\u53D6\u670D\u52A1\u7AEF\u8FDB\u5EA6");
276
- const serverProgress = await this.getUploadProgress();
277
- const serverPercentage = serverProgress?.percentage ?? 0;
278
- console.log(`[\u4E0A\u4F20\u6D41\u7A0B] \u670D\u52A1\u7AEF\u8FDB\u5EA6\uFF1A${serverPercentage}%`);
279
- const finalPercentage = serverProgress?.percentage ?? localPercentage;
280
- console.log(`[\u4E0A\u4F20\u6D41\u7A0B] 9. \u6700\u7EC8\u8FDB\u5EA6\uFF1A${finalPercentage}%`);
281
- if (finalPercentage >= 100) {
282
- console.log("[\u4E0A\u4F20\u6D41\u7A0B] 10. \u2705 \u8FDB\u5EA6\u8FBE\u5230100%\uFF0C\u8C03\u7528\u5B8C\u6210\u63A5\u53E3");
283
- const result = await this.completeUpload();
284
- this.status = "completed" /* COMPLETED */;
285
- this.options.onComplete(result);
286
- console.log("[\u4E0A\u4F20\u6D41\u7A0B] \u2705 \u4E0A\u4F20\u5B8C\u6210");
287
- return result;
288
- } else {
289
- console.error(`[\u4E0A\u4F20\u6D41\u7A0B] \u274C \u8FDB\u5EA6\u4E0D\u8DB3100%\uFF1A${finalPercentage}%`);
290
- throw new Error(`\u4E0A\u4F20\u672A\u5B8C\u6210\uFF1A\u5F53\u524D\u8FDB\u5EA6 ${finalPercentage.toFixed(2)}%`);
291
- }
292
- } catch (error) {
293
- this.status = "failed" /* FAILED */;
294
- const err = error instanceof Error ? error : new Error(String(error));
295
- this.options.onError(err);
296
- console.error("[\u4E0A\u4F20\u6D41\u7A0B] \u274C \u4E0A\u4F20\u5931\u8D25:", err);
297
- throw err;
298
- }
299
- }
300
- /**
301
- * 暂停上传
302
- */
303
- pause() {
304
- if (this.status === "uploading" /* UPLOADING */) {
305
- this.status = "paused" /* PAUSED */;
306
- if (this.abortController) {
307
- this.abortController.abort();
308
- }
309
- }
310
- }
311
- /**
312
- * 恢复上传
313
- */
314
- async resume() {
315
- if (this.status === "paused" /* PAUSED */) {
316
- return this.upload();
317
- }
318
- throw new Error("\u5F53\u524D\u72B6\u6001\u65E0\u6CD5\u6062\u590D\u4E0A\u4F20");
319
- }
320
- /**
321
- * 取消上传
322
- */
323
- async cancel() {
324
- if (this.taskId && this.status === "uploading" /* UPLOADING */) {
325
- try {
326
- await this.request(`/api/files/common/cancel/${this.taskId}`, {
327
- method: "POST",
328
- headers: this.options.headers
329
- });
330
- } catch (error) {
331
- console.warn("\u53D6\u6D88\u4E0A\u4F20\u5931\u8D25:", error);
332
- }
333
- }
334
- this.status = "cancelled" /* CANCELLED */;
335
- if (this.abortController) {
336
- this.abortController.abort();
337
- }
338
- }
339
- /**
340
- * 获取当前状态
341
- */
342
- getStatus() {
343
- return this.status;
344
- }
345
- /**
346
- * 获取任务ID
347
- */
348
- getTaskId() {
349
- return this.taskId;
350
- }
351
- /**
352
- * HTTP请求封装
353
- */
354
- async request(url, options = {}) {
355
- const fullUrl = `${this.options.baseURL}${url}`;
356
- const signal = this.abortController?.signal;
357
- const response = await fetch(fullUrl, {
358
- ...options,
359
- signal
360
- });
361
- if (!response.ok) {
362
- throw new Error(`HTTP\u9519\u8BEF: ${response.status} ${response.statusText}`);
363
- }
364
- return response.json();
365
- }
366
- /**
367
- * 延迟函数
368
- */
369
- delay(ms) {
370
- return new Promise((resolve) => setTimeout(resolve, ms));
371
- }
372
- };
373
- function createUploader(file, options) {
374
- return new ChunkUploader(file, options);
375
- }
376
- async function uploadFile(file, options) {
377
- const uploader = createUploader(file, options);
378
- return uploader.upload();
379
- }
380
-
381
- exports.ChunkUploader = ChunkUploader;
382
- exports.UploadStatus = UploadStatus;
383
- exports.createUploader = createUploader;
384
- exports.uploadFile = uploadFile;
385
- //# sourceMappingURL=chunk-FEBKPX5A.js.map
386
- //# sourceMappingURL=chunk-FEBKPX5A.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/types/upload.ts","../src/browser/upload.ts"],"names":["UploadStatus","splitFileIntoChunks","calculateBlobMD5"],"mappings":";;;;;AAoGO,IAAK,YAAA,qBAAAA,aAAAA,KAAL;AACL,EAAAA,cAAA,SAAA,CAAA,GAAU,SAAA;AACV,EAAAA,cAAA,WAAA,CAAA,GAAY,WAAA;AACZ,EAAAA,cAAA,QAAA,CAAA,GAAS,QAAA;AACT,EAAAA,cAAA,WAAA,CAAA,GAAY,WAAA;AACZ,EAAAA,cAAA,QAAA,CAAA,GAAS,QAAA;AACT,EAAAA,cAAA,WAAA,CAAA,GAAY,WAAA;AANF,EAAA,OAAAA,aAAAA;AAAA,CAAA,EAAA,YAAA,IAAA,EAAA;;;ACxDL,IAAM,gBAAN,MAAoB;AAAA,EASzB,WAAA,CAAY,IAAA,EAAY,OAAA,GAAyB,EAAC,EAAG;AANrD,IAAA,IAAA,CAAQ,MAAA,GAAwB,IAAA;AAChC,IAAA,IAAA,CAAQ,SAAsB,EAAC;AAC/B,IAAA,IAAA,CAAQ,cAAA,uBAAkC,GAAA,EAAI;AAC9C,IAAA,IAAA,CAAQ,MAAA,GAAA,SAAA;AACR,IAAA,IAAA,CAAQ,eAAA,GAA0C,IAAA;AAGhD,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU;AAAA,MACb,SAAA,EAAW,OAAA,CAAQ,SAAA,IAAa,CAAA,GAAI,IAAA,GAAO,IAAA;AAAA;AAAA,MAC3C,WAAA,EAAa,QAAQ,WAAA,IAAe,CAAA;AAAA,MACpC,UAAA,EAAY,QAAQ,UAAA,IAAc,CAAA;AAAA,MAClC,UAAA,EAAY,QAAQ,UAAA,IAAc,GAAA;AAAA,MAClC,OAAA,EAAS,QAAQ,OAAA,IAAW,EAAA;AAAA,MAC5B,OAAA,EAAS,OAAA,CAAQ,OAAA,IAAW,EAAC;AAAA,MAC7B,UAAA,EAAY,OAAA,CAAQ,UAAA,KAAe,MAAM;AAAA,MAAC,CAAA,CAAA;AAAA,MAC1C,UAAA,EAAY,OAAA,CAAQ,UAAA,KAAe,MAAM;AAAA,MAAC,CAAA,CAAA;AAAA,MAC1C,OAAA,EAAS,OAAA,CAAQ,OAAA,KAAY,MAAM;AAAA,MAAC,CAAA;AAAA,KACtC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,UAAA,GAA0C;AACtD,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,gBAAA,EAAiB;AAC5C,IAAA,MAAM,OAAA,GAA6B;AAAA,MACjC,QAAA,EAAU,KAAK,IAAA,CAAK,IAAA;AAAA,MACpB,QAAA,EAAU,KAAK,IAAA,CAAK,IAAA;AAAA,MACpB,OAAA;AAAA,MACA,SAAA,EAAW,KAAK,OAAA,CAAQ;AAAA,KAC1B;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAyC,wBAAA,EAA0B;AAAA,MAC7F,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,kBAAA;AAAA,QAChB,GAAG,KAAK,OAAA,CAAQ;AAAA,OAClB;AAAA,MACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,KAC7B,CAAA;AAED,IAAA,IAAI,QAAA,CAAS,SAAS,GAAA,EAAK;AACzB,MAAA,MAAM,IAAI,KAAA,CAAM,QAAA,CAAS,OAAA,IAAW,4CAAS,CAAA;AAAA,IAC/C;AAEA,IAAA,OAAO,QAAA,CAAS,IAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,gBAAA,GAAoC;AAChD,IAAA,MAAM,SAASC,oCAAA,CAAoB,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,QAAQ,SAAS,CAAA;AACpE,IAAA,MAAM,cAAc,MAAA,CAAO,GAAA;AAAA,MAAI,CAAC,KAAA,EAAO,KAAA,KACrCC,iCAAA,CAAiB,KAAK,CAAA,CAAE,IAAA,CAAK,CAAA,GAAA,MAAQ,EAAE,KAAA,EAAO,GAAA,EAAI,CAAE;AAAA,KACtD;AACA,IAAA,MAAM,UAAA,GAAa,MAAM,OAAA,CAAQ,GAAA,CAAI,WAAW,CAAA;AAChD,IAAA,OAAO,WAAW,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,GAAG,CAAA,CAAE,KAAK,EAAE,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAA,GAAsB;AAC5B,IAAA,MAAM,aAAaD,oCAAA,CAAoB,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,QAAQ,SAAS,CAAA;AACxE,IAAA,IAAA,CAAK,MAAA,GAAS,UAAA,CAAW,GAAA,CAAI,CAAC,MAAM,KAAA,MAAW;AAAA,MAC7C,KAAA;AAAA,MACA,KAAA,EAAO,KAAA,GAAQ,IAAA,CAAK,OAAA,CAAQ,SAAA;AAAA,MAC5B,GAAA,EAAK,IAAA,CAAK,GAAA,CAAA,CAAK,KAAA,GAAQ,CAAA,IAAK,KAAK,OAAA,CAAQ,SAAA,EAAW,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA;AAAA,MAClE;AAAA,KACF,CAAE,CAAA;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,iBAAA,GAAuC;AACnD,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,EAAQ,OAAO,EAAC;AAE1B,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA;AAAA,QAC1B,CAAA,yBAAA,EAA4B,KAAK,MAAM,CAAA,CAAA;AAAA,QACvC;AAAA,UACE,MAAA,EAAQ,KAAA;AAAA,UACR,OAAA,EAAS,KAAK,OAAA,CAAQ;AAAA;AACxB,OACF;AAEA,MAAA,IAAI,QAAA,CAAS,SAAS,GAAA,EAAK;AACzB,QAAA,OAAO,QAAA,CAAS,QAAQ,EAAC;AAAA,MAC3B;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,IAAA,CAAK,2DAAc,KAAK,CAAA;AAAA,IAClC;AAEA,IAAA,OAAO,EAAC;AAAA,EACV;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,WAAA,CAAY,SAAA,EAAsB,UAAA,GAAa,CAAA,EAAkB;AAC7E,IAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AAChB,MAAA,MAAM,IAAI,MAAM,kCAAS,CAAA;AAAA,IAC3B;AAEA,IAAA,IAAI,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,SAAA,CAAU,KAAK,CAAA,EAAG;AAC5C,MAAA;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAMC,iCAAA,CAAiB,SAAA,CAAU,IAAI,CAAA;AACtD,MAAA,MAAM,QAAA,GAAW,IAAI,QAAA,EAAS;AAC9B,MAAA,QAAA,CAAS,OAAO,MAAA,EAAQ,SAAA,CAAU,IAAA,EAAM,IAAA,CAAK,KAAK,IAAI,CAAA;AAEtD,MAAA,MAAM,GAAA,GAAM,kCAAkC,IAAA,CAAK,MAAM,eAAe,SAAA,CAAU,KAAK,aAAa,QAAQ,CAAA,CAAA;AAE5G,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAA0C,GAAA,EAAK;AAAA,QACzE,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,KAAK,OAAA,CAAQ,OAAA;AAAA,QACtB,IAAA,EAAM;AAAA,OACP,CAAA;AAED,MAAA,IAAI,QAAA,CAAS,IAAA,KAAS,GAAA,IAAO,QAAA,CAAS,KAAK,OAAA,EAAS;AAClD,QAAA,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,SAAA,CAAU,KAAK,CAAA;AAEvC,QAAA,MAAM,KAAK,cAAA,EAAe;AAAA,MAC5B,CAAA,MAAO;AACL,QAAA,MAAM,IAAI,KAAA,CAAM,QAAA,CAAS,OAAA,IAAW,sCAAQ,CAAA;AAAA,MAC9C;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,UAAA,GAAa,IAAA,CAAK,OAAA,CAAQ,UAAA,EAAY;AACxC,QAAA,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,OAAA,CAAQ,UAAU,CAAA;AACxC,QAAA,OAAO,IAAA,CAAK,WAAA,CAAY,SAAA,EAAW,UAAA,GAAa,CAAC,CAAA;AAAA,MACnD;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,wBAAA,GAA0C;AACtD,IAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,CAAA,KAAA,KAAS,CAAC,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,KAAA,CAAM,KAAK,CAAC,CAAA;AAExF,IAAA,IAAI,cAAA,CAAe,WAAW,CAAA,EAAG;AAC/B,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,YAAA,GAAe,CAAA;AACnB,IAAA,MAAM,aAAa,YAA2B;AAC5C,MAAA,OAAO,KAAK,MAAA,KAAA,WAAA,kBAAmC;AAC7C,QAAA,MAAM,UAAA,GAAa,YAAA,EAAA;AACnB,QAAA,IAAI,UAAA,IAAc,eAAe,MAAA,EAAQ;AACvC,UAAA;AAAA,QACF;AACA,QAAA,MAAM,KAAA,GAAQ,eAAe,UAAU,CAAA;AACvC,QAAA,MAAM,IAAA,CAAK,YAAY,KAAK,CAAA;AAAA,MAC9B;AAAA,IACF,CAAA;AAGA,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,IAAA,CAAK,OAAA,CAAQ,WAAW,CAAA,CACzC,IAAA,CAAK,IAAI,CAAA,CACT,GAAA,CAAI,MAAM,UAAA,EAAY,CAAA;AACzB,IAAA,MAAM,OAAA,CAAQ,IAAI,KAAK,CAAA;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cAAA,GAAgC;AAC5C,IAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AAElB,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA;AAAA,QAC1B,CAAA,2BAAA,EAA8B,KAAK,MAAM,CAAA,CAAA;AAAA,QACzC;AAAA,UACE,MAAA,EAAQ,KAAA;AAAA,UACR,OAAA,EAAS,KAAK,OAAA,CAAQ;AAAA;AACxB,OACF;AAEA,MAAA,IAAI,QAAA,CAAS,IAAA,KAAS,GAAA,IAAO,QAAA,CAAS,IAAA,EAAM;AAC1C,QAAA,IAAA,CAAK,OAAA,CAAQ,UAAA,CAAW,QAAA,CAAS,IAAI,CAAA;AAAA,MACvC;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,IAAA,CAAK,qDAAa,KAAK,CAAA;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,iBAAA,GAAoD;AAChE,IAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AAChB,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA;AAAA,QAC1B,CAAA,2BAAA,EAA8B,KAAK,MAAM,CAAA,CAAA;AAAA,QACzC;AAAA,UACE,MAAA,EAAQ,KAAA;AAAA,UACR,OAAA,EAAS,KAAK,OAAA,CAAQ;AAAA;AACxB,OACF;AAEA,MAAA,IAAI,QAAA,CAAS,IAAA,KAAS,GAAA,IAAO,QAAA,CAAS,IAAA,EAAM;AAC1C,QAAA,OAAA,CAAQ,GAAA,CAAI,4BAAA,EAAU,QAAA,CAAS,IAAI,CAAA;AACnC,QAAA,OAAO,QAAA,CAAS,IAAA;AAAA,MAClB;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,IAAA,CAAK,qDAAa,KAAK,CAAA;AAAA,IACjC;AAEA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cAAA,GAAkD;AAC9D,IAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AAChB,MAAA,MAAM,IAAI,MAAM,kCAAS,CAAA;AAAA,IAC3B;AAEA,IAAA,OAAA,CAAQ,GAAA,CAAI,kEAAA,EAAkB,CAAA,2BAAA,EAA8B,IAAA,CAAK,MAAM,CAAA,CAAE,CAAA;AAEzE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA;AAAA,MAC1B,CAAA,2BAAA,EAA8B,KAAK,MAAM,CAAA,CAAA;AAAA,MACzC;AAAA,QACE,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,KAAK,OAAA,CAAQ;AAAA;AACxB,KACF;AAEA,IAAA,OAAA,CAAQ,GAAA,CAAI,wDAAgB,QAAQ,CAAA;AAEpC,IAAA,IAAI,QAAA,CAAS,SAAS,GAAA,EAAK;AACzB,MAAA,MAAM,IAAI,KAAA,CAAM,QAAA,CAAS,OAAA,IAAW,sCAAQ,CAAA;AAAA,IAC9C;AAEA,IAAA,OAAO,QAAA,CAAS,IAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAA,GAA0C;AAC9C,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,MAAA,GAAA,WAAA;AACL,MAAA,IAAA,CAAK,eAAA,GAAkB,IAAI,eAAA,EAAgB;AAG3C,MAAA,OAAA,CAAQ,IAAI,8DAAiB,CAAA;AAC7B,MAAA,MAAM,YAAA,GAAe,MAAM,IAAA,CAAK,UAAA,EAAW;AAC3C,MAAA,IAAA,CAAK,SAAS,YAAA,CAAa,MAAA;AAG3B,MAAA,IAAI,YAAA,CAAa,aAAA,IAAiB,YAAA,CAAa,OAAA,EAAS;AACtD,QAAA,OAAA,CAAQ,IAAI,qDAAa,CAAA;AACzB,QAAA,IAAA,CAAK,MAAA,GAAA,WAAA;AACL,QAAA,MAAM,MAAA,GAAiC;AAAA,UACrC,QAAQ,IAAA,CAAK,MAAA;AAAA,UACb,SAAS,YAAA,CAAa,OAAA;AAAA,UACtB,QAAA,EAAU,KAAK,IAAA,CAAK,IAAA;AAAA,UACpB,QAAA,EAAU,KAAK,IAAA,CAAK,IAAA;AAAA,UACpB,OAAA,EAAS,EAAA;AAAA,UACT,OAAA,EAAS,IAAA;AAAA,UACT,OAAA,EAAS;AAAA,SACX;AACA,QAAA,IAAA,CAAK,OAAA,CAAQ,WAAW,MAAM,CAAA;AAC9B,QAAA,OAAO,MAAA;AAAA,MACT;AAGA,MAAA,OAAA,CAAQ,IAAI,wDAAgB,CAAA;AAC5B,MAAA,IAAA,CAAK,aAAA,EAAc;AACnB,MAAA,MAAM,WAAA,GAAc,KAAK,MAAA,CAAO,MAAA;AAChC,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,kCAAA,EAAY,WAAW,CAAA,mBAAA,CAAM,CAAA;AAGzC,MAAA,OAAA,CAAQ,IAAI,0EAAmB,CAAA;AAC/B,MAAA,MAAM,cAAA,GAAiB,MAAM,IAAA,CAAK,iBAAA,EAAkB;AACpD,MAAA,cAAA,CAAe,QAAQ,CAAA,KAAA,KAAS,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,KAAK,CAAC,CAAA;AAC9D,MAAA,OAAA,CAAQ,GAAA;AAAA,QACN,iDAAc,cAAA,CAAe,MAAM,CAAA,kDAAA,EAAa,WAAA,GAAc,eAAe,MAAM,CAAA,OAAA;AAAA,OACrF;AAGA,MAAA,OAAA,CAAQ,IAAI,oEAAkB,CAAA;AAC9B,MAAA,MAAM,KAAK,wBAAA,EAAyB;AACpC,MAAA,OAAA,CAAQ,IAAI,gFAAoB,CAAA;AAGhC,MAAA,MAAM,aAAA,GAAgB,KAAK,cAAA,CAAe,IAAA;AAC1C,MAAA,IAAI,gBAAgB,WAAA,EAAa;AAC/B,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,6DAAA,EAAc,aAAa,CAAA,CAAA,EAAI,WAAW,CAAA,mBAAA,CAAM,CAAA;AAAA,MAClE;AACA,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,4DAAA,EAAkB,aAAa,CAAA,CAAA,EAAI,WAAW,CAAA,qCAAA,CAAS,CAAA;AAGnE,MAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,KAAA,CAAO,aAAA,GAAgB,cAAe,GAAG,CAAA;AACtE,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,4DAAA,EAAkB,eAAe,CAAA,CAAA,CAAG,CAAA;AAGhD,MAAA,OAAA,CAAQ,IAAI,0EAAmB,CAAA;AAC/B,MAAA,MAAM,cAAA,GAAiB,MAAM,IAAA,CAAK,iBAAA,EAAkB;AACpD,MAAA,MAAM,gBAAA,GAAmB,gBAAgB,UAAA,IAAc,CAAA;AACvD,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,+DAAA,EAAgB,gBAAgB,CAAA,CAAA,CAAG,CAAA;AAG/C,MAAA,MAAM,eAAA,GAAkB,gBAAgB,UAAA,IAAc,eAAA;AACtD,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,4DAAA,EAAkB,eAAe,CAAA,CAAA,CAAG,CAAA;AAGhD,MAAA,IAAI,mBAAmB,GAAA,EAAK;AAC1B,QAAA,OAAA,CAAQ,IAAI,8GAA8B,CAAA;AAC1C,QAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,cAAA,EAAe;AAEzC,QAAA,IAAA,CAAK,MAAA,GAAA,WAAA;AACL,QAAA,IAAA,CAAK,OAAA,CAAQ,WAAW,MAAM,CAAA;AAE9B,QAAA,OAAA,CAAQ,IAAI,4DAAe,CAAA;AAC3B,QAAA,OAAO,MAAA;AAAA,MACT,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,oEAAA,EAAqB,eAAe,CAAA,CAAA,CAAG,CAAA;AACrD,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,6DAAA,EAAc,gBAAgB,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,MAC7D;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,MAAA,GAAA,QAAA;AACL,MAAA,MAAM,GAAA,GAAM,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AACpE,MAAA,IAAA,CAAK,OAAA,CAAQ,QAAQ,GAAG,CAAA;AACxB,MAAA,OAAA,CAAQ,KAAA,CAAM,+DAAkB,GAAG,CAAA;AACnC,MAAA,MAAM,GAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAc;AACZ,IAAA,IAAI,KAAK,MAAA,KAAA,WAAA,kBAAmC;AAC1C,MAAA,IAAA,CAAK,MAAA,GAAA,QAAA;AACL,MAAA,IAAI,KAAK,eAAA,EAAiB;AACxB,QAAA,IAAA,CAAK,gBAAgB,KAAA,EAAM;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAA,GAA0C;AAC9C,IAAA,IAAI,KAAK,MAAA,KAAA,QAAA,eAAgC;AACvC,MAAA,OAAO,KAAK,MAAA,EAAO;AAAA,IACrB;AACA,IAAA,MAAM,IAAI,MAAM,8DAAY,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAA,GAAwB;AAC5B,IAAA,IAAI,IAAA,CAAK,MAAA,IAAU,IAAA,CAAK,MAAA,KAAA,WAAA,kBAAmC;AACzD,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAK,OAAA,CAA2B,CAAA,yBAAA,EAA4B,IAAA,CAAK,MAAM,CAAA,CAAA,EAAI;AAAA,UAC/E,MAAA,EAAQ,MAAA;AAAA,UACR,OAAA,EAAS,KAAK,OAAA,CAAQ;AAAA,SACvB,CAAA;AAAA,MACH,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,IAAA,CAAK,yCAAW,KAAK,CAAA;AAAA,MAC/B;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,MAAA,GAAA,WAAA;AACL,IAAA,IAAI,KAAK,eAAA,EAAiB;AACxB,MAAA,IAAA,CAAK,gBAAgB,KAAA,EAAM;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,GAA0B;AACxB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,GAA2B;AACzB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,OAAA,CAAW,GAAA,EAAa,OAAA,GAAuB,EAAC,EAAe;AAC3E,IAAA,MAAM,UAAU,CAAA,EAAG,IAAA,CAAK,OAAA,CAAQ,OAAO,GAAG,GAAG,CAAA,CAAA;AAC7C,IAAA,MAAM,MAAA,GAAS,KAAK,eAAA,EAAiB,MAAA;AAErC,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,OAAA,EAAS;AAAA,MACpC,GAAG,OAAA;AAAA,MACH;AAAA,KACD,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,MAAM,CAAA,kBAAA,EAAW,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,IACrE;AAEA,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKQ,MAAM,EAAA,EAA2B;AACvC,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAA,OAAA,KAAW,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AAAA,EACvD;AACF;AAQO,SAAS,cAAA,CAAe,MAAY,OAAA,EAAwC;AACjF,EAAA,OAAO,IAAI,aAAA,CAAc,IAAA,EAAM,OAAO,CAAA;AACxC;AAQA,eAAsB,UAAA,CACpB,MACA,OAAA,EACiC;AACjC,EAAA,MAAM,QAAA,GAAW,cAAA,CAAe,IAAA,EAAM,OAAO,CAAA;AAC7C,EAAA,OAAO,SAAS,MAAA,EAAO;AACzB","file":"chunk-FEBKPX5A.js","sourcesContent":["/**\n * 文件上传相关类型定义\n */\n\n/**\n * 上传初始化请求参数\n */\nexport interface UploadInitRequest {\n fileName: string;\n fileSize: number;\n fileMd5: string;\n chunkSize?: number;\n}\n\n/**\n * 上传初始化响应\n */\nexport interface UploadInitResponse {\n taskId: string;\n totalChunks: number;\n existingChunks: number[];\n instantUpload: boolean;\n fileUrl?: string;\n chunkSize: number;\n}\n\n/**\n * 分片上传响应\n */\nexport interface ChunkUploadResponse {\n chunkIndex: number;\n success: boolean;\n message: string;\n chunkMd5: string;\n}\n\n/**\n * 完成上传响应\n */\nexport interface CompleteUploadResponse {\n taskId: string;\n fileUrl: string;\n fileName: string;\n fileSize: number;\n fileMd5: string;\n success: boolean;\n message: string;\n}\n\n/**\n * 上传进度信息\n */\nexport interface UploadProgress {\n taskId: string;\n fileName: string;\n fileSize: number;\n totalChunks: number;\n uploadedChunks: number;\n percentage: number;\n status: string;\n uploadedSize: number;\n}\n\n/**\n * API响应包装类型\n */\nexport interface ApiResponse<T> {\n code: number;\n message: string;\n data: T;\n timestamp: number;\n}\n\n/**\n * 上传配置选项\n */\nexport interface UploadOptions {\n /** 分片大小(字节),默认 2MB */\n chunkSize?: number;\n /** 并发上传数量,默认 3 */\n concurrency?: number;\n /** 重试次数,默认 3 */\n retryCount?: number;\n /** 重试延迟(毫秒),默认 1000 */\n retryDelay?: number;\n /** 基础API地址 */\n baseURL?: string;\n /** 请求头 */\n headers?: Record<string, string>;\n /** 上传进度回调 */\n onProgress?: (progress: UploadProgress) => void;\n /** 上传完成回调 */\n onComplete?: (result: CompleteUploadResponse) => void;\n /** 上传错误回调 */\n onError?: (error: Error) => void;\n}\n\n/**\n * 上传状态\n */\nexport enum UploadStatus {\n PENDING = 'pending',\n UPLOADING = 'uploading',\n PAUSED = 'paused',\n COMPLETED = 'completed',\n FAILED = 'failed',\n CANCELLED = 'cancelled',\n}\n\n/**\n * 文件分片信息\n */\nexport interface ChunkInfo {\n index: number;\n start: number;\n end: number;\n blob: Blob;\n md5?: string;\n}\n","/**\n * 文件分片上传工具类\n * 支持分片上传、断点续传、进度追踪、暂停/恢复/取消\n *\n * @example\n * ```typescript\n * import { createUploader } from '@alibarbar/common/upload';\n *\n * const uploader = createUploader(file, {\n * chunkSize: 2 * 1024 * 1024, // 2MB\n * concurrency: 3,\n * baseURL: 'https://api.example.com',\n * onProgress: (progress) => {\n * console.log(`进度:${progress.percentage}%`);\n * },\n * onComplete: (result) => {\n * console.log('上传完成:', result.fileUrl);\n * },\n * onError: (error) => {\n * console.error('上传失败:', error);\n * }\n * });\n *\n * // 开始上传\n * await uploader.upload();\n * ```\n */\n\nimport {\n UploadOptions,\n UploadInitRequest,\n UploadInitResponse,\n ChunkUploadResponse,\n CompleteUploadResponse,\n UploadProgress,\n UploadStatus,\n ChunkInfo,\n ApiResponse,\n} from '../types/upload';\nimport { calculateBlobMD5, splitFileIntoChunks } from './file';\n\n/**\n * 文件上传器类\n */\nexport class ChunkUploader {\n private file: File;\n private options: Required<UploadOptions>;\n private taskId: string | null = null;\n private chunks: ChunkInfo[] = [];\n private uploadedChunks: Set<number> = new Set();\n private status: UploadStatus = UploadStatus.PENDING;\n private abortController: AbortController | null = null;\n\n constructor(file: File, options: UploadOptions = {}) {\n this.file = file;\n this.options = {\n chunkSize: options.chunkSize || 2 * 1024 * 1024, // 默认2MB\n concurrency: options.concurrency || 3,\n retryCount: options.retryCount || 3,\n retryDelay: options.retryDelay || 1000,\n baseURL: options.baseURL || '',\n headers: options.headers || {},\n onProgress: options.onProgress || (() => {}),\n onComplete: options.onComplete || (() => {}),\n onError: options.onError || (() => {}),\n };\n }\n\n /**\n * 初始化上传\n */\n private async initUpload(): Promise<UploadInitResponse> {\n const fileMd5 = await this.calculateFileMD5();\n const request: UploadInitRequest = {\n fileName: this.file.name,\n fileSize: this.file.size,\n fileMd5,\n chunkSize: this.options.chunkSize,\n };\n\n const response = await this.request<ApiResponse<UploadInitResponse>>('/api/files/common/init', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...this.options.headers,\n },\n body: JSON.stringify(request),\n });\n\n if (response.code !== 200) {\n throw new Error(response.message || '初始化上传失败');\n }\n\n return response.data;\n }\n\n /**\n * 计算文件MD5\n */\n private async calculateFileMD5(): Promise<string> {\n const chunks = splitFileIntoChunks(this.file, this.options.chunkSize);\n const md5Promises = chunks.map((chunk, index) =>\n calculateBlobMD5(chunk).then(md5 => ({ index, md5 }))\n );\n const md5Results = await Promise.all(md5Promises);\n return md5Results.map(r => r.md5).join('');\n }\n\n /**\n * 准备分片\n */\n private prepareChunks(): void {\n const blobChunks = splitFileIntoChunks(this.file, this.options.chunkSize);\n this.chunks = blobChunks.map((blob, index) => ({\n index,\n start: index * this.options.chunkSize,\n end: Math.min((index + 1) * this.options.chunkSize, this.file.size),\n blob,\n }));\n }\n\n /**\n * 获取已上传的分片列表(用于断点续传)\n */\n private async getUploadedChunks(): Promise<number[]> {\n if (!this.taskId) return [];\n\n try {\n const response = await this.request<ApiResponse<number[]>>(\n `/api/files/common/chunks/${this.taskId}`,\n {\n method: 'GET',\n headers: this.options.headers,\n }\n );\n\n if (response.code === 200) {\n return response.data || [];\n }\n } catch (error) {\n console.warn('获取已上传分片失败:', error);\n }\n\n return [];\n }\n\n /**\n * 上传单个分片\n */\n private async uploadChunk(chunkInfo: ChunkInfo, retryCount = 0): Promise<void> {\n if (!this.taskId) {\n throw new Error('任务ID不存在');\n }\n\n if (this.uploadedChunks.has(chunkInfo.index)) {\n return; // 已上传,跳过\n }\n\n try {\n const chunkMd5 = await calculateBlobMD5(chunkInfo.blob);\n const formData = new FormData();\n formData.append('file', chunkInfo.blob, this.file.name);\n\n const url = `/api/files/common/chunk?taskId=${this.taskId}&chunkIndex=${chunkInfo.index}&chunkMd5=${chunkMd5}`;\n\n const response = await this.request<ApiResponse<ChunkUploadResponse>>(url, {\n method: 'POST',\n headers: this.options.headers,\n body: formData,\n });\n\n if (response.code === 200 && response.data.success) {\n this.uploadedChunks.add(chunkInfo.index);\n // 每上传一个分片,更新进度\n await this.updateProgress();\n } else {\n throw new Error(response.message || '分片上传失败');\n }\n } catch (error) {\n if (retryCount < this.options.retryCount) {\n await this.delay(this.options.retryDelay);\n return this.uploadChunk(chunkInfo, retryCount + 1);\n }\n throw error;\n }\n }\n\n /**\n * 并发上传分片\n */\n private async uploadChunksConcurrently(): Promise<void> {\n const chunksToUpload = this.chunks.filter(chunk => !this.uploadedChunks.has(chunk.index));\n\n if (chunksToUpload.length === 0) {\n return; // 所有分片已上传\n }\n\n let currentIndex = 0;\n const uploadNext = async (): Promise<void> => {\n while (this.status === UploadStatus.UPLOADING) {\n const chunkIndex = currentIndex++;\n if (chunkIndex >= chunksToUpload.length) {\n break;\n }\n const chunk = chunksToUpload[chunkIndex];\n await this.uploadChunk(chunk);\n }\n };\n\n // 启动并发任务\n const tasks = Array(this.options.concurrency)\n .fill(null)\n .map(() => uploadNext());\n await Promise.all(tasks);\n }\n\n /**\n * 更新上传进度(仅用于回调前端显示)\n */\n private async updateProgress(): Promise<void> {\n if (!this.taskId) return;\n\n try {\n const response = await this.request<ApiResponse<UploadProgress>>(\n `/api/files/common/progress/${this.taskId}`,\n {\n method: 'GET',\n headers: this.options.headers,\n }\n );\n\n if (response.code === 200 && response.data) {\n this.options.onProgress(response.data);\n }\n } catch (error) {\n console.warn('获取上传进度失败:', error);\n }\n }\n\n /**\n * 获取上传进度\n */\n private async getUploadProgress(): Promise<UploadProgress | null> {\n if (!this.taskId) {\n return null;\n }\n\n try {\n const response = await this.request<ApiResponse<UploadProgress>>(\n `/api/files/common/progress/${this.taskId}`,\n {\n method: 'GET',\n headers: this.options.headers,\n }\n );\n\n if (response.code === 200 && response.data) {\n console.log('[获取进度]', response.data);\n return response.data;\n }\n } catch (error) {\n console.warn('获取上传进度失败:', error);\n }\n\n return null;\n }\n\n /**\n * 完成上传(调用后端合并分片接口)\n */\n private async completeUpload(): Promise<CompleteUploadResponse> {\n if (!this.taskId) {\n throw new Error('任务ID不存在');\n }\n\n console.log('[完成上传] 调用完成接口:', `/api/files/common/complete/${this.taskId}`);\n\n const response = await this.request<ApiResponse<CompleteUploadResponse>>(\n `/api/files/common/complete/${this.taskId}`,\n {\n method: 'POST',\n headers: this.options.headers,\n }\n );\n\n console.log('[完成上传] 接口响应:', response);\n\n if (response.code !== 200) {\n throw new Error(response.message || '完成上传失败');\n }\n\n return response.data;\n }\n\n /**\n * 开始上传\n */\n async upload(): Promise<CompleteUploadResponse> {\n try {\n this.status = UploadStatus.UPLOADING;\n this.abortController = new AbortController();\n\n // 1. 初始化上传\n console.log('[上传流程] 1. 初始化上传');\n const initResponse = await this.initUpload();\n this.taskId = initResponse.taskId;\n\n // 2. 检查是否秒传\n if (initResponse.instantUpload && initResponse.fileUrl) {\n console.log('[上传流程] 秒传成功');\n this.status = UploadStatus.COMPLETED;\n const result: CompleteUploadResponse = {\n taskId: this.taskId,\n fileUrl: initResponse.fileUrl,\n fileName: this.file.name,\n fileSize: this.file.size,\n fileMd5: '',\n success: true,\n message: '文件已存在,秒传成功',\n };\n this.options.onComplete(result);\n return result;\n }\n\n // 3. 准备分片\n console.log('[上传流程] 2. 准备分片');\n this.prepareChunks();\n const totalChunks = this.chunks.length;\n console.log(`[上传流程] 共 ${totalChunks} 个分片`);\n\n // 4. 获取已上传的分片(断点续传)\n console.log('[上传流程] 3. 检查已上传分片');\n const existingChunks = await this.getUploadedChunks();\n existingChunks.forEach(index => this.uploadedChunks.add(index));\n console.log(\n `[上传流程] 已上传 ${existingChunks.length} 个分片,还需上传 ${totalChunks - existingChunks.length} 个`\n );\n\n // 5. 上传分片\n console.log('[上传流程] 4. 开始上传分片');\n await this.uploadChunksConcurrently();\n console.log('[上传流程] 5. 所有分片上传完成');\n\n // 6. 验证所有分片都已上传\n const uploadedCount = this.uploadedChunks.size;\n if (uploadedCount < totalChunks) {\n throw new Error(`上传验证失败:已上传 ${uploadedCount}/${totalChunks} 个分片`);\n }\n console.log(`[上传流程] 6. 验证通过:${uploadedCount}/${totalChunks} 个分片已上传`);\n\n // 7. 计算本地进度\n const localPercentage = Math.round((uploadedCount / totalChunks) * 100);\n console.log(`[上传流程] 7. 本地进度:${localPercentage}%`);\n\n // 8. 获取服务端进度\n console.log('[上传流程] 8. 获取服务端进度');\n const serverProgress = await this.getUploadProgress();\n const serverPercentage = serverProgress?.percentage ?? 0;\n console.log(`[上传流程] 服务端进度:${serverPercentage}%`);\n\n // 9. 计算最终进度(优先使用服务端进度)\n const finalPercentage = serverProgress?.percentage ?? localPercentage;\n console.log(`[上传流程] 9. 最终进度:${finalPercentage}%`);\n\n // 10. 判断是否可以调用完成接口\n if (finalPercentage >= 100) {\n console.log('[上传流程] 10. ✅ 进度达到100%,调用完成接口');\n const result = await this.completeUpload();\n\n this.status = UploadStatus.COMPLETED;\n this.options.onComplete(result);\n\n console.log('[上传流程] ✅ 上传完成');\n return result;\n } else {\n console.error(`[上传流程] ❌ 进度不足100%:${finalPercentage}%`);\n throw new Error(`上传未完成:当前进度 ${finalPercentage.toFixed(2)}%`);\n }\n } catch (error) {\n this.status = UploadStatus.FAILED;\n const err = error instanceof Error ? error : new Error(String(error));\n this.options.onError(err);\n console.error('[上传流程] ❌ 上传失败:', err);\n throw err;\n }\n }\n\n /**\n * 暂停上传\n */\n pause(): void {\n if (this.status === UploadStatus.UPLOADING) {\n this.status = UploadStatus.PAUSED;\n if (this.abortController) {\n this.abortController.abort();\n }\n }\n }\n\n /**\n * 恢复上传\n */\n async resume(): Promise<CompleteUploadResponse> {\n if (this.status === UploadStatus.PAUSED) {\n return this.upload();\n }\n throw new Error('当前状态无法恢复上传');\n }\n\n /**\n * 取消上传\n */\n async cancel(): Promise<void> {\n if (this.taskId && this.status === UploadStatus.UPLOADING) {\n try {\n await this.request<ApiResponse<null>>(`/api/files/common/cancel/${this.taskId}`, {\n method: 'POST',\n headers: this.options.headers,\n });\n } catch (error) {\n console.warn('取消上传失败:', error);\n }\n }\n\n this.status = UploadStatus.CANCELLED;\n if (this.abortController) {\n this.abortController.abort();\n }\n }\n\n /**\n * 获取当前状态\n */\n getStatus(): UploadStatus {\n return this.status;\n }\n\n /**\n * 获取任务ID\n */\n getTaskId(): string | null {\n return this.taskId;\n }\n\n /**\n * HTTP请求封装\n */\n private async request<T>(url: string, options: RequestInit = {}): Promise<T> {\n const fullUrl = `${this.options.baseURL}${url}`;\n const signal = this.abortController?.signal;\n\n const response = await fetch(fullUrl, {\n ...options,\n signal,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP错误: ${response.status} ${response.statusText}`);\n }\n\n return response.json();\n }\n\n /**\n * 延迟函数\n */\n private delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}\n\n/**\n * 创建文件上传器实例\n * @param file - 文件对象\n * @param options - 上传配置选项\n * @returns 上传器实例\n */\nexport function createUploader(file: File, options?: UploadOptions): ChunkUploader {\n return new ChunkUploader(file, options);\n}\n\n/**\n * 简单的文件上传函数(Promise风格)\n * @param file - 文件对象\n * @param options - 上传配置选项\n * @returns Promise<CompleteUploadResponse>\n */\nexport async function uploadFile(\n file: File,\n options?: UploadOptions\n): Promise<CompleteUploadResponse> {\n const uploader = createUploader(file, options);\n return uploader.upload();\n}\n"]}
@@ -1,39 +0,0 @@
1
- var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
- }) : x)(function(x) {
10
- if (typeof require !== "undefined") return require.apply(this, arguments);
11
- throw Error('Dynamic require of "' + x + '" is not supported');
12
- });
13
- var __commonJS = (cb, mod) => function __require2() {
14
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
15
- };
16
- var __export = (target, all) => {
17
- for (var name in all)
18
- __defProp(target, name, { get: all[name], enumerable: true });
19
- };
20
- var __copyProps = (to, from, except, desc) => {
21
- if (from && typeof from === "object" || typeof from === "function") {
22
- for (let key of __getOwnPropNames(from))
23
- if (!__hasOwnProp.call(to, key) && key !== except)
24
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
25
- }
26
- return to;
27
- };
28
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
29
- // If the importer is in node compatibility mode or this is not an ESM
30
- // file that has been converted to a CommonJS file using a Babel-
31
- // compatible transform (i.e. "__esModule" has not been set), then set
32
- // "default" to the CommonJS "module.exports" for node compatibility.
33
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
- mod
35
- ));
36
-
37
- export { __commonJS, __export, __require, __toESM };
38
- //# sourceMappingURL=chunk-FJ6ZGZIA.mjs.map
39
- //# sourceMappingURL=chunk-FJ6ZGZIA.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-FJ6ZGZIA.mjs"}