|
|
@@ -1,6 +1,6 @@
|
|
|
<template>
|
|
|
<!-- 右键列表 -->
|
|
|
- <transition name="el-fade-in-linear">
|
|
|
+ <transition name="fade">
|
|
|
<!-- 在某个文件上右键 -->
|
|
|
<ul
|
|
|
class="right-menu-list"
|
|
|
@@ -9,83 +9,79 @@
|
|
|
v-if="selectedFile !== undefined"
|
|
|
:style="`top: ${rightMenu.top};right: ${rightMenu.right};bottom: ${rightMenu.bottom};left: ${rightMenu.left};`"
|
|
|
>
|
|
|
- <li
|
|
|
- class="right-menu-item"
|
|
|
- @click="fileHelper.handleFileNameClick(selectedFile, 0, [selectedFile])"
|
|
|
- v-if="seeBtnShow"
|
|
|
- >
|
|
|
- <i class="el-icon-view"></i> 查看
|
|
|
+ <li class="right-menu-item" @click="$file.handleFileNameClick(selectedFile, 0, [selectedFile])" v-if="seeBtnShow">
|
|
|
+ <eye-outlined /> 查看
|
|
|
</li>
|
|
|
<li class="right-menu-item" @click="handleDeleteFileBtnClick(selectedFile)" v-if="deleteBtnShow">
|
|
|
- <i class="el-icon-delete"></i> 删除
|
|
|
+ <delete-outlined /> 删除
|
|
|
</li>
|
|
|
<li class="right-menu-item" @click="handleRestoreFileBtnClick(selectedFile)" v-if="restoreBtnShow">
|
|
|
- <i class="el-icon-refresh-left"></i> 还原
|
|
|
+ <rollback-outlined /> 还原
|
|
|
</li>
|
|
|
<li class="right-menu-item" @click="handleCopyFileBtnClick(selectedFile)" v-if="copyBtnShow">
|
|
|
- <i class="el-icon-copy-document"></i> 复制到
|
|
|
+ <copy-outlined /> 复制到
|
|
|
</li>
|
|
|
<li class="right-menu-item" @click="handleMoveFileBtnClick(selectedFile)" v-if="moveBtnShow">
|
|
|
- <i class="el-icon-s-promotion"></i> 移动
|
|
|
+ <export-outlined /> 移动
|
|
|
</li>
|
|
|
- <li class="right-menu-item" @click="handleAddMyFileList(selectedFile)" v-if="addMyFileListBtnShow">
|
|
|
- <i class="el-icon-edit-outline"></i> 添加至我的云盘
|
|
|
- </li>
|
|
|
-
|
|
|
- <li class="right-menu-item" @click="handleEnterpriseDisk(selectedFile)" v-if="addEnterpriseDiskBtnShow">
|
|
|
- <i class="el-icon-edit-outline"></i> 添加至企业云盘
|
|
|
- </li>
|
|
|
-
|
|
|
<li class="right-menu-item" @click="handleRenameFileBtnClick(selectedFile)" v-if="renameBtnShow">
|
|
|
- <i class="el-icon-edit-outline"></i> 重命名
|
|
|
+ <edit-outlined /> 重命名
|
|
|
</li>
|
|
|
<li class="right-menu-item" @click="handleShareFileBtnClick(selectedFile)" v-if="shareBtnShow">
|
|
|
- <i class="el-icon-share"></i> 分享
|
|
|
+ <share-alt-outlined /> 分享
|
|
|
</li>
|
|
|
- <li class="right-menu-item" @click="visible = false" v-if="downloadBtnShow">
|
|
|
+ <!-- <li class="right-menu-item" @click="visible = false" v-if="downloadBtnShow">
|
|
|
<a
|
|
|
- @click="geta1(fileHelper.getDownloadFilePath(selectedFile))"
|
|
|
- id="aaaa"
|
|
|
target="_blank"
|
|
|
style="display: block; color: inherit"
|
|
|
- :href="fileHelper.getDownloadFilePath(selectedFile)"
|
|
|
+ :href="$file.getDownloadFilePath(selectedFile)"
|
|
|
:download="selectedFile.fileName + '.' + selectedFile.extendName"
|
|
|
>
|
|
|
- <i class="el-icon-download"></i> 下载
|
|
|
+ <download-outlined /> 下载
|
|
|
</a>
|
|
|
- </li>
|
|
|
+ </li> -->
|
|
|
<!-- 0-解压到当前文件夹, 1-自动创建该文件名目录,并解压到目录里, 3-手动选择解压目录 -->
|
|
|
<li class="right-menu-item unzip-menu-item" v-if="unzipBtnShow">
|
|
|
- <i class="el-icon-files"></i> 解压缩
|
|
|
- <i class="el-icon-arrow-right"></i>
|
|
|
+ <folder-outlined /> 解压缩
|
|
|
+ <right-outlined />
|
|
|
<ul
|
|
|
class="unzip-list"
|
|
|
:style="`top: ${unzipMenu.top};bottom: ${unzipMenu.bottom};left: ${unzipMenu.left};right: ${unzipMenu.right};`"
|
|
|
>
|
|
|
<li class="unzip-item" @click="handleUnzipFileBtnClick(selectedFile, 0)">
|
|
|
- <i class="el-icon-files"></i> 解压到当前文件夹
|
|
|
+ <folder-outlined /> 解压到当前文件夹
|
|
|
</li>
|
|
|
<li
|
|
|
class="unzip-item"
|
|
|
@click="handleUnzipFileBtnClick(selectedFile, 1)"
|
|
|
:title="`解压到"${selectedFile.fileName}"`"
|
|
|
>
|
|
|
- <i class="el-icon-files"></i> 解压到"{{ selectedFile.fileName }}"
|
|
|
+ <folder-outlined /> 解压到"{{ selectedFile.fileName }}"
|
|
|
</li>
|
|
|
<li class="unzip-item" @click="handleUnzipFileBtnClick(selectedFile, 2)">
|
|
|
- <i class="el-icon-files"></i> 解压到目标文件夹
|
|
|
+ <folder-outlined /> 解压到目标文件夹
|
|
|
</li>
|
|
|
</ul>
|
|
|
</li>
|
|
|
- <li
|
|
|
+ <!-- <li
|
|
|
class="right-menu-item"
|
|
|
- @click="fileHelper.copyShareLink(selectedFile.shareBatchNum, selectedFile.extractionCode)"
|
|
|
- v-if="copyLinkBtnShow"
|
|
|
+ @click="handleClickFolderEdit"
|
|
|
+ v-if="folderEditBtnShow"
|
|
|
>
|
|
|
- <i class="el-icon-edit"></i> 复制链接
|
|
|
+ <edit-outlined /> 编辑文件夹
|
|
|
+ </li> -->
|
|
|
+ <li class="right-menu-item" @click="handleClickFileEdit(selectedFile)" v-if="onlineEditBtnShow">
|
|
|
+ <edit-outlined /> 在线编辑
|
|
|
</li>
|
|
|
+ <!-- <li
|
|
|
+ class="right-menu-item"
|
|
|
+ @click="$file.copyShareLink(selectedFile.shareBatchNum, selectedFile.extractionCode)"
|
|
|
+ v-if="copyLinkBtnShow"
|
|
|
+ >
|
|
|
+ <edit-outlined /> 复制链接
|
|
|
+ </li> -->
|
|
|
<li class="right-menu-item" @click="handleShowDetailInfo(selectedFile)" v-if="detailInfoBtnShow">
|
|
|
- <i class="el-icon-document"></i> 文件详情
|
|
|
+ <file-outlined /> 文件详情
|
|
|
</li>
|
|
|
</ul>
|
|
|
<!-- 在空白处右键,右键列表展示新建文件夹、新建文件等操作按钮 -->
|
|
|
@@ -96,58 +92,68 @@
|
|
|
v-else
|
|
|
:style="`top: ${rightMenu.top};right: ${rightMenu.right};bottom: ${rightMenu.bottom};left: ${rightMenu.left};`"
|
|
|
>
|
|
|
- <li class="right-menu-item" @click="callback('confirm')"><i class="el-icon-refresh"></i> 刷新</li>
|
|
|
+ <li class="right-menu-item" @click="callback('confirm')"><reload-outlined /> 刷新</li>
|
|
|
<template v-if="fileType === 0">
|
|
|
<a-divider />
|
|
|
- <li class="right-menu-item" @click="handleClickAddFolderBtn"><i class="el-icon-folder-add"></i> 新建文件夹</li>
|
|
|
- <!-- 图片路径需要修改 -->
|
|
|
+ <li class="right-menu-item" @click="handleClickAddFolderBtn"><folder-add-outlined /> 新建文件夹</li>
|
|
|
<li class="right-menu-item" @click="handleCreateFile('docx')"><img :src="wordImg" />新建 Word 文档</li>
|
|
|
<li class="right-menu-item" @click="handleCreateFile('xlsx')"><img :src="excelImg" />新建 Excel 工作表</li>
|
|
|
<li class="right-menu-item" @click="handleCreateFile('pptx')"><img :src="pptImg" />新建 PPT 演示文稿</li>
|
|
|
<a-divider />
|
|
|
- <li class="right-menu-item" @click="handleUploadFileBtnClick(1)"><i class="el-icon-upload2"></i> 上传文件</li>
|
|
|
- <li class="right-menu-item" @click="handleUploadFileBtnClick(2)">
|
|
|
- <i class="el-icon-folder-opened"></i> 上传文件夹
|
|
|
- </li>
|
|
|
- <li class="right-menu-item" @click="handleUploadFileBtnClick(3)"><i class="el-icon-thumb"></i> 拖拽上传</li>
|
|
|
+ <li class="right-menu-item" @click="handleUploadFileBtnClick(1)"><upload-outlined /> 上传文件</li>
|
|
|
+ <li class="right-menu-item" @click="handleUploadFileBtnClick(2)"><folder-open-outlined /> 上传文件夹</li>
|
|
|
+ <li class="right-menu-item" @click="handleUploadFileBtnClick(3)"><drag-outlined /> 拖拽上传</li>
|
|
|
</template>
|
|
|
</ul>
|
|
|
</transition>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
- import { ref, computed, watch, onMounted, getCurrentInstance } from 'vue'
|
|
|
- import { useRouter, useRoute } from 'vue-router'
|
|
|
- import { message as antMessage } from 'ant-design-vue' // 重命名以避免与 window.message 冲突
|
|
|
+ import { ref, computed, watch, getCurrentInstance } from 'vue'
|
|
|
+ import { useRouter } from 'vue-router'
|
|
|
+ import { useMyResourceStore } from '@/store/myResource.js'
|
|
|
+ import {
|
|
|
+ EyeOutlined,
|
|
|
+ DeleteOutlined,
|
|
|
+ RollbackOutlined,
|
|
|
+ CopyOutlined,
|
|
|
+ ExportOutlined,
|
|
|
+ EditOutlined,
|
|
|
+ ShareAltOutlined,
|
|
|
+ DownloadOutlined,
|
|
|
+ FolderOutlined,
|
|
|
+ RightOutlined,
|
|
|
+ FileOutlined,
|
|
|
+ ReloadOutlined,
|
|
|
+ FolderAddOutlined,
|
|
|
+ UploadOutlined,
|
|
|
+ FolderOpenOutlined,
|
|
|
+ DragOutlined
|
|
|
+ } from '@ant-design/icons-vue'
|
|
|
import { officeFileType, fileSuffixCodeModeMap, markdownFileType } from '@/libs/map.js'
|
|
|
- import { addMyFileListApi, addEnterpriseDiskApi } from '@/api/myResource/file'
|
|
|
- import axios from 'axios' // 如果需要
|
|
|
- import fileOperationPlugins from '@/libs/fileOperationPlugins.js'
|
|
|
- import globalFunction from '@/libs/globalFunction/index.js'
|
|
|
- import appConfig from '@/config/index.js'
|
|
|
+ // 导入图片资源
|
|
|
+ import dirImgSrc from '@/assets/images/myResource/file/dir.png'
|
|
|
+ import wordImgSrc from '@/assets/images/myResource/file/file_word.svg'
|
|
|
+ import excelImgSrc from '@/assets/images/myResource/file/file_excel.svg'
|
|
|
+ import pptImgSrc from '@/assets/images/myResource/file/file_ppt.svg'
|
|
|
|
|
|
- // 从插件或模块中获取方法
|
|
|
- const { openDialog } = fileOperationPlugins
|
|
|
- const { openBox } = fileOperationPlugins
|
|
|
- const fileHelper = globalFunction.file // $file
|
|
|
-
|
|
|
- // $common 的处理: common.js 未找到,暂时保留 proxy.$common
|
|
|
- // 如果 $common 是必须的,你需要找到它的定义并导入
|
|
|
- const { proxy } = getCurrentInstance() // 保留 proxy 以便访问 $common (如果确实需要且未找到其来源)
|
|
|
+ const router = useRouter()
|
|
|
+ const myResourceStore = useMyResourceStore()
|
|
|
|
|
|
+ // 定义props
|
|
|
const props = defineProps({
|
|
|
selectedFile: Object,
|
|
|
domEvent: Object,
|
|
|
serviceEl: Object,
|
|
|
- callType: String,
|
|
|
callback: Function
|
|
|
})
|
|
|
|
|
|
- const router = useRouter()
|
|
|
- const route = useRoute()
|
|
|
-
|
|
|
- const visible = ref(false)
|
|
|
-
|
|
|
+ // 响应式数据
|
|
|
+ const visible = ref(false) // 右键菜单是否显示
|
|
|
+ const sortedFileList = ref([]) // 排序后的表格数据
|
|
|
+ const { proxy } = getCurrentInstance()
|
|
|
+ console.log('proxy file', proxy.$file)
|
|
|
+ // 右键菜单位置
|
|
|
const rightMenu = ref({
|
|
|
top: 0,
|
|
|
left: 0,
|
|
|
@@ -155,6 +161,7 @@
|
|
|
right: 'auto'
|
|
|
})
|
|
|
|
|
|
+ // 右键解压缩菜单位置
|
|
|
const unzipMenu = ref({
|
|
|
top: 0,
|
|
|
bottom: 'auto',
|
|
|
@@ -162,82 +169,84 @@
|
|
|
right: 'auto'
|
|
|
})
|
|
|
|
|
|
- // 图片资源: 请将路径修改为实际项目中的正确路径
|
|
|
- // 例如: import wordIcon from '@/assets/images/file_word.svg'; const wordImg = ref(wordIcon);
|
|
|
- // 或者如果图片在 public 目录: const wordImg = ref('/images/file_word.svg');
|
|
|
- const dirImg = ref('/img/file/dir.png') // 示例: 假设在 public/img/file/dir.png
|
|
|
- const wordImg = ref('/img/file/file_word.svg') // 示例: 假设在 public/img/file/file_word.svg
|
|
|
- const excelImg = ref('/img/file/file_excel.svg') // 示例: 假设在 public/img/file/file_excel.svg
|
|
|
- const pptImg = ref('/img/file/file_ppt.svg') // 示例: 假设在 public/img/file/file_ppt.svg
|
|
|
-
|
|
|
- const newname = ref('')
|
|
|
+ // 图片资源 - 使用导入的图片资源
|
|
|
+ const dirImg = ref(dirImgSrc)
|
|
|
+ const wordImg = ref(wordImgSrc)
|
|
|
+ const excelImg = ref(excelImgSrc)
|
|
|
+ const pptImg = ref(pptImgSrc)
|
|
|
|
|
|
// 计算属性
|
|
|
- const routeName = computed(() => route.name)
|
|
|
- const fileType = computed(() => (route.query.fileType ? Number(route.query.fileType) : 0))
|
|
|
- const filePath = computed(() => route.query.filePath)
|
|
|
+ // 路由名称
|
|
|
+ const routeName = computed(() => {
|
|
|
+ return router.currentRoute.value.name
|
|
|
+ })
|
|
|
|
|
|
+ // 左侧菜单选中的文件类型
|
|
|
+ const fileType = computed(() => {
|
|
|
+ return router.currentRoute.value.query.fileType ? Number(router.currentRoute.value.query.fileType) : 0
|
|
|
+ })
|
|
|
+
|
|
|
+ // 当前路径
|
|
|
+ const filePath = computed(() => {
|
|
|
+ return router.currentRoute.value.query.filePath
|
|
|
+ })
|
|
|
+
|
|
|
+ // 查看按钮是否显示
|
|
|
const seeBtnShow = computed(() => {
|
|
|
- const PIC = ['png', 'jpg', 'jpeg', 'gif', 'svg', 'webp']
|
|
|
- return props.selectedFile && fileType.value !== 6 && PIC.includes(props.selectedFile.extendName?.toLowerCase())
|
|
|
+ return fileType.value !== 6
|
|
|
})
|
|
|
|
|
|
+ // 删除按钮是否显示
|
|
|
const deleteBtnShow = computed(() => {
|
|
|
return fileType.value !== 8 && !['Share'].includes(routeName.value)
|
|
|
})
|
|
|
|
|
|
+ // 还原按钮是否显示
|
|
|
const restoreBtnShow = computed(() => {
|
|
|
return fileType.value === 6 && !['Share'].includes(routeName.value)
|
|
|
})
|
|
|
|
|
|
+ // 复制按钮是否显示
|
|
|
const copyBtnShow = computed(() => {
|
|
|
- return ![6, 8, 15].includes(fileType.value) && !['Share'].includes(routeName.value)
|
|
|
+ return ![6, 8].includes(fileType.value) && !['Share'].includes(routeName.value)
|
|
|
})
|
|
|
|
|
|
+ // 移动按钮是否显示
|
|
|
const moveBtnShow = computed(() => {
|
|
|
- return ![6, 8, 15].includes(fileType.value) && !['Share'].includes(routeName.value)
|
|
|
- })
|
|
|
-
|
|
|
- const addMyFileListBtnShow = computed(() => {
|
|
|
- return fileType.value == 15 && !['Share'].includes(routeName.value)
|
|
|
- })
|
|
|
-
|
|
|
- const addEnterpriseDiskBtnShow = computed(() => {
|
|
|
- return ![6, 8, 15].includes(fileType.value) && !['Share'].includes(routeName.value)
|
|
|
+ return ![6, 8].includes(fileType.value) && !['Share'].includes(routeName.value)
|
|
|
})
|
|
|
|
|
|
+ // 重命名按钮是否显示
|
|
|
const renameBtnShow = computed(() => {
|
|
|
return ![6, 8].includes(fileType.value) && !['Share'].includes(routeName.value)
|
|
|
})
|
|
|
|
|
|
+ // 分享按钮是否显示
|
|
|
const shareBtnShow = computed(() => {
|
|
|
- return ![6, 8, 15].includes(fileType.value) && !['Share'].includes(routeName.value)
|
|
|
+ return ![6, 8].includes(fileType.value) && !['Share'].includes(routeName.value)
|
|
|
})
|
|
|
|
|
|
+ // 下载按钮是否显示
|
|
|
const downloadBtnShow = computed(() => {
|
|
|
return ![6, 8].includes(fileType.value)
|
|
|
})
|
|
|
|
|
|
+ // 解压缩按钮是否显示
|
|
|
const unzipBtnShow = computed(() => {
|
|
|
return (
|
|
|
- props.selectedFile &&
|
|
|
![6, 8].includes(fileType.value) &&
|
|
|
!['Share'].includes(routeName.value) &&
|
|
|
['zip', 'rar', '7z', 'tar', 'gz'].includes(props.selectedFile.extendName)
|
|
|
)
|
|
|
})
|
|
|
|
|
|
+ // 编辑文件夹按钮是否显示
|
|
|
const folderEditBtnShow = computed(() => {
|
|
|
- return (
|
|
|
- props.selectedFile &&
|
|
|
- ![6, 8].includes(fileType.value) &&
|
|
|
- props.selectedFile.isDir === 1 &&
|
|
|
- !['Share'].includes(routeName.value)
|
|
|
- )
|
|
|
+ return ![6, 8].includes(fileType.value) && props.selectedFile.isDir === 1 && !['Share'].includes(routeName.value)
|
|
|
})
|
|
|
|
|
|
+ // 在线编辑按钮是否显示
|
|
|
const onlineEditBtnShow = computed(() => {
|
|
|
- if (!props.selectedFile) return false
|
|
|
return (
|
|
|
![6, 8].includes(fileType.value) &&
|
|
|
(officeFileType.includes(props.selectedFile.extendName) ||
|
|
|
@@ -247,14 +256,17 @@
|
|
|
)
|
|
|
})
|
|
|
|
|
|
+ // 复制链接按钮是否显示
|
|
|
const copyLinkBtnShow = computed(() => {
|
|
|
return fileType.value === 8
|
|
|
})
|
|
|
|
|
|
+ // 文件详情按钮是否显示
|
|
|
const detailInfoBtnShow = computed(() => {
|
|
|
return true
|
|
|
})
|
|
|
|
|
|
+ // 上传文件组件参数
|
|
|
const uploadFileParams = computed(() => {
|
|
|
return {
|
|
|
filePath: filePath.value,
|
|
|
@@ -262,7 +274,7 @@
|
|
|
}
|
|
|
})
|
|
|
|
|
|
- // Watcher
|
|
|
+ // 监听右键列表状态
|
|
|
watch(visible, (newValue) => {
|
|
|
if (newValue === true) {
|
|
|
document.body.addEventListener('click', closeRightMenu)
|
|
|
@@ -272,102 +284,17 @@
|
|
|
}
|
|
|
})
|
|
|
|
|
|
- onMounted(() => {
|
|
|
- // onMounted logic if any
|
|
|
- })
|
|
|
-
|
|
|
- // Methods
|
|
|
- const geta1 = (src) => {
|
|
|
- console.log('src', src)
|
|
|
- // $common.getCookies 依赖 proxy.$common,如果 $common 无法解析,这里会报错
|
|
|
- const cookies = proxy.$common?.getCookies(appConfig.TOKEN_NAME)
|
|
|
- const aElement = document.getElementById('aaaa')
|
|
|
- if (!aElement) return
|
|
|
-
|
|
|
- const downloadNameParts = aElement.download.split('.')
|
|
|
- const name1 = downloadNameParts[0]
|
|
|
- const name2 = downloadNameParts[1]
|
|
|
-
|
|
|
- if (name2) {
|
|
|
- newname.value = name1 + '.' + name2
|
|
|
- } else {
|
|
|
- newname.value = name1 + '.' + 'zip'
|
|
|
- }
|
|
|
-
|
|
|
- console.log('appConfig.API_URL', appConfig.API_URL) // 使用导入的 appConfig
|
|
|
- const newname1 = newname.value
|
|
|
- // 确保 aElement.href 是完整的 URL 或者正确拼接
|
|
|
- const apiUrlPart = aElement.href.includes('/api') ? aElement.href.split('/api')[1] : aElement.href
|
|
|
- const url = `${
|
|
|
- (appConfig.API_URL.startsWith('http') ? '' : 'http://' + window.location.host) +
|
|
|
- appConfig.API_URL + // 使用导入的 appConfig
|
|
|
- apiUrlPart +
|
|
|
- '&' +
|
|
|
- cookies
|
|
|
- }`
|
|
|
-
|
|
|
- let isios = navigator.userAgent.indexOf('iPhone') > -1
|
|
|
- let isAndroid = navigator.userAgent.indexOf('Android') > -1
|
|
|
- console.log('url', url)
|
|
|
- console.log('cookies', cookies)
|
|
|
- console.log('newname1', newname1)
|
|
|
- if (isios) {
|
|
|
- window.webkit.messageHandlers.Download.postMessage({
|
|
|
- params: {
|
|
|
- url,
|
|
|
- cookies,
|
|
|
- newname1
|
|
|
- }
|
|
|
- })
|
|
|
- } else if (isAndroid) {
|
|
|
- window.Download.downList(url, cookies, newname1)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const downloadPost = (src) => {
|
|
|
- console.log(window.location.origin)
|
|
|
- console.log(33333, src)
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- axios({
|
|
|
- url: window.location.origin + src, // 确保 src 是正确的相对路径
|
|
|
- method: 'get',
|
|
|
- responseType: 'blob'
|
|
|
- })
|
|
|
- .then((res) => {
|
|
|
- fileDownload(res, props.selectedFile?.fileName || 'download')
|
|
|
- console.log(res)
|
|
|
- resolve(res)
|
|
|
- })
|
|
|
- .catch((err) => {
|
|
|
- reject(err)
|
|
|
- })
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- const fileDownload = (res, filename) => {
|
|
|
- let blob = new Blob([res.data])
|
|
|
- if ('msSaveOrOpenBlob' in navigator) {
|
|
|
- window.navigator.msSaveOrOpenBlob(blob, filename)
|
|
|
- } else {
|
|
|
- let objectUrl = (window.URL || window.webkitURL).createObjectURL(blob)
|
|
|
- let downFile = document.createElement('a')
|
|
|
- downFile.style.display = 'none'
|
|
|
- downFile.href = objectUrl
|
|
|
- downFile.download = filename
|
|
|
- document.body.appendChild(downFile)
|
|
|
- downFile.click()
|
|
|
- document.body.removeChild(downFile)
|
|
|
- window.URL.revokeObjectURL(objectUrl)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
+ // 方法
|
|
|
+ /**
|
|
|
+ * 打开右键菜单
|
|
|
+ */
|
|
|
const handleOpenContextMenu = () => {
|
|
|
- console.log('handleOpenContextMenu', props)
|
|
|
- if (!props.domEvent) return
|
|
|
+ // 纵坐标设置
|
|
|
if (
|
|
|
document.body.clientHeight - props.domEvent.clientY <
|
|
|
document.querySelectorAll('#rightMenuList > .right-menu-item').length * 36 + 10
|
|
|
) {
|
|
|
+ // 如果到底部的距离小于元素总高度
|
|
|
rightMenu.value.top = 'auto'
|
|
|
rightMenu.value.bottom = `${document.body.clientHeight - props.domEvent.clientY}px`
|
|
|
unzipMenu.value.top = 'auto'
|
|
|
@@ -378,7 +305,9 @@
|
|
|
unzipMenu.value.top = '0px'
|
|
|
unzipMenu.value.bottom = 'auto'
|
|
|
}
|
|
|
+ // 横坐标设置
|
|
|
if (document.body.clientWidth - props.domEvent.clientX < 138) {
|
|
|
+ // 如果到右边的距离小于元素总宽度
|
|
|
rightMenu.value.left = 'auto'
|
|
|
rightMenu.value.right = `${document.body.clientWidth - props.domEvent.clientX}px`
|
|
|
unzipMenu.value.left = '-200px'
|
|
|
@@ -392,90 +321,139 @@
|
|
|
visible.value = true
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 关闭右键列表
|
|
|
+ */
|
|
|
const closeRightMenu = (event) => {
|
|
|
- if (!event.target.className.includes('operate-more-') && !event.target.className.includes('unzip-menu-item')) {
|
|
|
+ // 使用 classList.contains 方法替代 className.includes
|
|
|
+ const target = event.target
|
|
|
+ const hasOperateMoreClass =
|
|
|
+ target.classList.contains('operate-more-') ||
|
|
|
+ (typeof target.className === 'string' && target.className.includes('operate-more-'))
|
|
|
+ const hasUnzipMenuItemClass =
|
|
|
+ target.classList.contains('unzip-menu-item') ||
|
|
|
+ (typeof target.className === 'string' && target.className.includes('unzip-menu-item'))
|
|
|
+
|
|
|
+ if (!hasOperateMoreClass && !hasUnzipMenuItemClass) {
|
|
|
visible.value = false
|
|
|
if (props.selectedFile !== undefined) {
|
|
|
- props.callback?.('cancel')
|
|
|
+ // 不是在空白处右键时
|
|
|
+ props.callback('cancel')
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 复制按钮点击事件
|
|
|
+ * @description 向父组件传递当前操作的文件信息,并打开"复制文件对话框"
|
|
|
+ * @param {object} fileInfo 文件信息
|
|
|
+ */
|
|
|
const handleCopyFileBtnClick = (fileInfo) => {
|
|
|
visible.value = false
|
|
|
- openDialog
|
|
|
+ proxy.$openDialog
|
|
|
.copyFile({
|
|
|
fileInfo
|
|
|
})
|
|
|
.then((res) => {
|
|
|
- props.callback?.(res)
|
|
|
+ props.callback(res)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 移动按钮点击事件
|
|
|
+ * @description 向父组件传递当前操作的文件信息,并打开"移动文件对话框"
|
|
|
+ * @param {object} fileInfo 文件信息
|
|
|
+ */
|
|
|
const handleMoveFileBtnClick = (fileInfo) => {
|
|
|
visible.value = false
|
|
|
- openDialog
|
|
|
+ proxy.$openDialog
|
|
|
.moveFile({
|
|
|
isBatchMove: false,
|
|
|
fileInfo
|
|
|
})
|
|
|
.then((res) => {
|
|
|
- props.callback?.(res)
|
|
|
+ props.callback(res)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 解压缩按钮点击事件
|
|
|
+ * @description 调用解压缩文件接口,并展示新的文件列表
|
|
|
+ * @param {object} fileInfo 文件信息
|
|
|
+ * @param {number} unzipMode 解压模式 0-解压到当前文件夹, 1-自动创建该文件名目录,并解压到目录里, 2-手动选择解压目录
|
|
|
+ */
|
|
|
const handleUnzipFileBtnClick = (fileInfo, unzipMode) => {
|
|
|
visible.value = false
|
|
|
- openDialog
|
|
|
+ proxy.$openDialog
|
|
|
.unzipFile({
|
|
|
unzipMode: unzipMode,
|
|
|
userFileId: fileInfo.userFileId
|
|
|
})
|
|
|
.then((res) => {
|
|
|
- props.callback?.(res)
|
|
|
+ props.callback(res)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 删除按钮点击事件
|
|
|
+ * @description 区分 删除到回收站中 | 在回收站中彻底删除,打开确认对话框
|
|
|
+ * @param {object} fileInfo 文件信息
|
|
|
+ */
|
|
|
const handleDeleteFileBtnClick = (fileInfo) => {
|
|
|
visible.value = false
|
|
|
- openDialog
|
|
|
+ proxy.$openDialog
|
|
|
.deleteFile({
|
|
|
isBatchOperation: false,
|
|
|
fileInfo,
|
|
|
- deleteMode: fileType.value === 6 ? 2 : 1
|
|
|
+ deleteMode: fileType.value === 6 ? 2 : 1 // 删除类型:1-删除到回收站 2-彻底删除
|
|
|
})
|
|
|
.then((res) => {
|
|
|
- props.callback?.(res)
|
|
|
+ props.callback(res)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 还原按钮点击事件
|
|
|
+ * @description 调用接口,在回收站中还原文件
|
|
|
+ * @param {object} fileInfo 文件信息
|
|
|
+ */
|
|
|
const handleRestoreFileBtnClick = (fileInfo) => {
|
|
|
visible.value = false
|
|
|
- openDialog
|
|
|
+ proxy.$openDialog
|
|
|
.restoreFile({
|
|
|
deleteBatchNum: fileInfo.deleteBatchNum,
|
|
|
filePath: fileInfo.filePath
|
|
|
})
|
|
|
.then((res) => {
|
|
|
- props.callback?.(res)
|
|
|
+ props.callback(res)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 文件重命名按钮点击事件
|
|
|
+ * @description 打开确认对话框让用户输入新的文件名
|
|
|
+ * @param {object} fileInfo 文件信息
|
|
|
+ */
|
|
|
const handleRenameFileBtnClick = (fileInfo) => {
|
|
|
visible.value = false
|
|
|
- openDialog
|
|
|
+ proxy.$openDialog
|
|
|
.renameFile({
|
|
|
oldFileName: fileInfo.fileName,
|
|
|
userFileId: fileInfo.userFileId
|
|
|
})
|
|
|
.then((res) => {
|
|
|
- props.callback?.(res)
|
|
|
+ props.callback(res)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 文件分享按钮点击事件
|
|
|
+ * @description 打开对话框让用户选择过期时间和提取码
|
|
|
+ * @param {object} fileInfo 文件信息
|
|
|
+ */
|
|
|
const handleShareFileBtnClick = (fileInfo) => {
|
|
|
visible.value = false
|
|
|
- openDialog.shareFile({
|
|
|
+ proxy.$openDialog.shareFile({
|
|
|
fileInfo: [
|
|
|
{
|
|
|
userFileId: fileInfo.userFileId
|
|
|
@@ -484,6 +462,9 @@
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 编辑文件夹按钮点击事件
|
|
|
+ */
|
|
|
const handleClickFolderEdit = () => {
|
|
|
router.push({
|
|
|
name: 'WebIDE',
|
|
|
@@ -491,177 +472,164 @@
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 文件在线编辑按钮点击事件
|
|
|
+ * @description 打开 代码预览对话框 或 office 编辑页面
|
|
|
+ * @param {object} fileInfo 文件信息
|
|
|
+ */
|
|
|
const handleClickFileEdit = (fileInfo) => {
|
|
|
if (officeFileType.includes(fileInfo.extendName)) {
|
|
|
- fileHelper.getFileOnlineEditPathByOffice(fileInfo)
|
|
|
+ // office 编辑页面
|
|
|
+ // proxy.$file.getFileOnlineEditPathByOffice(fileInfo)
|
|
|
} else if (markdownFileType.includes(fileInfo.extendName)) {
|
|
|
- openBox.markdownPreview({
|
|
|
+ // markdown 编辑浮层
|
|
|
+ proxy.$openBox.markdownPreview({
|
|
|
fileInfo: fileInfo,
|
|
|
editable: true
|
|
|
})
|
|
|
} else {
|
|
|
- openBox.codePreview({ fileInfo: fileInfo, isEdit: true })
|
|
|
+ // 代码编辑对话框
|
|
|
+ proxy.$openBox.codePreview({ fileInfo: fileInfo, isEdit: true })
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 文件详情按钮点击事件
|
|
|
+ * @description 打开对话框展示文件完整信息
|
|
|
+ * @param {object} fileInfo 文件信息
|
|
|
+ */
|
|
|
const handleShowDetailInfo = (fileInfo) => {
|
|
|
visible.value = false
|
|
|
- openDialog.showFileDetail({ fileInfo })
|
|
|
+ proxy.$openDialog.showFileDetail({ fileInfo })
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 新建文件夹按钮点击事件
|
|
|
+ * @description 调用新建文件夹服务,并在弹窗确认回调事件中刷新文件列表
|
|
|
+ */
|
|
|
const handleClickAddFolderBtn = () => {
|
|
|
- openDialog
|
|
|
+ proxy.$openDialog
|
|
|
.addFolder({
|
|
|
- filePath: route.query.filePath || '/'
|
|
|
+ filePath: router.currentRoute.value.query.filePath || '/'
|
|
|
})
|
|
|
.then((res) => {
|
|
|
- props.callback?.(res)
|
|
|
+ props.callback(res)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
- const handleCreateFile = (fileExt) => {
|
|
|
- // Renamed parameter to avoid conflict
|
|
|
- openDialog
|
|
|
- .createFile({
|
|
|
- fileType: fileExt, // Use the renamed parameter
|
|
|
- filePath: route.query.filePath || '/'
|
|
|
+ /**
|
|
|
+ * 新建 office 文件
|
|
|
+ * @description 调用新建 office 文件服务,并在弹窗确认回调事件中刷新文件列表
|
|
|
+ * @param {string} 文件扩展名 docx xlsx pptx
|
|
|
+ */
|
|
|
+ const handleCreateFile = (extendName) => {
|
|
|
+ proxy.$openDialog
|
|
|
+ .addFile({
|
|
|
+ extendName: extendName
|
|
|
})
|
|
|
.then((res) => {
|
|
|
- props.callback?.(res)
|
|
|
+ props.callback(res)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
- const handleUploadFileBtnClick = (uploadType) => {
|
|
|
- if (uploadType === 1 || uploadType === 2) {
|
|
|
- openDialog?.upload({ type: uploadType, filePath: filePath.value }).then((res) => {
|
|
|
- props.callback?.(res)
|
|
|
- })
|
|
|
- } else if (uploadType === 3) {
|
|
|
- antMessage.info('请拖拽文件或文件夹到此区域以上传')
|
|
|
- }
|
|
|
- visible.value = false
|
|
|
- }
|
|
|
-
|
|
|
- const handleAddMyFileList = (fileInfo) => {
|
|
|
- addMyFileListApi({ userFileId: fileInfo.userFileId, filePath: '/' }).then((res) => {
|
|
|
- if (res.success) {
|
|
|
- antMessage.success('添加成功')
|
|
|
- } else {
|
|
|
- antMessage.error(res.message)
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- const handleEnterpriseDisk = (fileInfo) => {
|
|
|
- addEnterpriseDiskApi({ userFileId: fileInfo.userFileId, filePath: '/' }).then((res) => {
|
|
|
- if (res.success) {
|
|
|
- antMessage.success('添加成功')
|
|
|
- } else {
|
|
|
- antMessage.error(res.message)
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 上传文件按钮点击事件
|
|
|
+ * @description 通过Bus通信,开启全局上传文件流程
|
|
|
+ * @param {boolean} uploadWay 上传方式 0-文件上传 1-文件夹上传 2-粘贴图片或拖拽上传
|
|
|
+ */
|
|
|
+ const handleUploadFileBtnClick = (uploadWay) => {
|
|
|
+ proxy.$openBox.uploadFile({
|
|
|
+ params: uploadFileParams.value,
|
|
|
+ uploadWay,
|
|
|
+ serviceEl: props.serviceEl,
|
|
|
+ callType: true // callType 调用此服务的方式:1 - 顶部栏,2 - 右键菜单
|
|
|
})
|
|
|
}
|
|
|
|
|
|
- // Expose any properties/methods that need to be accessed by the parent component
|
|
|
+ // 暴露方法给父组件
|
|
|
defineExpose({
|
|
|
- visible, // if parent needs to control visibility directly
|
|
|
- handleOpenContextMenu // if parent needs to trigger opening context menu
|
|
|
+ visible,
|
|
|
+ handleOpenContextMenu
|
|
|
})
|
|
|
</script>
|
|
|
|
|
|
<style lang="less" scoped>
|
|
|
- /* 保持原有样式 */
|
|
|
+ @import '@/style/myResource/varibles.less';
|
|
|
+ @import '@/style/myResource/mixins.less';
|
|
|
+
|
|
|
.right-menu-list {
|
|
|
position: fixed;
|
|
|
- z-index: 9999; // 确保在最上层
|
|
|
- width: auto;
|
|
|
- min-width: 128px;
|
|
|
- max-width: 200px;
|
|
|
- padding: 4px 0;
|
|
|
- border: 1px solid #e4e7ed;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ background: #fff;
|
|
|
+ border: 1px solid @border-color-light;
|
|
|
border-radius: 4px;
|
|
|
- background-color: #fff;
|
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
|
+ z-index: 2;
|
|
|
+ padding: 4px 0;
|
|
|
+ color: @regular-text;
|
|
|
+ list-style: none;
|
|
|
+
|
|
|
+ .right-menu-item,
|
|
|
+ .unzip-item {
|
|
|
+ padding: 0 16px;
|
|
|
+ height: 36px;
|
|
|
+ line-height: 36px;
|
|
|
+ cursor: pointer;
|
|
|
+ &:hover {
|
|
|
+ background: @primary-hover;
|
|
|
+ color: @Primary;
|
|
|
+ }
|
|
|
+ i {
|
|
|
+ margin-right: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
&.add {
|
|
|
.right-menu-item {
|
|
|
- padding: 0 8px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
img {
|
|
|
- width: 14px;
|
|
|
- margin-right: 8px;
|
|
|
+ margin-right: 4px;
|
|
|
+ height: 20px;
|
|
|
+ }
|
|
|
+ i {
|
|
|
+ margin-right: 4px;
|
|
|
+ font-size: 18px;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- .right-menu-item {
|
|
|
- box-sizing: border-box;
|
|
|
- position: relative;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- width: 100%;
|
|
|
- height: 36px;
|
|
|
- padding: 0 16px;
|
|
|
- font-size: 14px;
|
|
|
- line-height: 36px;
|
|
|
- color: #606266;
|
|
|
- cursor: pointer;
|
|
|
- user-select: none;
|
|
|
-
|
|
|
- &:hover {
|
|
|
- background: #ecf5ff;
|
|
|
- color: #409eff;
|
|
|
- }
|
|
|
-
|
|
|
- &.unzip-menu-item {
|
|
|
- justify-content: space-between;
|
|
|
- }
|
|
|
-
|
|
|
- .el-icon-arrow-right {
|
|
|
- position: absolute;
|
|
|
- right: 8px;
|
|
|
- }
|
|
|
-
|
|
|
- .unzip-list {
|
|
|
- position: absolute;
|
|
|
- z-index: 1;
|
|
|
- padding: 4px 0;
|
|
|
- border: 1px solid #e4e7ed;
|
|
|
- border-radius: 4px;
|
|
|
- background-color: #fff;
|
|
|
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
|
- display: none;
|
|
|
- }
|
|
|
-
|
|
|
- &.unzip-menu-item:hover > .unzip-list {
|
|
|
- display: block;
|
|
|
- }
|
|
|
-
|
|
|
- .unzip-item {
|
|
|
- box-sizing: border-box;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- width: 100%;
|
|
|
- min-width: max-content;
|
|
|
- height: 36px;
|
|
|
- padding: 0 16px;
|
|
|
- font-size: 14px;
|
|
|
- line-height: 36px;
|
|
|
- color: #606266;
|
|
|
- cursor: pointer;
|
|
|
|
|
|
+ .unzip-menu-item {
|
|
|
+ position: relative;
|
|
|
&:hover {
|
|
|
- background: #ecf5ff;
|
|
|
- color: #409eff;
|
|
|
+ .unzip-list {
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .unzip-list {
|
|
|
+ position: absolute;
|
|
|
+ display: none;
|
|
|
+ list-style: none;
|
|
|
+ .unzip-item {
|
|
|
+ width: 200px;
|
|
|
+ .setEllipsis(1);
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- i {
|
|
|
- margin-right: 8px;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- .el-divider--horizontal {
|
|
|
- margin: 4px 0;
|
|
|
+ .right-menu-list,
|
|
|
+ .unzip-list {
|
|
|
+ background: #fff;
|
|
|
+ border: 1px solid @border-color-light;
|
|
|
+ border-radius: 6px;
|
|
|
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
|
+ z-index: 2;
|
|
|
+ padding: 8px 0;
|
|
|
+ color: @regular-text;
|
|
|
+ font-size: 14px;
|
|
|
+ .a-divider {
|
|
|
+ margin: 2px 0;
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|