@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.
- package/package.json +20 -38
- package/public/cmaps/78-EUC-H.bcmap +0 -0
- package/public/cmaps/78-EUC-V.bcmap +0 -0
- package/public/cmaps/78-H.bcmap +0 -0
- package/public/cmaps/78-RKSJ-H.bcmap +0 -0
- package/public/cmaps/78-RKSJ-V.bcmap +0 -0
- package/public/cmaps/78-V.bcmap +0 -0
- package/public/cmaps/78ms-RKSJ-H.bcmap +0 -0
- package/public/cmaps/78ms-RKSJ-V.bcmap +0 -0
- package/public/cmaps/83pv-RKSJ-H.bcmap +0 -0
- package/public/cmaps/90ms-RKSJ-H.bcmap +0 -0
- package/public/cmaps/90ms-RKSJ-V.bcmap +0 -0
- package/public/cmaps/90msp-RKSJ-H.bcmap +0 -0
- package/public/cmaps/90msp-RKSJ-V.bcmap +0 -0
- package/public/cmaps/90pv-RKSJ-H.bcmap +0 -0
- package/public/cmaps/90pv-RKSJ-V.bcmap +0 -0
- package/public/cmaps/Add-H.bcmap +0 -0
- package/public/cmaps/Add-RKSJ-H.bcmap +0 -0
- package/public/cmaps/Add-RKSJ-V.bcmap +0 -0
- package/public/cmaps/Add-V.bcmap +0 -0
- package/public/cmaps/Adobe-CNS1-0.bcmap +0 -0
- package/public/cmaps/Adobe-CNS1-1.bcmap +0 -0
- package/public/cmaps/Adobe-CNS1-2.bcmap +0 -0
- package/public/cmaps/Adobe-CNS1-3.bcmap +0 -0
- package/public/cmaps/Adobe-CNS1-4.bcmap +0 -0
- package/public/cmaps/Adobe-CNS1-5.bcmap +0 -0
- package/public/cmaps/Adobe-CNS1-6.bcmap +0 -0
- package/public/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
- package/public/cmaps/Adobe-GB1-0.bcmap +0 -0
- package/public/cmaps/Adobe-GB1-1.bcmap +0 -0
- package/public/cmaps/Adobe-GB1-2.bcmap +0 -0
- package/public/cmaps/Adobe-GB1-3.bcmap +0 -0
- package/public/cmaps/Adobe-GB1-4.bcmap +0 -0
- package/public/cmaps/Adobe-GB1-5.bcmap +0 -0
- package/public/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
- package/public/cmaps/Adobe-Japan1-0.bcmap +0 -0
- package/public/cmaps/Adobe-Japan1-1.bcmap +0 -0
- package/public/cmaps/Adobe-Japan1-2.bcmap +0 -0
- package/public/cmaps/Adobe-Japan1-3.bcmap +0 -0
- package/public/cmaps/Adobe-Japan1-4.bcmap +0 -0
- package/public/cmaps/Adobe-Japan1-5.bcmap +0 -0
- package/public/cmaps/Adobe-Japan1-6.bcmap +0 -0
- package/public/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
- package/public/cmaps/Adobe-Korea1-0.bcmap +0 -0
- package/public/cmaps/Adobe-Korea1-1.bcmap +0 -0
- package/public/cmaps/Adobe-Korea1-2.bcmap +0 -0
- package/public/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
- package/public/cmaps/B5-H.bcmap +0 -0
- package/public/cmaps/B5-V.bcmap +0 -0
- package/public/cmaps/B5pc-H.bcmap +0 -0
- package/public/cmaps/B5pc-V.bcmap +0 -0
- package/public/cmaps/CNS-EUC-H.bcmap +0 -0
- package/public/cmaps/CNS-EUC-V.bcmap +0 -0
- package/public/cmaps/CNS1-H.bcmap +0 -0
- package/public/cmaps/CNS1-V.bcmap +0 -0
- package/public/cmaps/CNS2-H.bcmap +0 -0
- package/public/cmaps/CNS2-V.bcmap +3 -0
- package/public/cmaps/ETHK-B5-H.bcmap +0 -0
- package/public/cmaps/ETHK-B5-V.bcmap +0 -0
- package/public/cmaps/ETen-B5-H.bcmap +0 -0
- package/public/cmaps/ETen-B5-V.bcmap +0 -0
- package/public/cmaps/ETenms-B5-H.bcmap +3 -0
- package/public/cmaps/ETenms-B5-V.bcmap +0 -0
- package/public/cmaps/EUC-H.bcmap +0 -0
- package/public/cmaps/EUC-V.bcmap +0 -0
- package/public/cmaps/Ext-H.bcmap +0 -0
- package/public/cmaps/Ext-RKSJ-H.bcmap +0 -0
- package/public/cmaps/Ext-RKSJ-V.bcmap +0 -0
- package/public/cmaps/Ext-V.bcmap +0 -0
- package/public/cmaps/GB-EUC-H.bcmap +0 -0
- package/public/cmaps/GB-EUC-V.bcmap +0 -0
- package/public/cmaps/GB-H.bcmap +4 -0
- package/public/cmaps/GB-V.bcmap +0 -0
- package/public/cmaps/GBK-EUC-H.bcmap +0 -0
- package/public/cmaps/GBK-EUC-V.bcmap +0 -0
- package/public/cmaps/GBK2K-H.bcmap +0 -0
- package/public/cmaps/GBK2K-V.bcmap +0 -0
- package/public/cmaps/GBKp-EUC-H.bcmap +0 -0
- package/public/cmaps/GBKp-EUC-V.bcmap +0 -0
- package/public/cmaps/GBT-EUC-H.bcmap +0 -0
- package/public/cmaps/GBT-EUC-V.bcmap +0 -0
- package/public/cmaps/GBT-H.bcmap +0 -0
- package/public/cmaps/GBT-V.bcmap +0 -0
- package/public/cmaps/GBTpc-EUC-H.bcmap +0 -0
- package/public/cmaps/GBTpc-EUC-V.bcmap +0 -0
- package/public/cmaps/GBpc-EUC-H.bcmap +0 -0
- package/public/cmaps/GBpc-EUC-V.bcmap +0 -0
- package/public/cmaps/H.bcmap +0 -0
- package/public/cmaps/HKdla-B5-H.bcmap +0 -0
- package/public/cmaps/HKdla-B5-V.bcmap +0 -0
- package/public/cmaps/HKdlb-B5-H.bcmap +0 -0
- package/public/cmaps/HKdlb-B5-V.bcmap +0 -0
- package/public/cmaps/HKgccs-B5-H.bcmap +0 -0
- package/public/cmaps/HKgccs-B5-V.bcmap +0 -0
- package/public/cmaps/HKm314-B5-H.bcmap +0 -0
- package/public/cmaps/HKm314-B5-V.bcmap +0 -0
- package/public/cmaps/HKm471-B5-H.bcmap +0 -0
- package/public/cmaps/HKm471-B5-V.bcmap +0 -0
- package/public/cmaps/HKscs-B5-H.bcmap +0 -0
- package/public/cmaps/HKscs-B5-V.bcmap +0 -0
- package/public/cmaps/Hankaku.bcmap +0 -0
- package/public/cmaps/Hiragana.bcmap +0 -0
- package/public/cmaps/KSC-EUC-H.bcmap +0 -0
- package/public/cmaps/KSC-EUC-V.bcmap +0 -0
- package/public/cmaps/KSC-H.bcmap +0 -0
- package/public/cmaps/KSC-Johab-H.bcmap +0 -0
- package/public/cmaps/KSC-Johab-V.bcmap +0 -0
- package/public/cmaps/KSC-V.bcmap +0 -0
- package/public/cmaps/KSCms-UHC-H.bcmap +0 -0
- package/public/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
- package/public/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
- package/public/cmaps/KSCms-UHC-V.bcmap +0 -0
- package/public/cmaps/KSCpc-EUC-H.bcmap +0 -0
- package/public/cmaps/KSCpc-EUC-V.bcmap +0 -0
- package/public/cmaps/Katakana.bcmap +0 -0
- package/public/cmaps/LICENSE +36 -0
- package/public/cmaps/NWP-H.bcmap +0 -0
- package/public/cmaps/NWP-V.bcmap +0 -0
- package/public/cmaps/RKSJ-H.bcmap +0 -0
- package/public/cmaps/RKSJ-V.bcmap +0 -0
- package/public/cmaps/Roman.bcmap +0 -0
- package/public/cmaps/UniCNS-UCS2-H.bcmap +0 -0
- package/public/cmaps/UniCNS-UCS2-V.bcmap +0 -0
- package/public/cmaps/UniCNS-UTF16-H.bcmap +0 -0
- package/public/cmaps/UniCNS-UTF16-V.bcmap +0 -0
- package/public/cmaps/UniCNS-UTF32-H.bcmap +0 -0
- package/public/cmaps/UniCNS-UTF32-V.bcmap +0 -0
- package/public/cmaps/UniCNS-UTF8-H.bcmap +0 -0
- package/public/cmaps/UniCNS-UTF8-V.bcmap +0 -0
- package/public/cmaps/UniGB-UCS2-H.bcmap +0 -0
- package/public/cmaps/UniGB-UCS2-V.bcmap +0 -0
- package/public/cmaps/UniGB-UTF16-H.bcmap +0 -0
- package/public/cmaps/UniGB-UTF16-V.bcmap +0 -0
- package/public/cmaps/UniGB-UTF32-H.bcmap +0 -0
- package/public/cmaps/UniGB-UTF32-V.bcmap +0 -0
- package/public/cmaps/UniGB-UTF8-H.bcmap +0 -0
- package/public/cmaps/UniGB-UTF8-V.bcmap +0 -0
- package/public/cmaps/UniJIS-UCS2-H.bcmap +0 -0
- package/public/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
- package/public/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
- package/public/cmaps/UniJIS-UCS2-V.bcmap +0 -0
- package/public/cmaps/UniJIS-UTF16-H.bcmap +0 -0
- package/public/cmaps/UniJIS-UTF16-V.bcmap +0 -0
- package/public/cmaps/UniJIS-UTF32-H.bcmap +0 -0
- package/public/cmaps/UniJIS-UTF32-V.bcmap +0 -0
- package/public/cmaps/UniJIS-UTF8-H.bcmap +0 -0
- package/public/cmaps/UniJIS-UTF8-V.bcmap +0 -0
- package/public/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
- package/public/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
- package/public/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
- package/public/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
- package/public/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
- package/public/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
- package/public/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
- package/public/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
- package/public/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
- package/public/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
- package/public/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
- package/public/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
- package/public/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
- package/public/cmaps/UniKS-UCS2-H.bcmap +0 -0
- package/public/cmaps/UniKS-UCS2-V.bcmap +0 -0
- package/public/cmaps/UniKS-UTF16-H.bcmap +0 -0
- package/public/cmaps/UniKS-UTF16-V.bcmap +0 -0
- package/public/cmaps/UniKS-UTF32-H.bcmap +0 -0
- package/public/cmaps/UniKS-UTF32-V.bcmap +0 -0
- package/public/cmaps/UniKS-UTF8-H.bcmap +0 -0
- package/public/cmaps/UniKS-UTF8-V.bcmap +0 -0
- package/public/cmaps/V.bcmap +0 -0
- package/public/cmaps/WP-Symbol.bcmap +0 -0
- package/public/polyfills/polyfills.js +802 -0
- package/public/vendor/docx/docx.worker.js +5 -0
- package/public/vendor/docx/jszip.min.js +13 -0
- package/public/vendor/libarchive/libarchive.wasm +0 -0
- package/public/vendor/libarchive/worker-bundle.js +6 -0
- package/public/vendor/pptx/pptx.worker.js +26 -0
- package/public/wasm/cad/0.8.2/dwfv-render.wasm +0 -0
- package/public/wasm/cad/0.8.2/dwg-worker.js +24 -0
- package/public/wasm/cad/0.8.2/dwg-worker.js.map +1 -0
- package/public/wasm/cad/0.8.2/libredwg-web.js +2 -0
- package/public/wasm/cad/0.8.2/libredwg-web.wasm +0 -0
- package/public/wasm/cad/dwfv-render.wasm +0 -0
- package/public/wasm/cad/dwg-worker.js +24 -0
- package/public/wasm/cad/dwg-worker.js.map +1 -0
- package/public/wasm/cad/libredwg-web.js +2 -0
- package/public/wasm/cad/libredwg-web.wasm +0 -0
- package/public/wasm/data/sql-wasm.wasm +0 -0
- package/public/wasm/hdiff.wasm +0 -0
- package/public/wasm/model/LICENSE.occt-import-js.txt +504 -0
- package/public/wasm/model/LICENSE.occt.txt +502 -0
- package/public/wasm/model/occt-import-js.js +19 -0
- package/public/wasm/model/occt-import-js.wasm +0 -0
- package/public/wasm/model/occt-worker.js +83 -0
- package/public/wasm/typst/fonts/DejaVuSansMono-Bold.ttf +0 -0
- package/public/wasm/typst/fonts/DejaVuSansMono-BoldOblique.ttf +0 -0
- package/public/wasm/typst/fonts/DejaVuSansMono-Oblique.ttf +0 -0
- package/public/wasm/typst/fonts/DejaVuSansMono.ttf +0 -0
- package/public/wasm/typst/fonts/LibertinusSerif-Bold.otf +0 -0
- package/public/wasm/typst/fonts/LibertinusSerif-BoldItalic.otf +0 -0
- package/public/wasm/typst/fonts/LibertinusSerif-Italic.otf +0 -0
- package/public/wasm/typst/fonts/LibertinusSerif-Regular.otf +0 -0
- package/public/wasm/typst/fonts/LibertinusSerif-Semibold.otf +0 -0
- package/public/wasm/typst/fonts/LibertinusSerif-SemiboldItalic.otf +0 -0
- package/public/wasm/typst/fonts/NewCM10-Bold.otf +0 -0
- package/public/wasm/typst/fonts/NewCM10-BoldItalic.otf +0 -0
- package/public/wasm/typst/fonts/NewCM10-Italic.otf +0 -0
- package/public/wasm/typst/fonts/NewCM10-Regular.otf +0 -0
- package/public/wasm/typst/fonts/NewCMMath-Bold.otf +0 -0
- package/public/wasm/typst/fonts/NewCMMath-Book.otf +0 -0
- package/public/wasm/typst/fonts/NewCMMath-Regular.otf +0 -0
- package/public/wasm/typst/fonts/README.md +7 -0
- package/public/wasm/typst/typst_ts_renderer_bg.wasm +0 -0
- package/public/wasm/typst/typst_ts_web_compiler_bg.wasm +0 -0
- package/scripts/patch-docx-grid.cjs +412 -0
- package/src/api/_base.ts +243 -0
- package/src/api/index.ts +17 -0
- package/src/api/project.ts +1345 -0
- package/src/api/user.ts +1174 -0
- package/src/contract.ts +50 -0
- package/src/hooks/index.ts +2 -0
- package/{dist/hooks/index.js → src/hooks/useLongPress.ts} +53 -49
- package/src/hooks/useOnlineStatus.ts +22 -0
- package/src/index.ts +14 -0
- package/src/types/id.ts +2 -0
- package/src/types/index.ts +5 -0
- package/src/types/project/base.ts +63 -0
- package/src/types/project/contract.ts +79 -0
- package/src/types/project/contractStatus.tsx +15 -0
- package/src/types/project/index.ts +5 -0
- package/src/types/project/member.ts +46 -0
- package/src/types/project/progress.ts +43 -0
- package/src/types/projectRole.ts +17 -0
- package/src/types/theme.ts +1 -0
- package/src/types/user/index.ts +1 -0
- package/src/types/user/role.ts +7 -0
- package/src/ui/CommentTimeline/index.tsx +330 -0
- package/src/ui/FileManager/FileContextMenu.tsx +628 -0
- package/src/ui/FileManager/FileGridView.tsx +529 -0
- package/src/ui/FileManager/FileTableView.tsx +405 -0
- package/src/ui/FileManager/FileToolbar.tsx +119 -0
- package/src/ui/FileManager/FileVersionHistoryModal.tsx +175 -0
- package/src/ui/FileManager/MoveCopyToProjectModal.tsx +119 -0
- package/src/ui/FileManager/ShareToWechatModal.tsx +419 -0
- package/src/ui/FileManager/hooks/useFileManagerActions.ts +2532 -0
- package/src/ui/FileManager/hooks/useFileManagerState.ts +419 -0
- package/src/ui/FileManager/index.tsx +580 -0
- package/src/ui/FileManager/projectFileManagerApi.ts +57 -0
- package/src/ui/FileManager/types.ts +184 -0
- package/src/ui/FileManager/utils/fileDeltaWorker.ts +193 -0
- package/src/ui/FileManager/utils/fileTree.ts +178 -0
- package/src/ui/FileManager/utils/fileUpload.ts +714 -0
- package/src/ui/FileManager/utils/fileUtils.ts +65 -0
- package/src/ui/InvoiceRecordsList/index.tsx +813 -0
- package/src/ui/MyFileSelectorModal.tsx +261 -0
- package/src/ui/ProjectSelector/index.tsx +472 -0
- package/src/ui/ProjectSelector/projectCache.ts +40 -0
- package/src/ui/RoleSelector/index.tsx +473 -0
- package/src/ui/RoleSelector/roleCache.ts +40 -0
- package/src/ui/UIAlert.tsx +399 -0
- package/src/ui/UIAlertExample.tsx +129 -0
- package/src/ui/UIConfirm.tsx +335 -0
- package/src/ui/UIConfirmExample.tsx +165 -0
- package/src/ui/UIDatePicker.tsx +146 -0
- package/src/ui/UIDateRangePicker.tsx +38 -0
- package/src/ui/UIFilePreview/ExcelEditor/index.tsx +617 -0
- package/src/ui/UIFilePreview/ExcelEditor/types.ts +24 -0
- package/src/ui/UIFilePreview/ExportDropdown.css +85 -0
- package/src/ui/UIFilePreview/ExportDropdown.tsx +109 -0
- package/src/ui/UIFilePreview/IndexedDBUtils.ts +564 -0
- package/src/ui/UIFilePreview/MarkdownEditor/exportMarkdownPdf.ts +576 -0
- package/src/ui/UIFilePreview/MarkdownEditor/index.tsx +677 -0
- package/src/ui/UIFilePreview/MarkdownEditor/markdownEditor.css +1005 -0
- package/src/ui/UIFilePreview/MarkdownEditor/types.ts +15 -0
- package/src/ui/UIFilePreview/PPTXEditor/index.tsx +602 -0
- package/src/ui/UIFilePreview/RichDocEditor/exportRDocMarkdown.ts +77 -0
- package/src/ui/UIFilePreview/RichDocEditor/exportRDocPdf.ts +374 -0
- package/src/ui/UIFilePreview/RichDocEditor/index.tsx +730 -0
- package/src/ui/UIFilePreview/RichDocEditor/richdoc-editor.css +59 -0
- package/src/ui/UIFilePreview/UIFilePreview.tsx +611 -0
- package/src/ui/UIFilePreview/WordEditor/index.tsx +3933 -0
- package/src/ui/UIFilePreview/WordEditor/style.ts +1213 -0
- package/src/ui/UIFilePreview/WordEditor/word-editor.css +999 -0
- package/src/ui/UIFilePreview/filePreview.css +193 -0
- package/src/ui/UIFilePreview/filetypes/archive.tsx +66 -0
- package/src/ui/UIFilePreview/filetypes/cad.tsx +287 -0
- package/src/ui/UIFilePreview/filetypes/excel.tsx +355 -0
- package/src/ui/UIFilePreview/filetypes/image.tsx +20 -0
- package/src/ui/UIFilePreview/filetypes/imageLoader.ts +63 -0
- package/src/ui/UIFilePreview/filetypes/pdf.tsx +156 -0
- package/src/ui/UIFilePreview/filetypes/ppt.tsx +535 -0
- package/src/ui/UIFilePreview/filetypes/pptExportPdf.ts +523 -0
- package/src/ui/UIFilePreview/filetypes/video.tsx +482 -0
- package/src/ui/UIFilePreview/filetypes/word.tsx +245 -0
- package/src/ui/UIFilePreview/filetypes/wordExportMarkdown.ts +86 -0
- package/src/ui/UIFilePreview/filetypes/wordExportPdf.tsx +427 -0
- package/src/ui/UIFilePreview/index.ts +35 -0
- package/src/ui/UIFilePreview/pdfPagination.ts +143 -0
- package/src/ui/UIFilePreview/previewUtils.tsx +531 -0
- package/src/ui/UIFileUpload.tsx +382 -0
- package/src/ui/UIImageUpload.tsx +195 -0
- package/src/ui/UILoading.tsx +255 -0
- package/src/ui/UILoadingExample.tsx +139 -0
- package/src/ui/UISelect.tsx +105 -0
- package/src/ui/UIToast.tsx +381 -0
- package/src/ui/UIToastExample.tsx +69 -0
- package/src/ui/UIToastSingle.tsx +279 -0
- package/src/ui/UIViewToggle.tsx +64 -0
- package/src/ui/UserSelector/index.tsx +583 -0
- package/src/ui/index.ts +84 -0
- package/src/ui/upload/image.ts +135 -0
- package/src/ui/upload/index.ts +73 -0
- package/src/ui/upload/submitFile.ts +106 -0
- package/src/ui/upload/submitForm.ts +124 -0
- package/src/ui/upload/upload.err.ts +15 -0
- package/src/ui/upload/upload.ts +250 -0
- package/src/utils/CacheDepartmentInfo.ts +372 -0
- package/src/utils/CacheFileContent.ts +315 -0
- package/src/utils/CachePermissionInfo.ts +235 -0
- package/src/utils/CacheRoleInfo.ts +303 -0
- package/src/utils/CacheUserInfo.ts +818 -0
- package/src/utils/CacheViewToggleInfo.ts +182 -0
- package/src/utils/MessageContentUtils.ts +268 -0
- package/src/utils/clipboard.ts +70 -0
- package/src/utils/companyEmail.ts +19 -0
- package/src/utils/forbidDebugger.ts +59 -0
- package/src/utils/formatters.ts +94 -0
- package/src/utils/htmlUtils.tsx +59 -0
- package/src/utils/index.ts +18 -0
- package/src/utils/keyboard.ts +114 -0
- package/src/utils/mammothApi.ts +16 -0
- package/src/utils/polyfills.ts +928 -0
- package/src/utils/regex.ts +14 -0
- package/src/utils/storage.ts +95 -0
- package/src/utils/workerBootstrap.ts +87 -0
- package/dist/api/index.js +0 -1553
- package/dist/contract.js +0 -5
- package/dist/index.js +0 -4492
- package/dist/types/index.js +0 -49
- package/dist/ui/index.css +0 -1876
- package/dist/ui/index.js +0 -22245
- package/dist/utils/index.js +0 -4296
- /package/{dist → src}/styles/ant-modal.css +0 -0
- /package/{dist → src}/styles/ant-spin.css +0 -0
- /package/{dist → src}/styles/ant-table.css +0 -0
- /package/{dist → src}/styles/index.css +0 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/** 文件列表排序字段。 */
|
|
2
|
+
export type FileSortBy = 'fileName' | 'fileType' | 'fileSize' | 'uploadTime';
|
|
3
|
+
|
|
4
|
+
/** 项目文件或文件夹节点。 */
|
|
5
|
+
export interface ProjectFile {
|
|
6
|
+
/** 文件唯一标识。 */
|
|
7
|
+
id: string;
|
|
8
|
+
/** 是否为受保护文件。 */
|
|
9
|
+
isSecure: boolean;
|
|
10
|
+
/** 所属项目 ID。 */
|
|
11
|
+
projectId: string;
|
|
12
|
+
/** 子文件或子文件夹列表。 */
|
|
13
|
+
children?: ProjectFile[];
|
|
14
|
+
/** 父级文件夹 ID,根节点为空。 */
|
|
15
|
+
parentId?: string | null;
|
|
16
|
+
/** 文件名称。 */
|
|
17
|
+
fileName: string;
|
|
18
|
+
/** 文件展示或业务路径。 */
|
|
19
|
+
filePath: string;
|
|
20
|
+
/** 文件类型或扩展名。 */
|
|
21
|
+
fileType: string;
|
|
22
|
+
/** 文件大小,单位通常为字节。 */
|
|
23
|
+
fileSize: number;
|
|
24
|
+
/** 文件CRC32校验值。 */
|
|
25
|
+
crc32: number;
|
|
26
|
+
/** 是否有本地缓存。 */
|
|
27
|
+
hasLocalCache?: boolean;
|
|
28
|
+
/** 文件资源实际存储路径。 */
|
|
29
|
+
fileResourcePath: string;
|
|
30
|
+
/** 文件或文件夹备注。 */
|
|
31
|
+
descs?: string;
|
|
32
|
+
/** 上传人名称。 */
|
|
33
|
+
uploaderName: string;
|
|
34
|
+
/** 上传时间。 */
|
|
35
|
+
uploadTime: Date;
|
|
36
|
+
/** 创建时间。 */
|
|
37
|
+
createTime: Date;
|
|
38
|
+
/** 更新时间。 */
|
|
39
|
+
updateTime: Date;
|
|
40
|
+
/** 创建人 ID。 */
|
|
41
|
+
createBy: string;
|
|
42
|
+
/** 更新人 ID。 */
|
|
43
|
+
updateBy: string;
|
|
44
|
+
/** 层级,根节点为 0。 */
|
|
45
|
+
level?: number;
|
|
46
|
+
/** 本地文件唯一 ID:仅本地文件(从未上传)或服务器文件未同步修改时存在 */
|
|
47
|
+
localId?: string;
|
|
48
|
+
/** 是否为仅本地存在(从未上传到服务器) */
|
|
49
|
+
isLocalOnly?: boolean;
|
|
50
|
+
/** 是否有未同步的本地修改 */
|
|
51
|
+
hasUnsyncedChanges?: boolean;
|
|
52
|
+
/** 是否为合同附件链接文件(虚拟文件,仅支持查看和下载) */
|
|
53
|
+
isContractLink?: boolean;
|
|
54
|
+
/** 是否为虚拟合同文件夹(绿色置顶,显示名"合同",服务器名 __contracts__) */
|
|
55
|
+
isVirtualContractFolder?: boolean;
|
|
56
|
+
/** 是否为合同子文件夹(以合同名称命名的虚拟文件夹,不可重命名/删除/移动) */
|
|
57
|
+
isContractSubfolder?: boolean;
|
|
58
|
+
/** 关联合同是否已签约(仅合同相关虚拟节点存在;false 表示未签约,显示时弱化) */
|
|
59
|
+
contractSigned?: boolean;
|
|
60
|
+
/** 合同分类标签(仅合同相关虚拟节点存在;"按类型"排序时用于分组) */
|
|
61
|
+
contractTag?: string;
|
|
62
|
+
/** 是否为合同分类标签虚拟文件夹("按类型"排序时生成,位于合同文件夹一级) */
|
|
63
|
+
isContractTagFolder?: boolean;
|
|
64
|
+
}
|
|
65
|
+
/** 项目成员角色(统一由 core 的 types/projectRole 提供,避免重复定义)。 */
|
|
66
|
+
export { ProjectRole } from '../../types/projectRole';
|
|
67
|
+
|
|
68
|
+
/** 文件接口通用响应形状。 */
|
|
69
|
+
export interface FileManagerApiResponse<T = undefined> {
|
|
70
|
+
code: number;
|
|
71
|
+
message?: string;
|
|
72
|
+
data?: T;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** 新建文件/文件夹提交的数据。 */
|
|
76
|
+
export interface FileManagerAddFileInput {
|
|
77
|
+
fileName: string;
|
|
78
|
+
filePath: string;
|
|
79
|
+
isSecure?: boolean;
|
|
80
|
+
descs?: string;
|
|
81
|
+
fileType?: string;
|
|
82
|
+
fileSize?: number;
|
|
83
|
+
crc32?: number;
|
|
84
|
+
fileResourcePath: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** 移动/重命名提交的数据。 */
|
|
88
|
+
export interface FileManagerMoveFileInput {
|
|
89
|
+
oldFileName: string;
|
|
90
|
+
oldFilePath: string;
|
|
91
|
+
newFileName: string;
|
|
92
|
+
newFilePath: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** 文件夹打包下载任务状态。 */
|
|
96
|
+
export type FolderDownloadStatus = 'pending' | 'success' | 'failed';
|
|
97
|
+
|
|
98
|
+
/** 文件夹打包下载任务状态详情。 */
|
|
99
|
+
export interface FolderDownloadJobStatus {
|
|
100
|
+
jobId: string;
|
|
101
|
+
status: FolderDownloadStatus;
|
|
102
|
+
/** 打包成功后的下载地址(相对文件根路径) */
|
|
103
|
+
url?: string;
|
|
104
|
+
/** 下载文件名 */
|
|
105
|
+
fileName?: string;
|
|
106
|
+
/** 失败原因或提示 */
|
|
107
|
+
message?: string;
|
|
108
|
+
/** 下载地址过期时间戳(毫秒) */
|
|
109
|
+
expireAt?: number;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** 全量更新文件内容提交的数据。 */
|
|
113
|
+
export interface FileManagerUpdateDataInput {
|
|
114
|
+
fileId: string;
|
|
115
|
+
fileSize?: number;
|
|
116
|
+
crc32?: number;
|
|
117
|
+
fileName: string;
|
|
118
|
+
fileResourcePath: string;
|
|
119
|
+
/** 是否记录历史版本,默认 true;笔记等高频保存场景可传 false */
|
|
120
|
+
recordVersion?: boolean;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** 差分更新文件内容提交的数据。 */
|
|
124
|
+
export interface FileManagerUpdateDeltaInput {
|
|
125
|
+
fileId: string;
|
|
126
|
+
deltaData: string;
|
|
127
|
+
deltaSize: number;
|
|
128
|
+
newFileSize: number;
|
|
129
|
+
crc32?: number;
|
|
130
|
+
/** 是否记录历史版本,默认 true;笔记等高频保存场景可传 false */
|
|
131
|
+
recordVersion?: boolean;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 文件管理器数据接口适配器。
|
|
136
|
+
* 默认实现为项目文件 API(见 projectFileManagerApi);
|
|
137
|
+
* CRM 客户附件等场景注入自定义实现以复用同一套文件管理 UI。
|
|
138
|
+
*/
|
|
139
|
+
export interface FileManagerApi {
|
|
140
|
+
/** 获取文件列表,scopeId 为项目 ID 或客户 ID 等业务作用域 */
|
|
141
|
+
listFiles: (scopeId: string) => Promise<FileManagerApiResponse<ProjectFile[]>>;
|
|
142
|
+
/** 获取文件详情 */
|
|
143
|
+
getDetail: (fileId: string) => Promise<FileManagerApiResponse<ProjectFile>>;
|
|
144
|
+
/** 新建文件/文件夹 */
|
|
145
|
+
addFile: (scopeId: string, data: FileManagerAddFileInput) => Promise<FileManagerApiResponse<{ fileId: string; fileName: string }>>;
|
|
146
|
+
/** 删除文件/文件夹 */
|
|
147
|
+
removeFile: (fileId: string) => Promise<FileManagerApiResponse<boolean>>;
|
|
148
|
+
/** 移动/重命名 */
|
|
149
|
+
moveFile: (scopeId: string, data: FileManagerMoveFileInput) => Promise<FileManagerApiResponse<string>>;
|
|
150
|
+
/** 更新备注 */
|
|
151
|
+
updateFileDescs: (data: { fileId: string; descs?: string }) => Promise<FileManagerApiResponse<boolean>>;
|
|
152
|
+
/** 全量更新文件内容 */
|
|
153
|
+
updateFile: (data: FileManagerUpdateDataInput) => Promise<FileManagerApiResponse<string>>;
|
|
154
|
+
/** 差分更新文件内容;不提供时前端自动回退为全量上传 */
|
|
155
|
+
updateFileDelta?: (data: FileManagerUpdateDeltaInput) => Promise<FileManagerApiResponse<string>>;
|
|
156
|
+
/** 复制副本/复制到其他项目;不提供时隐藏相关入口 */
|
|
157
|
+
copyFileToProject?: (scopeId: string, fileId: string) => Promise<FileManagerApiResponse<string>>;
|
|
158
|
+
/** 生成临时访问令牌;不提供时隐藏「临时访问链接」入口 */
|
|
159
|
+
generateTempAccessToken?: (fileId: string, expireSeconds: number) => Promise<FileManagerApiResponse<string>>;
|
|
160
|
+
/** 发起文件夹异步打包下载(需管理权限);不提供时隐藏「下载文件夹」入口 */
|
|
161
|
+
downloadFolder?: (
|
|
162
|
+
scopeId: string,
|
|
163
|
+
folderPath: string,
|
|
164
|
+
folderName: string,
|
|
165
|
+
) => Promise<FileManagerApiResponse<{ jobId: string }>>;
|
|
166
|
+
/** 查询文件夹打包下载任务状态;与 downloadFolder 同时提供时才启用下载文件夹 */
|
|
167
|
+
getFolderDownloadStatus?: (jobId: string) => Promise<FileManagerApiResponse<FolderDownloadJobStatus>>;
|
|
168
|
+
/** 判定当前用户是否具备管理能力(控制加密文件夹等入口),缺省视为 false */
|
|
169
|
+
resolveIsManager?: (scopeId: string) => Promise<boolean>;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** FileManager 功能开关:缺省全部开启(项目场景);CRM 等场景按需关闭。 */
|
|
173
|
+
export interface FileManagerFeatures {
|
|
174
|
+
/** 合同虚拟文件夹与合同附件联动,默认 true */
|
|
175
|
+
contracts?: boolean;
|
|
176
|
+
/** 移动/复制到其他项目(含复制副本),默认 true */
|
|
177
|
+
moveCopyToProject?: boolean;
|
|
178
|
+
/** 分享到微信,默认 true */
|
|
179
|
+
shareToWechat?: boolean;
|
|
180
|
+
/** 查看历史版本,默认 true */
|
|
181
|
+
versionHistory?: boolean;
|
|
182
|
+
/** 复制链接/在新窗口打开(指向 /filepreview 路由),默认 true */
|
|
183
|
+
externalLink?: boolean;
|
|
184
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 文件差分计算 Web Worker
|
|
3
|
+
*
|
|
4
|
+
* 功能:
|
|
5
|
+
* - 在 Worker 线程中执行 bsdiff 差分计算
|
|
6
|
+
* - 定期向主线程报告计算进度
|
|
7
|
+
* - 支持中止计算
|
|
8
|
+
*
|
|
9
|
+
* 使用方式:
|
|
10
|
+
* const worker = new Worker(new URL('./fileDeltaWorker.ts', import.meta.url));
|
|
11
|
+
* worker.postMessage({ type: 'computeDelta', oldBuffer, newBuffer });
|
|
12
|
+
* worker.onmessage = (e) => { ... };
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import pako from 'pako';
|
|
16
|
+
|
|
17
|
+
// ==================== WASM 模块加载 ====================
|
|
18
|
+
let wasmInstance: WebAssembly.Instance | null = null;
|
|
19
|
+
let wasmMemory: WebAssembly.Memory | null = null;
|
|
20
|
+
|
|
21
|
+
interface BsdiffExports {
|
|
22
|
+
memory: WebAssembly.Memory;
|
|
23
|
+
alloc: (len: number) => number;
|
|
24
|
+
dealloc: (ptr: number, len: number) => void;
|
|
25
|
+
create_patch: (basePtr: number, baseLen: number, nextPtr: number, nextLen: number) => number;
|
|
26
|
+
output_ptr: () => number;
|
|
27
|
+
output_len: () => number;
|
|
28
|
+
free_output: () => void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const loadWasm = async (): Promise<BsdiffExports> => {
|
|
32
|
+
if (wasmInstance) return wasmInstance.exports as unknown as BsdiffExports;
|
|
33
|
+
|
|
34
|
+
// 从 public/wasm 目录加载 WASM 文件
|
|
35
|
+
const response = await fetch('/wasm/hdiff.wasm');
|
|
36
|
+
const wasmBuffer = await response.arrayBuffer();
|
|
37
|
+
const wasmModule = new WebAssembly.Module(wasmBuffer);
|
|
38
|
+
const instance = await WebAssembly.instantiate(wasmModule);
|
|
39
|
+
|
|
40
|
+
wasmInstance = instance;
|
|
41
|
+
wasmMemory = instance.exports.memory as unknown as WebAssembly.Memory;
|
|
42
|
+
|
|
43
|
+
return instance.exports as unknown as BsdiffExports;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// ==================== 差分计算 ====================
|
|
47
|
+
/**
|
|
48
|
+
* 在 Worker 中创建补丁
|
|
49
|
+
*/
|
|
50
|
+
const createPatch = async (base: Uint8Array, next: Uint8Array): Promise<Uint8Array> => {
|
|
51
|
+
const wasm = await loadWasm();
|
|
52
|
+
|
|
53
|
+
const basePtr = wasm.alloc(base.byteLength);
|
|
54
|
+
const nextPtr = wasm.alloc(next.byteLength);
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
new Uint8Array(wasm.memory.buffer, basePtr, base.byteLength).set(base);
|
|
58
|
+
new Uint8Array(wasm.memory.buffer, nextPtr, next.byteLength).set(next);
|
|
59
|
+
|
|
60
|
+
const status = wasm.create_patch(basePtr, base.byteLength, nextPtr, next.byteLength);
|
|
61
|
+
|
|
62
|
+
if (status !== 0) {
|
|
63
|
+
throw new Error(`BSDiff failed with status: ${status}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const outPtr = wasm.output_ptr();
|
|
67
|
+
const outLen = wasm.output_len();
|
|
68
|
+
|
|
69
|
+
if (outLen === 0) {
|
|
70
|
+
wasm.free_output();
|
|
71
|
+
return new Uint8Array();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const output = new Uint8Array(wasm.memory.buffer, outPtr, outLen);
|
|
75
|
+
const copied = new Uint8Array(output);
|
|
76
|
+
wasm.free_output();
|
|
77
|
+
return copied;
|
|
78
|
+
} finally {
|
|
79
|
+
if (base.byteLength > 0) wasm.dealloc(basePtr, base.byteLength);
|
|
80
|
+
if (next.byteLength > 0) wasm.dealloc(nextPtr, next.byteLength);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* 带进度的差分计算
|
|
86
|
+
* @param oldArray 旧文件数据
|
|
87
|
+
* @param newArray 新文件数据
|
|
88
|
+
* @param onProgress 进度回调
|
|
89
|
+
*/
|
|
90
|
+
const computeDeltaWithProgress = async (
|
|
91
|
+
oldArray: Uint8Array,
|
|
92
|
+
newArray: Uint8Array,
|
|
93
|
+
onProgress: (percent: number) => void
|
|
94
|
+
): Promise<Uint8Array> => {
|
|
95
|
+
onProgress(0.1);
|
|
96
|
+
|
|
97
|
+
// 加载 WASM(如果尚未加载)
|
|
98
|
+
await loadWasm();
|
|
99
|
+
|
|
100
|
+
onProgress(0.2);
|
|
101
|
+
|
|
102
|
+
// 执行差分计算
|
|
103
|
+
const patch = await createPatch(oldArray, newArray);
|
|
104
|
+
|
|
105
|
+
onProgress(0.6);
|
|
106
|
+
|
|
107
|
+
// 压缩
|
|
108
|
+
const compressed = pako.deflate(patch);
|
|
109
|
+
|
|
110
|
+
onProgress(0.9);
|
|
111
|
+
|
|
112
|
+
return new Uint8Array(compressed);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// ==================== Worker 消息处理 ====================
|
|
116
|
+
let currentTask: { oldArray: Uint8Array; newArray: Uint8Array } | null = null;
|
|
117
|
+
|
|
118
|
+
self.onmessage = async (e: MessageEvent) => {
|
|
119
|
+
const { type, id, data } = e.data;
|
|
120
|
+
|
|
121
|
+
switch (type) {
|
|
122
|
+
case 'computeDelta':
|
|
123
|
+
try {
|
|
124
|
+
const { oldBuffer, newBuffer, taskId } = data;
|
|
125
|
+
|
|
126
|
+
const oldArray = new Uint8Array(oldBuffer);
|
|
127
|
+
const newArray = new Uint8Array(newBuffer);
|
|
128
|
+
|
|
129
|
+
currentTask = { oldArray, newArray };
|
|
130
|
+
|
|
131
|
+
// 发送开始消息
|
|
132
|
+
self.postMessage({
|
|
133
|
+
type: 'progress',
|
|
134
|
+
id: taskId,
|
|
135
|
+
data: { stage: 'loading', percent: 0, message: '正在加载差分计算模块...' }
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
const compressedPatch = await computeDeltaWithProgress(
|
|
139
|
+
oldArray,
|
|
140
|
+
newArray,
|
|
141
|
+
(percent) => {
|
|
142
|
+
self.postMessage({
|
|
143
|
+
type: 'progress',
|
|
144
|
+
id: taskId,
|
|
145
|
+
data: {
|
|
146
|
+
stage: 'computing',
|
|
147
|
+
percent,
|
|
148
|
+
message: percent < 0.2 ? '加载中...' :
|
|
149
|
+
percent < 0.6 ? '计算文件差异...' :
|
|
150
|
+
percent < 0.9 ? '压缩差异数据...' : '即将完成...'
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
currentTask = null;
|
|
157
|
+
|
|
158
|
+
// 发送完成消息
|
|
159
|
+
self.postMessage({
|
|
160
|
+
type: 'success',
|
|
161
|
+
id: taskId,
|
|
162
|
+
data: {
|
|
163
|
+
compressedPatch: compressedPatch.buffer,
|
|
164
|
+
patchSize: compressedPatch.length
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
} catch (error) {
|
|
169
|
+
currentTask = null;
|
|
170
|
+
self.postMessage({
|
|
171
|
+
type: 'error',
|
|
172
|
+
id: data.taskId,
|
|
173
|
+
error: error instanceof Error ? error.message : '未知错误'
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
177
|
+
|
|
178
|
+
case 'abort':
|
|
179
|
+
// 终止当前任务(如果需要)
|
|
180
|
+
currentTask = null;
|
|
181
|
+
self.postMessage({
|
|
182
|
+
type: 'aborted',
|
|
183
|
+
id: data.taskId
|
|
184
|
+
});
|
|
185
|
+
break;
|
|
186
|
+
|
|
187
|
+
default:
|
|
188
|
+
console.warn('Unknown message type:', type);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// 通知主线程 Worker 已就绪
|
|
193
|
+
self.postMessage({ type: 'ready' });
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { ProjectFile, FileSortBy } from '../types';
|
|
2
|
+
|
|
3
|
+
const assignLevel = (items: ProjectFile[], level: number = 0): void => {
|
|
4
|
+
items.forEach((item) => {
|
|
5
|
+
(item as any).level = level;
|
|
6
|
+
if (item.children && item.children.length > 0) {
|
|
7
|
+
assignLevel(item.children, level + 1);
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const buildFileTree = (items: ProjectFile[]): ProjectFile[] => {
|
|
13
|
+
const map = new Map<string, ProjectFile>();
|
|
14
|
+
const roots: ProjectFile[] = [];
|
|
15
|
+
|
|
16
|
+
items.forEach((item) => {
|
|
17
|
+
const newItem = { ...item, children: [] };
|
|
18
|
+
map.set(item.id, newItem);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const pathMap = new Map<string, string>();
|
|
22
|
+
items.forEach((item) => {
|
|
23
|
+
if (item.fileType === 'folder') {
|
|
24
|
+
pathMap.set(item.filePath + item.fileName + '/', item.id);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
items.forEach((item) => {
|
|
29
|
+
const newItem = map.get(item.id)!;
|
|
30
|
+
const parentPath = item.filePath;
|
|
31
|
+
const parentId = pathMap.get(parentPath) || null;
|
|
32
|
+
|
|
33
|
+
if (parentId) {
|
|
34
|
+
newItem.parentId = parentId;
|
|
35
|
+
const parent = map.get(parentId);
|
|
36
|
+
if (parent && parent.children) {
|
|
37
|
+
parent.children.push(newItem);
|
|
38
|
+
} else {
|
|
39
|
+
roots.push(newItem);
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
roots.push(newItem);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
assignLevel(roots);
|
|
47
|
+
return roots;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const getDescendantIds = (item: ProjectFile, files: ProjectFile[]): string[] => {
|
|
51
|
+
const ids: string[] = [];
|
|
52
|
+
const stack: ProjectFile[] = [item];
|
|
53
|
+
|
|
54
|
+
while (stack.length) {
|
|
55
|
+
const node = stack.pop()!;
|
|
56
|
+
const children = files.filter((child) => child.parentId === node.id);
|
|
57
|
+
for (const c of children) {
|
|
58
|
+
ids.push(c.id);
|
|
59
|
+
stack.push(c);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return ids;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const getDescendantIdsOptimized = (item: ProjectFile, files: ProjectFile[]): string[] => {
|
|
67
|
+
const ids: string[] = [];
|
|
68
|
+
const parentIdMap = new Map<string, ProjectFile[]>();
|
|
69
|
+
|
|
70
|
+
files.forEach((file) => {
|
|
71
|
+
if (file.parentId) {
|
|
72
|
+
const children = parentIdMap.get(file.parentId) || [];
|
|
73
|
+
children.push(file);
|
|
74
|
+
parentIdMap.set(file.parentId, children);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const stack: ProjectFile[] = [item];
|
|
79
|
+
while (stack.length) {
|
|
80
|
+
const node = stack.pop()!;
|
|
81
|
+
const children = parentIdMap.get(node.id) || [];
|
|
82
|
+
for (const c of children) {
|
|
83
|
+
ids.push(c.id);
|
|
84
|
+
stack.push(c);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return ids;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export const getFileDescendants = (folder: ProjectFile, files: ProjectFile[]): ProjectFile[] => {
|
|
92
|
+
let items: ProjectFile[] = [];
|
|
93
|
+
if (folder && folder.fileType === 'folder') {
|
|
94
|
+
const folderPath = folder.filePath + folder.fileName + '/';
|
|
95
|
+
items = files.filter((item) =>
|
|
96
|
+
item.id === folder.id ||
|
|
97
|
+
(item.filePath && item.filePath.startsWith(folderPath))
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return items;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const sortFiles = (files: ProjectFile[]): ProjectFile[] => {
|
|
104
|
+
return [...files].sort((a: ProjectFile, b: ProjectFile) => {
|
|
105
|
+
// 虚拟合同文件夹始终置顶
|
|
106
|
+
if (a.isVirtualContractFolder && !b.isVirtualContractFolder) return -1;
|
|
107
|
+
if (!a.isVirtualContractFolder && b.isVirtualContractFolder) return 1;
|
|
108
|
+
|
|
109
|
+
if (a.fileType === 'folder' && b.fileType !== 'folder') {
|
|
110
|
+
return -1;
|
|
111
|
+
}
|
|
112
|
+
if (a.fileType !== 'folder' && b.fileType === 'folder') {
|
|
113
|
+
return 1;
|
|
114
|
+
}
|
|
115
|
+
if (a.isSecure && !b.isSecure) {
|
|
116
|
+
return -1;
|
|
117
|
+
}
|
|
118
|
+
if (!a.isSecure && b.isSecure) {
|
|
119
|
+
return 1;
|
|
120
|
+
}
|
|
121
|
+
return a.fileName.localeCompare(b.fileName);
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// 递归排序函数(支持按文件名、类型、大小、上传时间排序)
|
|
126
|
+
export const sortTree = (
|
|
127
|
+
items: ProjectFile[],
|
|
128
|
+
by: FileSortBy,
|
|
129
|
+
order: 'asc' | 'desc'
|
|
130
|
+
): ProjectFile[] => {
|
|
131
|
+
const sorted = [...items].sort((a, b) => {
|
|
132
|
+
// 虚拟合同文件夹始终置顶
|
|
133
|
+
if (a.isVirtualContractFolder && !b.isVirtualContractFolder) return -1;
|
|
134
|
+
if (!a.isVirtualContractFolder && b.isVirtualContractFolder) return 1;
|
|
135
|
+
|
|
136
|
+
// 文件夹始终排在文件前面
|
|
137
|
+
if (a.fileType === 'folder' && b.fileType !== 'folder') return -1;
|
|
138
|
+
if (a.fileType !== 'folder' && b.fileType === 'folder') return 1;
|
|
139
|
+
|
|
140
|
+
// 安全文件排前面
|
|
141
|
+
if (a.isSecure && !b.isSecure) return -1;
|
|
142
|
+
if (!a.isSecure && b.isSecure) return 1;
|
|
143
|
+
|
|
144
|
+
let comparison = 0;
|
|
145
|
+
if (by === 'fileName') {
|
|
146
|
+
comparison = a.fileName.localeCompare(b.fileName, 'zh-CN');
|
|
147
|
+
} else if (by === 'uploadTime') {
|
|
148
|
+
const timeA = a.uploadTime instanceof Date ? a.uploadTime.getTime() : new Date(a.uploadTime).getTime();
|
|
149
|
+
const timeB = b.uploadTime instanceof Date ? b.uploadTime.getTime() : new Date(b.uploadTime).getTime();
|
|
150
|
+
comparison = timeA - timeB;
|
|
151
|
+
} else if (by === 'fileSize') {
|
|
152
|
+
comparison = (a.fileSize || 0) - (b.fileSize || 0);
|
|
153
|
+
// 大小相同时再按文件名排序
|
|
154
|
+
if (comparison === 0) {
|
|
155
|
+
comparison = a.fileName.localeCompare(b.fileName, 'zh-CN');
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
// 按文件类型排序(通过文件名后缀判断)
|
|
159
|
+
const extA = a.fileType === 'folder' ? 'folder' : (a.fileName.split('.').pop() || '').toLowerCase();
|
|
160
|
+
const extB = b.fileType === 'folder' ? 'folder' : (b.fileName.split('.').pop() || '').toLowerCase();
|
|
161
|
+
comparison = extA.localeCompare(extB, 'zh-CN');
|
|
162
|
+
// 类型相同时再按文件名排序
|
|
163
|
+
if (comparison === 0) {
|
|
164
|
+
comparison = a.fileName.localeCompare(b.fileName, 'zh-CN');
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return order === 'asc' ? comparison : -comparison;
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// 递归排序子节点
|
|
172
|
+
return sorted.map(item => ({
|
|
173
|
+
...item,
|
|
174
|
+
children: item.children && item.children.length > 0
|
|
175
|
+
? sortTree(item.children, by, order)
|
|
176
|
+
: item.children
|
|
177
|
+
}));
|
|
178
|
+
};
|