sa2kit 1.6.44 → 1.6.45

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 (267) hide show
  1. package/dist/AliyunOSSProvider-2FARPAQD.js +15 -0
  2. package/dist/{AliyunOSSProvider-HCNGDJL7.js.map → AliyunOSSProvider-2FARPAQD.js.map} +1 -1
  3. package/dist/AliyunOSSProvider-UMVGVBDJ.mjs +9 -0
  4. package/dist/{AliyunOSSProvider-4W47OFEK.mjs.map → AliyunOSSProvider-UMVGVBDJ.mjs.map} +1 -1
  5. package/dist/CollisionBalls-BpHufX3H.d.mts +41 -0
  6. package/dist/CollisionBalls-BpHufX3H.d.ts +41 -0
  7. package/dist/ConfigService-QR67WYNK.mjs +4 -0
  8. package/dist/{ConfigService-V6ZK273Z.mjs.map → ConfigService-QR67WYNK.mjs.map} +1 -1
  9. package/dist/{ConfigService-3DIC6C3Q.js → ConfigService-UYC6ZTCM.js} +3 -3
  10. package/dist/{ConfigService-3DIC6C3Q.js.map → ConfigService-UYC6ZTCM.js.map} +1 -1
  11. package/dist/GenericOrderManager-e4WizpNf.d.mts +28 -0
  12. package/dist/GenericOrderManager-e4WizpNf.d.ts +28 -0
  13. package/dist/LocalStorageProvider-JQF5WK5H.js +15 -0
  14. package/dist/{LocalStorageProvider-PP7MA5OT.js.map → LocalStorageProvider-JQF5WK5H.js.map} +1 -1
  15. package/dist/LocalStorageProvider-PYOHETJV.mjs +9 -0
  16. package/dist/{LocalStorageProvider-3RVPCQB3.mjs.map → LocalStorageProvider-PYOHETJV.mjs.map} +1 -1
  17. package/dist/PMXParser-RLBDO7YK.mjs +4 -0
  18. package/dist/{PMXParser-RNVQL76A.mjs.map → PMXParser-RLBDO7YK.mjs.map} +1 -1
  19. package/dist/{PMXParser-2VTA737I.js → PMXParser-XHNO2KNI.js} +3 -3
  20. package/dist/{PMXParser-2VTA737I.js.map → PMXParser-XHNO2KNI.js.map} +1 -1
  21. package/dist/UniversalFileService-RBV6EN5J.js +15 -0
  22. package/dist/UniversalFileService-RBV6EN5J.js.map +1 -0
  23. package/dist/UniversalFileService-TNYKO6JN.mjs +9 -0
  24. package/dist/UniversalFileService-TNYKO6JN.mjs.map +1 -0
  25. package/dist/analytics/index.js +1 -1
  26. package/dist/analytics/index.mjs +1 -1
  27. package/dist/analytics/server/index.js +1 -1
  28. package/dist/analytics/server/index.mjs +1 -1
  29. package/dist/api/index.js +1 -1
  30. package/dist/api/index.mjs +1 -1
  31. package/dist/audioDetection/index.js +1 -1
  32. package/dist/audioDetection/index.mjs +1 -1
  33. package/dist/auth/client/index.js +1 -1
  34. package/dist/auth/client/index.mjs +1 -1
  35. package/dist/auth/components/index.js +1 -1
  36. package/dist/auth/components/index.mjs +1 -1
  37. package/dist/auth/hooks/index.js +1 -1
  38. package/dist/auth/hooks/index.mjs +1 -1
  39. package/dist/auth/index.js +1 -1
  40. package/dist/auth/index.mjs +1 -1
  41. package/dist/auth/middleware/index.js +1 -1
  42. package/dist/auth/middleware/index.mjs +1 -1
  43. package/dist/auth/routes/index.js +1 -1
  44. package/dist/auth/routes/index.mjs +1 -1
  45. package/dist/auth/schema/index.js +1 -1
  46. package/dist/auth/schema/index.mjs +1 -1
  47. package/dist/auth/services/index.js +1 -1
  48. package/dist/auth/services/index.mjs +1 -1
  49. package/dist/calendar/index.js +12 -12
  50. package/dist/calendar/index.mjs +5 -5
  51. package/dist/calendar/routes/index.js +1 -1
  52. package/dist/calendar/routes/index.mjs +1 -1
  53. package/dist/calendar/server.js +1 -1
  54. package/dist/calendar/server.mjs +1 -1
  55. package/dist/chunk-2PS5PIXV.mjs +443 -0
  56. package/dist/chunk-2PS5PIXV.mjs.map +1 -0
  57. package/dist/chunk-35CXIK5Y.js +277 -0
  58. package/dist/chunk-35CXIK5Y.js.map +1 -0
  59. package/dist/{chunk-GMIUSZXC.mjs → chunk-3JW4X3AC.mjs} +3 -3
  60. package/dist/{chunk-GMIUSZXC.mjs.map → chunk-3JW4X3AC.mjs.map} +1 -1
  61. package/dist/chunk-3M6T5KVD.js +453 -0
  62. package/dist/chunk-3M6T5KVD.js.map +1 -0
  63. package/dist/chunk-3TNR6IMC.js +168 -0
  64. package/dist/chunk-3TNR6IMC.js.map +1 -0
  65. package/dist/chunk-4NFOSCM6.js +34 -0
  66. package/dist/chunk-4NFOSCM6.js.map +1 -0
  67. package/dist/{chunk-3NHAT7D4.mjs → chunk-4VJQZSPU.mjs} +4 -3
  68. package/dist/chunk-4VJQZSPU.mjs.map +1 -0
  69. package/dist/{chunk-SCDDMIF6.js → chunk-4XXIBWCO.js} +66 -66
  70. package/dist/{chunk-SCDDMIF6.js.map → chunk-4XXIBWCO.js.map} +1 -1
  71. package/dist/chunk-6AHYPPUP.js +344 -0
  72. package/dist/chunk-6AHYPPUP.js.map +1 -0
  73. package/dist/{chunk-EGJPS7OL.mjs → chunk-6BJ76BYC.mjs} +3 -3
  74. package/dist/{chunk-EGJPS7OL.mjs.map → chunk-6BJ76BYC.mjs.map} +1 -1
  75. package/dist/chunk-76V7EKBX.mjs +796 -0
  76. package/dist/chunk-76V7EKBX.mjs.map +1 -0
  77. package/dist/chunk-ACLOJXXE.js +195 -0
  78. package/dist/chunk-ACLOJXXE.js.map +1 -0
  79. package/dist/chunk-AEXPAH7Z.mjs +32 -0
  80. package/dist/chunk-AEXPAH7Z.mjs.map +1 -0
  81. package/dist/chunk-CFGX3EKK.js +560 -0
  82. package/dist/chunk-CFGX3EKK.js.map +1 -0
  83. package/dist/chunk-D2HXMGXS.js +46 -0
  84. package/dist/chunk-D2HXMGXS.js.map +1 -0
  85. package/dist/chunk-DM2GUVUH.js +1201 -0
  86. package/dist/chunk-DM2GUVUH.js.map +1 -0
  87. package/dist/{chunk-ZWQJSZEY.js → chunk-DVENFCQY.js} +5 -4
  88. package/dist/chunk-DVENFCQY.js.map +1 -0
  89. package/dist/chunk-EONPKLEJ.mjs +163 -0
  90. package/dist/chunk-EONPKLEJ.mjs.map +1 -0
  91. package/dist/{chunk-L47ZOYHL.js → chunk-EUIXQPPU.js} +4 -4
  92. package/dist/{chunk-L47ZOYHL.js.map → chunk-EUIXQPPU.js.map} +1 -1
  93. package/dist/chunk-K7WNCB4V.mjs +554 -0
  94. package/dist/chunk-K7WNCB4V.mjs.map +1 -0
  95. package/dist/chunk-L4ZYBFB2.mjs +44 -0
  96. package/dist/chunk-L4ZYBFB2.mjs.map +1 -0
  97. package/dist/chunk-M4HGHTIC.js +820 -0
  98. package/dist/chunk-M4HGHTIC.js.map +1 -0
  99. package/dist/{chunk-HHVDOIPV.js → chunk-MZKATHB7.js} +4 -4
  100. package/dist/{chunk-HHVDOIPV.js.map → chunk-MZKATHB7.js.map} +1 -1
  101. package/dist/{chunk-UKT3PLON.mjs → chunk-NXQVTAOP.mjs} +3 -3
  102. package/dist/{chunk-UKT3PLON.mjs.map → chunk-NXQVTAOP.mjs.map} +1 -1
  103. package/dist/chunk-OBIPI4GU.mjs +266 -0
  104. package/dist/chunk-OBIPI4GU.mjs.map +1 -0
  105. package/dist/chunk-PAX4S7QM.mjs +94 -0
  106. package/dist/chunk-PAX4S7QM.mjs.map +1 -0
  107. package/dist/chunk-PXWDQFWV.mjs +192 -0
  108. package/dist/chunk-PXWDQFWV.mjs.map +1 -0
  109. package/dist/chunk-QROLPPXP.mjs +5797 -0
  110. package/dist/chunk-QROLPPXP.mjs.map +1 -0
  111. package/dist/chunk-TGNUEULF.mjs +1158 -0
  112. package/dist/chunk-TGNUEULF.mjs.map +1 -0
  113. package/dist/chunk-VBQFVXOW.mjs +2772 -0
  114. package/dist/chunk-VBQFVXOW.mjs.map +1 -0
  115. package/dist/chunk-VLZ5N6XZ.js +5888 -0
  116. package/dist/chunk-VLZ5N6XZ.js.map +1 -0
  117. package/dist/chunk-VTGPHE4Z.mjs +322 -0
  118. package/dist/chunk-VTGPHE4Z.mjs.map +1 -0
  119. package/dist/chunk-WMJKH4XE.mjs +30 -0
  120. package/dist/{chunk-BJTO5JO5.mjs.map → chunk-WMJKH4XE.mjs.map} +1 -1
  121. package/dist/chunk-XYQMAF7H.js +96 -0
  122. package/dist/chunk-XYQMAF7H.js.map +1 -0
  123. package/dist/chunk-Z3G3IXEF.js +2814 -0
  124. package/dist/chunk-Z3G3IXEF.js.map +1 -0
  125. package/dist/chunk-Z6ZWNWWR.js +35 -0
  126. package/dist/{chunk-DGUM43GV.js.map → chunk-Z6ZWNWWR.js.map} +1 -1
  127. package/dist/components/index.d.mts +378 -0
  128. package/dist/components/index.d.ts +378 -0
  129. package/dist/components/index.js +414 -0
  130. package/dist/components/index.js.map +1 -0
  131. package/dist/components/index.mjs +9 -0
  132. package/dist/components/index.mjs.map +1 -0
  133. package/dist/config/index.js +1 -1
  134. package/dist/config/index.mjs +1 -1
  135. package/dist/config/server/index.js +1 -1
  136. package/dist/config/server/index.mjs +1 -1
  137. package/dist/fileService-O3W6YXCI.mjs +4 -0
  138. package/dist/fileService-O3W6YXCI.mjs.map +1 -0
  139. package/dist/fileService-YUDIYOAS.js +13 -0
  140. package/dist/fileService-YUDIYOAS.js.map +1 -0
  141. package/dist/i18n/index.js +7 -7
  142. package/dist/i18n/index.mjs +1 -1
  143. package/dist/imageCrop/index.js +1 -1
  144. package/dist/imageCrop/index.mjs +1 -1
  145. package/dist/index.d.mts +9 -580
  146. package/dist/index.d.ts +9 -580
  147. package/dist/index.js +297 -956
  148. package/dist/index.js.map +1 -1
  149. package/dist/index.mjs +103 -789
  150. package/dist/index.mjs.map +1 -1
  151. package/dist/logger/index.js +8 -8
  152. package/dist/logger/index.mjs +5 -2
  153. package/dist/mikuFireworks3D/index.js +1 -1
  154. package/dist/mikuFireworks3D/index.mjs +1 -1
  155. package/dist/mikuFireworks3D/server/index.js +1 -1
  156. package/dist/mikuFireworks3D/server/index.mjs +1 -1
  157. package/dist/mikuFusionGame/index.js +5 -5
  158. package/dist/mikuFusionGame/index.mjs +4 -4
  159. package/dist/mmd/admin/index.js +1 -1
  160. package/dist/mmd/admin/index.mjs +1 -1
  161. package/dist/mmd/index.js +2 -2
  162. package/dist/mmd/index.mjs +2 -2
  163. package/dist/mmd/server/index.js +1 -1
  164. package/dist/mmd/server/index.mjs +1 -1
  165. package/dist/music/index.js +1 -1
  166. package/dist/music/index.mjs +1 -1
  167. package/dist/music/server/index.js +1 -1
  168. package/dist/music/server/index.mjs +1 -1
  169. package/dist/navigation/index.d.mts +93 -0
  170. package/dist/navigation/index.d.ts +93 -0
  171. package/dist/navigation/index.js +29 -0
  172. package/dist/navigation/index.js.map +1 -0
  173. package/dist/navigation/index.mjs +4 -0
  174. package/dist/navigation/index.mjs.map +1 -0
  175. package/dist/popupConfig-BznThU1O.d.mts +330 -0
  176. package/dist/popupConfig-BznThU1O.d.ts +330 -0
  177. package/dist/portfolio/index.d.mts +57 -0
  178. package/dist/portfolio/index.d.ts +57 -0
  179. package/dist/portfolio/index.js +35 -0
  180. package/dist/portfolio/index.js.map +1 -0
  181. package/dist/portfolio/index.mjs +10 -0
  182. package/dist/portfolio/index.mjs.map +1 -0
  183. package/dist/request/index.js +1 -1
  184. package/dist/request/index.mjs +1 -1
  185. package/dist/showmasterpiece/index.d.mts +2524 -0
  186. package/dist/showmasterpiece/index.d.ts +2524 -0
  187. package/dist/showmasterpiece/index.js +9681 -0
  188. package/dist/showmasterpiece/index.js.map +1 -0
  189. package/dist/showmasterpiece/index.mjs +9631 -0
  190. package/dist/showmasterpiece/index.mjs.map +1 -0
  191. package/dist/showmasterpiece/migration/index.d.mts +120 -0
  192. package/dist/showmasterpiece/migration/index.d.ts +120 -0
  193. package/dist/showmasterpiece/migration/index.js +595 -0
  194. package/dist/showmasterpiece/migration/index.js.map +1 -0
  195. package/dist/showmasterpiece/migration/index.mjs +589 -0
  196. package/dist/showmasterpiece/migration/index.mjs.map +1 -0
  197. package/dist/showmasterpiece/scripts/index.d.mts +28 -0
  198. package/dist/showmasterpiece/scripts/index.d.ts +28 -0
  199. package/dist/showmasterpiece/scripts/index.js +327 -0
  200. package/dist/showmasterpiece/scripts/index.js.map +1 -0
  201. package/dist/showmasterpiece/scripts/index.mjs +325 -0
  202. package/dist/showmasterpiece/scripts/index.mjs.map +1 -0
  203. package/dist/showmasterpiece/server/index.d.mts +2698 -0
  204. package/dist/showmasterpiece/server/index.d.ts +2698 -0
  205. package/dist/showmasterpiece/server/index.js +179 -0
  206. package/dist/showmasterpiece/server/index.js.map +1 -0
  207. package/dist/showmasterpiece/server/index.mjs +6 -0
  208. package/dist/showmasterpiece/server/index.mjs.map +1 -0
  209. package/dist/storage/index.js +8 -8
  210. package/dist/storage/index.mjs +2 -2
  211. package/dist/testYourself/admin/index.js +1 -1
  212. package/dist/testYourself/admin/index.mjs +1 -1
  213. package/dist/testYourself/index.js +2 -2
  214. package/dist/testYourself/index.mjs +2 -2
  215. package/dist/testYourself/server/index.js +1 -1
  216. package/dist/testYourself/server/index.mjs +1 -1
  217. package/dist/universalExport/index.js +154 -1195
  218. package/dist/universalExport/index.js.map +1 -1
  219. package/dist/universalExport/index.mjs +2 -1157
  220. package/dist/universalExport/index.mjs.map +1 -1
  221. package/dist/universalExport/server/index.js +5 -3
  222. package/dist/universalExport/server/index.js.map +1 -1
  223. package/dist/universalExport/server/index.mjs +4 -2
  224. package/dist/universalExport/server/index.mjs.map +1 -1
  225. package/dist/universalFile/index.js +10 -7
  226. package/dist/universalFile/index.js.map +1 -1
  227. package/dist/universalFile/index.mjs +6 -2
  228. package/dist/universalFile/index.mjs.map +1 -1
  229. package/dist/universalFile/server/index.d.mts +592 -265
  230. package/dist/universalFile/server/index.d.ts +592 -265
  231. package/dist/universalFile/server/index.js +298 -5637
  232. package/dist/universalFile/server/index.js.map +1 -1
  233. package/dist/universalFile/server/index.mjs +8 -5559
  234. package/dist/universalFile/server/index.mjs.map +1 -1
  235. package/dist/utils/index.js +12 -12
  236. package/dist/utils/index.mjs +3 -3
  237. package/package.json +36 -1
  238. package/dist/AliyunOSSProvider-4W47OFEK.mjs +0 -6
  239. package/dist/AliyunOSSProvider-HCNGDJL7.js +0 -15
  240. package/dist/ConfigService-V6ZK273Z.mjs +0 -4
  241. package/dist/LocalStorageProvider-3RVPCQB3.mjs +0 -6
  242. package/dist/LocalStorageProvider-PP7MA5OT.js +0 -15
  243. package/dist/PMXParser-RNVQL76A.mjs +0 -4
  244. package/dist/chunk-25OFOKNF.js +0 -171
  245. package/dist/chunk-25OFOKNF.js.map +0 -1
  246. package/dist/chunk-3DXPQ4YV.mjs +0 -165
  247. package/dist/chunk-3DXPQ4YV.mjs.map +0 -1
  248. package/dist/chunk-3NHAT7D4.mjs.map +0 -1
  249. package/dist/chunk-BJTO5JO5.mjs +0 -10
  250. package/dist/chunk-CIVO4R6N.mjs +0 -37
  251. package/dist/chunk-CIVO4R6N.mjs.map +0 -1
  252. package/dist/chunk-DGUM43GV.js +0 -12
  253. package/dist/chunk-HDMIOOZY.mjs +0 -546
  254. package/dist/chunk-HDMIOOZY.mjs.map +0 -1
  255. package/dist/chunk-HJ6MH7J7.js +0 -552
  256. package/dist/chunk-HJ6MH7J7.js.map +0 -1
  257. package/dist/chunk-KH6RQ4J5.js +0 -28
  258. package/dist/chunk-KH6RQ4J5.js.map +0 -1
  259. package/dist/chunk-Q5EDCKQA.js +0 -336
  260. package/dist/chunk-Q5EDCKQA.js.map +0 -1
  261. package/dist/chunk-YOTQG4NP.mjs +0 -314
  262. package/dist/chunk-YOTQG4NP.mjs.map +0 -1
  263. package/dist/chunk-ZGVB35L2.mjs +0 -25
  264. package/dist/chunk-ZGVB35L2.mjs.map +0 -1
  265. package/dist/chunk-ZRAW3HXA.js +0 -43
  266. package/dist/chunk-ZRAW3HXA.js.map +0 -1
  267. package/dist/chunk-ZWQJSZEY.js.map +0 -1
