@spacecorexdev/core 0.0.2 → 0.0.5

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 (345) hide show
  1. package/package.json +20 -38
  2. package/public/cmaps/78-EUC-H.bcmap +0 -0
  3. package/public/cmaps/78-EUC-V.bcmap +0 -0
  4. package/public/cmaps/78-H.bcmap +0 -0
  5. package/public/cmaps/78-RKSJ-H.bcmap +0 -0
  6. package/public/cmaps/78-RKSJ-V.bcmap +0 -0
  7. package/public/cmaps/78-V.bcmap +0 -0
  8. package/public/cmaps/78ms-RKSJ-H.bcmap +0 -0
  9. package/public/cmaps/78ms-RKSJ-V.bcmap +0 -0
  10. package/public/cmaps/83pv-RKSJ-H.bcmap +0 -0
  11. package/public/cmaps/90ms-RKSJ-H.bcmap +0 -0
  12. package/public/cmaps/90ms-RKSJ-V.bcmap +0 -0
  13. package/public/cmaps/90msp-RKSJ-H.bcmap +0 -0
  14. package/public/cmaps/90msp-RKSJ-V.bcmap +0 -0
  15. package/public/cmaps/90pv-RKSJ-H.bcmap +0 -0
  16. package/public/cmaps/90pv-RKSJ-V.bcmap +0 -0
  17. package/public/cmaps/Add-H.bcmap +0 -0
  18. package/public/cmaps/Add-RKSJ-H.bcmap +0 -0
  19. package/public/cmaps/Add-RKSJ-V.bcmap +0 -0
  20. package/public/cmaps/Add-V.bcmap +0 -0
  21. package/public/cmaps/Adobe-CNS1-0.bcmap +0 -0
  22. package/public/cmaps/Adobe-CNS1-1.bcmap +0 -0
  23. package/public/cmaps/Adobe-CNS1-2.bcmap +0 -0
  24. package/public/cmaps/Adobe-CNS1-3.bcmap +0 -0
  25. package/public/cmaps/Adobe-CNS1-4.bcmap +0 -0
  26. package/public/cmaps/Adobe-CNS1-5.bcmap +0 -0
  27. package/public/cmaps/Adobe-CNS1-6.bcmap +0 -0
  28. package/public/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  29. package/public/cmaps/Adobe-GB1-0.bcmap +0 -0
  30. package/public/cmaps/Adobe-GB1-1.bcmap +0 -0
  31. package/public/cmaps/Adobe-GB1-2.bcmap +0 -0
  32. package/public/cmaps/Adobe-GB1-3.bcmap +0 -0
  33. package/public/cmaps/Adobe-GB1-4.bcmap +0 -0
  34. package/public/cmaps/Adobe-GB1-5.bcmap +0 -0
  35. package/public/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  36. package/public/cmaps/Adobe-Japan1-0.bcmap +0 -0
  37. package/public/cmaps/Adobe-Japan1-1.bcmap +0 -0
  38. package/public/cmaps/Adobe-Japan1-2.bcmap +0 -0
  39. package/public/cmaps/Adobe-Japan1-3.bcmap +0 -0
  40. package/public/cmaps/Adobe-Japan1-4.bcmap +0 -0
  41. package/public/cmaps/Adobe-Japan1-5.bcmap +0 -0
  42. package/public/cmaps/Adobe-Japan1-6.bcmap +0 -0
  43. package/public/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  44. package/public/cmaps/Adobe-Korea1-0.bcmap +0 -0
  45. package/public/cmaps/Adobe-Korea1-1.bcmap +0 -0
  46. package/public/cmaps/Adobe-Korea1-2.bcmap +0 -0
  47. package/public/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  48. package/public/cmaps/B5-H.bcmap +0 -0
  49. package/public/cmaps/B5-V.bcmap +0 -0
  50. package/public/cmaps/B5pc-H.bcmap +0 -0
  51. package/public/cmaps/B5pc-V.bcmap +0 -0
  52. package/public/cmaps/CNS-EUC-H.bcmap +0 -0
  53. package/public/cmaps/CNS-EUC-V.bcmap +0 -0
  54. package/public/cmaps/CNS1-H.bcmap +0 -0
  55. package/public/cmaps/CNS1-V.bcmap +0 -0
  56. package/public/cmaps/CNS2-H.bcmap +0 -0
  57. package/public/cmaps/CNS2-V.bcmap +3 -0
  58. package/public/cmaps/ETHK-B5-H.bcmap +0 -0
  59. package/public/cmaps/ETHK-B5-V.bcmap +0 -0
  60. package/public/cmaps/ETen-B5-H.bcmap +0 -0
  61. package/public/cmaps/ETen-B5-V.bcmap +0 -0
  62. package/public/cmaps/ETenms-B5-H.bcmap +3 -0
  63. package/public/cmaps/ETenms-B5-V.bcmap +0 -0
  64. package/public/cmaps/EUC-H.bcmap +0 -0
  65. package/public/cmaps/EUC-V.bcmap +0 -0
  66. package/public/cmaps/Ext-H.bcmap +0 -0
  67. package/public/cmaps/Ext-RKSJ-H.bcmap +0 -0
  68. package/public/cmaps/Ext-RKSJ-V.bcmap +0 -0
  69. package/public/cmaps/Ext-V.bcmap +0 -0
  70. package/public/cmaps/GB-EUC-H.bcmap +0 -0
  71. package/public/cmaps/GB-EUC-V.bcmap +0 -0
  72. package/public/cmaps/GB-H.bcmap +4 -0
  73. package/public/cmaps/GB-V.bcmap +0 -0
  74. package/public/cmaps/GBK-EUC-H.bcmap +0 -0
  75. package/public/cmaps/GBK-EUC-V.bcmap +0 -0
  76. package/public/cmaps/GBK2K-H.bcmap +0 -0
  77. package/public/cmaps/GBK2K-V.bcmap +0 -0
  78. package/public/cmaps/GBKp-EUC-H.bcmap +0 -0
  79. package/public/cmaps/GBKp-EUC-V.bcmap +0 -0
  80. package/public/cmaps/GBT-EUC-H.bcmap +0 -0
  81. package/public/cmaps/GBT-EUC-V.bcmap +0 -0
  82. package/public/cmaps/GBT-H.bcmap +0 -0
  83. package/public/cmaps/GBT-V.bcmap +0 -0
  84. package/public/cmaps/GBTpc-EUC-H.bcmap +0 -0
  85. package/public/cmaps/GBTpc-EUC-V.bcmap +0 -0
  86. package/public/cmaps/GBpc-EUC-H.bcmap +0 -0
  87. package/public/cmaps/GBpc-EUC-V.bcmap +0 -0
  88. package/public/cmaps/H.bcmap +0 -0
  89. package/public/cmaps/HKdla-B5-H.bcmap +0 -0
  90. package/public/cmaps/HKdla-B5-V.bcmap +0 -0
  91. package/public/cmaps/HKdlb-B5-H.bcmap +0 -0
  92. package/public/cmaps/HKdlb-B5-V.bcmap +0 -0
  93. package/public/cmaps/HKgccs-B5-H.bcmap +0 -0
  94. package/public/cmaps/HKgccs-B5-V.bcmap +0 -0
  95. package/public/cmaps/HKm314-B5-H.bcmap +0 -0
  96. package/public/cmaps/HKm314-B5-V.bcmap +0 -0
  97. package/public/cmaps/HKm471-B5-H.bcmap +0 -0
  98. package/public/cmaps/HKm471-B5-V.bcmap +0 -0
  99. package/public/cmaps/HKscs-B5-H.bcmap +0 -0
  100. package/public/cmaps/HKscs-B5-V.bcmap +0 -0
  101. package/public/cmaps/Hankaku.bcmap +0 -0
  102. package/public/cmaps/Hiragana.bcmap +0 -0
  103. package/public/cmaps/KSC-EUC-H.bcmap +0 -0
  104. package/public/cmaps/KSC-EUC-V.bcmap +0 -0
  105. package/public/cmaps/KSC-H.bcmap +0 -0
  106. package/public/cmaps/KSC-Johab-H.bcmap +0 -0
  107. package/public/cmaps/KSC-Johab-V.bcmap +0 -0
  108. package/public/cmaps/KSC-V.bcmap +0 -0
  109. package/public/cmaps/KSCms-UHC-H.bcmap +0 -0
  110. package/public/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  111. package/public/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  112. package/public/cmaps/KSCms-UHC-V.bcmap +0 -0
  113. package/public/cmaps/KSCpc-EUC-H.bcmap +0 -0
  114. package/public/cmaps/KSCpc-EUC-V.bcmap +0 -0
  115. package/public/cmaps/Katakana.bcmap +0 -0
  116. package/public/cmaps/LICENSE +36 -0
  117. package/public/cmaps/NWP-H.bcmap +0 -0
  118. package/public/cmaps/NWP-V.bcmap +0 -0
  119. package/public/cmaps/RKSJ-H.bcmap +0 -0
  120. package/public/cmaps/RKSJ-V.bcmap +0 -0
  121. package/public/cmaps/Roman.bcmap +0 -0
  122. package/public/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  123. package/public/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  124. package/public/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  125. package/public/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  126. package/public/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  127. package/public/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  128. package/public/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  129. package/public/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  130. package/public/cmaps/UniGB-UCS2-H.bcmap +0 -0
  131. package/public/cmaps/UniGB-UCS2-V.bcmap +0 -0
  132. package/public/cmaps/UniGB-UTF16-H.bcmap +0 -0
  133. package/public/cmaps/UniGB-UTF16-V.bcmap +0 -0
  134. package/public/cmaps/UniGB-UTF32-H.bcmap +0 -0
  135. package/public/cmaps/UniGB-UTF32-V.bcmap +0 -0
  136. package/public/cmaps/UniGB-UTF8-H.bcmap +0 -0
  137. package/public/cmaps/UniGB-UTF8-V.bcmap +0 -0
  138. package/public/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  139. package/public/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  140. package/public/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  141. package/public/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  142. package/public/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  143. package/public/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  144. package/public/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  145. package/public/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  146. package/public/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  147. package/public/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  148. package/public/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  149. package/public/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  150. package/public/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  151. package/public/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  152. package/public/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  153. package/public/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  154. package/public/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  155. package/public/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  156. package/public/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  157. package/public/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  158. package/public/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  159. package/public/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  160. package/public/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  161. package/public/cmaps/UniKS-UCS2-H.bcmap +0 -0
  162. package/public/cmaps/UniKS-UCS2-V.bcmap +0 -0
  163. package/public/cmaps/UniKS-UTF16-H.bcmap +0 -0
  164. package/public/cmaps/UniKS-UTF16-V.bcmap +0 -0
  165. package/public/cmaps/UniKS-UTF32-H.bcmap +0 -0
  166. package/public/cmaps/UniKS-UTF32-V.bcmap +0 -0
  167. package/public/cmaps/UniKS-UTF8-H.bcmap +0 -0
  168. package/public/cmaps/UniKS-UTF8-V.bcmap +0 -0
  169. package/public/cmaps/V.bcmap +0 -0
  170. package/public/cmaps/WP-Symbol.bcmap +0 -0
  171. package/public/polyfills/polyfills.js +802 -0
  172. package/public/vendor/docx/docx.worker.js +5 -0
  173. package/public/vendor/docx/jszip.min.js +13 -0
  174. package/public/vendor/libarchive/libarchive.wasm +0 -0
  175. package/public/vendor/libarchive/worker-bundle.js +6 -0
  176. package/public/vendor/pptx/pptx.worker.js +26 -0
  177. package/public/wasm/cad/0.8.2/dwfv-render.wasm +0 -0
  178. package/public/wasm/cad/0.8.2/dwg-worker.js +24 -0
  179. package/public/wasm/cad/0.8.2/dwg-worker.js.map +1 -0
  180. package/public/wasm/cad/0.8.2/libredwg-web.js +2 -0
  181. package/public/wasm/cad/0.8.2/libredwg-web.wasm +0 -0
  182. package/public/wasm/cad/dwfv-render.wasm +0 -0
  183. package/public/wasm/cad/dwg-worker.js +24 -0
  184. package/public/wasm/cad/dwg-worker.js.map +1 -0
  185. package/public/wasm/cad/libredwg-web.js +2 -0
  186. package/public/wasm/cad/libredwg-web.wasm +0 -0
  187. package/public/wasm/data/sql-wasm.wasm +0 -0
  188. package/public/wasm/hdiff.wasm +0 -0
  189. package/public/wasm/model/LICENSE.occt-import-js.txt +504 -0
  190. package/public/wasm/model/LICENSE.occt.txt +502 -0
  191. package/public/wasm/model/occt-import-js.js +19 -0
  192. package/public/wasm/model/occt-import-js.wasm +0 -0
  193. package/public/wasm/model/occt-worker.js +83 -0
  194. package/public/wasm/typst/fonts/DejaVuSansMono-Bold.ttf +0 -0
  195. package/public/wasm/typst/fonts/DejaVuSansMono-BoldOblique.ttf +0 -0
  196. package/public/wasm/typst/fonts/DejaVuSansMono-Oblique.ttf +0 -0
  197. package/public/wasm/typst/fonts/DejaVuSansMono.ttf +0 -0
  198. package/public/wasm/typst/fonts/LibertinusSerif-Bold.otf +0 -0
  199. package/public/wasm/typst/fonts/LibertinusSerif-BoldItalic.otf +0 -0
  200. package/public/wasm/typst/fonts/LibertinusSerif-Italic.otf +0 -0
  201. package/public/wasm/typst/fonts/LibertinusSerif-Regular.otf +0 -0
  202. package/public/wasm/typst/fonts/LibertinusSerif-Semibold.otf +0 -0
  203. package/public/wasm/typst/fonts/LibertinusSerif-SemiboldItalic.otf +0 -0
  204. package/public/wasm/typst/fonts/NewCM10-Bold.otf +0 -0
  205. package/public/wasm/typst/fonts/NewCM10-BoldItalic.otf +0 -0
  206. package/public/wasm/typst/fonts/NewCM10-Italic.otf +0 -0
  207. package/public/wasm/typst/fonts/NewCM10-Regular.otf +0 -0
  208. package/public/wasm/typst/fonts/NewCMMath-Bold.otf +0 -0
  209. package/public/wasm/typst/fonts/NewCMMath-Book.otf +0 -0
  210. package/public/wasm/typst/fonts/NewCMMath-Regular.otf +0 -0
  211. package/public/wasm/typst/fonts/README.md +7 -0
  212. package/public/wasm/typst/typst_ts_renderer_bg.wasm +0 -0
  213. package/public/wasm/typst/typst_ts_web_compiler_bg.wasm +0 -0
  214. package/scripts/patch-docx-grid.cjs +412 -0
  215. package/src/api/_base.ts +243 -0
  216. package/src/api/index.ts +17 -0
  217. package/src/api/project.ts +1345 -0
  218. package/src/api/user.ts +1174 -0
  219. package/src/contract.ts +50 -0
  220. package/src/hooks/index.ts +2 -0
  221. package/{dist/hooks/index.js → src/hooks/useLongPress.ts} +53 -49
  222. package/src/hooks/useOnlineStatus.ts +22 -0
  223. package/src/index.ts +14 -0
  224. package/src/types/id.ts +2 -0
  225. package/src/types/index.ts +5 -0
  226. package/src/types/project/base.ts +63 -0
  227. package/src/types/project/contract.ts +79 -0
  228. package/src/types/project/contractStatus.tsx +15 -0
  229. package/src/types/project/index.ts +5 -0
  230. package/src/types/project/member.ts +46 -0
  231. package/src/types/project/progress.ts +43 -0
  232. package/src/types/projectRole.ts +17 -0
  233. package/src/types/theme.ts +1 -0
  234. package/src/types/user/index.ts +1 -0
  235. package/src/types/user/role.ts +7 -0
  236. package/src/ui/CommentTimeline/index.tsx +330 -0
  237. package/src/ui/FileManager/FileContextMenu.tsx +628 -0
  238. package/src/ui/FileManager/FileGridView.tsx +529 -0
  239. package/src/ui/FileManager/FileTableView.tsx +405 -0
  240. package/src/ui/FileManager/FileToolbar.tsx +119 -0
  241. package/src/ui/FileManager/FileVersionHistoryModal.tsx +175 -0
  242. package/src/ui/FileManager/MoveCopyToProjectModal.tsx +119 -0
  243. package/src/ui/FileManager/ShareToWechatModal.tsx +419 -0
  244. package/src/ui/FileManager/hooks/useFileManagerActions.ts +2532 -0
  245. package/src/ui/FileManager/hooks/useFileManagerState.ts +419 -0
  246. package/src/ui/FileManager/index.tsx +580 -0
  247. package/src/ui/FileManager/projectFileManagerApi.ts +57 -0
  248. package/src/ui/FileManager/types.ts +184 -0
  249. package/src/ui/FileManager/utils/fileDeltaWorker.ts +193 -0
  250. package/src/ui/FileManager/utils/fileTree.ts +178 -0
  251. package/src/ui/FileManager/utils/fileUpload.ts +714 -0
  252. package/src/ui/FileManager/utils/fileUtils.ts +65 -0
  253. package/src/ui/InvoiceRecordsList/index.tsx +813 -0
  254. package/src/ui/MyFileSelectorModal.tsx +261 -0
  255. package/src/ui/ProjectSelector/index.tsx +472 -0
  256. package/src/ui/ProjectSelector/projectCache.ts +40 -0
  257. package/src/ui/RoleSelector/index.tsx +473 -0
  258. package/src/ui/RoleSelector/roleCache.ts +40 -0
  259. package/src/ui/UIAlert.tsx +399 -0
  260. package/src/ui/UIAlertExample.tsx +129 -0
  261. package/src/ui/UIConfirm.tsx +335 -0
  262. package/src/ui/UIConfirmExample.tsx +165 -0
  263. package/src/ui/UIDatePicker.tsx +146 -0
  264. package/src/ui/UIDateRangePicker.tsx +38 -0
  265. package/src/ui/UIFilePreview/ExcelEditor/index.tsx +617 -0
  266. package/src/ui/UIFilePreview/ExcelEditor/types.ts +24 -0
  267. package/src/ui/UIFilePreview/ExportDropdown.css +85 -0
  268. package/src/ui/UIFilePreview/ExportDropdown.tsx +109 -0
  269. package/src/ui/UIFilePreview/IndexedDBUtils.ts +564 -0
  270. package/src/ui/UIFilePreview/MarkdownEditor/exportMarkdownPdf.ts +576 -0
  271. package/src/ui/UIFilePreview/MarkdownEditor/index.tsx +677 -0
  272. package/src/ui/UIFilePreview/MarkdownEditor/markdownEditor.css +1005 -0
  273. package/src/ui/UIFilePreview/MarkdownEditor/types.ts +15 -0
  274. package/src/ui/UIFilePreview/PPTXEditor/index.tsx +602 -0
  275. package/src/ui/UIFilePreview/RichDocEditor/exportRDocMarkdown.ts +77 -0
  276. package/src/ui/UIFilePreview/RichDocEditor/exportRDocPdf.ts +374 -0
  277. package/src/ui/UIFilePreview/RichDocEditor/index.tsx +730 -0
  278. package/src/ui/UIFilePreview/RichDocEditor/richdoc-editor.css +59 -0
  279. package/src/ui/UIFilePreview/UIFilePreview.tsx +611 -0
  280. package/src/ui/UIFilePreview/WordEditor/index.tsx +3933 -0
  281. package/src/ui/UIFilePreview/WordEditor/style.ts +1213 -0
  282. package/src/ui/UIFilePreview/WordEditor/word-editor.css +999 -0
  283. package/src/ui/UIFilePreview/filePreview.css +193 -0
  284. package/src/ui/UIFilePreview/filetypes/archive.tsx +66 -0
  285. package/src/ui/UIFilePreview/filetypes/cad.tsx +287 -0
  286. package/src/ui/UIFilePreview/filetypes/excel.tsx +355 -0
  287. package/src/ui/UIFilePreview/filetypes/image.tsx +20 -0
  288. package/src/ui/UIFilePreview/filetypes/imageLoader.ts +63 -0
  289. package/src/ui/UIFilePreview/filetypes/pdf.tsx +156 -0
  290. package/src/ui/UIFilePreview/filetypes/ppt.tsx +535 -0
  291. package/src/ui/UIFilePreview/filetypes/pptExportPdf.ts +523 -0
  292. package/src/ui/UIFilePreview/filetypes/video.tsx +482 -0
  293. package/src/ui/UIFilePreview/filetypes/word.tsx +245 -0
  294. package/src/ui/UIFilePreview/filetypes/wordExportMarkdown.ts +86 -0
  295. package/src/ui/UIFilePreview/filetypes/wordExportPdf.tsx +427 -0
  296. package/src/ui/UIFilePreview/index.ts +35 -0
  297. package/src/ui/UIFilePreview/pdfPagination.ts +143 -0
  298. package/src/ui/UIFilePreview/previewUtils.tsx +531 -0
  299. package/src/ui/UIFileUpload.tsx +382 -0
  300. package/src/ui/UIImageUpload.tsx +195 -0
  301. package/src/ui/UILoading.tsx +255 -0
  302. package/src/ui/UILoadingExample.tsx +139 -0
  303. package/src/ui/UISelect.tsx +105 -0
  304. package/src/ui/UIToast.tsx +381 -0
  305. package/src/ui/UIToastExample.tsx +69 -0
  306. package/src/ui/UIToastSingle.tsx +279 -0
  307. package/src/ui/UIViewToggle.tsx +64 -0
  308. package/src/ui/UserSelector/index.tsx +583 -0
  309. package/src/ui/index.ts +84 -0
  310. package/src/ui/upload/image.ts +135 -0
  311. package/src/ui/upload/index.ts +73 -0
  312. package/src/ui/upload/submitFile.ts +106 -0
  313. package/src/ui/upload/submitForm.ts +124 -0
  314. package/src/ui/upload/upload.err.ts +15 -0
  315. package/src/ui/upload/upload.ts +250 -0
  316. package/src/utils/CacheDepartmentInfo.ts +372 -0
  317. package/src/utils/CacheFileContent.ts +315 -0
  318. package/src/utils/CachePermissionInfo.ts +235 -0
  319. package/src/utils/CacheRoleInfo.ts +303 -0
  320. package/src/utils/CacheUserInfo.ts +818 -0
  321. package/src/utils/CacheViewToggleInfo.ts +182 -0
  322. package/src/utils/MessageContentUtils.ts +268 -0
  323. package/src/utils/clipboard.ts +70 -0
  324. package/src/utils/companyEmail.ts +19 -0
  325. package/src/utils/forbidDebugger.ts +59 -0
  326. package/src/utils/formatters.ts +94 -0
  327. package/src/utils/htmlUtils.tsx +59 -0
  328. package/src/utils/index.ts +18 -0
  329. package/src/utils/keyboard.ts +114 -0
  330. package/src/utils/mammothApi.ts +16 -0
  331. package/src/utils/polyfills.ts +928 -0
  332. package/src/utils/regex.ts +14 -0
  333. package/src/utils/storage.ts +95 -0
  334. package/src/utils/workerBootstrap.ts +87 -0
  335. package/dist/api/index.js +0 -1553
  336. package/dist/contract.js +0 -5
  337. package/dist/index.js +0 -4492
  338. package/dist/types/index.js +0 -49
  339. package/dist/ui/index.css +0 -1876
  340. package/dist/ui/index.js +0 -22245
  341. package/dist/utils/index.js +0 -4296
  342. /package/{dist → src}/styles/ant-modal.css +0 -0
  343. /package/{dist → src}/styles/ant-spin.css +0 -0
  344. /package/{dist → src}/styles/ant-table.css +0 -0
  345. /package/{dist → src}/styles/index.css +0 -0
