| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638 |
- <template>
- <!-- 右键列表 -->
- <transition name="fade">
- <!-- 在某个文件上右键 -->
- <ul
- class="right-menu-list"
- id="rightMenuList"
- v-show="visible"
- v-if="selectedFile !== undefined"
- :style="`top: ${rightMenu.top};right: ${rightMenu.right};bottom: ${rightMenu.bottom};left: ${rightMenu.left};`"
- >
- <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">
- <delete-outlined /> 删除
- </li>
- <li class="right-menu-item" @click="handleRestoreFileBtnClick(selectedFile)" v-if="restoreBtnShow">
- <rollback-outlined /> 还原
- </li>
- <li class="right-menu-item" @click="handleCopyFileBtnClick(selectedFile)" v-if="copyBtnShow">
- <copy-outlined /> 复制到
- </li>
- <li class="right-menu-item" @click="handleMoveFileBtnClick(selectedFile)" v-if="moveBtnShow">
- <export-outlined /> 移动
- </li>
- <li class="right-menu-item" @click="handleRenameFileBtnClick(selectedFile)" v-if="renameBtnShow">
- <edit-outlined /> 重命名
- </li>
- <li class="right-menu-item" @click="handleShareFileBtnClick(selectedFile)" v-if="shareBtnShow">
- <share-alt-outlined /> 分享
- </li>
- <li class="right-menu-item" @click="visible = false" v-if="downloadBtnShow">
- <a
- target="_blank"
- style="display: block; color: inherit"
- :href="$file.getDownloadFilePath(selectedFile)"
- :download="selectedFile.fileName + '.' + selectedFile.extendName"
- >
- <download-outlined /> 下载
- </a>
- </li>
- <!-- 0-解压到当前文件夹, 1-自动创建该文件名目录,并解压到目录里, 3-手动选择解压目录 -->
- <li class="right-menu-item unzip-menu-item" v-if="unzipBtnShow">
- <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)">
- <folder-outlined /> 解压到当前文件夹
- </li>
- <li
- class="unzip-item"
- @click="handleUnzipFileBtnClick(selectedFile, 1)"
- :title="`解压到"${selectedFile.fileName}"`"
- >
- <folder-outlined /> 解压到"{{ selectedFile.fileName }}"
- </li>
- <li class="unzip-item" @click="handleUnzipFileBtnClick(selectedFile, 2)">
- <folder-outlined /> 解压到目标文件夹
- </li>
- </ul>
- </li>
- <!-- <li
- class="right-menu-item"
- @click="handleClickFolderEdit"
- v-if="folderEditBtnShow"
- >
- <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">
- <file-outlined /> 文件详情
- </li>
- </ul>
- <!-- 在空白处右键,右键列表展示新建文件夹、新建文件等操作按钮 -->
- <ul
- class="right-menu-list add"
- id="rightMenuList"
- v-show="visible"
- v-else
- :style="`top: ${rightMenu.top};right: ${rightMenu.right};bottom: ${rightMenu.bottom};left: ${rightMenu.left};`"
- >
- <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"><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)"><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, 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 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 router = useRouter()
- const myResourceStore = useMyResourceStore()
- // 定义props
- const props = defineProps({
- selectedFile: Object,
- domEvent: Object,
- serviceEl: Object,
- callback: Function
- })
- // 响应式数据
- const visible = ref(false) // 右键菜单是否显示
- const sortedFileList = ref([]) // 排序后的表格数据
- const { proxy } = getCurrentInstance()
- // 右键菜单位置
- const rightMenu = ref({
- top: 0,
- left: 0,
- bottom: 'auto',
- right: 'auto'
- })
- // 右键解压缩菜单位置
- const unzipMenu = ref({
- top: 0,
- bottom: 'auto',
- left: '126px',
- right: 'auto'
- })
- // 图片资源 - 使用导入的图片资源
- const dirImg = ref(dirImgSrc)
- const wordImg = ref(wordImgSrc)
- const excelImg = ref(excelImgSrc)
- const pptImg = ref(pptImgSrc)
- // 计算属性
- // 路由名称
- const routeName = computed(() => {
- return router.currentRoute.value.name
- })
- // 左侧菜单选中的文件类型
- const fileType = computed(() => {
- // return router.currentRoute.value.query.fileType ? Number(router.currentRoute.value.query.fileType) : 0
- return myResourceStore.getQuery.fileType ? Number(myResourceStore.getQuery.fileType) : 0
- })
- // 当前路径
- const filePath = computed(() => {
- // return router.currentRoute.value.query.filePath
- return myResourceStore.getQuery.filePath ? myResourceStore.getQuery.filePath : '/'
- })
- // 查看按钮是否显示
- const seeBtnShow = computed(() => {
- 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].includes(fileType.value) && !['Share'].includes(routeName.value)
- })
- // 移动按钮是否显示
- const moveBtnShow = computed(() => {
- 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].includes(fileType.value) && !['Share'].includes(routeName.value)
- })
- // 下载按钮是否显示
- const downloadBtnShow = computed(() => {
- return ![6, 8].includes(fileType.value)
- })
- // 解压缩按钮是否显示
- const unzipBtnShow = computed(() => {
- return (
- ![6, 8].includes(fileType.value) &&
- !['Share'].includes(routeName.value) &&
- ['zip', 'rar', '7z', 'tar', 'gz'].includes(props.selectedFile.extendName)
- )
- })
- // 编辑文件夹按钮是否显示
- const folderEditBtnShow = computed(() => {
- return ![6, 8].includes(fileType.value) && props.selectedFile.isDir === 1 && !['Share'].includes(routeName.value)
- })
- // 在线编辑按钮是否显示
- const onlineEditBtnShow = computed(() => {
- return (
- ![6, 8].includes(fileType.value) &&
- (officeFileType.includes(props.selectedFile.extendName) ||
- markdownFileType.includes(props.selectedFile.extendName) ||
- fileSuffixCodeModeMap.has(props.selectedFile.extendName)) &&
- !['Share'].includes(routeName.value)
- )
- })
- // 复制链接按钮是否显示
- const copyLinkBtnShow = computed(() => {
- return fileType.value === 8
- })
- // 文件详情按钮是否显示
- const detailInfoBtnShow = computed(() => {
- return true
- })
- // 上传文件组件参数
- const uploadFileParams = computed(() => {
- return {
- filePath: filePath.value,
- isDir: 0
- }
- })
- // 监听右键列表状态
- watch(visible, (newValue) => {
- if (newValue === true) {
- document.body.addEventListener('click', closeRightMenu)
- handleOpenContextMenu()
- } else {
- document.body.removeEventListener('click', closeRightMenu)
- }
- })
- // 方法
- /**
- * 打开右键菜单
- */
- const handleOpenContextMenu = () => {
- // 纵坐标设置
- 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'
- unzipMenu.value.bottom = '0px'
- } else {
- rightMenu.value.top = `${props.domEvent.clientY}px`
- rightMenu.value.bottom = 'auto'
- 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'
- unzipMenu.value.right = 'auto'
- } else {
- rightMenu.value.left = `${props.domEvent.clientX + 8}px`
- rightMenu.value.right = 'auto'
- unzipMenu.value.left = '126px'
- unzipMenu.value.right = 'auto'
- }
- visible.value = true
- }
- /**
- * 关闭右键列表
- */
- const closeRightMenu = (event) => {
- // 使用 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')
- }
- }
- }
- /**
- * 复制按钮点击事件
- * @description 向父组件传递当前操作的文件信息,并打开"复制文件对话框"
- * @param {object} fileInfo 文件信息
- */
- const handleCopyFileBtnClick = (fileInfo) => {
- visible.value = false
- proxy.$openDialog
- .copyFile({
- fileInfo
- })
- .then((res) => {
- props.callback(res)
- })
- }
- /**
- * 移动按钮点击事件
- * @description 向父组件传递当前操作的文件信息,并打开"移动文件对话框"
- * @param {object} fileInfo 文件信息
- */
- const handleMoveFileBtnClick = (fileInfo) => {
- visible.value = false
- proxy.$openDialog
- .moveFile({
- isBatchOperation: false,
- fileInfo
- })
- .then((res) => {
- props.callback(res)
- })
- }
- /**
- * 解压缩按钮点击事件
- * @description 调用解压缩文件接口,并展示新的文件列表
- * @param {object} fileInfo 文件信息
- * @param {number} unzipMode 解压模式 0-解压到当前文件夹, 1-自动创建该文件名目录,并解压到目录里, 2-手动选择解压目录
- */
- const handleUnzipFileBtnClick = (fileInfo, unzipMode) => {
- visible.value = false
- proxy.$openDialog
- .unzipFile({
- unzipMode: unzipMode,
- userFileId: fileInfo.userFileId
- })
- .then((res) => {
- props.callback(res)
- })
- }
- /**
- * 删除按钮点击事件
- * @description 区分 删除到回收站中 | 在回收站中彻底删除,打开确认对话框
- * @param {object} fileInfo 文件信息
- */
- const handleDeleteFileBtnClick = (fileInfo) => {
- visible.value = false
- proxy.$openDialog
- .deleteFile({
- isBatchOperation: false,
- fileInfo,
- deleteMode: fileType.value === 6 ? 2 : 1 // 删除类型:1-删除到回收站 2-彻底删除
- })
- .then((res) => {
- props.callback(res)
- })
- }
- /**
- * 还原按钮点击事件
- * @description 调用接口,在回收站中还原文件
- * @param {object} fileInfo 文件信息
- */
- const handleRestoreFileBtnClick = (fileInfo) => {
- visible.value = false
- proxy.$openDialog
- .restoreFile({
- deleteBatchNum: fileInfo.deleteBatchNum,
- filePath: fileInfo.filePath
- })
- .then((res) => {
- props.callback(res)
- })
- }
- /**
- * 文件重命名按钮点击事件
- * @description 打开确认对话框让用户输入新的文件名
- * @param {object} fileInfo 文件信息
- */
- const handleRenameFileBtnClick = (fileInfo) => {
- visible.value = false
- proxy.$openDialog
- .renameFile({
- oldFileName: fileInfo.fileName,
- userFileId: fileInfo.userFileId
- })
- .then((res) => {
- props.callback(res)
- })
- }
- /**
- * 文件分享按钮点击事件
- * @description 打开对话框让用户选择过期时间和提取码
- * @param {object} fileInfo 文件信息
- */
- const handleShareFileBtnClick = (fileInfo) => {
- visible.value = false
- proxy.$openDialog.shareFile({
- fileInfo: [
- {
- userFileId: fileInfo.userFileId
- }
- ]
- })
- }
- /**
- * 编辑文件夹按钮点击事件
- */
- const handleClickFolderEdit = () => {
- router.push({
- name: 'WebIDE',
- query: { filePath: props.selectedFile.filePath }
- })
- }
- /**
- * 文件在线编辑按钮点击事件
- * @description 打开 代码预览对话框 或 office 编辑页面
- * @param {object} fileInfo 文件信息
- */
- const handleClickFileEdit = (fileInfo) => {
- if (officeFileType.includes(fileInfo.extendName)) {
- // office 编辑页面
- // proxy.$file.getFileOnlineEditPathByOffice(fileInfo)
- } else if (markdownFileType.includes(fileInfo.extendName)) {
- // markdown 编辑浮层
- proxy.$openBox.markdownPreview({
- fileInfo: fileInfo,
- editable: true
- })
- } else {
- // 代码编辑对话框
- proxy.$openBox.codePreview({ fileInfo: fileInfo, isEdit: true })
- }
- }
- /**
- * 文件详情按钮点击事件
- * @description 打开对话框展示文件完整信息
- * @param {object} fileInfo 文件信息
- */
- const handleShowDetailInfo = (fileInfo) => {
- visible.value = false
- proxy.$openDialog.showFileDetail({ fileInfo })
- }
- /**
- * 新建文件夹按钮点击事件
- * @description 调用新建文件夹服务,并在弹窗确认回调事件中刷新文件列表
- */
- const handleClickAddFolderBtn = () => {
- proxy.$openDialog
- .addFolder({
- // filePath: router.currentRoute.value.query.filePath || '/'
- filePath: myResourceStore.getQuery.filePath || '/'
- })
- .then((res) => {
- props.callback(res)
- })
- }
- /**
- * 新建 office 文件
- * @description 调用新建 office 文件服务,并在弹窗确认回调事件中刷新文件列表
- * @param {string} 文件扩展名 docx xlsx pptx
- */
- const handleCreateFile = (extendName) => {
- proxy.$openDialog
- .addFile({
- extendName: extendName
- })
- .then((res) => {
- props.callback(res)
- })
- }
- /**
- * 上传文件按钮点击事件
- * @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 - 右键菜单
- })
- }
- // 暴露方法给父组件
- defineExpose({
- visible,
- handleOpenContextMenu
- })
- </script>
- <style lang="less" scoped>
- @import '@/style/myResource/varibles.less';
- @import '@/style/myResource/mixins.less';
- .right-menu-list {
- position: fixed;
- display: flex;
- flex-direction: column;
- background: #fff;
- border: 1px solid @border-color-light;
- border-radius: 4px;
- 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 {
- display: flex;
- align-items: center;
- img {
- margin-right: 4px;
- height: 20px;
- }
- i {
- margin-right: 4px;
- font-size: 18px;
- }
- }
- }
- .unzip-menu-item {
- position: relative;
- &:hover {
- .unzip-list {
- display: block;
- }
- }
- .unzip-list {
- position: absolute;
- display: none;
- list-style: none;
- margin-left: -15px;
- .unzip-item {
- width: 200px;
- .setEllipsis(1);
- }
- }
- }
- }
- .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>
|