@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.
- package/.vscode/extensions.json +3 -0
- package/README.md +5 -0
- package/auto-imports.d.ts +12 -0
- package/components.d.ts +45 -0
- package/dist.zip +0 -0
- package/index.html +13 -0
- package/package.json +100 -0
- package/presets/eslint/.eslintrc-auto-import.json +462 -0
- package/presets/plugins/html.ts +14 -0
- package/presets/shared/env.ts +46 -0
- package/presets/shared/resolvers.ts +29 -0
- package/presets/tov.ts +132 -0
- package/presets/types/auto-imports.d.ts +806 -0
- package/presets/types/components.d.ts +164 -0
- package/presets/types/env.d.ts +17 -0
- package/public/favicon.svg +1 -0
- package/public/icons.svg +24 -0
- package/public/testfile/README.md +5 -0
- package/public/testfile/useFileContextMenu.js +74 -0
- package/public/testfile//345/217/221/347/245/250.pdf +0 -0
- package/public/testfile//346/216/245/346/224/266/345/207/275.docx +0 -0
- package/public/testfile//350/247/204/346/240/274/345/236/213/345/217/2671.txt +263 -0
- package/public/testfile//350/247/206/351/242/2211.mp4 +0 -0
- package/public/testfile//351/237/263/351/242/2211.mp3 +0 -0
- package/src/App.vue +8 -0
- package/src/api/admin/admin-2fa.js +18 -0
- package/src/api/admin/admin-download-log.js +37 -0
- package/src/api/admin/admin-login-log.js +9 -0
- package/src/api/admin/admin-permission.js +9 -0
- package/src/api/admin/admin-setting.js +121 -0
- package/src/api/admin/admin-share.js +20 -0
- package/src/api/admin/admin-short-link.js +49 -0
- package/src/api/admin/admin-sso.js +38 -0
- package/src/api/admin/admin-storage.js +189 -0
- package/src/api/admin/admin-user.js +61 -0
- package/src/api/home/common.js +9 -0
- package/src/api/home/file-operator.js +89 -0
- package/src/api/home/home.js +87 -0
- package/src/api/home/install.js +18 -0
- package/src/api/home/login.js +9 -0
- package/src/api/home/only-office.js +10 -0
- package/src/api/home/share.js +115 -0
- package/src/api/home/user.js +74 -0
- package/src/api/tools/tools-115.js +17 -0
- package/src/api/tools/tools-gd.js +13 -0
- package/src/api/tools/tools-s3.js +25 -0
- package/src/api/tools/tools-sharepoint.js +19 -0
- package/src/assets/hero.png +0 -0
- package/src/assets/icons/401.svg +1 -0
- package/src/assets/icons/403.svg +45 -0
- package/src/assets/icons/404.svg +1 -0
- package/src/assets/icons/500.svg +1 -0
- package/src/assets/icons/admin-login.svg +1 -0
- package/src/assets/icons/document.svg +1 -0
- package/src/assets/icons/empty.svg +145 -0
- package/src/assets/icons/file-type-apk.svg +1 -0
- package/src/assets/icons/file-type-archive.svg +1 -0
- package/src/assets/icons/file-type-audio.svg +1 -0
- package/src/assets/icons/file-type-back.svg +1 -0
- package/src/assets/icons/file-type-css.svg +1 -0
- package/src/assets/icons/file-type-deb.svg +1 -0
- package/src/assets/icons/file-type-dll.svg +1 -0
- package/src/assets/icons/file-type-doc.svg +1 -0
- package/src/assets/icons/file-type-document.svg +1 -0
- package/src/assets/icons/file-type-docx.svg +1 -0
- package/src/assets/icons/file-type-exe.svg +1 -0
- package/src/assets/icons/file-type-expression.svg +1 -0
- package/src/assets/icons/file-type-file.svg +1 -0
- package/src/assets/icons/file-type-folder.svg +1 -0
- package/src/assets/icons/file-type-html.svg +1 -0
- package/src/assets/icons/file-type-image.svg +1 -0
- package/src/assets/icons/file-type-java.svg +1 -0
- package/src/assets/icons/file-type-js.svg +1 -0
- package/src/assets/icons/file-type-less.svg +1 -0
- package/src/assets/icons/file-type-md.svg +1 -0
- package/src/assets/icons/file-type-office.svg +1 -0
- package/src/assets/icons/file-type-pdf.svg +1 -0
- package/src/assets/icons/file-type-php.svg +1 -0
- package/src/assets/icons/file-type-ppt.svg +1 -0
- package/src/assets/icons/file-type-pptx.svg +1 -0
- package/src/assets/icons/file-type-py.svg +1 -0
- package/src/assets/icons/file-type-rb.svg +1 -0
- package/src/assets/icons/file-type-root.svg +1 -0
- package/src/assets/icons/file-type-rpm.svg +1 -0
- package/src/assets/icons/file-type-rust.svg +1 -0
- package/src/assets/icons/file-type-script.svg +1 -0
- package/src/assets/icons/file-type-text.svg +1 -0
- package/src/assets/icons/file-type-three3d.svg +5 -0
- package/src/assets/icons/file-type-vbs.svg +1 -0
- package/src/assets/icons/file-type-video.svg +1 -0
- package/src/assets/icons/file-type-xls.svg +1 -0
- package/src/assets/icons/file-type-xlsx.svg +1 -0
- package/src/assets/icons/file-type-xml.svg +1 -0
- package/src/assets/icons/file-type-yaml.svg +1 -0
- package/src/assets/icons/file-upload.svg +1 -0
- package/src/assets/icons/github.svg +1 -0
- package/src/assets/icons/install-step.svg +40 -0
- package/src/assets/icons/reset-password.svg +1 -0
- package/src/assets/icons/storage-aliyun.svg +1 -0
- package/src/assets/icons/storage-baidu.svg +1 -0
- package/src/assets/icons/storage-doge-cloud.svg +207 -0
- package/src/assets/icons/storage-ftp.svg +13 -0
- package/src/assets/icons/storage-google-drive.svg +8 -0
- package/src/assets/icons/storage-huawei.svg +1 -0
- package/src/assets/icons/storage-local.svg +11 -0
- package/src/assets/icons/storage-minio.svg +1 -0
- package/src/assets/icons/storage-onedrive-china.svg +18 -0
- package/src/assets/icons/storage-onedrive.svg +4 -0
- package/src/assets/icons/storage-open115.svg +23 -0
- package/src/assets/icons/storage-qiniu.svg +1 -0
- package/src/assets/icons/storage-s3.svg +5 -0
- package/src/assets/icons/storage-sftp.svg +13 -0
- package/src/assets/icons/storage-sharepoint-china.svg +23 -0
- package/src/assets/icons/storage-sharepoint.svg +1 -0
- package/src/assets/icons/storage-tencent.svg +9 -0
- package/src/assets/icons/storage-ufile.svg +14 -0
- package/src/assets/icons/storage-upyun.svg +1 -0
- package/src/assets/icons/storage-webdav.svg +1 -0
- package/src/assets/icons/upload.svg +50 -0
- package/src/assets/icons/zfile-basic.svg +17 -0
- package/src/assets/icons/zfile-horizontal.svg +16 -0
- package/src/assets/icons/zfile.svg +1 -0
- package/src/assets/vite.svg +1 -0
- package/src/assets/vue.svg +1 -0
- package/src/components/HelloWorld.vue +319 -0
- package/src/components/common/QrCodePreview.vue +118 -0
- package/src/components/common/dialog/ZDialog.vue +171 -0
- package/src/components/common/dialog/types.ts +19 -0
- package/src/components/common/dialog/useDialog.ts +18 -0
- package/src/components/common/dialog/useDialogWithForm.ts +21 -0
- package/src/components/copy.vue +133 -0
- package/src/components/file/preview/AudioPlayer.vue +333 -0
- package/src/components/file/preview/CopyCode.vue +47 -0
- package/src/components/file/preview/FileGallery.vue +199 -0
- package/src/components/file/preview/ImageViewer.vue +432 -0
- package/src/components/file/preview/KkFileViewer.vue +86 -0
- package/src/components/file/preview/KkFileViewerDialog.vue +42 -0
- package/src/components/file/preview/MarkdownViewer.vue +102 -0
- package/src/components/file/preview/MarkdownViewerAsyncLoading.vue +17 -0
- package/src/components/file/preview/MarkdownViewerDialogAsyncLoading.vue +12 -0
- package/src/components/file/preview/OfficeViewer.vue +76 -0
- package/src/components/file/preview/OfficeViewerDialog.vue +55 -0
- package/src/components/file/preview/PdfViewer.vue +157 -0
- package/src/components/file/preview/PdfViewerDialog.vue +41 -0
- package/src/components/file/preview/TextViewer.vue +232 -0
- package/src/components/file/preview/TextViewerAsyncLoading.vue +22 -0
- package/src/components/file/preview/TextViewerDialog.vue +53 -0
- package/src/components/file/preview/Three3dPreview.vue +114 -0
- package/src/components/file/preview/Three3dPreviewDialog.vue +50 -0
- package/src/components/file/preview/VideoPlayer.vue +341 -0
- package/src/components/file/preview/VideoPlayerAsyncLoading.vue +45 -0
- package/src/components/file/preview/VideoPlayerDialog.vue +51 -0
- package/src/components/file/selectFolder/SelectFolder.vue +208 -0
- package/src/components/file/selectFolder/index.ts +50 -0
- package/src/components/file/selectFolder/types.ts +5 -0
- package/src/components/fileReview/AudioPlayer-copy.vue +333 -0
- package/src/components/fileReview/PdfViewer-copy.vue +157 -0
- package/src/components/fileReview/TextViewer-copy.vue +44 -0
- package/src/components/fileReview/VideoPlayer-copy.vue +341 -0
- package/src/components/messageBox/confirm/confirm.vue +137 -0
- package/src/components/messageBox/confirm/index.ts +27 -0
- package/src/components/messageBox/confirm/types.ts +15 -0
- package/src/components/messageBox/messageBox.ts +9 -0
- package/src/components/messageBox/prompt/index.ts +27 -0
- package/src/components/messageBox/prompt/prompt.vue +178 -0
- package/src/components/messageBox/prompt/types.ts +24 -0
- package/src/components/vue-codemirror/editor.vue +212 -0
- package/src/components/vue-codemirror/encodings.ts +27 -0
- package/src/components/vue-codemirror/index.vue +380 -0
- package/src/components/vue-codemirror/lang-code/cpp/index.ts +3 -0
- package/src/components/vue-codemirror/lang-code/css/index.ts +2 -0
- package/src/components/vue-codemirror/lang-code/dockerfile/index.ts +5 -0
- package/src/components/vue-codemirror/lang-code/erlang/index.ts +6 -0
- package/src/components/vue-codemirror/lang-code/go/index.ts +5 -0
- package/src/components/vue-codemirror/lang-code/html/index.ts +3 -0
- package/src/components/vue-codemirror/lang-code/java/index.ts +3 -0
- package/src/components/vue-codemirror/lang-code/javascript/index.ts +3 -0
- package/src/components/vue-codemirror/lang-code/json/index.ts +3 -0
- package/src/components/vue-codemirror/lang-code/jsx/index.ts +3 -0
- package/src/components/vue-codemirror/lang-code/lua/index.ts +6 -0
- package/src/components/vue-codemirror/lang-code/markdown/index.ts +2 -0
- package/src/components/vue-codemirror/lang-code/mysql/index.ts +3 -0
- package/src/components/vue-codemirror/lang-code/nginx/index.ts +6 -0
- package/src/components/vue-codemirror/lang-code/perl/index.ts +5 -0
- package/src/components/vue-codemirror/lang-code/pgsql/index.ts +2 -0
- package/src/components/vue-codemirror/lang-code/php/index.ts +3 -0
- package/src/components/vue-codemirror/lang-code/powershell/index.ts +3 -0
- package/src/components/vue-codemirror/lang-code/python/index.ts +2 -0
- package/src/components/vue-codemirror/lang-code/r/index.ts +5 -0
- package/src/components/vue-codemirror/lang-code/ruby/index.ts +5 -0
- package/src/components/vue-codemirror/lang-code/rust/index.ts +2 -0
- package/src/components/vue-codemirror/lang-code/shell/index.ts +5 -0
- package/src/components/vue-codemirror/lang-code/sql/index.ts +3 -0
- package/src/components/vue-codemirror/lang-code/stylus/index.ts +3 -0
- package/src/components/vue-codemirror/lang-code/swift/index.ts +4 -0
- package/src/components/vue-codemirror/lang-code/toml/index.ts +3 -0
- package/src/components/vue-codemirror/lang-code/tsx/index.ts +2 -0
- package/src/components/vue-codemirror/lang-code/typescript/index.ts +2 -0
- package/src/components/vue-codemirror/lang-code/vb/index.ts +3 -0
- package/src/components/vue-codemirror/lang-code/vbscript/index.ts +3 -0
- package/src/components/vue-codemirror/lang-code/xml/index.ts +2 -0
- package/src/components/vue-codemirror/lang-code/yaml/index.ts +3 -0
- package/src/components/vue-codemirror/languages.ts +8 -0
- package/src/components/vue-codemirror/themes.ts +5 -0
- package/src/components/vue-codemirror/toolbar.vue +183 -0
- package/src/components/vue-codemirror/types.ts +12 -0
- package/src/components.d.ts +49 -0
- package/src/composables/admin/layout/admin-layout.js +53 -0
- package/src/composables/admin/link/useLinkSetting.js +16 -0
- package/src/composables/admin/sso/baseSsoConfig.js +54 -0
- package/src/composables/admin/sso/useSsoConfig.js +176 -0
- package/src/composables/admin/storage/storage-copy.js +89 -0
- package/src/composables/admin/storage/storage-filter.js +64 -0
- package/src/composables/admin/storage/storage-list.js +202 -0
- package/src/composables/admin/storage/storage-password.js +101 -0
- package/src/composables/admin/storage/storage-readme.js +102 -0
- package/src/composables/admin/storage/utils/open115-util.js +61 -0
- package/src/composables/admin/useAdminSetting.js +60 -0
- package/src/composables/admin/useClientInfo.js +20 -0
- package/src/composables/admin/user/user-copy.js +79 -0
- package/src/composables/file/useBatchOperatorResult.js +19 -0
- package/src/composables/file/useFileContextMenu.js +74 -0
- package/src/composables/file/useFileData.js +243 -0
- package/src/composables/file/useFileLink.js +175 -0
- package/src/composables/file/useFileLoading.js +41 -0
- package/src/composables/file/useFileLongPressEvent.js +71 -0
- package/src/composables/file/useFileOperator.js +347 -0
- package/src/composables/file/useFilePreview.js +99 -0
- package/src/composables/file/useFilePwd.js +138 -0
- package/src/composables/file/useFileSelect.js +105 -0
- package/src/composables/file/useFileShare.js +39 -0
- package/src/composables/file/useFileUpload.js +1045 -0
- package/src/composables/file/useKkFileViewDialog.js +24 -0
- package/src/composables/file/useOfficeViewerDialog.js +20 -0
- package/src/composables/file/usePdfViewerDialog.js +22 -0
- package/src/composables/file/useShareActions.js +94 -0
- package/src/composables/file/useShareTableOperator.js +84 -0
- package/src/composables/file/useTableOperator.js +211 -0
- package/src/composables/file/useTextViewerDialog.js +22 -0
- package/src/composables/file/useThree3dPreviewDialog.js +23 -0
- package/src/composables/file/useVideoPlayerDialog.js +19 -0
- package/src/composables/header/useHeaderBreadcrumb.js +111 -0
- package/src/composables/header/useHeaderStorageList.js +150 -0
- package/src/composables/header/useSetting.js +58 -0
- package/src/composables/share/useShareData.js +178 -0
- package/src/composables/useDarks.ts +4 -0
- package/src/composables/useRouterData.js +41 -0
- package/src/constant/index.js +193 -0
- package/src/http/index.js +153 -0
- package/src/http/request.js +31 -0
- package/src/main.ts +23 -0
- package/src/stores/file-data.ts +108 -0
- package/src/stores/global-config.ts +115 -0
- package/src/stores/storage-config.ts +123 -0
- package/src/style.css +296 -0
- package/src/styles/admin.scss +91 -0
- package/src/styles/code-editor-variables.scss +52 -0
- package/src/styles/element-plus.scss +22 -0
- package/src/styles/error-page.css +26 -0
- package/src/styles/main.css +142 -0
- package/src/styles/tailwind/index.scss +33 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/models/base.ts +34 -0
- package/src/utils/models/file.ts +95 -0
- package/src/utils/models/path.ts +117 -0
- package/src/utils/models/qrcode.ts +21 -0
- package/src/utils/models/time.ts +132 -0
- package/src/utils/models/util.ts +42 -0
- package/src/utils/models/window.ts +14 -0
- package/stats.html +4950 -0
- package/tsconfig.app.json +16 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +26 -0
- package/vite.config.ts +57 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import useDialog from "~/components/common/dialog/useDialog";
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
|
|
4
|
+
const { visible, openDialog } = useDialog();
|
|
5
|
+
|
|
6
|
+
const name = ref("");
|
|
7
|
+
const url = ref(""); // kkfileview 需要文件的完整 URL
|
|
8
|
+
|
|
9
|
+
export default function useKkFileViewDialog() {
|
|
10
|
+
|
|
11
|
+
// 接收文件名和文件URL
|
|
12
|
+
const openDialogWithData = (_name, _url) => {
|
|
13
|
+
name.value = _name;
|
|
14
|
+
url.value = _url;
|
|
15
|
+
openDialog();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
openDialogWithData,
|
|
20
|
+
visible,
|
|
21
|
+
name,
|
|
22
|
+
url
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
import useDialog from "~/components/common/dialog/useDialog";
|
|
3
|
+
|
|
4
|
+
const { visible, openDialog } = useDialog();
|
|
5
|
+
|
|
6
|
+
const name = ref("");
|
|
7
|
+
|
|
8
|
+
export default function useOfficeViewerDialog() {
|
|
9
|
+
|
|
10
|
+
const openDialogWithData = (_name) => {
|
|
11
|
+
name.value = _name;
|
|
12
|
+
openDialog();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
openDialogWithData,
|
|
17
|
+
visible,
|
|
18
|
+
name
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import useDialog from "~/components/common/dialog/useDialog";
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
const { visible, openDialog } = useDialog();
|
|
4
|
+
|
|
5
|
+
const name = ref("");
|
|
6
|
+
const url = ref("");
|
|
7
|
+
|
|
8
|
+
export default function usePdfViewerDialog() {
|
|
9
|
+
|
|
10
|
+
const openDialogWithData = (_name, _url) => {
|
|
11
|
+
name.value = _name;
|
|
12
|
+
url.value = _url;
|
|
13
|
+
openDialog();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
openDialogWithData,
|
|
18
|
+
visible,
|
|
19
|
+
name,
|
|
20
|
+
url
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { toClipboard } from '@soerenmartius/vue3-clipboard'
|
|
2
|
+
import { concatPath, getFileType, buildShareBasePath } from '~/utils'
|
|
3
|
+
import { getShareFileDownloadUrlReq } from '~/api/home/share'
|
|
4
|
+
|
|
5
|
+
import useRouterData from '~/composables/useRouterData'
|
|
6
|
+
const { routeRef, routerRef } = useRouterData()
|
|
7
|
+
|
|
8
|
+
import useFileDataStore from '~/stores/file-data'
|
|
9
|
+
const { updateCurrentClickRow } = useFileDataStore()
|
|
10
|
+
|
|
11
|
+
import useFilePreview from '~/composables/file/useFilePreview'
|
|
12
|
+
const {
|
|
13
|
+
openAudio,
|
|
14
|
+
openImage,
|
|
15
|
+
openOffice,
|
|
16
|
+
openPdf,
|
|
17
|
+
openText,
|
|
18
|
+
openVideo,
|
|
19
|
+
open3d,
|
|
20
|
+
openKkFileView,
|
|
21
|
+
} = useFilePreview()
|
|
22
|
+
|
|
23
|
+
import useShareData from '~/composables/share/useShareData'
|
|
24
|
+
const { sharePassword } = useShareData()
|
|
25
|
+
|
|
26
|
+
export default function useShareActions() {
|
|
27
|
+
const shareKey = () => routeRef.value?.params?.shareKey
|
|
28
|
+
const pwd = () => sharePassword?.value || routeRef.value?.query?.pwd
|
|
29
|
+
const currentPath = () => routeRef.value?.query?.path || '/'
|
|
30
|
+
|
|
31
|
+
const buildDownloadUrl = (row) => {
|
|
32
|
+
const key = shareKey()
|
|
33
|
+
if (!key || !row?.name) return ''
|
|
34
|
+
const fullPath = concatPath(row.path, row.name)
|
|
35
|
+
return getShareFileDownloadUrlReq(key, fullPath, pwd())
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const openFolder = (row) => {
|
|
39
|
+
if (!row?.name) return
|
|
40
|
+
const base = buildShareBasePath(shareKey())
|
|
41
|
+
const cur = currentPath()
|
|
42
|
+
const newPath = concatPath(cur === '/' ? '' : cur, row.name)
|
|
43
|
+
routerRef.value.push({
|
|
44
|
+
path: base,
|
|
45
|
+
query: { ...(routeRef.value?.query || {}), path: newPath, pwd: pwd() },
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const previewFile = (row) => {
|
|
50
|
+
const url = buildDownloadUrl(row)
|
|
51
|
+
const rowWithUrl = { ...row, url }
|
|
52
|
+
updateCurrentClickRow(rowWithUrl)
|
|
53
|
+
const ft = getFileType(row.name)
|
|
54
|
+
switch (ft) {
|
|
55
|
+
case 'video':
|
|
56
|
+
return openVideo()
|
|
57
|
+
case 'image':
|
|
58
|
+
return openImage(rowWithUrl)
|
|
59
|
+
case 'text':
|
|
60
|
+
return openText()
|
|
61
|
+
case 'audio':
|
|
62
|
+
return openAudio()
|
|
63
|
+
case 'office':
|
|
64
|
+
return openOffice()
|
|
65
|
+
case 'pdf':
|
|
66
|
+
return openPdf()
|
|
67
|
+
case 'three3d':
|
|
68
|
+
return open3d()
|
|
69
|
+
case 'kkfileview':
|
|
70
|
+
return openKkFileView(rowWithUrl)
|
|
71
|
+
default:
|
|
72
|
+
window.open(url, '_blank')
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const downloadFile = (row) => {
|
|
77
|
+
const url = buildDownloadUrl(row)
|
|
78
|
+
if (url) window.open(url, '_blank')
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const copyDownloadLink = async (row) => {
|
|
82
|
+
const url = buildDownloadUrl(row)
|
|
83
|
+
if (!url) return
|
|
84
|
+
await toClipboard(url)
|
|
85
|
+
ElMessage.success('下载链接已复制')
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
openFolder,
|
|
90
|
+
previewFile,
|
|
91
|
+
downloadFile,
|
|
92
|
+
copyDownloadLink,
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { concatPath, buildShareBasePath } from "~/utils";
|
|
2
|
+
import useRouterData from "~/composables/useRouterData";
|
|
3
|
+
import { buildTableOperator } from "~/composables/file/useTableOperator";
|
|
4
|
+
|
|
5
|
+
import useFileDataStore from "~/stores/file-data";
|
|
6
|
+
const fileDataStore = useFileDataStore();
|
|
7
|
+
|
|
8
|
+
import useFileContextMenu from "~/composables/file/useFileContextMenu";
|
|
9
|
+
const { contextMenuTargetFile, contextMenuTargetBlank } = useFileContextMenu();
|
|
10
|
+
|
|
11
|
+
import useShareActions from "~/composables/file/useShareActions";
|
|
12
|
+
const { previewFile, downloadFile } = useShareActions();
|
|
13
|
+
|
|
14
|
+
import useFileSelect from "~/composables/file/useFileSelect";
|
|
15
|
+
const { clearSelection } = useFileSelect();
|
|
16
|
+
|
|
17
|
+
import useShareData from "~/composables/share/useShareData";
|
|
18
|
+
const { sharePassword } = useShareData();
|
|
19
|
+
|
|
20
|
+
import useStorageConfigStore from "~/stores/storage-config";
|
|
21
|
+
const storageConfigStore = useStorageConfigStore();
|
|
22
|
+
|
|
23
|
+
export default function useShareTableOperator() {
|
|
24
|
+
const { routeRef, routerRef } = useRouterData();
|
|
25
|
+
const shareKey = computed(() => routeRef.value?.params?.shareKey);
|
|
26
|
+
|
|
27
|
+
const getCurrentPath = () => {
|
|
28
|
+
return routeRef.value?.query?.path || '/';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const openRow = (row) => {
|
|
32
|
+
if (!row?.name) return;
|
|
33
|
+
|
|
34
|
+
// 当右键菜单打开时,双击不触发打开动作,保持与文件页一致
|
|
35
|
+
if (contextMenuTargetFile.value === true || contextMenuTargetBlank.value === true) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const pwd = sharePassword?.value || routeRef.value?.query?.pwd;
|
|
40
|
+
const currentPath = getCurrentPath();
|
|
41
|
+
|
|
42
|
+
if (row.type === 'FOLDER') {
|
|
43
|
+
const newPath = concatPath(currentPath === '/' ? '' : currentPath, row.name);
|
|
44
|
+
routerRef.value.push({ path: buildShareBasePath(shareKey.value), query: { ...(routeRef.value?.query || {}), path: newPath, pwd } });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (row.type === 'BACK') {
|
|
49
|
+
const parts = (currentPath || '/').split('/').filter(Boolean);
|
|
50
|
+
parts.pop();
|
|
51
|
+
const parentPath = '/' + parts.join('/');
|
|
52
|
+
routerRef.value.push({ path: buildShareBasePath(shareKey.value), query: { ...(routeRef.value?.query || {}), path: parentPath === '//' ? '/' : parentPath, pwd } });
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 文件:遵循主站逻辑,先尝试预览,权限不足时回退为下载
|
|
57
|
+
const permissions = storageConfigStore.folderConfig?.permission || {};
|
|
58
|
+
const canPreviewType = row.preview === true || !!row.fileType; // fileList getter 会填充
|
|
59
|
+
const allowPreview = permissions.preview;
|
|
60
|
+
const allowDownload = permissions.download;
|
|
61
|
+
|
|
62
|
+
if (!allowPreview && !allowDownload) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
fileDataStore.updateCurrentClickRow(row);
|
|
67
|
+
|
|
68
|
+
let acted = false;
|
|
69
|
+
if (canPreviewType && allowPreview) {
|
|
70
|
+
previewFile(row);
|
|
71
|
+
acted = true;
|
|
72
|
+
} else if (allowDownload) {
|
|
73
|
+
downloadFile(row);
|
|
74
|
+
acted = true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (acted) {
|
|
78
|
+
clearSelection();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 复用通用表格行为(选择、拖拽、hover、双击),仅替换 openRow
|
|
83
|
+
return buildTableOperator(openRow);
|
|
84
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { useKeyModifier } from '@vueuse/core'
|
|
2
|
+
|
|
3
|
+
import { isMobile, isNotMobile } from "~/utils";
|
|
4
|
+
|
|
5
|
+
import useStorageConfigStore from "~/stores/storage-config";
|
|
6
|
+
let storageConfigStore = useStorageConfigStore();
|
|
7
|
+
|
|
8
|
+
import useFileDataStore from "~/stores/file-data";
|
|
9
|
+
let fileDataStore = useFileDataStore();
|
|
10
|
+
|
|
11
|
+
// 按键监听
|
|
12
|
+
const mateState = useKeyModifier('Meta');
|
|
13
|
+
const controlState = useKeyModifier('Control');
|
|
14
|
+
const shiftState = useKeyModifier('Shift');
|
|
15
|
+
|
|
16
|
+
// 是否按住了 Ctrl(Windows) 或者 Command(Mac) 键
|
|
17
|
+
let isMultiSelectState = computed(() => {
|
|
18
|
+
return mateState.value || controlState.value;
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
import useFileOperator from "~/composables/file/useFileOperator";
|
|
22
|
+
let { batchDelete } = useFileOperator();
|
|
23
|
+
|
|
24
|
+
import useFileData from "~/composables/file/useFileData";
|
|
25
|
+
const { openRow: openRowDefault } = useFileData();
|
|
26
|
+
|
|
27
|
+
import useFileLoading from "~/composables/file/useFileLoading";
|
|
28
|
+
const { skeletonLoading } = useFileLoading();
|
|
29
|
+
|
|
30
|
+
import useFileSelect from "~/composables/file/useFileSelect";
|
|
31
|
+
const { selectRows, selectRow, clearSelection, toggleRowSelection, toggleAllSelection } = useFileSelect();
|
|
32
|
+
|
|
33
|
+
// ctrl + a 全选
|
|
34
|
+
window.addEventListener("keydown", function(e) {
|
|
35
|
+
if (e.key === 'Escape' && allowShortcuts()) {
|
|
36
|
+
clearSelection();
|
|
37
|
+
} else if (e.key === 'a' && (e.metaKey || e.ctrlKey) && allowShortcuts()) {
|
|
38
|
+
e.preventDefault();
|
|
39
|
+
toggleAllSelection();
|
|
40
|
+
} else if (e.key === 'Delete' && allowShortcuts()) { // 如果按了删除键,且当前状态允许快捷键操作
|
|
41
|
+
if (batchDelete && selectRows?.value?.length > 0) {
|
|
42
|
+
e.preventDefault();
|
|
43
|
+
batchDelete();
|
|
44
|
+
}
|
|
45
|
+
} else if (e.key === 'Backspace' && allowShortcuts()) { // 如果按了删除键,且当前状态允许快捷键操作
|
|
46
|
+
if (fileDataStore.fileList.length > 0 && fileDataStore.fileList[0].type === 'BACK') {
|
|
47
|
+
tableClickRow(fileDataStore.fileList[0]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}, false);
|
|
51
|
+
|
|
52
|
+
export const allowShortcuts = () => {
|
|
53
|
+
// 仅鼠标悬浮在 table 上时且没有打开 dialog 时,才允许快捷键操作.
|
|
54
|
+
return hoverBody() && hasDialog() === false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 是否悬浮在首页上
|
|
58
|
+
export const hoverBody = () => {
|
|
59
|
+
// 仅鼠标悬浮在 table 上时且没有打开 dialog 时,才允许快捷键操作.
|
|
60
|
+
return document.querySelector(".zfile-index-body:hover")
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 当前是否打开了 dialog
|
|
64
|
+
export const hasDialog = () => {
|
|
65
|
+
return !!document.querySelector(".el-popup-parent--hidden")
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 当前是否聚焦在密码输入框
|
|
69
|
+
export const hasPasswordInputFocus = () => {
|
|
70
|
+
return document.querySelector(".is-message-box .el-input__inner") === document.activeElement;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
// 当前是否聚焦在搜索输入框
|
|
75
|
+
export const hasSearchInputFocus = () => {
|
|
76
|
+
return document.querySelector(".zfile-search-input .el-input__inner") === document.activeElement;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
// 拖拽选择相关
|
|
81
|
+
// 开始拖拽的文件行索引
|
|
82
|
+
const startDragClickIndex = ref(-1);
|
|
83
|
+
// 结束拖拽的文件行索引
|
|
84
|
+
const endDragClickIndex = ref(-1);
|
|
85
|
+
// 是否按下鼠标左键
|
|
86
|
+
import { useMousePressed } from '@vueuse/core'
|
|
87
|
+
const { pressed } = useMousePressed()
|
|
88
|
+
|
|
89
|
+
watch(() => pressed.value, (value, oldValue) => {
|
|
90
|
+
// 如果之前是点击状态, 现在松开了则清除记录的拖拽索引
|
|
91
|
+
if (value === false && oldValue === true) {
|
|
92
|
+
startDragClickIndex.value = -1;
|
|
93
|
+
endDragClickIndex.value = -1;
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
let tableClickRow;
|
|
99
|
+
|
|
100
|
+
export function buildTableOperator(openRow) {
|
|
101
|
+
|
|
102
|
+
// 文件单击事件
|
|
103
|
+
const tableClickRow = (row, event) => {
|
|
104
|
+
if (event === undefined) {
|
|
105
|
+
openRow(row);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let isClickSelection = event.type === 'selection';
|
|
110
|
+
|
|
111
|
+
// 如果点击的是文件或文件夹, 且点击的不是 checkbox 列, 且操作习惯是单击打开, 则打开文件/文件夹
|
|
112
|
+
if (!isClickSelection &&
|
|
113
|
+
(
|
|
114
|
+
(isNotMobile.value && storageConfigStore.globalConfig.fileClickMode === 'click')
|
|
115
|
+
||
|
|
116
|
+
(isMobile.value && storageConfigStore.globalConfig.mobileFileClickMode === 'click')
|
|
117
|
+
)
|
|
118
|
+
) {
|
|
119
|
+
openRow(row);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 加载骨架屏时,点击无效.
|
|
124
|
+
if (skeletonLoading.value) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
let isClickSelf = selectRows.value.length === 1 && selectRow.value?.name === row.name;
|
|
129
|
+
|
|
130
|
+
// 如果按住了 shift 选中
|
|
131
|
+
if (shiftState.value) {
|
|
132
|
+
|
|
133
|
+
// 上一个选择的 index
|
|
134
|
+
let prevSelectIndex = fileDataStore.fileList.findIndex(value => value.name === selectRow.value.name);
|
|
135
|
+
|
|
136
|
+
// 如果选中行之前也按 shift 选中过行,表示要进行多选
|
|
137
|
+
if (prevSelectIndex !== null) {
|
|
138
|
+
let currentShiftIndex = fileDataStore.fileList.findIndex(value => value.name === row.name);
|
|
139
|
+
|
|
140
|
+
let start = Math.min(currentShiftIndex, prevSelectIndex);
|
|
141
|
+
let end = Math.max(currentShiftIndex, prevSelectIndex);
|
|
142
|
+
|
|
143
|
+
for (let i = start + 1; i < end; i++) {
|
|
144
|
+
let item = fileDataStore.fileList[i];
|
|
145
|
+
toggleRowSelection(item, true);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// 如果不是以下情况,则取消所有选择:
|
|
150
|
+
// 1. 多选状态:按住 command (Mac) 或 Ctrl (Windows)
|
|
151
|
+
// 2. 选中当前文件: 如目前只选中了一个文件,且就是当前文件, 则不需要取消所有选择, 取消后, 无法 toggle 当前行.
|
|
152
|
+
// 3. 点击的区域不是 selection, 如果点击的是 selection, 则可能为误触, 实际想点击的是 checkbox
|
|
153
|
+
else if (!isMultiSelectState.value && !isClickSelf && !isClickSelection) {
|
|
154
|
+
clearSelection();
|
|
155
|
+
}
|
|
156
|
+
toggleRowSelection(row);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// 文件双击事件
|
|
160
|
+
const tableDbClickRow = (row) => {
|
|
161
|
+
// 加载骨架屏时,点击无效.
|
|
162
|
+
if (skeletonLoading.value) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
openRow(row);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// 进入悬浮事件
|
|
169
|
+
const tableHoverRow = (row, column, cell, event) => {
|
|
170
|
+
// 如果当前是点击状态,且开始拖拽选中索引不为 -1, 表示要进行拖拽了.
|
|
171
|
+
if (event.buttons === 1 && startDragClickIndex.value !== -1) {
|
|
172
|
+
// 将开始拖拽的行选中
|
|
173
|
+
if (endDragClickIndex.value === -1) {
|
|
174
|
+
clearSelection();
|
|
175
|
+
let item = fileDataStore.fileList[startDragClickIndex.value];
|
|
176
|
+
toggleRowSelection(item, true);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
let newEndDragClickIndex = row.index;
|
|
181
|
+
|
|
182
|
+
let oldEndDragClickIndex = endDragClickIndex.value >= 0 ? endDragClickIndex.value : newEndDragClickIndex - 1;
|
|
183
|
+
|
|
184
|
+
// 可能是倒序拖拽的,所以要区分 start 和 end
|
|
185
|
+
let start = Math.min(oldEndDragClickIndex, newEndDragClickIndex);
|
|
186
|
+
let end = Math.max(oldEndDragClickIndex, newEndDragClickIndex);
|
|
187
|
+
for (let i = start; i <= end; i++) {
|
|
188
|
+
let item = fileDataStore.fileList[i];
|
|
189
|
+
toggleRowSelection(item, true);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
endDragClickIndex.value = newEndDragClickIndex;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// 离开悬浮事件
|
|
197
|
+
const tableLeaveRow = (row, column, cell, event) => {
|
|
198
|
+
if (event.buttons === 1 && startDragClickIndex.value === -1) {
|
|
199
|
+
startDragClickIndex.value = row.index;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return {
|
|
204
|
+
tableClickRow, tableDbClickRow,
|
|
205
|
+
tableHoverRow, tableLeaveRow
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export default function useTableOperator() {
|
|
210
|
+
return buildTableOperator(openRowDefault);
|
|
211
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import useDialog from "~/components/common/dialog/useDialog";
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
const { visible, openDialog} = useDialog();
|
|
4
|
+
|
|
5
|
+
const name = ref("");
|
|
6
|
+
const url = ref("");
|
|
7
|
+
|
|
8
|
+
export default function useTextViewerDialog() {
|
|
9
|
+
|
|
10
|
+
const openDialogWithData = (_name, _url) => {
|
|
11
|
+
name.value = _name;
|
|
12
|
+
url.value = _url;
|
|
13
|
+
openDialog();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
openDialogWithData,
|
|
18
|
+
visible,
|
|
19
|
+
name,
|
|
20
|
+
url
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
import useDialog from "~/components/common/dialog/useDialog";
|
|
3
|
+
|
|
4
|
+
const { visible, openDialog } = useDialog();
|
|
5
|
+
|
|
6
|
+
const name = ref("");
|
|
7
|
+
const url = ref("");
|
|
8
|
+
|
|
9
|
+
export default function useThree3dPreviewDialog() {
|
|
10
|
+
|
|
11
|
+
const openDialogWithData = (_name, _url) => {
|
|
12
|
+
name.value = _name;
|
|
13
|
+
url.value = _url;
|
|
14
|
+
openDialog();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
openDialogWithData,
|
|
19
|
+
visible,
|
|
20
|
+
name,
|
|
21
|
+
url
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
import useDialog from "~/components/common/dialog/useDialog";
|
|
3
|
+
|
|
4
|
+
const { visible, openDialog } = useDialog();
|
|
5
|
+
|
|
6
|
+
const name = ref("");
|
|
7
|
+
|
|
8
|
+
export default function useVideoPlayerDialog() {
|
|
9
|
+
const openDialogWithData = (_name) => {
|
|
10
|
+
name.value = _name;
|
|
11
|
+
openDialog();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
openDialogWithData,
|
|
16
|
+
visible,
|
|
17
|
+
name
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { concatPathAndEncodeAll, buildShareBasePath } from "~/utils";
|
|
2
|
+
import useHeaderStorageList from "./useHeaderStorageList";
|
|
3
|
+
|
|
4
|
+
import useStorageConfigStore from "~/stores/storage-config";
|
|
5
|
+
let storageConfigStore = useStorageConfigStore();
|
|
6
|
+
|
|
7
|
+
import useRouterData from "~/composables/useRouterData";
|
|
8
|
+
let { fullpath, storageKey, routeRef } = useRouterData();
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
// 面包屑数据
|
|
13
|
+
let breadcrumbData = ref([]);
|
|
14
|
+
let initialized = false;
|
|
15
|
+
export default function useBreadcrumb() {
|
|
16
|
+
|
|
17
|
+
let rootShowStorage = storageConfigStore.globalConfig.rootShowStorage;
|
|
18
|
+
|
|
19
|
+
// 构建面包屑
|
|
20
|
+
const buildBreadcrumbData = () => {
|
|
21
|
+
// 1) 分享页面包屑(/share/:shareKey)
|
|
22
|
+
const shareKey = routeRef.value?.params?.shareKey;
|
|
23
|
+
if (shareKey) {
|
|
24
|
+
const pwd = routeRef.value?.query?.pwd;
|
|
25
|
+
const curPath = routeRef.value?.query?.path || '/';
|
|
26
|
+
const base = buildShareBasePath(shareKey);
|
|
27
|
+
|
|
28
|
+
const items = [];
|
|
29
|
+
// 根:分享
|
|
30
|
+
items.push({
|
|
31
|
+
name: '分享',
|
|
32
|
+
href: `${base}?${pwd ? `pwd=${encodeURIComponent(pwd)}&` : ''}path=/`,
|
|
33
|
+
disable: false
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
if (curPath !== '/') {
|
|
37
|
+
let acc = '';
|
|
38
|
+
curPath.split('/').filter(Boolean).forEach((part, index, arr) => {
|
|
39
|
+
acc += '/' + part;
|
|
40
|
+
items.push({
|
|
41
|
+
name: part,
|
|
42
|
+
href: `${base}?${pwd ? `pwd=${encodeURIComponent(pwd)}&` : ''}path=${encodeURIComponent(acc)}`,
|
|
43
|
+
disable: index === arr.length - 1
|
|
44
|
+
})
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
breadcrumbData.value = items;
|
|
49
|
+
} else {
|
|
50
|
+
// 2) 普通文件页面包屑
|
|
51
|
+
if (!rootShowStorage && !storageKey.value) {
|
|
52
|
+
breadcrumbData.value = [];
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
breadcrumbData.value = [
|
|
56
|
+
{
|
|
57
|
+
name: storageConfigStore.globalConfig.siteHomeName || '首页',
|
|
58
|
+
href: rootPath.value,
|
|
59
|
+
disable: false
|
|
60
|
+
}
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
// 如果为包含根目录模式,则面包屑显示驱动器
|
|
64
|
+
if (rootShowStorage) {
|
|
65
|
+
let { findStorageByKey } = useHeaderStorageList();
|
|
66
|
+
let storageByKey = findStorageByKey(storageKey.value);
|
|
67
|
+
if (storageByKey) {
|
|
68
|
+
breadcrumbData.value.push({
|
|
69
|
+
name: storageByKey.name,
|
|
70
|
+
href: concatPathAndEncodeAll('/', storageByKey.key)
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (fullpath.value) {
|
|
76
|
+
fullpath.value.forEach((item, index, arr) => {
|
|
77
|
+
if (item) {
|
|
78
|
+
let breadcrumbItem = {
|
|
79
|
+
name: item,
|
|
80
|
+
href: concatPathAndEncodeAll('/', storageKey.value, arr.slice(0, index + 1).join('/')),
|
|
81
|
+
disable: index === arr.length - 1
|
|
82
|
+
}
|
|
83
|
+
breadcrumbData.value.push(breadcrumbItem);
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 根目录路径
|
|
92
|
+
*/
|
|
93
|
+
let rootPath = computed(() => '/' + (rootShowStorage ? '' : storageKey.value));
|
|
94
|
+
|
|
95
|
+
if (!initialized) {
|
|
96
|
+
// 普通文件页相关
|
|
97
|
+
watch(() => fullpath.value, () => buildBreadcrumbData())
|
|
98
|
+
watch(() => storageKey.value, () => buildBreadcrumbData())
|
|
99
|
+
|
|
100
|
+
// 分享页相关
|
|
101
|
+
watch(() => [routeRef.value?.params?.shareKey, routeRef.value?.query?.path, routeRef.value?.query?.pwd], () => buildBreadcrumbData(), { deep: true })
|
|
102
|
+
}
|
|
103
|
+
initialized = true;
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
rootPath,
|
|
107
|
+
breadcrumbData,
|
|
108
|
+
buildBreadcrumbData
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
}
|