@@ -0,0 +1,372 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Copyright (c) 2025 SPACECORE Co.,Ltd. All Rights Reserved.
5
+ * Author: brian.li
6
+ * Date: 2025-04-02 11:43
7
+ * Desc: 部门信息工具类 - 支持Dexie缓存
8
+ *
9
+ * @example 使用方法
10
+ *
11
+ * // 1. 获取所有部门信息
12
+ * import { CacheDepartmentInfo } from './CacheDepartmentInfo';
13
+ * const depts = await CacheDepartmentInfo.getDepartmentInfo({});
14
+ * console.log(depts);
15
+ *
16
+ * // 2. 强制刷新缓存(不使用缓存)
17
+ * const depts = await CacheDepartmentInfo.getDepartmentInfo({ forceRefresh: true });
18
+ * console.log(depts);
19
+ *
20
+ * // 3. 清除部门缓存
21
+ * CacheDepartmentInfo.clearDepartmentCache();
22
+ *
23
+ * // 4. 获取缓存统计信息
24
+ * const stats = await CacheDepartmentInfo.getCacheStats();
25
+ * console.log(`缓存数量: ${stats.count}`);
26
+ */
27
+
28
+ import Dexie, { Table } from 'dexie';
29
+ import { API } from "../api";
30
+ import { ResponseCode } from "../api/_base";
31
+
32
+ /** 部门信息缓存时间(毫秒)24小时 */
33
+ const CACHE_EXPIRATION_MS = 24 * 60 * 60 * 1000;
34
+
35
+ /** 公司信息数据类型 */
36
+ export interface CompanyInfo {
37
+ id: string;
38
+ name: string;
39
+ descs: string;
40
+ parent_id: string;
41
+ admin_id: string;
42
+ is_spv_company?: boolean;
43
+ created_at?: Date;
44
+ }
45
+
46
+ /** 部门信息数据类型 */
47
+ export interface DepartmentInfo {
48
+ id: string;
49
+ name: string;
50
+ descs: string;
51
+ parent_id: string;
52
+ admin_id: string;
53
+ company_id?: string;
54
+ company?: CompanyInfo;
55
+ created_at?: Date;
56
+ children?: DepartmentInfo[];
57
+ }
58
+
59
+ /** 部门信息缓存数据结构 */
60
+ interface DepartmentCache {
61
+ id: string;
62
+ data: DepartmentInfo[];
63
+ timestamp: number;
64
+ }
65
+
66
+ /** Dexie 数据库类 */
67
+ class DepartmentInfoDatabase extends Dexie {
68
+ departmentCache!: Table<DepartmentCache, string>;
69
+
70
+ constructor() {
71
+ super('DepartmentInfoDB');
72
+ this.version(1).stores({
73
+ departmentCache: 'id, timestamp'
74
+ });
75
+ }
76
+ }
77
+
78
+ /** 单例数据库实例 */
79
+ const db = new DepartmentInfoDatabase();
80
+ let departmentListPromise: Promise<DepartmentInfo[] | null> | null = null;
81
+
82
+ /**
83
+ * 从缓存获取部门信息
84
+ * @returns 缓存的部门信息或null
85
+ */
86
+ const getFromCache = async (): Promise<DepartmentInfo[] | null> => {
87
+ try {
88
+ const cached = await db.departmentCache.get('DEPARTMENT_ALL');
89
+ if (cached) {
90
+ const now = Date.now();
91
+ if (now - cached.timestamp < CACHE_EXPIRATION_MS) {
92
+ return cached.data;
93
+ }
94
+ // 缓存过期,删除
95
+ await db.departmentCache.delete('DEPARTMENT_ALL');
96
+ }
97
+ return null;
98
+ } catch (error) {
99
+ console.error('读取部门缓存失败:', error);
100
+ return null;
101
+ }
102
+ };
103
+
104
+ /**
105
+ * 设置部门信息到缓存
106
+ * @param data 部门信息数组
107
+ */
108
+ const setToCache = async (data: DepartmentInfo[]): Promise<void> => {
109
+ try {
110
+ await db.departmentCache.put({
111
+ id: 'DEPARTMENT_ALL',
112
+ data,
113
+ timestamp: Date.now()
114
+ });
115
+ } catch (error) {
116
+ console.error('写入部门缓存失败:', error);
117
+ }
118
+ };
119
+
120
+ /**
121
+ * 清除所有部门缓存
122
+ */
123
+ const clearCache = async (): Promise<void> => {
124
+ try {
125
+ await db.departmentCache.clear();
126
+ } catch (error) {
127
+ console.error('清除部门缓存失败:', error);
128
+ }
129
+ };
130
+
131
+ const attachCompanyInfo = (
132
+ departments: DepartmentInfo[],
133
+ company: CompanyInfo
134
+ ): DepartmentInfo[] => {
135
+ return departments.map(department => ({
136
+ ...department,
137
+ company_id: department.company_id || company.id,
138
+ company,
139
+ children: department.children
140
+ ? attachCompanyInfo(department.children, company)
141
+ : undefined
142
+ }));
143
+ };
144
+
145
+ /**
146
+ * 从API获取公司下的部门信息
147
+ * 公司信息不做缓存,刷新部门缓存时实时获取公司后再获取部门
148
+ */
149
+ const fetchDepartmentsFromApi = async (): Promise<DepartmentInfo[] | null> => {
150
+ const companyRes = await API.user.role.listCompanies();
151
+
152
+ if (companyRes.code !== ResponseCode.SUCCESS) {
153
+ return null;
154
+ }
155
+
156
+ const companies: CompanyInfo[] = (companyRes.data || []).map(company => ({
157
+ id: company.id,
158
+ name: company.name,
159
+ descs: company.descs,
160
+ parent_id: company.parent_id,
161
+ admin_id: company.admin_id,
162
+ is_spv_company: company.is_spv_company,
163
+ created_at: company.created_at
164
+ }));
165
+
166
+ if (companies.length === 0) {
167
+ return [];
168
+ }
169
+
170
+ const departmentResults = await Promise.all(
171
+ companies.map(async (company) => {
172
+ const departmentRes = await API.user.role.listCompanyDepartments({ company_id: company.id });
173
+
174
+ if (departmentRes.code !== ResponseCode.SUCCESS) {
175
+ return null;
176
+ }
177
+
178
+ return attachCompanyInfo((departmentRes.data || []) as DepartmentInfo[], company);
179
+ })
180
+ );
181
+
182
+ if (departmentResults.some(result => result === null)) {
183
+ return null;
184
+ }
185
+
186
+ return departmentResults.flatMap(result => result || []);
187
+ };
188
+
189
+ /**
190
+ * 获取所有部门信息
191
+ * @param forceRefresh 是否强制刷新缓存(默认false,使用缓存)
192
+ * @returns 部门信息数组
193
+ */
194
+ const getDepartmentList = async (
195
+ {
196
+ forceRefresh = false
197
+ }: {
198
+ forceRefresh?: boolean
199
+ }
200
+ ): Promise<DepartmentInfo[] | null> => {
201
+
202
+ // 尝试从缓存获取(除非强制刷新)
203
+ if (!forceRefresh) {
204
+ const cachedDeptInfo = await getFromCache();
205
+ if (cachedDeptInfo) {
206
+ return cachedDeptInfo;
207
+ }
208
+ }
209
+
210
+ if (!departmentListPromise) {
211
+ departmentListPromise = fetchDepartmentsFromApi()
212
+ .then(async (departments) => {
213
+ if (departments) {
214
+ await setToCache(departments);
215
+ }
216
+ return departments;
217
+ })
218
+ .finally(() => {
219
+ departmentListPromise = null;
220
+ });
221
+ }
222
+
223
+ const departments = await departmentListPromise;
224
+ if (!departments) {
225
+ return null;
226
+ }
227
+
228
+ return departments;
229
+ };
230
+
231
+ /**
232
+ * 获取扁平化的部门列表(包含所有子部门)
233
+ * @param forceRefresh 是否强制刷新缓存(默认false,使用缓存)
234
+ * @returns 扁平化的部门信息数组
235
+ */
236
+ const getFlatDepartmentList = async (
237
+ {
238
+ forceRefresh = false
239
+ }: {
240
+ forceRefresh?: boolean
241
+ }
242
+ ): Promise<DepartmentInfo[] | null> => {
243
+ const departments = await getDepartmentList({ forceRefresh });
244
+
245
+ if (!departments) {
246
+ return null;
247
+ }
248
+
249
+ const flatten = (depts: DepartmentInfo[]): DepartmentInfo[] => {
250
+ let result: DepartmentInfo[] = [];
251
+ for (const dept of depts) {
252
+ const { children, ...deptWithoutChildren } = dept;
253
+ result.push(deptWithoutChildren as DepartmentInfo);
254
+ if (dept.children && dept.children.length > 0) {
255
+ result = result.concat(flatten(dept.children));
256
+ }
257
+ }
258
+ return result;
259
+ };
260
+
261
+ return flatten(departments);
262
+ };
263
+
264
+ /**
265
+ * 根据部门ID获取部门信息
266
+ * @param deptId 部门ID
267
+ * @param forceRefresh 是否强制刷新缓存(默认false,使用缓存)
268
+ * @returns 部门信息或null
269
+ */
270
+ const getDepartmentById = async (
271
+ {
272
+ deptId,
273
+ forceRefresh = false
274
+ }: {
275
+ deptId: string,
276
+ forceRefresh?: boolean
277
+ }
278
+ ): Promise<DepartmentInfo | null> => {
279
+ const departments = await getFlatDepartmentList({ forceRefresh });
280
+
281
+ if (!departments) {
282
+ return null;
283
+ }
284
+
285
+ return departments.find(dept => dept.id === deptId) || null;
286
+ };
287
+
288
+ /**
289
+ * 根据部门ID获取部门名称
290
+ * @param deptId 部门ID
291
+ * @param forceRefresh 是否强制刷新缓存(默认false,使用缓存)
292
+ * @returns 部门名称或空字符串
293
+ */
294
+ const getDepartmentNameById = async (
295
+ {
296
+ deptId,
297
+ forceRefresh = false
298
+ }: {
299
+ deptId: string,
300
+ forceRefresh?: boolean
301
+ }
302
+ ): Promise<string> => {
303
+ const dept = await getDepartmentById({ deptId, forceRefresh });
304
+ return dept?.name || '';
305
+ };
306
+
307
+ /**
308
+ * 清除部门缓存
309
+ */
310
+ const clearDepartmentCache = async (): Promise<void> => {
311
+ await clearCache();
312
+ };
313
+
314
+ /**
315
+ * 获取缓存统计信息
316
+ * @returns 缓存统计信息
317
+ */
318
+ const getCacheStats = async (): Promise<{ count: number; oldest: number | null; newest: number | null }> => {
319
+ try {
320
+ const all = await db.departmentCache.toArray();
321
+ if (all.length === 0) {
322
+ return { count: 0, oldest: null, newest: null };
323
+ }
324
+ const timestamps = all.map(item => item.timestamp);
325
+ return {
326
+ count: all.length,
327
+ oldest: Math.min(...timestamps),
328
+ newest: Math.max(...timestamps)
329
+ };
330
+ } catch (error) {
331
+ console.error('获取缓存统计失败:', error);
332
+ return { count: 0, oldest: null, newest: null };
333
+ }
334
+ };
335
+
336
+ export const CacheDepartmentInfo = {
337
+ /**
338
+ * 获取所有部门信息
339
+ * @param forceRefresh 是否强制刷新缓存(默认false,使用缓存)
340
+ * @returns 部门信息数组
341
+ */
342
+ getDepartmentList,
343
+ /**
344
+ * 获取扁平化的部门列表(包含所有子部门)
345
+ * @param forceRefresh 是否强制刷新缓存(默认false,使用缓存)
346
+ * @returns 扁平化的部门信息数组
347
+ */
348
+ getFlatDepartmentList,
349
+ /**
350
+ * 根据部门ID获取部门信息
351
+ * @param deptId 部门ID
352
+ * @param forceRefresh 是否强制刷新缓存(默认false,使用缓存)
353
+ * @returns 部门信息或null
354
+ */
355
+ getDepartmentById,
356
+ /**
357
+ * 根据部门ID获取部门名称
358
+ * @param deptId 部门ID
359
+ * @param forceRefresh 是否强制刷新缓存(默认false,使用缓存)
360
+ * @returns 部门名称或空字符串
361
+ */
362
+ getDepartmentNameById,
363
+ /**
364
+ * 清除部门缓存
365
+ */
366
+ clearDepartmentCache,
367
+ /**
368
+ * 获取缓存统计信息
369
+ * @returns 缓存统计信息
370
+ */
371
+ getCacheStats
372
+ };
@@ -0,0 +1,315 @@
1
+ 'use strict';
2
+
3
+ import Dexie, { Table } from 'dexie';
4
+ import * as febs from 'febs-browser';
5
+
6
+ interface FileCacheRecord {
7
+ id: string;
8
+ fileId: string;
9
+ /** 文件内容使用 ArrayBuffer 存储 —— Safari 对 IndexedDB 中 Blob 的序列化/反序列化存在兼容性问题
10
+ * (Blob 可能变成 size=0 空对象或在 GC 后变成 detached 状态),而 ArrayBuffer 是纯二进制数据,
11
+ * 在所有浏览器(包括 Safari)的 IndexedDB 中都能可靠存取。
12
+ * 读取时通过 `new Blob([arrayBuffer], { type: contentType })` 重新构造 Blob。 */
13
+ content: ArrayBuffer;
14
+ crc32: number;
15
+ fileSize: number;
16
+ /** 单独存储的 MIME 类型(字符串持久化不受 Safari IndexedDB Blob.type 丢失 Bug 影响) */
17
+ contentType: string;
18
+ updateTime: number;
19
+ }
20
+
21
+ /** 服务器文件元数据缓存记录(用于离线时重建文件列表) */
22
+ interface FileMetaRecord {
23
+ id: string;
24
+ fileId: string;
25
+ projectId: string;
26
+ /** 完整 ProjectFile 对象(序列化后) */
27
+ meta: any;
28
+ updateTime: number;
29
+ }
30
+
31
+ class FileContentDatabase extends Dexie {
32
+ fileCache!: Table<FileCacheRecord, string>;
33
+ fileMeta!: Table<FileMetaRecord, string>;
34
+
35
+ constructor() {
36
+ super('FileContentDB');
37
+ this.version(1).stores({
38
+ fileCache: 'id, fileId, crc32, fileSize, updateTime'
39
+ });
40
+ // v2: 新增 fileMeta store,用于离线显示缓存文件元数据
41
+ this.version(2).stores({
42
+ fileCache: 'id, fileId, crc32, fileSize, updateTime',
43
+ fileMeta: 'id, fileId, projectId, updateTime',
44
+ });
45
+ }
46
+ }
47
+
48
+ const db = new FileContentDatabase();
49
+
50
+ const calculateCrc32 = async (blob: Blob): Promise<number> => {
51
+ return new Promise((resolve, reject) => {
52
+ const file = new File([blob], 'temp');
53
+ febs.crypt.crc32_file(file as unknown as File, (crc: number) => {
54
+ if (crc === 0) {
55
+ reject(new Error('CRC32 计算失败'));
56
+ } else {
57
+ resolve(crc);
58
+ }
59
+ });
60
+ });
61
+ };
62
+
63
+ const getCacheRecord = async (fileId: string): Promise<FileCacheRecord | undefined> => {
64
+ try {
65
+ const records = await db.fileCache.where('fileId').equals(fileId).toArray();
66
+ return records.length > 0 ? records[0] : undefined;
67
+ } catch (error) {
68
+ console.error('读取文件缓存失败:', error);
69
+ return undefined;
70
+ }
71
+ };
72
+
73
+ const saveToCache = async (fileId: string, content: Blob, crc32?: number, fileSize?: number, contentType?: string): Promise<void> => {
74
+ try {
75
+ const actualCrc32 = crc32 ?? await calculateCrc32(content);
76
+ const actualSize = fileSize ?? content.size;
77
+ // 显式传入的 contentType 优先;否则用 Blob.type(注意:Safari IndexedDB 回读后 Blob.type 可能丢失,所以必须独立保存)
78
+ const actualContentType = contentType ?? content.type ?? '';
79
+
80
+ // 关键修复:将 Blob 转为 ArrayBuffer 存储,避免 Safari IndexedDB Blob 损坏问题
81
+ // ArrayBuffer 是纯二进制数据,在 Safari IndexedDB 中可靠存取
82
+ const arrayBuffer = await content.arrayBuffer();
83
+
84
+ // 先删除旧记录,确保同一个fileId只有一条记录
85
+ await db.fileCache.where('fileId').equals(fileId).delete();
86
+
87
+ const record: FileCacheRecord = {
88
+ id: fileId,
89
+ fileId,
90
+ content: arrayBuffer,
91
+ crc32: actualCrc32,
92
+ fileSize: actualSize,
93
+ contentType: actualContentType,
94
+ updateTime: Date.now(),
95
+ };
96
+
97
+ await db.fileCache.put(record);
98
+ } catch (error) {
99
+ console.error('写入文件缓存失败:', error);
100
+ }
101
+ };
102
+
103
+ const removeFromCache = async (fileId: string): Promise<void> => {
104
+ try {
105
+ await db.fileCache.where('fileId').equals(fileId).delete();
106
+ } catch (error) {
107
+ console.error('删除文件缓存失败:', error);
108
+ }
109
+ };
110
+
111
+ const hasCache = async (fileId: string): Promise<boolean> => {
112
+ const record = await getCacheRecord(fileId);
113
+ return record !== undefined;
114
+ };
115
+
116
+ const getCachedContent = async (fileId: string): Promise<{ content: Blob; crc32: number; contentType: string } | null> => {
117
+ const record = await getCacheRecord(fileId);
118
+ if (!record) {
119
+ console.log('[CacheFileContent] getCachedContent: 无缓存记录 fileId=', fileId);
120
+ return null;
121
+ }
122
+
123
+ // 读取兼容处理:
124
+ // 新版本:record.content 是 ArrayBuffer(Safari 兼容存储方式)
125
+ // 旧版本:record.content 可能是 Blob(之前的存储方式,Safari 可能已损坏)
126
+ // 为了兼容旧数据,检测类型后统一转为 ArrayBuffer,再构造 Blob
127
+ const safeContentType = record.contentType ?? '';
128
+ let blob: Blob;
129
+
130
+ if (record.content instanceof ArrayBuffer) {
131
+ // 新版本:直接从 ArrayBuffer 构造 Blob
132
+ blob = new Blob([record.content], { type: safeContentType });
133
+ console.log('[CacheFileContent] getCachedContent: fileId=', fileId,
134
+ '[ArrayBuffer] byteLength=', record.content.byteLength,
135
+ 'reconstructedBlob.size=', blob.size,
136
+ 'contentType=', safeContentType);
137
+ } else if ((record.content as any) instanceof Blob) {
138
+ // 旧版本:兼容处理。检测旧 Blob 是否在 Safari 中已损坏
139
+ const oldBlob = record.content as unknown as Blob;
140
+ if (oldBlob.size === 0) {
141
+ console.warn('[CacheFileContent] getCachedContent: 旧 Blob 已损坏 (size=0),将删除缓存并重新下载');
142
+ await removeFromCache(fileId);
143
+ return null;
144
+ }
145
+ // 将旧 Blob 转换为 ArrayBuffer 再重建 Blob,确保数据完整性
146
+ try {
147
+ const ab = await oldBlob.arrayBuffer();
148
+ blob = new Blob([ab], { type: safeContentType || oldBlob.type });
149
+ console.log('[CacheFileContent] getCachedContent: fileId=', fileId,
150
+ '[Blob→ArrayBuffer] size=', blob.size,
151
+ 'contentType=', safeContentType);
152
+ // 迁移:将旧 Blob 记录转换为 ArrayBuffer 存储
153
+ await saveToCache(fileId, blob, record.crc32, record.fileSize, safeContentType || oldBlob.type);
154
+ } catch (e) {
155
+ console.warn('[CacheFileContent] getCachedContent: 旧 Blob 读取失败,删除缓存:', e);
156
+ await removeFromCache(fileId);
157
+ return null;
158
+ }
159
+ } else {
160
+ // 未知类型,删除缓存
161
+ console.warn('[CacheFileContent] getCachedContent: 未知 content 类型,删除缓存');
162
+ await removeFromCache(fileId);
163
+ return null;
164
+ }
165
+
166
+ return { content: blob, crc32: record.crc32, contentType: safeContentType };
167
+ };
168
+
169
+ const validateCache = async (fileId: string, expectedCrc32: number): Promise<boolean> => {
170
+ const record = await getCacheRecord(fileId);
171
+ if (!record) {
172
+ console.log('[CacheFileContent] validateCache: 无缓存记录 fileId=', fileId);
173
+ return false;
174
+ }
175
+ // Safari 调试:输出 crc32 的类型和值,排查类型不一致问题
176
+ const storedCrc32 = record.crc32;
177
+ const expected = expectedCrc32;
178
+ const isMatch = storedCrc32 === expected;
179
+ if (!isMatch) {
180
+ console.warn('[CacheFileContent] validateCache: crc32 不匹配',
181
+ 'stored=', storedCrc32, typeof storedCrc32,
182
+ 'expected=', expected, typeof expected);
183
+ }
184
+ return isMatch;
185
+ };
186
+
187
+ const clearAllCache = async (): Promise<void> => {
188
+ try {
189
+ await db.fileCache.clear();
190
+ } catch (error) {
191
+ console.error('清除所有文件缓存失败:', error);
192
+ }
193
+ };
194
+
195
+ const getCacheStats = async (): Promise<{ fileCount: number; totalSize: number; oldestTime: number | null; newestTime: number | null }> => {
196
+ try {
197
+ const all = await db.fileCache.toArray();
198
+ if (all.length === 0) {
199
+ return { fileCount: 0, totalSize: 0, oldestTime: null, newestTime: null };
200
+ }
201
+ const totalSize = all.reduce((sum, record) => sum + record.fileSize, 0);
202
+ const updateTimes = all.map(record => record.updateTime);
203
+ return {
204
+ fileCount: all.length,
205
+ totalSize,
206
+ oldestTime: Math.min(...updateTimes),
207
+ newestTime: Math.max(...updateTimes),
208
+ };
209
+ } catch (error) {
210
+ console.error('获取文件缓存统计失败:', error);
211
+ return { fileCount: 0, totalSize: 0, oldestTime: null, newestTime: null };
212
+ }
213
+ };
214
+
215
+ const getCacheList = async (): Promise<{ fileId: string; crc32: number; fileSize: number; updateTime: number }[]> => {
216
+ try {
217
+ const all = await db.fileCache.toArray();
218
+ return all.map(record => ({
219
+ fileId: record.fileId,
220
+ crc32: record.crc32,
221
+ fileSize: record.fileSize,
222
+ updateTime: record.updateTime,
223
+ }));
224
+ } catch (error) {
225
+ console.error('获取文件缓存列表失败:', error);
226
+ return [];
227
+ }
228
+ };
229
+
230
+ export const CacheFileContent = {
231
+ saveToCache,
232
+ removeFromCache,
233
+ hasCache,
234
+ getCachedContent,
235
+ validateCache,
236
+ clearAllCache,
237
+ getCacheStats,
238
+ getCacheList,
239
+ };
240
+
241
+ // ============================================================
242
+ // 服务器文件元数据缓存(FileMeta store)— 用于离线时重建文件列表
243
+ // ============================================================
244
+
245
+ /** 批量保存/更新服务器文件元数据(online 时每次 listFiles 后调用) */
246
+ const saveFileMetaBatch = async (projectId: string, files: any[]): Promise<void> => {
247
+ try {
248
+ if (!files || files.length === 0) return;
249
+ const now = Date.now();
250
+ const records: FileMetaRecord[] = files.map(f => ({
251
+ id: f.id,
252
+ fileId: f.id,
253
+ projectId,
254
+ meta: f,
255
+ updateTime: now,
256
+ }));
257
+ await db.fileMeta.bulkPut(records);
258
+ } catch (error) {
259
+ console.error('批量保存文件元数据缓存失败:', error);
260
+ }
261
+ };
262
+
263
+ /** 保存单个文件元数据(预览/编辑单个文件时调用) */
264
+ const saveFileMeta = async (projectId: string, file: any): Promise<void> => {
265
+ try {
266
+ await db.fileMeta.put({
267
+ id: file.id,
268
+ fileId: file.id,
269
+ projectId,
270
+ meta: file,
271
+ updateTime: Date.now(),
272
+ });
273
+ } catch (error) {
274
+ console.error('保存文件元数据缓存失败:', error);
275
+ }
276
+ };
277
+
278
+ /** 按项目列出所有缓存过的文件元数据(offline 时用于重建列表) */
279
+ const listFileMetaByProject = async (projectId: string): Promise<any[]> => {
280
+ try {
281
+ const records = await db.fileMeta.where('projectId').equals(projectId).toArray();
282
+ return records.map(r => r.meta);
283
+ } catch (error) {
284
+ console.error('列出项目文件元数据缓存失败:', error);
285
+ return [];
286
+ }
287
+ };
288
+
289
+ /** 按 fileId 获取单个元数据 */
290
+ const getFileMeta = async (fileId: string): Promise<any | undefined> => {
291
+ try {
292
+ const records = await db.fileMeta.where('fileId').equals(fileId).toArray();
293
+ return records.length > 0 ? records[0].meta : undefined;
294
+ } catch (error) {
295
+ console.error('获取文件元数据缓存失败:', error);
296
+ return undefined;
297
+ }
298
+ };
299
+
300
+ /** 删除单个文件的元数据 */
301
+ const removeFileMeta = async (fileId: string): Promise<void> => {
302
+ try {
303
+ await db.fileMeta.where('fileId').equals(fileId).delete();
304
+ } catch (error) {
305
+ console.error('删除文件元数据缓存失败:', error);
306
+ }
307
+ };
308
+
309
+ export const CacheFileMeta = {
310
+ saveFileMetaBatch,
311
+ saveFileMeta,
312
+ listFileMetaByProject,
313
+ getFileMeta,
314
+ removeFileMeta,
315
+ };