@chenghongyu/xpt-file-viewer 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. package/.vscode/extensions.json +3 -0
  2. package/README.md +5 -0
  3. package/auto-imports.d.ts +12 -0
  4. package/components.d.ts +45 -0
  5. package/dist.zip +0 -0
  6. package/index.html +13 -0
  7. package/package.json +100 -0
  8. package/presets/eslint/.eslintrc-auto-import.json +462 -0
  9. package/presets/plugins/html.ts +14 -0
  10. package/presets/shared/env.ts +46 -0
  11. package/presets/shared/resolvers.ts +29 -0
  12. package/presets/tov.ts +132 -0
  13. package/presets/types/auto-imports.d.ts +806 -0
  14. package/presets/types/components.d.ts +164 -0
  15. package/presets/types/env.d.ts +17 -0
  16. package/public/favicon.svg +1 -0
  17. package/public/icons.svg +24 -0
  18. package/public/testfile/README.md +5 -0
  19. package/public/testfile/useFileContextMenu.js +74 -0
  20. package/public/testfile//345/217/221/347/245/250.pdf +0 -0
  21. package/public/testfile//346/216/245/346/224/266/345/207/275.docx +0 -0
  22. package/public/testfile//350/247/204/346/240/274/345/236/213/345/217/2671.txt +263 -0
  23. package/public/testfile//350/247/206/351/242/2211.mp4 +0 -0
  24. package/public/testfile//351/237/263/351/242/2211.mp3 +0 -0
  25. package/src/App.vue +8 -0
  26. package/src/api/admin/admin-2fa.js +18 -0
  27. package/src/api/admin/admin-download-log.js +37 -0
  28. package/src/api/admin/admin-login-log.js +9 -0
  29. package/src/api/admin/admin-permission.js +9 -0
  30. package/src/api/admin/admin-setting.js +121 -0
  31. package/src/api/admin/admin-share.js +20 -0
  32. package/src/api/admin/admin-short-link.js +49 -0
  33. package/src/api/admin/admin-sso.js +38 -0
  34. package/src/api/admin/admin-storage.js +189 -0
  35. package/src/api/admin/admin-user.js +61 -0
  36. package/src/api/home/common.js +9 -0
  37. package/src/api/home/file-operator.js +89 -0
  38. package/src/api/home/home.js +87 -0
  39. package/src/api/home/install.js +18 -0
  40. package/src/api/home/login.js +9 -0
  41. package/src/api/home/only-office.js +10 -0
  42. package/src/api/home/share.js +115 -0
  43. package/src/api/home/user.js +74 -0
  44. package/src/api/tools/tools-115.js +17 -0
  45. package/src/api/tools/tools-gd.js +13 -0
  46. package/src/api/tools/tools-s3.js +25 -0
  47. package/src/api/tools/tools-sharepoint.js +19 -0
  48. package/src/assets/hero.png +0 -0
  49. package/src/assets/icons/401.svg +1 -0
  50. package/src/assets/icons/403.svg +45 -0
  51. package/src/assets/icons/404.svg +1 -0
  52. package/src/assets/icons/500.svg +1 -0
  53. package/src/assets/icons/admin-login.svg +1 -0
  54. package/src/assets/icons/document.svg +1 -0
  55. package/src/assets/icons/empty.svg +145 -0
  56. package/src/assets/icons/file-type-apk.svg +1 -0
  57. package/src/assets/icons/file-type-archive.svg +1 -0
  58. package/src/assets/icons/file-type-audio.svg +1 -0
  59. package/src/assets/icons/file-type-back.svg +1 -0
  60. package/src/assets/icons/file-type-css.svg +1 -0
  61. package/src/assets/icons/file-type-deb.svg +1 -0
  62. package/src/assets/icons/file-type-dll.svg +1 -0
  63. package/src/assets/icons/file-type-doc.svg +1 -0
  64. package/src/assets/icons/file-type-document.svg +1 -0
  65. package/src/assets/icons/file-type-docx.svg +1 -0
  66. package/src/assets/icons/file-type-exe.svg +1 -0
  67. package/src/assets/icons/file-type-expression.svg +1 -0
  68. package/src/assets/icons/file-type-file.svg +1 -0
  69. package/src/assets/icons/file-type-folder.svg +1 -0
  70. package/src/assets/icons/file-type-html.svg +1 -0
  71. package/src/assets/icons/file-type-image.svg +1 -0
  72. package/src/assets/icons/file-type-java.svg +1 -0
  73. package/src/assets/icons/file-type-js.svg +1 -0
  74. package/src/assets/icons/file-type-less.svg +1 -0
  75. package/src/assets/icons/file-type-md.svg +1 -0
  76. package/src/assets/icons/file-type-office.svg +1 -0
  77. package/src/assets/icons/file-type-pdf.svg +1 -0
  78. package/src/assets/icons/file-type-php.svg +1 -0
  79. package/src/assets/icons/file-type-ppt.svg +1 -0
  80. package/src/assets/icons/file-type-pptx.svg +1 -0
  81. package/src/assets/icons/file-type-py.svg +1 -0
  82. package/src/assets/icons/file-type-rb.svg +1 -0
  83. package/src/assets/icons/file-type-root.svg +1 -0
  84. package/src/assets/icons/file-type-rpm.svg +1 -0
  85. package/src/assets/icons/file-type-rust.svg +1 -0
  86. package/src/assets/icons/file-type-script.svg +1 -0
  87. package/src/assets/icons/file-type-text.svg +1 -0
  88. package/src/assets/icons/file-type-three3d.svg +5 -0
  89. package/src/assets/icons/file-type-vbs.svg +1 -0
  90. package/src/assets/icons/file-type-video.svg +1 -0
  91. package/src/assets/icons/file-type-xls.svg +1 -0
  92. package/src/assets/icons/file-type-xlsx.svg +1 -0
  93. package/src/assets/icons/file-type-xml.svg +1 -0
  94. package/src/assets/icons/file-type-yaml.svg +1 -0
  95. package/src/assets/icons/file-upload.svg +1 -0
  96. package/src/assets/icons/github.svg +1 -0
  97. package/src/assets/icons/install-step.svg +40 -0
  98. package/src/assets/icons/reset-password.svg +1 -0
  99. package/src/assets/icons/storage-aliyun.svg +1 -0
  100. package/src/assets/icons/storage-baidu.svg +1 -0
  101. package/src/assets/icons/storage-doge-cloud.svg +207 -0
  102. package/src/assets/icons/storage-ftp.svg +13 -0
  103. package/src/assets/icons/storage-google-drive.svg +8 -0
  104. package/src/assets/icons/storage-huawei.svg +1 -0
  105. package/src/assets/icons/storage-local.svg +11 -0
  106. package/src/assets/icons/storage-minio.svg +1 -0
  107. package/src/assets/icons/storage-onedrive-china.svg +18 -0
  108. package/src/assets/icons/storage-onedrive.svg +4 -0
  109. package/src/assets/icons/storage-open115.svg +23 -0
  110. package/src/assets/icons/storage-qiniu.svg +1 -0
  111. package/src/assets/icons/storage-s3.svg +5 -0
  112. package/src/assets/icons/storage-sftp.svg +13 -0
  113. package/src/assets/icons/storage-sharepoint-china.svg +23 -0
  114. package/src/assets/icons/storage-sharepoint.svg +1 -0
  115. package/src/assets/icons/storage-tencent.svg +9 -0
  116. package/src/assets/icons/storage-ufile.svg +14 -0
  117. package/src/assets/icons/storage-upyun.svg +1 -0
  118. package/src/assets/icons/storage-webdav.svg +1 -0
  119. package/src/assets/icons/upload.svg +50 -0
  120. package/src/assets/icons/zfile-basic.svg +17 -0
  121. package/src/assets/icons/zfile-horizontal.svg +16 -0
  122. package/src/assets/icons/zfile.svg +1 -0
  123. package/src/assets/vite.svg +1 -0
  124. package/src/assets/vue.svg +1 -0
  125. package/src/components/HelloWorld.vue +319 -0
  126. package/src/components/common/QrCodePreview.vue +118 -0
  127. package/src/components/common/dialog/ZDialog.vue +171 -0
  128. package/src/components/common/dialog/types.ts +19 -0
  129. package/src/components/common/dialog/useDialog.ts +18 -0
  130. package/src/components/common/dialog/useDialogWithForm.ts +21 -0
  131. package/src/components/copy.vue +133 -0
  132. package/src/components/file/preview/AudioPlayer.vue +333 -0
  133. package/src/components/file/preview/CopyCode.vue +47 -0
  134. package/src/components/file/preview/FileGallery.vue +199 -0
  135. package/src/components/file/preview/ImageViewer.vue +432 -0
  136. package/src/components/file/preview/KkFileViewer.vue +86 -0
  137. package/src/components/file/preview/KkFileViewerDialog.vue +42 -0
  138. package/src/components/file/preview/MarkdownViewer.vue +102 -0
  139. package/src/components/file/preview/MarkdownViewerAsyncLoading.vue +17 -0
  140. package/src/components/file/preview/MarkdownViewerDialogAsyncLoading.vue +12 -0
  141. package/src/components/file/preview/OfficeViewer.vue +76 -0
  142. package/src/components/file/preview/OfficeViewerDialog.vue +55 -0
  143. package/src/components/file/preview/PdfViewer.vue +157 -0
  144. package/src/components/file/preview/PdfViewerDialog.vue +41 -0
  145. package/src/components/file/preview/TextViewer.vue +232 -0
  146. package/src/components/file/preview/TextViewerAsyncLoading.vue +22 -0
  147. package/src/components/file/preview/TextViewerDialog.vue +53 -0
  148. package/src/components/file/preview/Three3dPreview.vue +114 -0
  149. package/src/components/file/preview/Three3dPreviewDialog.vue +50 -0
  150. package/src/components/file/preview/VideoPlayer.vue +341 -0
  151. package/src/components/file/preview/VideoPlayerAsyncLoading.vue +45 -0
  152. package/src/components/file/preview/VideoPlayerDialog.vue +51 -0
  153. package/src/components/file/selectFolder/SelectFolder.vue +208 -0
  154. package/src/components/file/selectFolder/index.ts +50 -0
  155. package/src/components/file/selectFolder/types.ts +5 -0
  156. package/src/components/fileReview/AudioPlayer-copy.vue +333 -0
  157. package/src/components/fileReview/PdfViewer-copy.vue +157 -0
  158. package/src/components/fileReview/TextViewer-copy.vue +44 -0
  159. package/src/components/fileReview/VideoPlayer-copy.vue +341 -0
  160. package/src/components/messageBox/confirm/confirm.vue +137 -0
  161. package/src/components/messageBox/confirm/index.ts +27 -0
  162. package/src/components/messageBox/confirm/types.ts +15 -0
  163. package/src/components/messageBox/messageBox.ts +9 -0
  164. package/src/components/messageBox/prompt/index.ts +27 -0
  165. package/src/components/messageBox/prompt/prompt.vue +178 -0
  166. package/src/components/messageBox/prompt/types.ts +24 -0
  167. package/src/components/vue-codemirror/editor.vue +212 -0
  168. package/src/components/vue-codemirror/encodings.ts +27 -0
  169. package/src/components/vue-codemirror/index.vue +380 -0
  170. package/src/components/vue-codemirror/lang-code/cpp/index.ts +3 -0
  171. package/src/components/vue-codemirror/lang-code/css/index.ts +2 -0
  172. package/src/components/vue-codemirror/lang-code/dockerfile/index.ts +5 -0
  173. package/src/components/vue-codemirror/lang-code/erlang/index.ts +6 -0
  174. package/src/components/vue-codemirror/lang-code/go/index.ts +5 -0
  175. package/src/components/vue-codemirror/lang-code/html/index.ts +3 -0
  176. package/src/components/vue-codemirror/lang-code/java/index.ts +3 -0
  177. package/src/components/vue-codemirror/lang-code/javascript/index.ts +3 -0
  178. package/src/components/vue-codemirror/lang-code/json/index.ts +3 -0
  179. package/src/components/vue-codemirror/lang-code/jsx/index.ts +3 -0
  180. package/src/components/vue-codemirror/lang-code/lua/index.ts +6 -0
  181. package/src/components/vue-codemirror/lang-code/markdown/index.ts +2 -0
  182. package/src/components/vue-codemirror/lang-code/mysql/index.ts +3 -0
  183. package/src/components/vue-codemirror/lang-code/nginx/index.ts +6 -0
  184. package/src/components/vue-codemirror/lang-code/perl/index.ts +5 -0
  185. package/src/components/vue-codemirror/lang-code/pgsql/index.ts +2 -0
  186. package/src/components/vue-codemirror/lang-code/php/index.ts +3 -0
  187. package/src/components/vue-codemirror/lang-code/powershell/index.ts +3 -0
  188. package/src/components/vue-codemirror/lang-code/python/index.ts +2 -0
  189. package/src/components/vue-codemirror/lang-code/r/index.ts +5 -0
  190. package/src/components/vue-codemirror/lang-code/ruby/index.ts +5 -0
  191. package/src/components/vue-codemirror/lang-code/rust/index.ts +2 -0
  192. package/src/components/vue-codemirror/lang-code/shell/index.ts +5 -0
  193. package/src/components/vue-codemirror/lang-code/sql/index.ts +3 -0
  194. package/src/components/vue-codemirror/lang-code/stylus/index.ts +3 -0
  195. package/src/components/vue-codemirror/lang-code/swift/index.ts +4 -0
  196. package/src/components/vue-codemirror/lang-code/toml/index.ts +3 -0
  197. package/src/components/vue-codemirror/lang-code/tsx/index.ts +2 -0
  198. package/src/components/vue-codemirror/lang-code/typescript/index.ts +2 -0
  199. package/src/components/vue-codemirror/lang-code/vb/index.ts +3 -0
  200. package/src/components/vue-codemirror/lang-code/vbscript/index.ts +3 -0
  201. package/src/components/vue-codemirror/lang-code/xml/index.ts +2 -0
  202. package/src/components/vue-codemirror/lang-code/yaml/index.ts +3 -0
  203. package/src/components/vue-codemirror/languages.ts +8 -0
  204. package/src/components/vue-codemirror/themes.ts +5 -0
  205. package/src/components/vue-codemirror/toolbar.vue +183 -0
  206. package/src/components/vue-codemirror/types.ts +12 -0
  207. package/src/components.d.ts +49 -0
  208. package/src/composables/admin/layout/admin-layout.js +53 -0
  209. package/src/composables/admin/link/useLinkSetting.js +16 -0
  210. package/src/composables/admin/sso/baseSsoConfig.js +54 -0
  211. package/src/composables/admin/sso/useSsoConfig.js +176 -0
  212. package/src/composables/admin/storage/storage-copy.js +89 -0
  213. package/src/composables/admin/storage/storage-filter.js +64 -0
  214. package/src/composables/admin/storage/storage-list.js +202 -0
  215. package/src/composables/admin/storage/storage-password.js +101 -0
  216. package/src/composables/admin/storage/storage-readme.js +102 -0
  217. package/src/composables/admin/storage/utils/open115-util.js +61 -0
  218. package/src/composables/admin/useAdminSetting.js +60 -0
  219. package/src/composables/admin/useClientInfo.js +20 -0
  220. package/src/composables/admin/user/user-copy.js +79 -0
  221. package/src/composables/file/useBatchOperatorResult.js +19 -0
  222. package/src/composables/file/useFileContextMenu.js +74 -0
  223. package/src/composables/file/useFileData.js +243 -0
  224. package/src/composables/file/useFileLink.js +175 -0
  225. package/src/composables/file/useFileLoading.js +41 -0
  226. package/src/composables/file/useFileLongPressEvent.js +71 -0
  227. package/src/composables/file/useFileOperator.js +347 -0
  228. package/src/composables/file/useFilePreview.js +99 -0
  229. package/src/composables/file/useFilePwd.js +138 -0
  230. package/src/composables/file/useFileSelect.js +105 -0
  231. package/src/composables/file/useFileShare.js +39 -0
  232. package/src/composables/file/useFileUpload.js +1045 -0
  233. package/src/composables/file/useKkFileViewDialog.js +24 -0
  234. package/src/composables/file/useOfficeViewerDialog.js +20 -0
  235. package/src/composables/file/usePdfViewerDialog.js +22 -0
  236. package/src/composables/file/useShareActions.js +94 -0
  237. package/src/composables/file/useShareTableOperator.js +84 -0
  238. package/src/composables/file/useTableOperator.js +211 -0
  239. package/src/composables/file/useTextViewerDialog.js +22 -0
  240. package/src/composables/file/useThree3dPreviewDialog.js +23 -0
  241. package/src/composables/file/useVideoPlayerDialog.js +19 -0
  242. package/src/composables/header/useHeaderBreadcrumb.js +111 -0
  243. package/src/composables/header/useHeaderStorageList.js +150 -0
  244. package/src/composables/header/useSetting.js +58 -0
  245. package/src/composables/share/useShareData.js +178 -0
  246. package/src/composables/useDarks.ts +4 -0
  247. package/src/composables/useRouterData.js +41 -0
  248. package/src/constant/index.js +193 -0
  249. package/src/http/index.js +153 -0
  250. package/src/http/request.js +31 -0
  251. package/src/main.ts +23 -0
  252. package/src/stores/file-data.ts +108 -0
  253. package/src/stores/global-config.ts +115 -0
  254. package/src/stores/storage-config.ts +123 -0
  255. package/src/style.css +296 -0
  256. package/src/styles/admin.scss +91 -0
  257. package/src/styles/code-editor-variables.scss +52 -0
  258. package/src/styles/element-plus.scss +22 -0
  259. package/src/styles/error-page.css +26 -0
  260. package/src/styles/main.css +142 -0
  261. package/src/styles/tailwind/index.scss +33 -0
  262. package/src/utils/index.ts +7 -0
  263. package/src/utils/models/base.ts +34 -0
  264. package/src/utils/models/file.ts +95 -0
  265. package/src/utils/models/path.ts +117 -0
  266. package/src/utils/models/qrcode.ts +21 -0
  267. package/src/utils/models/time.ts +132 -0
  268. package/src/utils/models/util.ts +42 -0
  269. package/src/utils/models/window.ts +14 -0
  270. package/stats.html +4950 -0
  271. package/tsconfig.app.json +16 -0
  272. package/tsconfig.json +7 -0
  273. package/tsconfig.node.json +26 -0
  274. package/vite.config.ts +57 -0