@@ -1,1160 +1,5 @@
1
+ export { API_BASE_PATH, API_ENDPOINTS, DEFAULT_ADD_BOM, DEFAULT_CONFIG_CACHE_TTL, DEFAULT_CSV_DELIMITER, DEFAULT_ENCODING, DEFAULT_EXPORT_FORMAT, DEFAULT_EXPORT_TIMEOUT, DEFAULT_FORMATTERS, DEFAULT_MAX_CONCURRENT_EXPORTS, DEFAULT_MAX_FILE_SIZE, DEFAULT_MAX_ROWS, DEFAULT_RESULT_CACHE_TTL, ERROR_CODES, EXPORT_FORMAT_EXTENSIONS, EXPORT_FORMAT_MIME_TYPES, ExportConfigEditor, UNIVERSAL_EXPORT_NAME, UNIVERSAL_EXPORT_VERSION, UniversalExportButton, UniversalExportClient, applyFormatter, createExportClient, createExportError, escapeCSVField, estimateEndTime, formatDuration, formatErrorMessage, formatFileSize, generateExportFileName, getNestedValue, parseCSVField, sanitizeFileName, setNestedValue, universalExportClient, validateExportConfig, validateExportRequest, validateFileName } from '../chunk-TGNUEULF.mjs';
1
2
  export { ExportConfigError, ExportDataError, ExportFileError, ExportServiceError } from '../chunk-LFB5EIIM.mjs';