@@ -0,0 +1,347 @@
1
+ import {
2
+ batchDeleteReq,
3
+ newFolderReq,
4
+ renameFileReq, renameFolderReq,
5
+ moveFolderReq, moveFileReq,
6
+ copyFileReq, copyFolderReq
7
+ } from "~/api/home/file-operator";
8
+
9
+ import useStorageConfigStore from "~/stores/storage-config";
10
+ let storageConfigStore = useStorageConfigStore();
11
+
12
+ import useFileData from "~/composables/file/useFileData";
13
+ import useRouterData from "~/composables/useRouterData";
14
+ let { storageKey, currentPath } = useRouterData();
15
+
16
+ import useFileSelect from "~/composables/file/useFileSelect";
17
+ let { selectRows, selectRow, selectFolders, selectFiles } = useFileSelect();
18
+
19
+ import useFilePwd from "~/composables/file/useFilePwd";
20
+ let { getPathPwd } = useFilePwd();
21
+
22
+ import useBatchOperatorResult from "~/composables/file/useBatchOperatorResult";
23
+ let { open:openBatchOperatorResultDialog } = useBatchOperatorResult();
24
+
25
+ import { ElLoading } from "element-plus";
26
+
27
+ import selectFolder from "~/components/file/selectFolder";
28
+
29
+
30
+ export default function useFileOperator() {
31
+
32
+ const { loadFile } = useFileData();
33
+
34
+ /**
35
+ * 批量下载已选择的所有文件
36
+ * @param {Object} row 已选择的文件
37
+ */
38
+ const batchDownloadFile = (row) => {
39
+ if (storageConfigStore.folderConfig.permission.download === false) {
40
+ return;
41
+ }
42
+ if (!selectRows.value && selectRows.value.length === 0) {
43
+ ElMessage.warning("请至少选择一个文件");
44
+ return;
45
+ }
46
+
47
+ let confirmMsg;
48
+
49
+ if (row?.name) {
50
+ confirmMsg = `是否确认下载文件 <span class="text-blue-500">${row.name}</span> ?`;
51
+ } else if (selectRows.value.length === 1) {
52
+ confirmMsg = `是否确认下载文件 <span class="text-blue-500">${selectRows.value[0].name}</span> ?`;
53
+ row = selectRows.value[0];
54
+ }
55
+
56
+
57
+ function performDownload() {
58
+ // 单个文件下载, 直接下载
59
+ if (row?.name) {
60
+ console.log("进行指定文件下载, 文件:", row);
61
+ downloadFileUseWindowOpenMode(row.url);
62
+ }
63
+ }
64
+ if (storageConfigStore.globalConfig.enableNormalDownloadConfirm) {
65
+ ElMessageBox.confirm(confirmMsg, '提示', {
66
+ dangerouslyUseHTMLString: true,
67
+ confirmButtonText: '确定',
68
+ cancelButtonText: '取消',
69
+ type: 'info',
70
+ callback: (val) => {
71
+ let action = '';
72
+ if (val instanceof Object) {
73
+ action = val.action;
74
+ } else if (typeof val === 'string') {
75
+ action = val;
76
+ }
77
+
78
+ if (action === 'confirm') {
79
+ performDownload();
80
+ }
81
+ }
82
+ })
83
+ } else {
84
+ performDownload();
85
+ }
86
+ }
87
+
88
+ /**
89
+ * 使用 windows.open 模式下载文件
90
+ *
91
+ * @param url 下载文件 url
92
+ */
93
+ const downloadFileUseWindowOpenMode = (url) => {
94
+ window.open(url);
95
+ }
96
+
97
+ // 新建文件夹
98
+ const newFolder = (basePath) => new Promise((resolve, reject) => {
99
+ if (basePath === null || typeof basePath !== 'string') {
100
+ basePath = currentPath.value;
101
+ }
102
+ ElMessageBox.prompt(`在 <b>${basePath}</b> 下创建文件夹,请输入要创建的文件夹名称`, '提示', {
103
+ dangerouslyUseHTMLString: true,
104
+ confirmButtonText: '确定',
105
+ cancelButtonText: '取消',
106
+ draggable: true,
107
+ inputValidator(val) {
108
+ if (!val) {
109
+ return '文件夹名称不能为空';
110
+ }
111
+
112
+ if (val.includes("/")) {
113
+ return '文件夹名称不能包含 / (不支持多级创建)';
114
+ }
115
+ return true;
116
+ },
117
+ }).then(({ value }) => {
118
+ let param = {
119
+ storageKey: storageKey.value,
120
+ path: basePath,
121
+ name: value
122
+ }
123
+ newFolderReq(param).then(() => {
124
+ ElMessage.success('创建成功');
125
+ resolve();
126
+ }).catch(() => {
127
+ reject();
128
+ }).finally(() => {
129
+ loadFile();
130
+ });
131
+ }).catch(() => {
132
+ reject();
133
+ });
134
+ });
135
+
136
+ // 重命名文件夹
137
+ const rename = () => {
138
+ let row = selectRow.value;
139
+ if (row === null) {
140
+ ElMessage.warning('请先选中一个文件或文件夹!');
141
+ return;
142
+ }
143
+ if (row.type === 'FOLDER' && !storageConfigStore.folderConfig.metadata.supportRenameFolder) {
144
+ ElMessage.warning('当前存储源不支持重命名文件夹!');
145
+ return;
146
+ }
147
+
148
+ ElMessageBox.prompt(`将 <b>${row.name}</b> 修改为:`, '提示', {
149
+ dangerouslyUseHTMLString: true,
150
+ confirmButtonText: '确定',
151
+ cancelButtonText: '取消',
152
+ inputValue: row.name,
153
+ inputValidator(val) {
154
+ return !!val
155
+ },
156
+ inputErrorMessage: '模板名称不能为空.'
157
+ }).then(({value}) => {
158
+ let param = {
159
+ storageKey: storageKey.value,
160
+ path: row.path,
161
+ name: row.name,
162
+ newName: value,
163
+ }
164
+
165
+ let reqMethod;
166
+ if (row.type === 'FILE') {
167
+ reqMethod = renameFileReq;
168
+ } else if (row.type === 'FOLDER') {
169
+ reqMethod = renameFolderReq;
170
+ }
171
+
172
+ const renameLoadingInstance = ElLoading.service({
173
+ fullscreen: true,
174
+ text: '重命名中...',
175
+ background: 'rgba(255, 255, 255, 0.6)'
176
+ })
177
+
178
+ reqMethod(param).then(() => {
179
+ ElMessage.success('重命名成功');
180
+ }).finally(() => {
181
+ renameLoadingInstance.close();
182
+ loadFile();
183
+ });
184
+
185
+ });
186
+ }
187
+
188
+ // 复制至
189
+ const copyTo = () => {
190
+ if (selectFolders.value.length > 0 && !storageConfigStore.folderConfig.metadata.supportCopyFolder) {
191
+ ElMessage.warning('当前存储源不支持复制文件夹!');
192
+ return;
193
+ }
194
+ moveOrCopy('复制', selectRow.value?.type === 'FILE' ? copyFileReq : copyFolderReq);
195
+ }
196
+
197
+ // 移动至重命名
198
+ const moveTo = () => {
199
+ if (selectFolders.value.length > 0 && !storageConfigStore.folderConfig.metadata.supportMoveFolder) {
200
+ ElMessage.warning('当前存储源不支持移动文件夹!');
201
+ return;
202
+ }
203
+ moveOrCopy('移动', selectRow.value?.type === 'FILE' ? moveFileReq : moveFolderReq);
204
+ }
205
+
206
+ const moveOrCopy = (title, reqFun) => {
207
+ const nameList = selectRows.value.map(item => item.name);
208
+ selectFolder(title, storageKey.value, currentPath.value, ({ value:path, callback }) => {
209
+ if (path === currentPath.value) {
210
+ ElMessage.warning('你选择的目标文件夹与源文件夹相同!');
211
+ callback.stopLoading();
212
+ return;
213
+ }
214
+
215
+ let param = {
216
+ storageKey: storageKey.value,
217
+ path: currentPath.value,
218
+ nameList: nameList,
219
+ targetPath: path,
220
+ targetNameList: nameList,
221
+ srcPathPassword: getPathPwd(currentPath.value),
222
+ targetPathPassword: getPathPwd(path)
223
+ }
224
+
225
+ reqFun(param).then((res) => {
226
+ let data = res.data;
227
+ let hasFail = false;
228
+ for (let item of data) {
229
+ if (item.success === false) {
230
+ hasFail = true;
231
+ }
232
+ }
233
+ if (hasFail) {
234
+ ElMessageBox.confirm(`部分文件${title}失败,是否查看详情?`, '提示', {
235
+ confirmButtonText: '确定',
236
+ cancelButtonText: '取消',
237
+ closeOnClickModal: false,
238
+ closeOnPressEscape: false,
239
+ type: 'warning'
240
+ }).then(() => {
241
+ openBatchOperatorResultDialog(data);
242
+ });
243
+ } else {
244
+ ElMessage.success(`${title}成功`);
245
+ }
246
+ }).finally(() => {
247
+ callback.stopLoading();
248
+ callback.closeDialog();
249
+ loadFile();
250
+ });
251
+ });
252
+ }
253
+
254
+ // 删除相关 start
255
+ const batchDelete = () => {
256
+ if (!storageConfigStore.permission.delete) {
257
+ return;
258
+ }
259
+
260
+ if (selectRows.value.length === 0) {
261
+ ElMessage.warning('请先至少选中一个文件或文件夹!');
262
+ return;
263
+ }
264
+
265
+ let deleteConfirmMsg = selectRows.value.length === 1 ? '是否确认删除 ' : '是否确认批量删除 ';
266
+
267
+ if (selectFolders.value.length > 0) {
268
+ deleteConfirmMsg += (' ' + selectFolders.value.length + ' 个文件夹');
269
+ }
270
+
271
+ if (selectFolders.value.length > 0 && selectFiles.value.length > 0) {
272
+ deleteConfirmMsg += ',';
273
+ }
274
+
275
+ if (selectFiles.value.length > 0) {
276
+ deleteConfirmMsg += (selectFiles.value.length + ' 个文件');
277
+ }
278
+
279
+ if (selectFolders.value.length > 0 && !storageConfigStore.folderConfig.metadata.supportDeleteNotEmptyFolder) {
280
+ deleteConfirmMsg += ('<span class="font-bold text-red-400">(不支持删除非空文件夹)</span>');
281
+ }
282
+
283
+ deleteConfirmMsg += "?"
284
+
285
+ ElMessageBox.confirm(deleteConfirmMsg, '提示', {
286
+ confirmButtonText: '确定',
287
+ cancelButtonText: '取消',
288
+ draggable: true,
289
+ dangerouslyUseHTMLString: true,
290
+ callback: action => {
291
+ if (action === 'confirm') {
292
+ let param = {
293
+ storageKey: storageKey.value,
294
+ deleteItems: []
295
+ };
296
+
297
+ selectRows.value.forEach((item) => {
298
+ param.deleteItems.push({
299
+ path: item.path,
300
+ name: item.name,
301
+ type: item.type,
302
+ password: getPathPwd(item.path)
303
+ });
304
+ })
305
+
306
+ // 打开全屏 loading
307
+ const loadingInstance = ElLoading.service({
308
+ text: '删除中...',
309
+ background: 'rgba(0, 0, 0, .3)'
310
+ })
311
+
312
+ batchDeleteReq(param).then((res) => {
313
+ let data = res.data;
314
+ let hasFail = false;
315
+ for (let item of data) {
316
+ if (item.success === false) {
317
+ hasFail = true;
318
+ }
319
+ }
320
+ if (hasFail) {
321
+ ElMessageBox.confirm('部分文件删除失败,是否查看详情?', '提示', {
322
+ confirmButtonText: '确定',
323
+ cancelButtonText: '取消',
324
+ closeOnClickModal: false,
325
+ closeOnPressEscape: false,
326
+ type: 'warning'
327
+ }).then(() => {
328
+ openBatchOperatorResultDialog(data);
329
+ });
330
+ } else {
331
+ ElMessage.success("删除成功");
332
+ }
333
+ }).finally(() => {
334
+ loadingInstance.close();
335
+ loadFile();
336
+ });
337
+ }
338
+ }
339
+ });
340
+ }
341
+ // 删除相关 end
342
+
343
+ return {
344
+ batchDownloadFile, rename, newFolder, moveTo, copyTo,
345
+ batchDelete
346
+ }
347
+ }
@@ -0,0 +1,99 @@
1
+ import { v3ImgPreviewFn } from 'v3-img-preview-enhance'
2
+ import { buildKkFileViewUrl } from "~/utils/models/path";
3
+
4
+ // 基础依赖引入
5
+ import useGlobalConfigStore from "~/stores/global-config";
6
+ let globalConfigStore = useGlobalConfigStore();
7
+
8
+ // 基础依赖引入
9
+ import useStorageConfigStore from "~/stores/storage-config";
10
+ const storageConfigStore = useStorageConfigStore();
11
+
12
+ import useFileDataStore from "~/stores/file-data";
13
+ import useTextViewerDialog from "~/composables/file/useTextViewerDialog";
14
+ import usePdfViewerDialog from "~/composables/file/usePdfViewerDialog";
15
+ import useVideoPlayerDialog from "~/composables/file/useVideoPlayerDialog";
16
+ import useOfficeViewerDialog from "~/composables/file/useOfficeViewerDialog";
17
+ import useThree3dPreviewDialog from "~/composables/file/useThree3dPreviewDialog";
18
+ import useKkFileViewDialog from "~/composables/file/useKkFileViewDialog";
19
+
20
+ let fileDataStore = useFileDataStore();
21
+
22
+ const { openDialogWithData: openTextDialog } = useTextViewerDialog();
23
+ const { openDialogWithData: openPdfDialog } = usePdfViewerDialog();
24
+ const { openDialogWithData: openVideoDialog } = useVideoPlayerDialog();
25
+ const { openDialogWithData: openOfficeDialog } = useOfficeViewerDialog();
26
+ const { openDialogWithData: open3DDialog } = useThree3dPreviewDialog();
27
+ const { openDialogWithData: openKkFileViewDialog } = useKkFileViewDialog();
28
+
29
+ export default function useFilePreview() {
30
+
31
+ const openVideo = () => {
32
+ openVideoDialog(fileDataStore.currentClickRow.name);
33
+ }
34
+
35
+ const openAudio = () => {
36
+ fileDataStore.updateAudioList(fileDataStore.filterFileByType('audio'));
37
+ }
38
+
39
+ const openImage = (row) => {
40
+ // 过滤当前页面中所有图片,并记录当前打开的文件的索引位置
41
+ let images = [];
42
+ let currIndex = 0;
43
+ let imagePreviewMode = globalConfigStore.zfileConfig.imagePreview.mode;
44
+ if (imagePreviewMode === 'only') {
45
+ images.push(row.url);
46
+ } else {
47
+ fileDataStore.filterFileByType('image').forEach((image, index) => {
48
+ if (row.name === image.name) {
49
+ currIndex = index;
50
+ }
51
+ images.push(image.url);
52
+ })
53
+ }
54
+
55
+ v3ImgPreviewFn({
56
+ images: images,
57
+ index: currIndex
58
+ })
59
+ }
60
+
61
+ const openText = () => {
62
+ openTextDialog(fileDataStore.currentClickRow.name, fileDataStore.currentClickRow.url);
63
+ }
64
+
65
+ const openOffice = () => {
66
+ openOfficeDialog(fileDataStore.currentClickRow.name);
67
+ }
68
+
69
+ const openPdf = () => {
70
+ openPdfDialog(fileDataStore.currentClickRow.name, fileDataStore.currentClickRow.url);
71
+ }
72
+
73
+ const open3d = () => {
74
+ open3DDialog(fileDataStore.currentClickRow.name, fileDataStore.currentClickRow.url);
75
+ }
76
+
77
+ const openKkFileView = (row) => {
78
+ const kkFileViewUrl = storageConfigStore.globalConfig.kkFileViewUrl;
79
+ const openMode = storageConfigStore.globalConfig.kkFileViewOpenMode;
80
+ const finalUrl = buildKkFileViewUrl(row, kkFileViewUrl);
81
+ if (openMode === 'newTab') {
82
+ window.open(finalUrl, '_blank');
83
+ } else {
84
+ openKkFileViewDialog(row.name, row.url);
85
+ }
86
+ }
87
+
88
+ return {
89
+ openVideo,
90
+ openText,
91
+ openOffice,
92
+ openImage,
93
+ openAudio,
94
+ openPdf,
95
+ open3d,
96
+ openKkFileView
97
+ }
98
+
99
+ }
@@ -0,0 +1,138 @@
1
+ import { useStorage } from "@vueuse/core";
2
+ import { minimatch } from 'minimatch'
3
+ import useRouterData from "~/composables/useRouterData";
4
+ import {concatPath, removeDuplicateSeparator} from "~/utils";
5
+ import MessageBox from "~/components/messageBox/messageBox";
6
+
7
+ let { storageKey, currentPath } = useRouterData()
8
+
9
+ const zfilePasswordCache = useStorage('zfile-pwd-cache', {});
10
+ const fullZFilePasswordCache = useStorage('zfile-pwd-full-cache', {}, sessionStorage);
11
+
12
+ import useStorageConfigStore from "~/stores/storage-config";
13
+ let storageConfigStore = useStorageConfigStore();
14
+
15
+ export default function useFilePwd() {
16
+
17
+ /**
18
+ * 弹出目录密码输入框(可配置是否展示“记住密码”)
19
+ * - Promise 风格:popPassword(options?) => Promise<{ value, checkbox }>
20
+ * - 兼容旧式:popPassword(onConfirm, onCancel)
21
+ */
22
+ const popPassword = (arg1, arg2) => {
23
+ const isCallbackStyle = typeof arg1 === 'function' || typeof arg2 === 'function';
24
+ const onConfirm = isCallbackStyle ? arg1 : null;
25
+ const onCancel = isCallbackStyle ? arg2 : null;
26
+
27
+ // 默认配置
28
+ const opts = isCallbackStyle ? {} : (arg1 || {});
29
+ const {
30
+ showRemember = true,
31
+ defaultRemember = storageConfigStore.globalConfig?.defaultSavePwd,
32
+ defaultValue = getPathPwd(null, true),
33
+ title = '提示',
34
+ message = '此文件夹已加密,请输入密码:',
35
+ inputPlaceholder = '请输入'
36
+ } = opts;
37
+
38
+ const promise = MessageBox.prompt(message, title, {
39
+ confirmButtonText: '确定',
40
+ cancelButtonText: '取消',
41
+ inputType: 'password',
42
+ inputPlaceholder,
43
+ checkbox: !!showRemember,
44
+ defaultChecked: !!defaultRemember,
45
+ inputDefault: defaultValue || '',
46
+ checkboxLabel: '记住密码',
47
+ inputValidator(val) { return !!val },
48
+ inputErrorMessage: '密码不能为空.'
49
+ });
50
+
51
+ if (isCallbackStyle) {
52
+ promise.then(({ value, checkbox }) => {
53
+ onConfirm && onConfirm(value, checkbox);
54
+ }).catch(() => {
55
+ onCancel && onCancel();
56
+ });
57
+ // 同步返回 undefined(与旧式保持行为,真正结果通过回调)
58
+ return;
59
+ }
60
+
61
+ return promise.then(({ value, checkbox }) => ({ value, checkbox }));
62
+ };
63
+
64
+ // 向缓存中写入当前路径密码
65
+ let putPathPwd = (pattern, password, rememberPassword) => {
66
+ if (pattern) {
67
+ // 如果表达式开头没写 / ,则自动补全
68
+ pattern = pattern.startsWith('/') ? pattern : '/' + pattern;
69
+
70
+ // 初始化存储源 key
71
+ if (!zfilePasswordCache.value[storageKey.value]) {
72
+ zfilePasswordCache.value[storageKey.value]= {};
73
+ }
74
+ if (!fullZFilePasswordCache.value[storageKey.value]) {
75
+ fullZFilePasswordCache.value[storageKey.value]= {};
76
+ }
77
+
78
+ // 修正 glob 表达式兼容性和服务端不同的 bug
79
+ if (pattern.endsWith("**") && !pattern.endsWith("/**")) {
80
+ pattern = removeDuplicateSeparator(pattern.substring(0, pattern.length - 2) + "/**");
81
+ console.log('检测到密码文件夹通配符 ** 前未写 /,自动将其修正为为:', pattern);
82
+ }
83
+
84
+ // 根据是否记住密码,写入不同的缓存
85
+ if (rememberPassword) {
86
+ zfilePasswordCache.value[storageKey.value][pattern] = password;
87
+ }
88
+ fullZFilePasswordCache.value[storageKey.value][pattern] = password;
89
+ }
90
+ };
91
+
92
+ // 获取当前路径缓存中的密码
93
+ let getPathPwd = (path, ignoreTempPassword) => {
94
+ // 如果没传递 path,则使用当前路径
95
+ let currentPathValue = path || currentPath.value;
96
+ // 用户存储源基目录
97
+ let rootPath = storageConfigStore.user.rootPath;
98
+ // 自动修正为标准路径
99
+ currentPathValue = concatPath('/', rootPath, currentPathValue, '/');
100
+
101
+ // 如果全量密码缓存为空,则自动初始化为当前密码缓存
102
+ if (Object.keys(fullZFilePasswordCache.value).length === 0 && Object.keys(zfilePasswordCache.value).length !== 0) {
103
+ fullZFilePasswordCache.value = JSON.parse(JSON.stringify(zfilePasswordCache.value));
104
+ console.log('检测到全量密码缓存为空,自动将其初始化为:', fullZFilePasswordCache.value);
105
+ }
106
+ // 根据是否需要获取全量密码(含未记住的密码),选择不同的缓存
107
+ let cache = ignoreTempPassword ? zfilePasswordCache.value : fullZFilePasswordCache.value;
108
+
109
+ for (let storageTag of Object.keys(cache)) {
110
+ if (storageTag === storageKey.value) {
111
+ for (let key of Object.keys(cache[storageTag])) {
112
+ // 如果 key 以 * 结尾,则给 currentPathValue 加上任意字符,以匹配通配符
113
+ if (key.endsWith('*')) {
114
+ currentPathValue = currentPathValue + '*';
115
+ }
116
+ if (minimatch(currentPathValue, key)) {
117
+ return cache[storageTag][key];
118
+ }
119
+ }
120
+ }
121
+ }
122
+ return '';
123
+ };
124
+
125
+ const clearPwdCache = () => {
126
+ zfilePasswordCache.value = {};
127
+ fullZFilePasswordCache.value = {};
128
+ ElMessage.success('操作成功')
129
+ }
130
+
131
+ return {
132
+ putPathPwd,
133
+ getPathPwd,
134
+ popPassword,
135
+ clearPwdCache
136
+ }
137
+
138
+ }
@@ -0,0 +1,105 @@
1
+ import { computed, ref } from "vue";
2
+ const selectRows = ref([]);
3
+ const selectFun = ref({
4
+ clearSelection: null,
5
+ toggleRowSelection: null,
6
+ toggleAllSelection: null
7
+ })
8
+
9
+
10
+ export default function useFileSelect() {
11
+
12
+ const initSelectFun = (clearSelection, toggleRowSelection, toggleAllSelection) => {
13
+ selectFun.value.clearSelection = clearSelection;
14
+ selectFun.value.toggleRowSelection = toggleRowSelection;
15
+ selectFun.value.toggleAllSelection = toggleAllSelection;
16
+ }
17
+
18
+ const clearSelection = () => {
19
+ selectFun.value.clearSelection();
20
+ }
21
+
22
+ const toggleRowSelection = (row, selected) => {
23
+ if (row?.type === 'BACK') {
24
+ return;
25
+ }
26
+ selectFun.value.toggleRowSelection(row, selected);
27
+ }
28
+
29
+ const toggleAllSelection = () => {
30
+ selectFun.value.toggleAllSelection();
31
+ }
32
+
33
+ // 文件是否可被选择
34
+ const checkSelectable = (row) => {
35
+ return row.type === "FILE" || row.type === "FOLDER";
36
+ };
37
+
38
+ // 当前最后选中的文件行
39
+ const selectRow = computed(() => {
40
+ if (selectRows.value.length > 0) {
41
+ return selectRows.value[selectRows.value.length - 1];
42
+ } else {
43
+ return null;
44
+ }
45
+ });
46
+
47
+ // 当前选中的文件
48
+ const selectFiles = computed(() => {
49
+ return selectRows.value.filter((row) => {
50
+ return row.type === "FILE";
51
+ });
52
+ });
53
+
54
+ // 当前选中的文件夹
55
+ const selectFolders = computed(() => {
56
+ return selectRows.value.filter((row) => {
57
+ return row.type === "FOLDER";
58
+ });
59
+ });
60
+
61
+ // 更新选中的文件列表
62
+ const selectRowsChange = (selection) => {
63
+ selectRows.value = selection;
64
+ };
65
+
66
+ // 行选中 class
67
+ const tableRowClassName = ({ row, rowIndex }) => {
68
+ row.index = rowIndex;
69
+ return selectRows.value.indexOf(row) !== -1 ? "select-row" : "";
70
+ };
71
+
72
+ // 多选统计信息
73
+ const selectStatistics = computed(() => {
74
+ let selectRowsLength = selectRows.value.length;
75
+ let selectFilesLength = selectFiles.value.length;
76
+ let selectFoldersLength = selectFolders.value.length;
77
+
78
+ let isSelected = selectRowsLength > 0;
79
+ let isSingleSelect = selectRowsLength === 1;
80
+ let isMultiSelect = selectRowsLength > 1;
81
+ let isAllFile = selectFilesLength === selectRowsLength;
82
+ let isAllFolder = selectFoldersLength === selectRowsLength;
83
+ let isSingleSelectFile = isSingleSelect && selectFilesLength === 1;
84
+ let isSingleSelectFolder = isSingleSelect && selectFoldersLength === 1;
85
+
86
+ return {
87
+ isSelected,
88
+ isSingleSelect,
89
+ isMultiSelect,
90
+ isAllFile,
91
+ isAllFolder,
92
+ isSingleSelectFile,
93
+ isSingleSelectFolder
94
+ };
95
+ });
96
+
97
+ return {
98
+ initSelectFun,
99
+ checkSelectable, tableRowClassName, selectRowsChange,
100
+ selectRow, selectRows,
101
+ selectFiles, selectFolders,
102
+ selectStatistics,
103
+ clearSelection, toggleRowSelection, toggleAllSelection
104
+ };
105
+ }