2
- import '../chunk-BJTO5JO5.mjs';
3
- import React, { useState, useCallback, useEffect } from 'react';
4
- import { clsx } from 'clsx';
5
- import { Settings, X, Eye, EyeOff, MoveUp, MoveDown, Trash2, Group, Save, Loader2, Download, ChevronDown, Type, Database, FileText, FileSpreadsheet } from 'lucide-react';
6
-
7
- // src/universalExport/constants.ts
8
- var UNIVERSAL_EXPORT_VERSION = "1.0.0";
9
- var UNIVERSAL_EXPORT_NAME = "@lyricnote/universal-export";
10
- var DEFAULT_EXPORT_FORMAT = "csv";
11
- var DEFAULT_CSV_DELIMITER = ",";
12
- var DEFAULT_ENCODING = "utf-8";
13
- var DEFAULT_ADD_BOM = true;
14
- var DEFAULT_MAX_FILE_SIZE = 100 * 1024 * 1024;
15
- var DEFAULT_MAX_ROWS = 1e5;
16
- var DEFAULT_MAX_CONCURRENT_EXPORTS = 5;
17
- var DEFAULT_EXPORT_TIMEOUT = 3e5;
18
- var DEFAULT_CONFIG_CACHE_TTL = 3600;
19
- var DEFAULT_RESULT_CACHE_TTL = 1800;
20
- var EXPORT_FORMAT_EXTENSIONS = {
21
- csv: "csv",
22
- excel: "xlsx",
23
- json: "json"
24
- };
25
- var EXPORT_FORMAT_MIME_TYPES = {
26
- csv: "text/csv; charset=utf-8",
27
- excel: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
28
- json: "application/json; charset=utf-8"
29
- };
30
- var API_BASE_PATH = "/api/universal-export";
31
- var API_ENDPOINTS = {
32
- /** 获取配置列表 */
33
- GET_CONFIGS: API_BASE_PATH + "/configs",
34
- /** 创建配置 */
35
- CREATE_CONFIG: API_BASE_PATH + "/configs",
36
- /** 更新配置 */
37
- UPDATE_CONFIG: (configId) => API_BASE_PATH + "/configs/" + configId,
38
- /** 删除配置 */
39
- DELETE_CONFIG: (configId) => API_BASE_PATH + "/configs/" + configId,
40
- /** 触发导出 */
41
- EXPORT_DATA: API_BASE_PATH + "/export",
42
- /** 查询导出进度 */
43
- GET_PROGRESS: (exportId) => API_BASE_PATH + "/export/" + exportId + "/progress",
44
- /** 下载导出文件 */
45
- DOWNLOAD_FILE: (exportId) => API_BASE_PATH + "/export/" + exportId + "/download"
46
- };
47
- var ERROR_CODES = {
48
- /** 导出配置错误 */
49
- EXPORT_CONFIG_ERROR: "EXPORT_CONFIG_ERROR",
50
- /** 导出数据错误 */
51
- EXPORT_DATA_ERROR: "EXPORT_DATA_ERROR",
52
- /** 导出文件错误 */
53
- EXPORT_FILE_ERROR: "EXPORT_FILE_ERROR",
54
- /** 网络错误 */
55
- NETWORK_ERROR: "NETWORK_ERROR",
56
- /** 超时错误 */
57
- TIMEOUT_ERROR: "TIMEOUT_ERROR",
58
- /** 未授权 */
59
- UNAUTHORIZED: "UNAUTHORIZED",
60
- /** 服务器错误 */
61
- SERVER_ERROR: "SERVER_ERROR"
62
- };
63
-
64
- // src/universalExport/utils.ts
65
- function generateExportFileName(template, format) {
66
- const now = /* @__PURE__ */ new Date();
67
- const dateStr = now.toISOString().split("T")[0] || "";
68
- const timeStr = (now.toTimeString().split(" ")[0] || "").replace(/:/g, "-");
69
- const extension = EXPORT_FORMAT_EXTENSIONS[format];
70
- return template.replace("{date}", dateStr).replace("{time}", timeStr).replace("{timestamp}", now.getTime().toString()) + "." + extension;
71
- }
72
- function validateFileName(fileName) {
73
- const invalidChars = /[<>:"|?*\/\\]/;
74
- if (invalidChars.test(fileName)) {
75
- return false;
76
- }
77
- if (fileName.length === 0 || fileName.length > 255) {
78
- return false;
79
- }
80
- return true;
81
- }
82
- function sanitizeFileName(fileName) {
83
- return fileName.replace(/[<>:"|?*\/\\]/g, "_").substring(0, 255);
84
- }
85
- function escapeCSVField(value, delimiter = ",") {
86
- const valueStr = String(value || "");
87
- if (valueStr.includes(delimiter) || valueStr.includes('"') || valueStr.includes("\n")) {
88
- return '"' + valueStr.replace(/"/g, '""') + '"';
89
- }
90
- return valueStr;
91
- }
92
- function parseCSVField(field) {
93
- if (field.startsWith('"') && field.endsWith('"')) {
94
- return field.slice(1, -1).replace(/""/g, '"');
95
- }
96
- return field;
97
- }
98
- var DEFAULT_FORMATTERS = {
99
- // 日期格式化
100
- date: (value) => {
101
- if (!value) return "";
102
- const date = new Date(value);
103
- if (isNaN(date.getTime())) return String(value);
104
- return date.toISOString().split("T")[0] || "";
105
- },
106
- // 时间格式化
107
- datetime: (value) => {
108
- if (!value) return "";
109
- const date = new Date(value);
110
- if (isNaN(date.getTime())) return String(value);
111
- return date.toLocaleString("zh-CN");
112
- },
113
- // 数字格式化
114
- number: (value) => {
115
- if (value === null || value === void 0) return "";
116
- return String(value);
117
- },
118
- // 货币格式化
119
- currency: (value) => {
120
- if (value === null || value === void 0) return "";
121
- return "\xA5" + Number(value).toFixed(2);
122
- },
123
- // 百分比格式化
124
- percentage: (value) => {
125
- if (value === null || value === void 0) return "";
126
- return (Number(value) * 100).toFixed(2) + "%";
127
- },
128
- // 布尔值格式化
129
- boolean: (value) => {
130
- if (value === null || value === void 0) return "";
131
- return value ? "\u662F" : "\u5426";
132
- },
133
- // 数组格式化
134
- array: (value) => {
135
- if (!Array.isArray(value)) return "";
136
- return value.join(", ");
137
- },
138
- // 对象格式化
139
- object: (value) => {
140
- if (!value || typeof value !== "object") return "";
141
- return JSON.stringify(value);
142
- }
143
- };
144
- function applyFormatter(value, formatter, type) {
145
- if (formatter) {
146
- return formatter(value);
147
- }
148
- if (type && DEFAULT_FORMATTERS[type]) {
149
- return DEFAULT_FORMATTERS[type](value);
150
- }
151
- return String(value || "");
152
- }
153
- function validateExportConfig(config) {
154
- const errors = [];
155
- if (!config.name || config.name.trim() === "") {
156
- errors.push("\u914D\u7F6E\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");
157
- }
158
- if (!config.fields || !Array.isArray(config.fields) || config.fields.length === 0) {
159
- errors.push("\u81F3\u5C11\u9700\u8981\u5B9A\u4E49\u4E00\u4E2A\u5B57\u6BB5");
160
- }
161
- if (config.fields) {
162
- const enabledFields = config.fields.filter((f) => f.enabled);
163
- if (enabledFields.length === 0) {
164
- errors.push("\u81F3\u5C11\u9700\u8981\u542F\u7528\u4E00\u4E2A\u5B57\u6BB5");
165
- }
166
- const keys = config.fields.map((f) => f.key);
167
- const uniqueKeys = new Set(keys);
168
- if (keys.length !== uniqueKeys.size) {
169
- errors.push("\u5B57\u6BB5\u952E\u540D\u5FC5\u987B\u552F\u4E00");
170
- }
171
- }
172
- return {
173
- valid: errors.length === 0,
174
- errors
175
- };
176
- }
177
- function validateExportRequest(request) {
178
- const errors = [];
179
- if (!request.configId) {
180
- errors.push("\u5BFC\u51FA\u914D\u7F6EID\u4E0D\u80FD\u4E3A\u7A7A");
181
- }
182
- if (!request.dataSource) {
183
- errors.push("\u6570\u636E\u6E90\u4E0D\u80FD\u4E3A\u7A7A");
184
- }
185
- return {
186
- valid: errors.length === 0,
187
- errors
188
- };
189
- }
190
- function formatFileSize(bytes) {
191
- if (bytes === 0) return "0 B";
192
- const units = ["B", "KB", "MB", "GB", "TB"];
193
- const k = 1024;
194
- const i = Math.floor(Math.log(bytes) / Math.log(k));
195
- return (bytes / Math.pow(k, i)).toFixed(2) + " " + units[i];
196
- }
197
- function formatDuration(milliseconds) {
198
- if (milliseconds < 1e3) {
199
- return milliseconds + "ms";
200
- }
201
- const seconds = Math.floor(milliseconds / 1e3);
202
- if (seconds < 60) {
203
- return seconds + "\u79D2";
204
- }
205
- const minutes = Math.floor(seconds / 60);
206
- const remainingSeconds = seconds % 60;
207
- if (minutes < 60) {
208
- return remainingSeconds > 0 ? minutes + "\u5206" + remainingSeconds + "\u79D2" : minutes + "\u5206\u949F";
209
- }
210
- const hours = Math.floor(minutes / 60);
211
- const remainingMinutes = minutes % 60;
212
- return remainingMinutes > 0 ? hours + "\u5C0F\u65F6" + remainingMinutes + "\u5206\u949F" : hours + "\u5C0F\u65F6";
213
- }
214
- function estimateEndTime(startTime, processedRows, totalRows) {
215
- if (processedRows === 0 || totalRows === 0) {
216
- return void 0;
217
- }
218
- const elapsed = Date.now() - startTime.getTime();
219
- const avgTimePerRow = elapsed / processedRows;
220
- const remainingRows = totalRows - processedRows;
221
- const remainingTime = avgTimePerRow * remainingRows;
222
- return new Date(Date.now() + remainingTime);
223
- }
224
- function getNestedValue(obj, path) {
225
- return path.split(".").reduce((current, key) => {
226
- return current && current[key] !== void 0 ? current[key] : null;
227
- }, obj);
228
- }
229
- function setNestedValue(obj, path, value) {
230
- const keys = path.split(".");
231
- const lastKey = keys.pop();
232
- if (!lastKey) return;
233
- const target = keys.reduce((current, key) => {
234
- if (!current[key] || typeof current[key] !== "object") {
235
- current[key] = {};
236
- }
237
- return current[key];
238
- }, obj);
239
- target[lastKey] = value;
240
- }
241
- function createExportError(code, message, details) {
242
- return {
243
- code,
244
- message,
245
- details,
246
- timestamp: /* @__PURE__ */ new Date()
247
- };
248
- }
249
- function formatErrorMessage(error) {
250
- if (error instanceof Error) {
251
- return error.message;
252
- }
253
- if (typeof error === "string") {
254
- return error;
255
- }
256
- return "\u672A\u77E5\u9519\u8BEF";
257
- }
258
-
259
- // src/universalExport/client.ts
260
- var UniversalExportClient = class {
261
- constructor(config = {}) {
262
- this.config = {
263
- baseUrl: config.baseUrl || "",
264
- timeout: config.timeout || 3e4,
265
- headers: config.headers || {}
266
- };
267
- }
268
- // ============= 配置管理API =============
269
- /**
270
- * 获取模块的导出配置列表
271
- */
272
- async getConfigsByModule(moduleId, businessId) {
273
- const params = new URLSearchParams({ moduleId });
274
- if (businessId) {
275
- params.append("businessId", businessId);
276
- }
277
- const url = this.config.baseUrl + API_ENDPOINTS.GET_CONFIGS + "?" + params;
278
- try {
279
- const response = await this.fetchWithTimeout(url, {
280
- method: "GET",
281
- headers: this.getHeaders()
282
- });
283
- if (!response.ok) {
284
- throw new Error("\u83B7\u53D6\u914D\u7F6E\u5931\u8D25: " + response.statusText);
285
- }
286
- const data = await response.json();
287
- return this.transformConfigsFromAPI(data.configs || []);
288
- } catch (error) {
289
- throw createExportError(
290
- ERROR_CODES.NETWORK_ERROR,
291
- "\u83B7\u53D6\u5BFC\u51FA\u914D\u7F6E\u5931\u8D25: " + formatErrorMessage(error),
292
- { moduleId, businessId, originalError: error }
293
- );
294
- }
295
- }
296
- /**
297
- * 创建导出配置
298
- */
299
- async createConfig(config) {
300
- const url = this.config.baseUrl + API_ENDPOINTS.CREATE_CONFIG;
301
- try {
302
- const response = await this.fetchWithTimeout(url, {
303
- method: "POST",
304
- headers: {
305
- ...this.getHeaders(),
306
- "Content-Type": "application/json"
307
- },
308
- body: JSON.stringify(config)
309
- });
310
- if (!response.ok) {
311
- throw new Error("\u521B\u5EFA\u914D\u7F6E\u5931\u8D25: " + response.statusText);
312
- }
313
- const data = await response.json();
314
- return this.transformConfigFromAPI(data.config);
315
- } catch (error) {
316
- throw createExportError(
317
- ERROR_CODES.NETWORK_ERROR,
318
- "\u521B\u5EFA\u5BFC\u51FA\u914D\u7F6E\u5931\u8D25: " + formatErrorMessage(error),
319
- { config, originalError: error }
320
- );
321
- }
322
- }
323
- /**
324
- * 更新导出配置
325
- */
326
- async updateConfig(configId, updates) {
327
- const url = this.config.baseUrl + API_ENDPOINTS.UPDATE_CONFIG(configId);
328
- try {
329
- const response = await this.fetchWithTimeout(url, {
330
- method: "PUT",
331
- headers: {
332
- ...this.getHeaders(),
333
- "Content-Type": "application/json"
334
- },
335
- body: JSON.stringify(updates)
336
- });
337
- if (!response.ok) {
338
- throw new Error("\u66F4\u65B0\u914D\u7F6E\u5931\u8D25: " + response.statusText);
339
- }
340
- const data = await response.json();
341
- return this.transformConfigFromAPI(data.config);
342
- } catch (error) {
343
- throw createExportError(
344
- ERROR_CODES.NETWORK_ERROR,
345
- "\u66F4\u65B0\u5BFC\u51FA\u914D\u7F6E\u5931\u8D25: " + formatErrorMessage(error),
346
- { configId, updates, originalError: error }
347
- );
348
- }
349
- }
350
- /**
351
- * 删除导出配置
352
- */
353
- async deleteConfig(configId) {
354
- const url = this.config.baseUrl + API_ENDPOINTS.DELETE_CONFIG(configId);
355
- try {
356
- const response = await this.fetchWithTimeout(url, {
357
- method: "DELETE",
358
- headers: this.getHeaders()
359
- });
360
- if (!response.ok) {
361
- throw new Error("\u5220\u9664\u914D\u7F6E\u5931\u8D25: " + response.statusText);
362
- }
363
- } catch (error) {
364
- throw createExportError(
365
- ERROR_CODES.NETWORK_ERROR,
366
- "\u5220\u9664\u5BFC\u51FA\u914D\u7F6E\u5931\u8D25: " + formatErrorMessage(error),
367
- { configId, originalError: error }
368
- );
369
- }
370
- }
371
- // ============= 导出执行API =============
372
- /**
373
- * 触发数据导出
374
- */
375
- async exportData(request) {
376
- const url = this.config.baseUrl + API_ENDPOINTS.EXPORT_DATA;
377
- try {
378
- const isDataArray = Array.isArray(request.dataSource);
379
- const requestBody = {
380
- configId: request.configId,
381
- queryParams: request.queryParams,
382
- fieldMapping: request.fieldMapping,
383
- filters: request.filters,
384
- sortBy: request.sortBy,
385
- pagination: request.pagination,
386
- customFileName: request.customFileName
387
- };
388
- if (isDataArray) {
389
- requestBody.data = request.dataSource;
390
- } else {
391
- requestBody.dataSource = request.dataSource;
392
- }
393
- const response = await this.fetchWithTimeout(url, {
394
- method: "POST",
395
- headers: {
396
- ...this.getHeaders(),
397
- "Content-Type": "application/json"
398
- },
399
- body: JSON.stringify(requestBody)
400
- });
401
- if (!response.ok) {
402
- const errorText = await response.text();
403
- let errorData;
404
- try {
405
- errorData = JSON.parse(errorText);
406
- } catch {
407
- errorData = { message: errorText };
408
- }
409
- throw new Error(errorData.message || "\u5BFC\u51FA\u5931\u8D25: " + response.statusText);
410
- }
411
- const data = await response.json();
412
- return this.transformExportResultFromAPI(data.result);
413
- } catch (error) {
414
- throw createExportError(
415
- ERROR_CODES.EXPORT_DATA_ERROR,
416
- "\u6570\u636E\u5BFC\u51FA\u5931\u8D25: " + formatErrorMessage(error),
417
- { request, originalError: error }
418
- );
419
- }
420
- }
421
- /**
422
- * 查询导出进度
423
- */
424
- async getExportProgress(exportId) {
425
- const url = this.config.baseUrl + API_ENDPOINTS.GET_PROGRESS(exportId);
426
- try {
427
- const response = await this.fetchWithTimeout(url, {
428
- method: "GET",
429
- headers: this.getHeaders()
430
- });
431
- if (!response.ok) {
432
- throw new Error("\u83B7\u53D6\u5BFC\u51FA\u8FDB\u5EA6\u5931\u8D25: " + response.statusText);
433
- }
434
- const data = await response.json();
435
- return this.transformProgressFromAPI(data.progress);
436
- } catch (error) {
437
- throw createExportError(
438
- ERROR_CODES.NETWORK_ERROR,
439
- "\u83B7\u53D6\u5BFC\u51FA\u8FDB\u5EA6\u5931\u8D25: " + formatErrorMessage(error),
440
- { exportId, originalError: error }
441
- );
442
- }
443
- }
444
- /**
445
- * 下载导出文件
446
- */
447
- async downloadExportFile(exportId) {
448
- const url = this.config.baseUrl + API_ENDPOINTS.DOWNLOAD_FILE(exportId);
449
- try {
450
- const response = await this.fetchWithTimeout(url, {
451
- method: "GET",
452
- headers: this.getHeaders()
453
- });
454
- if (!response.ok) {
455
- throw new Error("\u4E0B\u8F7D\u6587\u4EF6\u5931\u8D25: " + response.statusText);
456
- }
457
- return await response.blob();
458
- } catch (error) {
459
- throw createExportError(
460
- ERROR_CODES.NETWORK_ERROR,
461
- "\u4E0B\u8F7D\u5BFC\u51FA\u6587\u4EF6\u5931\u8D25: " + formatErrorMessage(error),
462
- { exportId, originalError: error }
463
- );
464
- }
465
- }
466
- // ============= 私有辅助方法 =============
467
- /**
468
- * 获取请求头
469
- */
470
- getHeaders() {
471
- return {
472
- ...this.config.headers
473
- };
474
- }
475
- /**
476
- * 带超时的fetch请求
477
- */
478
- async fetchWithTimeout(url, options) {
479
- const controller = new AbortController();
480
- const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
481
- try {
482
- const response = await fetch(url, {
483
- ...options,
484
- signal: controller.signal
485
- });
486
- return response;
487
- } catch (error) {
488
- if (error instanceof Error && error.name === "AbortError") {
489
- throw createExportError(ERROR_CODES.TIMEOUT_ERROR, "\u8BF7\u6C42\u8D85\u65F6", {
490
- url,
491
- timeout: this.config.timeout
492
- });
493
- }
494
- throw error;
495
- } finally {
496
- clearTimeout(timeoutId);
497
- }
498
- }
499
- /**
500
- * 转换API返回的配置数据
501
- */
502
- transformConfigFromAPI(apiConfig) {
503
- return {
504
- id: apiConfig.id,
505
- name: apiConfig.name,
506
- description: apiConfig.description || void 0,
507
- format: apiConfig.format,
508
- fields: apiConfig.fields,
509
- grouping: apiConfig.grouping,
510
- fileNameTemplate: apiConfig.fileNameTemplate,
511
- includeHeader: apiConfig.includeHeader,
512
- delimiter: apiConfig.delimiter,
513
- encoding: apiConfig.encoding,
514
- addBOM: apiConfig.addBOM,
515
- maxRows: apiConfig.maxRows || void 0,
516
- createdAt: new Date(apiConfig.createdAt),
517
- updatedAt: new Date(apiConfig.updatedAt),
518
- moduleId: apiConfig.moduleId,
519
- businessId: apiConfig.businessId || void 0,
520
- createdBy: apiConfig.createdBy || void 0
521
- };
522
- }
523
- /**
524
- * 转换API返回的配置列表
525
- */
526
- transformConfigsFromAPI(apiConfigs) {
527
- return apiConfigs.map((config) => this.transformConfigFromAPI(config));
528
- }
529
- /**
530
- * 转换API返回的导出结果
531
- */
532
- transformExportResultFromAPI(apiResult) {
533
- return {
534
- exportId: apiResult.exportId,
535
- fileName: apiResult.fileName,
536
- fileSize: apiResult.fileSize,
537
- fileUrl: apiResult.fileUrl,
538
- exportedRows: apiResult.exportedRows,
539
- startTime: new Date(apiResult.startTime),
540
- endTime: new Date(apiResult.endTime),
541
- duration: apiResult.duration,
542
- statistics: apiResult.statistics
543
- };
544
- }
545
- /**
546
- * 转换API返回的进度数据
547
- */
548
- transformProgressFromAPI(apiProgress) {
549
- return {
550
- exportId: apiProgress.exportId,
551
- status: apiProgress.status,
552
- progress: apiProgress.progress,
553
- processedRows: apiProgress.processedRows,
554
- totalRows: apiProgress.totalRows,
555
- startTime: new Date(apiProgress.startTime),
556
- estimatedEndTime: apiProgress.estimatedEndTime ? new Date(apiProgress.estimatedEndTime) : void 0,
557
- currentData: apiProgress.currentData,
558
- error: apiProgress.error
559
- };
560
- }
561
- };
562
- var universalExportClient = new UniversalExportClient();
563
- function createExportClient(config) {
564
- return new UniversalExportClient(config);
565
- }
566
- var FORMAT_ICONS = {
567
- csv: /* @__PURE__ */ React.createElement(FileText, { className: "w-4 h-4" }),
568
- excel: /* @__PURE__ */ React.createElement(FileSpreadsheet, { className: "w-4 h-4" }),
569
- json: /* @__PURE__ */ React.createElement(Database, { className: "w-4 h-4" })
570
- };
571
- var FORMAT_DESCRIPTIONS = {
572
- csv: "\u9017\u53F7\u5206\u9694\u503C\u6587\u4EF6\uFF0C\u517C\u5BB9\u6027\u6700\u597D",
573
- excel: "Excel\u8868\u683C\u6587\u4EF6\uFF0C\u652F\u6301\u683C\u5F0F\u5316\u548C\u5355\u5143\u683C\u5408\u5E76",
574
- json: "JSON\u6570\u636E\u6587\u4EF6\uFF0C\u9002\u5408\u5F00\u53D1\u8005\u4F7F\u7528"
575
- };
576
- var ExportConfigEditor = ({
577
- initialConfig,
578
- moduleId,
579
- businessId,
580
- availableFields,
581
- onSave,
582
- onCancel,
583
- visible = false,
584
- className = "",
585
- onConfigChange
586
- }) => {
587
- const [config, setConfig] = useState(() => {
588
- if (initialConfig) {
589
- return { ...initialConfig };
590
- }
591
- return {
592
- id: "",
593
- name: "\u65B0\u5EFA\u5BFC\u51FA\u914D\u7F6E",
594
- description: "",
595
- format: "csv",
596
- fields: availableFields.map((field, index) => ({
597
- ...field,
598
- enabled: true,
599
- sortOrder: index
600
- })),
601
- grouping: {
602
- enabled: false,
603
- fields: [],
604
- preserveOrder: true,
605
- nullValueHandling: "separate",
606
- nullGroupName: "\u672A\u5206\u7EC4"
607
- },
608
- fileNameTemplate: "\u5BFC\u51FA\u6570\u636E_{date}",
609
- includeHeader: true,
610
- delimiter: ",",
611
- encoding: "utf-8",
612
- addBOM: true,
613
- maxRows: void 0,
614
- createdAt: /* @__PURE__ */ new Date(),
615
- updatedAt: /* @__PURE__ */ new Date(),
616
- moduleId,
617
- businessId
618
- };
619
- });
620
- const [activeTab, setActiveTab] = useState("basic");
621
- const [savedConfigs, setSavedConfigs] = useState([]);
622
- const [loadingConfigs, setLoadingConfigs] = useState(false);
623
- const [deletingConfigId, setDeletingConfigId] = useState(null);
624
- const loadSavedConfigs = useCallback(async () => {
625
- if (!visible || activeTab !== "manage") return;
626
- setLoadingConfigs(true);
627
- try {
628
- const params = new URLSearchParams({ moduleId });
629
- if (businessId) {
630
- params.set("businessId", businessId);
631
- }
632
- const response = await fetch("/api/universal-export/configs?" + params.toString());
633
- if (response.ok) {
634
- const data = await response.json();
635
- setSavedConfigs(data.configs || []);
636
- }
637
- } catch (error) {
638
- console.error("\u52A0\u8F7D\u914D\u7F6E\u5F02\u5E38:", error);
639
- } finally {
640
- setLoadingConfigs(false);
641
- }
642
- }, [visible, activeTab, moduleId, businessId]);
643
- const deleteConfig = useCallback(async (configId) => {
644
- setDeletingConfigId(configId);
645
- try {
646
- const response = await fetch("/api/universal-export/configs/" + configId, {
647
- method: "DELETE"
648
- });
649
- if (response.ok) {
650
- setSavedConfigs((prev) => prev.filter((cfg) => cfg.id !== configId));
651
- onConfigChange?.();
652
- }
653
- } catch (error) {
654
- console.error("\u5220\u9664\u914D\u7F6E\u5931\u8D25:", error);
655
- } finally {
656
- setDeletingConfigId(null);
657
- }
658
- }, [onConfigChange]);
659
- const loadConfigToEditor = useCallback((config2) => {
660
- setConfig(config2);
661
- setActiveTab("basic");
662
- }, []);
663
- useEffect(() => {
664
- if (activeTab === "manage") {
665
- loadSavedConfigs();
666
- }
667
- }, [activeTab, loadSavedConfigs]);
668
- useEffect(() => {
669
- if (!visible) return;
670
- const scrollY = window.scrollY;
671
- document.body.style.position = "fixed";
672
- document.body.style.top = "-" + scrollY + "px";
673
- document.body.style.left = "0";
674
- document.body.style.right = "0";
675
- document.body.style.overflow = "hidden";
676
- const handleKeyDown = (e) => {
677
- if (e.key === "Escape") {
678
- onCancel?.();
679
- }
680
- };
681
- document.addEventListener("keydown", handleKeyDown);
682
- return () => {
683
- document.body.style.position = "";
684
- document.body.style.top = "";
685
- document.body.style.left = "";
686
- document.body.style.right = "";
687
- document.body.style.overflow = "";
688
- window.scrollTo(0, scrollY);
689
- document.removeEventListener("keydown", handleKeyDown);
690
- };
691
- }, [visible, onCancel]);
692
- const toggleFieldEnabled = useCallback((fieldKey) => {
693
- setConfig((prev) => ({
694
- ...prev,
695
- fields: prev.fields.map(
696
- (field) => field.key === fieldKey ? { ...field, enabled: !field.enabled } : field
697
- )
698
- }));
699
- }, []);
700
- useCallback((fieldKey, updates) => {
701
- setConfig((prev) => ({
702
- ...prev,
703
- fields: prev.fields.map(
704
- (field) => field.key === fieldKey ? { ...field, ...updates } : field
705
- )
706
- }));
707
- }, []);
708
- const moveField = useCallback((fieldKey, direction) => {
709
- setConfig((prev) => {
710
- const fields = [...prev.fields];
711
- const index = fields.findIndex((f) => f.key === fieldKey);
712
- if (direction === "up" && index > 0) {
713
- const temp = fields[index - 1];
714
- fields[index - 1] = fields[index];
715
- fields[index] = temp;
716
- } else if (direction === "down" && index < fields.length - 1) {
717
- const temp = fields[index + 1];
718
- fields[index + 1] = fields[index];
719
- fields[index] = temp;
720
- }
721
- return {
722
- ...prev,
723
- fields: fields.map((field, idx) => ({ ...field, sortOrder: idx }))
724
- };
725
- });
726
- }, []);
727
- const removeField = useCallback((fieldKey) => {
728
- setConfig((prev) => ({
729
- ...prev,
730
- fields: prev.fields.filter((f) => f.key !== fieldKey)
731
- }));
732
- }, []);
733
- const toggleGrouping = useCallback((enabled) => {
734
- setConfig((prev) => ({
735
- ...prev,
736
- grouping: {
737
- ...prev.grouping,
738
- enabled
739
- }
740
- }));
741
- }, []);
742
- const addGroupingField = useCallback((fieldKey) => {
743
- const field = config.fields.find((f) => f.key === fieldKey);
744
- if (!field) return;
745
- const groupField = {
746
- key: field.key,
747
- label: field.label,
748
- mode: "merge",
749
- valueProcessing: "first",
750
- showGroupHeader: false,
751
- mergeCells: true
752
- };
753
- setConfig((prev) => ({
754
- ...prev,
755
- grouping: {
756
- ...prev.grouping,
757
- fields: [...prev.grouping.fields, groupField]
758
- }
759
- }));
760
- }, [config.fields]);
761
- const removeGroupingField = useCallback((fieldKey) => {
762
- setConfig((prev) => ({
763
- ...prev,
764
- grouping: {
765
- ...prev.grouping,
766
- fields: prev.grouping.fields.filter((f) => f.key !== fieldKey)
767
- }
768
- }));
769
- }, []);
770
- const updateGroupingField = useCallback((fieldKey, updates) => {
771
- setConfig((prev) => ({
772
- ...prev,
773
- grouping: {
774
- ...prev.grouping,
775
- fields: prev.grouping.fields.map(
776
- (field) => field.key === fieldKey ? { ...field, ...updates } : field
777
- )
778
- }
779
- }));
780
- }, []);
781
- useCallback((fieldKey, direction) => {
782
- setConfig((prev) => {
783
- const fields = [...prev.grouping.fields];
784
- const index = fields.findIndex((f) => f.key === fieldKey);
785
- if (direction === "up" && index > 0) {
786
- const temp = fields[index - 1];
787
- fields[index - 1] = fields[index];
788
- fields[index] = temp;
789
- } else if (direction === "down" && index < fields.length - 1) {
790
- const temp = fields[index + 1];
791
- fields[index + 1] = fields[index];
792
- fields[index] = temp;
793
- }
794
- return {
795
- ...prev,
796
- grouping: {
797
- ...prev.grouping,
798
- fields
799
- }
800
- };
801
- });
802
- }, []);
803
- useCallback((updates) => {
804
- setConfig((prev) => ({
805
- ...prev,
806
- grouping: {
807
- ...prev.grouping,
808
- ...updates
809
- }
810
- }));
811
- }, []);
812
- const handleSave = useCallback(() => {
813
- if (!config.name.trim()) {
814
- alert("\u8BF7\u8F93\u5165\u914D\u7F6E\u540D\u79F0");
815
- return;
816
- }
817
- const enabledFields = config.fields.filter((f) => f.enabled);
818
- if (enabledFields.length === 0) {
819
- alert("\u81F3\u5C11\u9700\u8981\u542F\u7528\u4E00\u4E2A\u5B57\u6BB5");
820
- return;
821
- }
822
- const updatedConfig = {
823
- ...config,
824
- updatedAt: /* @__PURE__ */ new Date()
825
- };
826
- onSave?.(updatedConfig);
827
- onConfigChange?.();
828
- }, [config, onSave, onConfigChange]);
829
- if (!visible) {
830
- return null;
831
- }
832
- const tabs = [
833
- { id: "basic", label: "\u57FA\u672C\u914D\u7F6E", icon: /* @__PURE__ */ React.createElement(Settings, { className: "w-4 h-4" }), description: "\u914D\u7F6E\u540D\u79F0\u3001\u683C\u5F0F\u548C\u57FA\u672C\u9009\u9879" },
834
- { id: "fields", label: "\u5B57\u6BB5\u8BBE\u7F6E", icon: /* @__PURE__ */ React.createElement(Type, { className: "w-4 h-4" }), description: "\u9009\u62E9\u548C\u914D\u7F6E\u5BFC\u51FA\u5B57\u6BB5" },
835
- { id: "grouping", label: "\u5206\u7EC4\u8BBE\u7F6E", icon: /* @__PURE__ */ React.createElement(Group, { className: "w-4 h-4" }), description: "\u914D\u7F6E\u6570\u636E\u5206\u7EC4\u548C\u5408\u5E76\u9009\u9879" },
836
- { id: "manage", label: "\u914D\u7F6E\u7BA1\u7406", icon: /* @__PURE__ */ React.createElement(Database, { className: "w-4 h-4" }), description: "\u7BA1\u7406\u5DF2\u4FDD\u5B58\u7684\u5BFC\u51FA\u914D\u7F6E" }
837
- ];
838
- return /* @__PURE__ */ React.createElement(
839
- "div",
840
- {
841
- className: clsx("fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-[50] p-4", className),
842
- onClick: onCancel
843
- },
844
- /* @__PURE__ */ React.createElement(
845
- "div",
846
- {
847
- className: "bg-white rounded-lg shadow-xl w-full max-w-5xl max-h-[90vh] flex flex-col",
848
- onClick: (e) => e.stopPropagation()
849
- },
850
- /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-between p-4 border-b flex-shrink-0" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React.createElement(Settings, { className: "w-6 h-6 text-blue-600" }), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("h2", { className: "text-xl font-semibold text-gray-900" }, "\u5BFC\u51FA\u914D\u7F6E\u7F16\u8F91\u5668"), /* @__PURE__ */ React.createElement("p", { className: "text-sm text-gray-600" }, "\u914D\u7F6E\u5BFC\u51FA\u5B57\u6BB5\u548C\u683C\u5F0F\u9009\u9879"))), /* @__PURE__ */ React.createElement("button", { onClick: onCancel, className: "p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-lg" }, /* @__PURE__ */ React.createElement(X, { className: "w-5 h-5" }))),
851
- /* @__PURE__ */ React.createElement("div", { className: "border-b bg-gray-50 flex-shrink-0" }, /* @__PURE__ */ React.createElement("nav", { className: "flex space-x-1 p-2" }, tabs.map((tab) => /* @__PURE__ */ React.createElement(
852
- "button",
853
- {
854
- key: tab.id,
855
- onClick: () => setActiveTab(tab.id),
856
- className: clsx("flex items-center gap-2 px-4 py-3 text-sm font-medium rounded-lg transition-colors", activeTab === tab.id ? "bg-white text-blue-600 shadow-sm border border-gray-200" : "text-gray-600 hover:text-gray-900")
857
- },
858
- tab.icon,
859
- /* @__PURE__ */ React.createElement("span", null, tab.label)
860
- )))),
861
- /* @__PURE__ */ React.createElement("div", { className: "flex-1 overflow-hidden flex flex-col" }, /* @__PURE__ */ React.createElement("div", { className: "bg-blue-50 border-b border-blue-100 p-4 flex-shrink-0" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 text-blue-800 text-sm font-medium" }, tabs.find((t) => t.id === activeTab)?.icon, tabs.find((t) => t.id === activeTab)?.description)), /* @__PURE__ */ React.createElement("div", { className: "flex-1 overflow-y-auto p-4 sm:p-6" }, activeTab === "basic" && /* @__PURE__ */ React.createElement("div", { className: "max-w-2xl mx-auto space-y-6" }, /* @__PURE__ */ React.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React.createElement("label", { className: "block text-sm font-medium text-gray-700" }, "\u914D\u7F6E\u540D\u79F0 *"), /* @__PURE__ */ React.createElement(
862
- "input",
863
- {
864
- type: "text",
865
- value: config.name,
866
- onChange: (e) => setConfig((prev) => ({ ...prev, name: e.target.value })),
867
- className: "w-full px-3 py-2 border border-gray-300 rounded-lg"
868
- }
869
- ), /* @__PURE__ */ React.createElement("label", { className: "block text-sm font-medium text-gray-700" }, "\u63CF\u8FF0"), /* @__PURE__ */ React.createElement(
870
- "textarea",
871
- {
872
- value: config.description,
873
- onChange: (e) => setConfig((prev) => ({ ...prev, description: e.target.value })),
874
- className: "w-full px-3 py-2 border border-gray-300 rounded-lg",
875
- rows: 3
876
- }
877
- ), /* @__PURE__ */ React.createElement("label", { className: "block text-sm font-medium text-gray-700" }, "\u5BFC\u51FA\u683C\u5F0F"), /* @__PURE__ */ React.createElement("div", { className: "space-y-3" }, ["csv", "excel", "json"].map((format) => /* @__PURE__ */ React.createElement("label", { key: format, className: "flex items-start gap-3 p-3 border rounded-lg cursor-pointer hover:border-blue-300" }, /* @__PURE__ */ React.createElement(
878
- "input",
879
- {
880
- type: "radio",
881
- checked: config.format === format,
882
- onChange: () => setConfig((prev) => ({ ...prev, format })),
883
- className: "mt-1"
884
- }
885
- ), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 font-medium" }, FORMAT_ICONS[format], " ", format.toUpperCase()), /* @__PURE__ */ React.createElement("p", { className: "text-sm text-gray-600" }, FORMAT_DESCRIPTIONS[format]))))))), activeTab === "fields" && /* @__PURE__ */ React.createElement("div", { className: "space-y-4" }, config.fields.map((field, index) => /* @__PURE__ */ React.createElement("div", { key: field.key, className: "flex items-center gap-3 p-3 border rounded-lg bg-white" }, /* @__PURE__ */ React.createElement("button", { onClick: () => toggleFieldEnabled(field.key), className: field.enabled ? "text-blue-600" : "text-gray-400" }, field.enabled ? /* @__PURE__ */ React.createElement(Eye, { className: "w-4 h-4" }) : /* @__PURE__ */ React.createElement(EyeOff, { className: "w-4 h-4" })), /* @__PURE__ */ React.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React.createElement("div", { className: "font-medium" }, field.label), /* @__PURE__ */ React.createElement("div", { className: "text-xs text-gray-500" }, field.key)), /* @__PURE__ */ React.createElement("div", { className: "flex gap-1" }, /* @__PURE__ */ React.createElement("button", { onClick: () => moveField(field.key, "up"), disabled: index === 0, className: "disabled:opacity-30" }, /* @__PURE__ */ React.createElement(MoveUp, { className: "w-4 h-4" })), /* @__PURE__ */ React.createElement("button", { onClick: () => moveField(field.key, "down"), disabled: index === config.fields.length - 1, className: "disabled:opacity-30" }, /* @__PURE__ */ React.createElement(MoveDown, { className: "w-4 h-4" })), /* @__PURE__ */ React.createElement("button", { onClick: () => removeField(field.key), className: "text-red-600" }, /* @__PURE__ */ React.createElement(Trash2, { className: "w-4 h-4" })))))), activeTab === "grouping" && /* @__PURE__ */ React.createElement("div", { className: "space-y-6" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React.createElement("h3", { className: "text-lg font-medium flex items-center gap-2" }, /* @__PURE__ */ React.createElement(Group, { className: "w-5 h-5 text-blue-600" }), " \u5206\u7EC4\u914D\u7F6E"), /* @__PURE__ */ React.createElement("label", { className: "flex items-center gap-2" }, /* @__PURE__ */ React.createElement("input", { type: "checkbox", checked: config.grouping?.enabled, onChange: (e) => toggleGrouping(e.target.checked) }), "\u542F\u7528\u5206\u7EC4")), config.grouping?.enabled && /* @__PURE__ */ React.createElement("div", { className: "space-y-4" }, config.grouping.fields.map((gf, index) => /* @__PURE__ */ React.createElement("div", { key: gf.key, className: "p-4 border rounded-lg bg-blue-50 border-blue-200" }, /* @__PURE__ */ React.createElement("div", { className: "flex justify-between items-center mb-4" }, /* @__PURE__ */ React.createElement("span", { className: "font-medium text-blue-900" }, gf.label), /* @__PURE__ */ React.createElement("button", { onClick: () => removeGroupingField(gf.key), className: "text-red-600" }, /* @__PURE__ */ React.createElement(Trash2, { className: "w-4 h-4" }))), /* @__PURE__ */ React.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React.createElement("select", { value: gf.mode, onChange: (e) => updateGroupingField(gf.key, { mode: e.target.value }), className: "border rounded p-2" }, /* @__PURE__ */ React.createElement("option", { value: "merge" }, "\u5408\u5E76\u6A21\u5F0F"), /* @__PURE__ */ React.createElement("option", { value: "separate" }, "\u5206\u79BB\u6A21\u5F0F"), /* @__PURE__ */ React.createElement("option", { value: "nested" }, "\u5D4C\u5957\u6A21\u5F0F")), /* @__PURE__ */ React.createElement("select", { value: gf.valueProcessing, onChange: (e) => updateGroupingField(gf.key, { valueProcessing: e.target.value }), className: "border rounded p-2" }, /* @__PURE__ */ React.createElement("option", { value: "first" }, "\u9996\u503C"), /* @__PURE__ */ React.createElement("option", { value: "sum" }, "\u6C42\u548C"), /* @__PURE__ */ React.createElement("option", { value: "count" }, "\u8BA1\u6570"))))), /* @__PURE__ */ React.createElement("select", { onChange: (e) => e.target.value && addGroupingField(e.target.value), className: "w-full border rounded p-2" }, /* @__PURE__ */ React.createElement("option", { value: "" }, "\u6DFB\u52A0\u5206\u7EC4\u5B57\u6BB5..."), config.fields.filter((f) => f.enabled && !config.grouping?.fields.some((gf) => gf.key === f.key)).map((f) => /* @__PURE__ */ React.createElement("option", { key: f.key, value: f.key }, f.label))))), activeTab === "manage" && /* @__PURE__ */ React.createElement("div", { className: "space-y-4" }, loadingConfigs ? /* @__PURE__ */ React.createElement("div", { className: "text-center py-10" }, "\u52A0\u8F7D\u4E2D...") : savedConfigs.map((sc) => /* @__PURE__ */ React.createElement("div", { key: sc.id, className: "flex justify-between items-center p-4 border rounded-lg" }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { className: "font-medium" }, sc.name), /* @__PURE__ */ React.createElement("div", { className: "text-sm text-gray-500" }, sc.format)), /* @__PURE__ */ React.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React.createElement("button", { onClick: () => loadConfigToEditor(sc), className: "text-blue-600 px-3 py-1 border rounded" }, "\u7F16\u8F91"), /* @__PURE__ */ React.createElement("button", { onClick: () => deleteConfig(sc.id), className: "text-red-600 px-3 py-1 border rounded" }, "\u5220\u9664"))))))),
886
- /* @__PURE__ */ React.createElement("div", { className: "flex justify-end gap-3 p-4 border-t bg-gray-50" }, /* @__PURE__ */ React.createElement("button", { onClick: onCancel, className: "px-4 py-2 border rounded" }, "\u53D6\u6D88"), activeTab !== "manage" && /* @__PURE__ */ React.createElement("button", { onClick: handleSave, className: "px-4 py-2 bg-blue-600 text-white rounded flex items-center gap-2" }, /* @__PURE__ */ React.createElement(Save, { className: "w-4 h-4" }), " \u4FDD\u5B58\u914D\u7F6E"))
887
- )
888
- );
889
- };
890
-
891
- // src/universalExport/components/UniversalExportButton.tsx
892
- var BUTTON_STYLES = {
893
- primary: {
894
- sm: "px-3 py-1.5 text-sm bg-blue-600 text-white hover:bg-blue-700",
895
- md: "px-4 py-2 text-sm bg-blue-600 text-white hover:bg-blue-700",
896
- lg: "px-6 py-3 text-base bg-blue-600 text-white hover:bg-blue-700"
897
- },
898
- secondary: {
899
- sm: "px-3 py-1.5 text-sm bg-gray-600 text-white hover:bg-gray-700",
900
- md: "px-4 py-2 text-sm bg-gray-600 text-white hover:bg-gray-700",
901
- lg: "px-6 py-3 text-base bg-gray-600 text-white hover:bg-gray-700"
902
- },
903
- outline: {
904
- sm: "px-3 py-1.5 text-sm border border-gray-300 text-gray-700 hover:bg-gray-50",
905
- md: "px-4 py-2 text-sm border border-gray-300 text-gray-700 hover:bg-gray-50",
906
- lg: "px-6 py-3 text-base border border-gray-300 text-gray-700 hover:bg-gray-50"
907
- }
908
- };
909
- var UniversalExportButton = ({
910
- exportService,
911
- moduleId,
912
- businessId,
913
- availableFields,
914
- dataSource,
915
- defaultConfig,
916
- buttonText = "\u5BFC\u51FA\u6570\u636E",
917
- variant = "primary",
918
- size = "md",
919
- disabled = false,
920
- className = "",
921
- onExportSuccess,
922
- onExportError,
923
- onConfigSave
924
- }) => {
925
- const [showConfigEditor, setShowConfigEditor] = useState(false);
926
- const [showDropdown, setShowDropdown] = useState(false);
927
- const [isExporting, setIsExporting] = useState(false);
928
- const [exportProgress, setExportProgress] = useState(null);
929
- const [savedConfigs, setSavedConfigs] = useState([]);
930
- const loadSavedConfigs = useCallback(async () => {
931
- try {
932
- if (exportService) {
933
- const configs = await exportService.getConfigsByModule(moduleId, businessId);
934
- setSavedConfigs(configs);
935
- }
936
- } catch (error) {
937
- console.error("\u52A0\u8F7D\u4FDD\u5B58\u7684\u914D\u7F6E\u5931\u8D25:", error);
938
- }
939
- }, [exportService, moduleId, businessId]);
940
- React.useEffect(() => {
941
- loadSavedConfigs();
942
- }, [loadSavedConfigs]);
943
- const handleExport = useCallback(async (config) => {
944
- console.log("\u{1F680} [UniversalExportButton] \u5F00\u59CB\u5BFC\u51FA:", {
945
- configId: config.id,
946
- configName: config.name,
947
- format: config.format,
948
- fieldsCount: config.fields.length
949
- });
950
- if (!exportService) {
951
- console.error("\u274C [UniversalExportButton] \u5BFC\u51FA\u670D\u52A1\u672A\u521D\u59CB\u5316");
952
- onExportError?.("\u5BFC\u51FA\u670D\u52A1\u672A\u521D\u59CB\u5316");
953
- return;
954
- }
955
- setIsExporting(true);
956
- setExportProgress(null);
957
- try {
958
- console.log("\u{1F4CA} [UniversalExportButton] \u83B7\u53D6\u6570\u636E...");
959
- const data = await dataSource();
960
- console.log("\u2705 [UniversalExportButton] \u6570\u636E\u83B7\u53D6\u6210\u529F:", {
961
- dataType: typeof data,
962
- isArray: Array.isArray(data),
963
- length: Array.isArray(data) ? data.length : "N/A"
964
- });
965
- const request = {
966
- configId: config,
967
- dataSource: data,
968
- // 传递实际数据而不是函数
969
- queryParams: void 0,
970
- fieldMapping: void 0,
971
- filters: void 0,
972
- sortBy: void 0,
973
- pagination: void 0,
974
- customFileName: void 0
975
- };
976
- console.log("\u{1F4DE} [UniversalExportButton] \u8C03\u7528\u5BFC\u51FA\u670D\u52A1...");
977
- const result = await exportService.exportData(request);
978
- console.log("\u2705 [UniversalExportButton] \u5BFC\u51FA\u6210\u529F:", {
979
- fileName: result.fileName,
980
- fileSize: result.fileSize,
981
- exportedRows: result.exportedRows
982
- });
983
- const progress = {
984
- exportId: result.exportId,
985
- status: "completed",
986
- progress: 100,
987
- processedRows: result.exportedRows,
988
- totalRows: result.exportedRows,
989
- startTime: result.startTime,
990
- estimatedEndTime: result.endTime
991
- };
992
- setExportProgress(progress);
993
- if (result.fileUrl) {
994
- console.log("\u{1F4E5} [UniversalExportButton] \u4ECEURL\u4E0B\u8F7D\u6587\u4EF6...");
995
- const link = document.createElement("a");
996
- link.href = result.fileUrl;
997
- link.download = result.fileName;
998
- document.body.appendChild(link);
999
- link.click();
1000
- document.body.removeChild(link);
1001
- console.log("\u2705 [UniversalExportButton] \u6587\u4EF6\u4E0B\u8F7D\u5B8C\u6210");
1002
- } else if (result.fileBlob) {
1003
- console.log("\u{1F4E5} [UniversalExportButton] \u4ECEBlob\u4E0B\u8F7D\u6587\u4EF6...");
1004
- const url = window.URL.createObjectURL(result.fileBlob);
1005
- const link = document.createElement("a");
1006
- link.href = url;
1007
- link.download = result.fileName;
1008
- document.body.appendChild(link);
1009
- link.click();
1010
- document.body.removeChild(link);
1011
- window.URL.revokeObjectURL(url);
1012
- console.log("\u2705 [UniversalExportButton] \u6587\u4EF6\u4E0B\u8F7D\u5B8C\u6210");
1013
- }
1014
- setTimeout(() => {
1015
- setIsExporting(false);
1016
- setExportProgress(null);
1017
- }, 1e3);
1018
- onExportSuccess?.(result);
1019
- } catch (error) {
1020
- console.error("\u274C [UniversalExportButton] \u5BFC\u51FA\u5F02\u5E38:", error);
1021
- setIsExporting(false);
1022
- setExportProgress(null);
1023
- let errorMessage = "\u5BFC\u51FA\u5931\u8D25";
1024
- if (error && typeof error === "object") {
1025
- if ("message" in error && typeof error.message === "string") {
1026
- errorMessage = error.message;
1027
- } else if ("code" in error && "message" in error) {
1028
- errorMessage = error.code + ": " + error.message;
1029
- }
1030
- } else if (typeof error === "string") {
1031
- errorMessage = error;
1032
- }
1033
- onExportError?.(errorMessage);
1034
- }
1035
- }, [exportService, dataSource, onExportSuccess, onExportError]);
1036
- const handleQuickExport = useCallback(async () => {
1037
- if (defaultConfig) {
1038
- await handleExport(defaultConfig);
1039
- } else {
1040
- const config = {
1041
- id: "quick_export",
1042
- name: "\u5FEB\u901F\u5BFC\u51FA",
1043
- description: "\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E\u5FEB\u901F\u5BFC\u51FA",
1044
- format: "csv",
1045
- fields: availableFields.map((field, index) => ({
1046
- ...field,
1047
- enabled: true,
1048
- sortOrder: index
1049
- })),
1050
- fileNameTemplate: "\u5BFC\u51FA\u6570\u636E_{date}",
1051
- includeHeader: true,
1052
- delimiter: ",",
1053
- encoding: "utf-8",
1054
- addBOM: true,
1055
- createdAt: /* @__PURE__ */ new Date(),
1056
- updatedAt: /* @__PURE__ */ new Date(),
1057
- moduleId,
1058
- businessId
1059
- };
1060
- await handleExport(config);
1061
- }
1062
- }, [defaultConfig, availableFields, moduleId, businessId, handleExport]);
1063
- const handleConfigSave = useCallback(async (config) => {
1064
- try {
1065
- if (exportService) {
1066
- const savedConfig = await exportService.createConfig(config);
1067
- await loadSavedConfigs();
1068
- onConfigSave?.(savedConfig);
1069
- }
1070
- setShowConfigEditor(false);
1071
- } catch (error) {
1072
- onExportError?.(error instanceof Error ? error.message : "\u4FDD\u5B58\u914D\u7F6E\u5931\u8D25");
1073
- }
1074
- }, [exportService, onConfigSave, onExportError, loadSavedConfigs]);
1075
- const renderProgress = () => {
1076
- if (!exportProgress) return null;
1077
- const { status, progress, processedRows, totalRows } = exportProgress;
1078
- return /* @__PURE__ */ React.createElement("div", { className: "absolute top-full left-0 right-0 mt-2 bg-white border border-gray-200 rounded-lg shadow-lg p-4 z-[10]" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-3 mb-2" }, /* @__PURE__ */ React.createElement(Loader2, { className: "w-4 h-4 animate-spin text-blue-600" }), /* @__PURE__ */ React.createElement("span", { className: "text-sm font-medium text-gray-900" }, status === "processing" ? "\u6B63\u5728\u5BFC\u51FA..." : "\u5BFC\u51FA\u5B8C\u6210")), /* @__PURE__ */ React.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React.createElement("div", { className: "flex justify-between text-xs text-gray-600" }, /* @__PURE__ */ React.createElement("span", null, "\u8FDB\u5EA6: ", progress, "%"), /* @__PURE__ */ React.createElement("span", null, processedRows, " / ", totalRows, " \u884C")), /* @__PURE__ */ React.createElement("div", { className: "w-full bg-gray-200 rounded-full h-2" }, /* @__PURE__ */ React.createElement(
1079
- "div",
1080
- {
1081
- className: "bg-blue-600 h-2 rounded-full transition-all duration-300",
1082
- style: { width: progress + "%" }
1083
- }
1084
- ))));
1085
- };
1086
- const renderDropdown = () => {
1087
- if (!showDropdown) return null;
1088
- return /* @__PURE__ */ React.createElement("div", { className: "absolute top-full left-0 mt-2 bg-white border border-gray-200 rounded-lg shadow-lg py-2 z-[10] min-w-48" }, /* @__PURE__ */ React.createElement(
1089
- "button",
1090
- {
1091
- onClick: () => {
1092
- setShowDropdown(false);
1093
- handleQuickExport();
1094
- },
1095
- disabled: isExporting,
1096
- className: "w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50 flex items-center gap-2"
1097
- },
1098
- /* @__PURE__ */ React.createElement(Download, { className: "w-4 h-4" }),
1099
- "\u5FEB\u901F\u5BFC\u51FA"
1100
- ), savedConfigs.length > 0 && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "border-t border-gray-200 my-1" }), savedConfigs.map((config) => /* @__PURE__ */ React.createElement(
1101
- "button",
1102
- {
1103
- key: config.id,
1104
- onClick: () => {
1105
- setShowDropdown(false);
1106
- handleExport(config);
1107
- },
1108
- disabled: isExporting,
1109
- className: "w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50 flex items-center gap-2"
1110
- },
1111
- /* @__PURE__ */ React.createElement(FileText, { className: "w-4 h-4" }),
1112
- config.name
1113
- ))), /* @__PURE__ */ React.createElement("div", { className: "border-t border-gray-200 my-1" }), /* @__PURE__ */ React.createElement(
1114
- "button",
1115
- {
1116
- onClick: () => {
1117
- setShowDropdown(false);
1118
- setShowConfigEditor(true);
1119
- },
1120
- className: "w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50 flex items-center gap-2"
1121
- },
1122
- /* @__PURE__ */ React.createElement(Settings, { className: "w-4 h-4" }),
1123
- "\u81EA\u5B9A\u4E49\u914D\u7F6E"
1124
- ));
1125
- };
1126
- const buttonStyle = BUTTON_STYLES[variant][size];
1127
- const baseClasses = "inline-flex items-center gap-2 rounded-lg font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed " + buttonStyle;
1128
- return /* @__PURE__ */ React.createElement("div", { className: clsx("relative", className) }, /* @__PURE__ */ React.createElement(
1129
- "button",
1130
- {
1131
- onClick: () => setShowDropdown(!showDropdown),
1132
- disabled: disabled || isExporting,
1133
- className: clsx(baseClasses, isExporting ? "cursor-not-allowed" : "")
1134
- },
1135
- isExporting ? /* @__PURE__ */ React.createElement(Loader2, { className: "w-4 h-4 animate-spin" }) : /* @__PURE__ */ React.createElement(Download, { className: "w-4 h-4" }),
1136
- /* @__PURE__ */ React.createElement("span", null, isExporting ? "\u5BFC\u51FA\u4E2D..." : buttonText),
1137
- /* @__PURE__ */ React.createElement(ChevronDown, { className: "w-4 h-4" })
1138
- ), renderDropdown(), renderProgress(), /* @__PURE__ */ React.createElement(
1139
- ExportConfigEditor,
1140
- {
1141
- moduleId,
1142
- businessId,
1143
- availableFields,
1144
- onSave: handleConfigSave,
1145
- onCancel: () => setShowConfigEditor(false),
1146
- visible: showConfigEditor,
1147
- onConfigChange: loadSavedConfigs
1148
- }
1149
- ), showDropdown && /* @__PURE__ */ React.createElement(
1150
- "div",
1151
- {
1152
- className: "fixed inset-0 z-[0]",
1153
- onClick: () => setShowDropdown(false)
1154
- }
1155
- ));
1156
- };
1157
-
1158
- export { API_BASE_PATH, API_ENDPOINTS, DEFAULT_ADD_BOM, DEFAULT_CONFIG_CACHE_TTL, DEFAULT_CSV_DELIMITER, DEFAULT_ENCODING, DEFAULT_EXPORT_FORMAT, DEFAULT_EXPORT_TIMEOUT, DEFAULT_FORMATTERS, DEFAULT_MAX_CONCURRENT_EXPORTS, DEFAULT_MAX_FILE_SIZE, DEFAULT_MAX_ROWS, DEFAULT_RESULT_CACHE_TTL, ERROR_CODES, EXPORT_FORMAT_EXTENSIONS, EXPORT_FORMAT_MIME_TYPES, ExportConfigEditor, UNIVERSAL_EXPORT_NAME, UNIVERSAL_EXPORT_VERSION, UniversalExportButton, UniversalExportClient, applyFormatter, createExportClient, createExportError, escapeCSVField, estimateEndTime, formatDuration, formatErrorMessage, formatFileSize, generateExportFileName, getNestedValue, parseCSVField, sanitizeFileName, setNestedValue, universalExportClient, validateExportConfig, validateExportRequest, validateFileName };
3
+ import '../chunk-WMJKH4XE.mjs';
1159
4
  //# sourceMappingURL=index.mjs.map
1160
5
  //# sourceMappingURL=index.mjs.map