diff --git a/src/components/ShowFile/ShowFile.vue b/src/components/ShowFile/ShowFile.vue
index bd6f5d0..a82e6f3 100644
--- a/src/components/ShowFile/ShowFile.vue
+++ b/src/components/ShowFile/ShowFile.vue
@@ -306,7 +306,6 @@
:fit="true"
:cell-style="rowStyle"
:height-change="false"
- :row-class-name="tableRowClassName"
element-loading-text="文件加载中"
element-loading-spinner="el-icon-loading"
element-loading-background="#f6f7fa88"
@@ -505,8 +504,7 @@
renameInputFocus($event.currentTarget, item.suffix)
"
@blur="setInputBlur()"
- @keyup.enter.prevent.native="
- rowRename(renameFileName, item)
+ @keyup.enter.prevent.native="rowRename(renameFileName, item)
"
>
@@ -739,7 +737,6 @@
@@ -4692,348 +1097,6 @@ export default {
diff --git a/src/components/ShowFile/mixins/clipboard.js b/src/components/ShowFile/mixins/clipboard.js
new file mode 100644
index 0000000..b290f65
--- /dev/null
+++ b/src/components/ShowFile/mixins/clipboard.js
@@ -0,0 +1,49 @@
+import store from '@/store'
+import fileConfig from '@/utils/file-config'
+
+export default {
+ created() {
+ },
+ computed: {
+ fileClipboard() {
+ return store.getters.fileClipboard
+ },
+ getClipboardFileIdList() {
+ return store.getters.fileClipboard.map(file => file.id)
+ },
+ },
+ props: {
+ showClipboard: {
+ type: Boolean,
+ default: false,
+ }
+ },
+ methods: {
+ // 复制下载链接
+ copyDownloadLink(row) {
+ let url = window.location.origin + fileConfig.previewUrl(this.$store.getters.name, row, undefined, this.shareToken)
+ if (row.isFolder) {
+ url = fileConfig.packageDownloadUrl(row.id, row.name + '.zip', this.shareToken)
+ }
+ let clipboard = new Clipboard('.file-contextmenu', {
+ text: function() {
+ return url
+ },
+ })
+ clipboard.on('success', () => {
+ this.$message({ message: '复制成功', type: 'success', duration: 1000 })
+ // 释放内存
+ clipboard.destroy()
+ })
+ clipboard.on('error', () => {
+ // 不支持复制
+ this.$message({
+ message: '该浏览器不支持自动复制',
+ type: 'warning',
+ duration: 1000,
+ })
+ clipboard.destroy()
+ })
+ },
+ }
+}
diff --git a/src/components/ShowFile/mixins/common.js b/src/components/ShowFile/mixins/common.js
new file mode 100644
index 0000000..5cc643f
--- /dev/null
+++ b/src/components/ShowFile/mixins/common.js
@@ -0,0 +1,20 @@
+import { formatSize, formatTime } from '@/utils/number'
+
+export default {
+ data() {
+ return {
+ imageUrl: `${process.env.VUE_APP_BASE_API}/view/thumbnail?jmal-token=${this.$store.state.user.token}&name=${this.$store.state.user.name}&id=`,
+ audioCoverUrl: `${process.env.VUE_APP_BASE_API}/view/cover?jmal-token=${this.$store.state.user.token}&name=${this.$store.state.user.name}&id=`,
+ }
+ },
+ methods: {
+ // 格式化最近时间
+ formatTime(time) {
+ return formatTime(time)
+ },
+ // 格式化文件大小
+ formatSize(size) {
+ return formatSize(size)
+ },
+ }
+}
diff --git a/src/components/ShowFile/mixins/fileContextmenu.js b/src/components/ShowFile/mixins/fileContextmenu.js
new file mode 100644
index 0000000..044ade5
--- /dev/null
+++ b/src/components/ShowFile/mixins/fileContextmenu.js
@@ -0,0 +1,452 @@
+import api from '@/api/file-api'
+import fileConfig from '@/utils/file-config'
+import { directLinkSubMenus, fileOperations } from '@/utils/file-operations'
+import { suffix } from '@/utils/file-type'
+
+export default {
+ props: {
+ singleMenus: {
+ type: Array,
+ default: function() {
+ return [
+ fileOperations.open,
+ { iconClass: 'link', label: '直链', operation: 'directLink', child: directLinkSubMenus },
+ fileOperations.download,
+ { iconClass: 'share', label: '分享...', operation: 'share' },
+ { iconClass: 'tag', label: '标签...' , operation: 'tag'},
+ { iconClass: 'menu-favorite', label: '收藏', operation: 'favorite' },
+ fileOperations.detail,
+ fileOperations.copyOnly,
+ fileOperations.rename,
+ fileOperations.copy,
+ fileOperations.remove,
+ ]
+ },
+ },
+ multipleRightMenus: {
+ type: Array,
+ default: function() {
+ return [
+ {
+ iconClass: 'menu-deselect',
+ label: '取消选定',
+ operation: 'deselect',
+ },
+ fileOperations.download,
+ { iconClass: 'tag', label: '标签', operation: 'tag' },
+ fileOperations.copyOnly,
+ fileOperations.copy,
+ fileOperations.remove,
+ ]
+ },
+ },
+ },
+ data() {
+ return {
+ isJustHideMenus: false,
+ menusIsMultiple: false,
+ menus: [],
+ rowContextData: {},
+ }
+ },
+ methods: {
+ contextmenu(e) {
+ e.preventDefault()
+ e.stopPropagation()
+ },
+ show() {
+ const that = this
+ this.contextmenuDisabled = true
+ setTimeout(function() {
+ that.contextmenuDisabled = false
+ }, 1000)
+ },
+ hide() {
+ const that = this
+ this.isJustHideMenus = true
+ setTimeout(function() {
+ that.isJustHideMenus = false
+ }, 100)
+ this.cellMouseIndex = -1
+ },
+ setMenus(row) {
+ this.menus = JSON.parse(JSON.stringify(this.singleMenus))
+ // 挂载的文件
+ const owner = localStorage.getItem('mountFileOwner')
+ const notSelf = row.userId && row.userId !== this.$store.getters.userId
+ if ((this.$route.query.folder && owner) || notSelf) {
+ // 根据权限设置菜单
+ this.setMenusByPermission(row)
+ } else {
+ if (row.suffix && row.suffix === 'md' && this.queryFileType !== 'trash') {
+ this.menus.splice(this.getIndexOfFileContextMenus(fileOperations.copyOnly.operation), 0, {
+ iconClass: 'menu-edit1',
+ label: '编辑',
+ operation: 'edit',
+ })
+ }
+ if (row.isFolder && row.mountFileId) {
+ const reservations = ['open', 'tag', 'favorite', 'remove']
+ // 删除this.menus中不要的菜单, 仅保留reservations中的菜单
+ this.menus = this.menus.filter(item =>
+ reservations.includes(item.operation)
+ )
+ }
+ if (!row.isFolder && this.queryFileType !== 'trash') {
+ // 创建副本
+ const copyIndex = this.getIndexOfFileContextMenus(fileOperations.copy.operation)
+ if (copyIndex > -1) {
+ this.menus.splice(copyIndex, 0, fileOperations.duplicate)
+ }
+ }
+ if (row.ossFolder) {
+ const reservations = ['open', 'tag']
+ // 删除this.menus中不要的菜单, 仅保留reservations中的菜单
+ this.menus = this.menus.filter(item =>
+ reservations.includes(item.operation)
+ )
+ }
+ this.setMenusCopyDownLoadLinks(row)
+ }
+ this.preliminaryRowData(row)
+ },
+ setFileContextMenusDivider() {
+ // 下载栏下面添加分隔符
+ const downloadIndex = this.getIndexOfFileContextMenus(fileOperations.download.operation)
+ if (downloadIndex > -1 && this.menus.length - 1 > downloadIndex && !this.menus[downloadIndex + 1].divider) {
+ this.menus.splice(downloadIndex + 1, 0, { divider: true, operation: 'divider' })
+ }
+ // 删除栏上面添加分隔符
+ const removeIndex = this.getIndexOfFileContextMenus(fileOperations.remove.operation)
+ if (removeIndex > 0 && !this.menus[removeIndex - 1].divider) {
+ this.menus.splice(removeIndex, 0, { divider: true, operation: 'divider' })
+ }
+ // 详情栏下面添加分隔符
+ const detailIndex = this.getIndexOfFileContextMenus(fileOperations.detail.operation)
+ if (detailIndex > -1 && this.menus.length - 1 > detailIndex && !this.menus[detailIndex + 1].divider) {
+ this.menus.splice(detailIndex + 1, 0, { divider: true, operation: 'divider' })
+ }
+ },
+ getIndexOfFileContextMenus(operation) {
+ return this.menus.findIndex(item => item.operation === operation)
+ },
+ setMenusCopyDownLoadLinks(row) {
+ if (row.isShare) {
+ // 获取this.menus中download的索引
+ const downloadIndex = this.menus.findIndex(
+ item => item.operation === 'download'
+ )
+ this.shareToken = undefined
+ // 在download之前添加复制下载链接选项
+ this.addMenusCopyDownLoadLinks(downloadIndex)
+ if (row.isPrivacy) {
+ // 如果是私密分享需要先获取shareToken
+ api.generateShareToken({fileId: row.id}).then(res => {
+ this.shareToken = res.data
+ }).catch(() => {
+ this.menus.splice(downloadIndex, 1)
+ })
+ }
+ }
+ },
+ addMenusCopyDownLoadLinks(index) {
+ this.menus.splice(index, 0, {
+ iconClass: 'menu-fuzhi',
+ label: '复制下载链接',
+ operation: 'copyDownloadLink',
+ })
+ },
+ setMenusByPermission(file) {
+ const reservations = ['open', 'download', 'details']
+ // 删除this.menus中不要的菜单, 仅保留reservations中的菜单
+ this.menus = this.menus.filter(item =>
+ reservations.includes(item.operation)
+ )
+ if (file.operationPermissionList && file.operationPermissionList.length > 0) {
+ if (file.operationPermissionList.indexOf('PUT') > -1) {
+ this.menus.splice(this.menus.length, 0, fileOperations.rename)
+ }
+ if (file.operationPermissionList.indexOf('UPLOAD') > -1) {
+ if (file.operationPermissionList.indexOf('DELETE') > -1) {
+ this.menus.splice(this.menus.length, 0, fileOperations.copy)
+ this.menus.splice(this.menus.length, 0, fileOperations.copyOnly)
+ }
+ if (!file.isFolder) {
+ this.menus.splice(this.menus.length, 0, fileOperations.duplicate)
+ }
+ }
+ if (file.operationPermissionList.indexOf('DELETE') > -1) {
+ this.menus.splice(this.menus.length, 0, fileOperations.remove)
+ }
+ }
+ this.setMenusCopyDownLoadLinks(file)
+ },
+ // 鼠标右击
+ rowContextmenu(row) {
+ this.$refs.homeContextmenu.hide()
+ if (this.selectFile) {
+ return
+ }
+ if (
+ this.$refs.fileListTable.tableSelectData.length > 1 &&
+ this.$refs.fileListTable.tableSelectData.findIndex(item => item.index === row.index) > -1
+ ) {
+ this.menusIsMultiple = true
+ this.menus = JSON.parse(JSON.stringify(this.multipleRightMenus))
+ this.highlightFavorite(false, false)
+ } else {
+ this.fileListTableClearSelection()
+ this.$refs.fileListTable.toggleRowSelection([{ row: row }])
+ this.menusIsMultiple = false
+ this.setMenus(row)
+ }
+
+ // 设置分割线
+ this.setFileContextMenusDivider()
+
+ event.preventDefault()
+ event.stopPropagation()
+ const e = {}
+ e.pageX = event.pageX + 5
+ e.pageY = event.pageY + 20
+ e.clientX = event.clientX + 50
+ e.clientY = event.clientY + 2
+ e.top = event.clientY
+ e.left = event.clientX + 2
+
+ const dividerSize = this.menus.filter(item => item.divider).length
+
+ const containerWidth = 180 + 10
+ const containerHeight = (this.menus.length - dividerSize) * 35 + (dividerSize * 11) + 18 + 10
+ const distanceToBottom = document.documentElement.clientHeight - event.clientY
+ const distanceToRight = document.documentElement.clientWidth - event.clientX
+
+ if (distanceToBottom < containerHeight) {
+ e.top = event.clientY - (containerHeight - distanceToBottom)
+ }
+ if (distanceToRight < containerWidth) {
+ e.left = event.clientX - containerWidth + 8
+ }
+
+ this.$refs.contextShow.showMenu(e)
+ this.cellMouseIndex = -1
+ },
+ // 列表右键菜单操作
+ menusOperations(operation, event) {
+ switch (operation) {
+ case 'share':
+ // 分配标签
+ this.share()
+ break
+ case 'tag':
+ // 分配标签
+ this.allocateTag()
+ break
+ case 'favorite':
+ // 收藏
+ this.favoriteOperating(true)
+ break
+ case 'edit':
+ // 编辑
+ window.open(
+ `/setting/website/manager-articles?operation=editor&id=${this.rowContextData.id}`,
+ '_blank'
+ )
+ break
+ case 'open':
+ // 打开
+ this.fileClick(this.rowContextData, event)
+ break
+ case 'deselect':
+ // 取消选定
+ this.fileListTableClearSelection()
+ break
+ case 'unFavorite':
+ // 取消收藏
+ this.favoriteOperating(false)
+ break
+ case 'details':
+ this.drawer = true
+ break
+ case 'rename':
+ // 重命名
+ this.renameFileName = this.rowContextData.name
+ this.editingIndex = this.rowContextData.index
+ break
+ case 'duplicate':
+ // 创建副本
+ this.duplicate()
+ break
+ case 'copy':
+ // 移动或复制
+ this.moveOrCopy()
+ break
+ case 'copyOnly':
+ this.copyOperation()
+ break
+ case 'download':
+ // 下载
+ this.downloadFile()
+ break
+ case 'copyDownloadLink':
+ // 复制下载链接
+ this.copyDownloadLink(this.rowContextData)
+ break
+ case 'remove':
+ // 删除
+ this.removeOperation()
+ break
+ case 'sweep':
+ // 清空回收站
+ this.sweepFile()
+ break
+ case 'restore':
+ // 返回原处
+ this.restoreFile()
+ break
+ case 'manageDirectLink':
+ // 管理直链
+ this.directLinkDialogVisible = true
+ this.directLinkDialogGetDirectLink(this.rowContextData)
+ break
+ case 'copyDirectLink':
+ // 复制直链
+ this.directLinkDialogGetDirectLink(this.rowContextData, true)
+ break
+ }
+ this.$refs.contextShow.hideMenu()
+ },
+ // 点击文件或文件夹
+ fileClick(row, event) {
+ this.drawer = false
+ if (this.queryFileType === 'trash') {
+ return
+ }
+ if (this.editingIndex === row.index) {
+ return
+ }
+ this.openingFile = row
+ if (row.isFolder) {
+ this.editingIndex = -1
+ const queryTagId = this.$route.query.tagId ? `&tagId=${this.$route.query.tagId}` : ''
+ const keyword = this.$route.query.keyword ? `&keyword=${this.$route.query.keyword}` : ''
+ // 打开文件夹
+ if (this.listModeSearch) {
+ const item = {}
+ item['folder'] = row.name
+ item['search'] = true
+ item['row'] = row
+ this.pathList.push(item)
+ this.pagination.pageIndex = 1
+ const searchOpenFolder = row.id ? `&searchOpenFolder=${row.id}` : ''
+ const path = this.$route.query.path ? `&path=${this.$route.query.path}` : ''
+ const folder = this.$route.query.folder ? `&folder=${this.$route.query.folder}` : ''
+ const basePath = this.getBasePath()
+ this.$router.push(
+ `?vmode=${
+ this.vmode
+ }${path}${keyword}${searchOpenFolder}${folder}${queryTagId}${basePath}`
+ )
+ this.searchFileAndOpenDir(row.id)
+ } else {
+ let notHomePage = this.$route.path.length > 1
+ if (
+ notHomePage &&
+ this.path + '/' !== row.path &&
+ this.basePath.length === 1
+ ) {
+ this.basePath = row.path
+ }
+
+ this.path += '/' + row.name
+ this.path = this.path.replace(/\\/g, '/')
+ this.path = this.path.replace(/\/\//g, '/')
+ // 去掉this.path开头的this.basePath
+ this.path = this.path.replace(this.basePath, '/')
+ const path = encodeURIComponent(this.path)
+ const item = { folder: row.name, shareBase: row.shareBase }
+ this.pathList.push(item)
+ this.pagination.pageIndex = 1
+ if (this.$store.getters.userId !== row.userId) {
+ row.mountFileId = row.id
+ }
+ if (row.mountFileId) {
+ localStorage.setItem(this.path, row.mountFileId)
+ }
+ const basePath = this.basePath && this.basePath.length > 1 ? `&basePath=${this.basePath}` : ''
+ const searchOpenFolder = this.$route.query.searchOpenFolder ? `&searchOpenFolder=${this.$route.query.searchOpenFolder}` : ''
+ this.$router.push(`?vmode=${this.vmode}&path=${path}${row.mountFileId ? '&folder=' + row.mountFileId : ''}${queryTagId}${basePath}${keyword}${searchOpenFolder}`)
+ this.openDir(row)
+ }
+ } else {
+ if (this.selectFile) {
+ let selectFile = row
+ const selectData = this.$refs.fileListTable.tableSelectData
+ if (selectData.length < 1 || selectData[0].id !== row.id) {
+ this.fileListTableClearSelection()
+ this.$refs.fileListTable.toggleRowSelection([{ row: row }])
+ this.pinSelect(row, event)
+ } else {
+ this.fileListTableClearSelection()
+ selectFile = {}
+ }
+ this.$emit('selectedFile', selectFile)
+ return
+ }
+ const fileHandler = fileConfig.hasIframePreview(row.suffix, this.$store.getters.iframePreviewConfig)
+ if (fileHandler !== null) {
+ // iframe 预览
+ this.iframePreviewVisible = true
+ this.iframePreviewRow = row
+ this.fileHandler = fileHandler
+ return
+ }
+ if (row.contentType.startsWith('image')) {
+ // 图片
+ this.imagePreviewVisible = true
+ this.imagePreviewRow = row
+ return
+ }
+ if (suffix.simText.includes(row.suffix)) {
+ // 文本文件
+ this.textPreviewRow = row
+ this.textPreviewVisible = true
+ return
+ }
+ if (row.contentType.indexOf('video') > -1) {
+ // 视频文件
+ this.videoPreviewVisible = true
+ this.videoPreviewRow = row
+ return
+ }
+ if (row.contentType.indexOf('audio') > -1) {
+ // 音频文件
+ this.$store.dispatch('updateMessage', {
+ event: 'onAddAudio',
+ data: { row: row, audioCoverUrl: this.audioCoverUrl },
+ })
+ return
+ }
+ if (suffix.compressedFile.includes(row.suffix)) {
+ // 压缩文件
+ this.openCompressionVisible = true
+ return
+ }
+ if (row.contentType.indexOf('office') > -1 || suffix.iframePreviewFile.includes(row.suffix)) {
+ // iframe 预览
+ this.iframePreviewVisible = true
+ this.iframePreviewRow = row
+ this.fileHandler = {}
+ return
+ }
+ if (row.contentType.indexOf('utf-8') > -1) {
+ // 文本文件
+ this.textPreviewRow = row
+ this.textPreviewVisible = true
+ return
+ }
+ this.notPreviewDialogVisible = true
+ }
+ },
+ }
+}
diff --git a/src/components/ShowFile/mixins/fileDrag.js b/src/components/ShowFile/mixins/fileDrag.js
new file mode 100644
index 0000000..b0ddc45
--- /dev/null
+++ b/src/components/ShowFile/mixins/fileDrag.js
@@ -0,0 +1,738 @@
+import { getElementToPageLeft } from '@/utils/dom'
+
+export default {
+ data() {
+ return {
+ dragElementList: [],
+ drawFlag: false,
+ draging: 0, // 是否正在拖拽中,0:没有拖拽,1:拖拽中,
+ selectRowData: [],
+ selectOrigin: -1, // 选择起点(主要用于按住shift键多选)
+ selectEnd: -1, // 选择终点
+ inputting: false, // 是否正在输入
+ fileListScrollTop: 0,
+ initFileListScrollTop: 0,
+ }
+ },
+ methods: {
+ // 画矩形选区
+ drawRectangle() {
+ let scrollDiv = this.$refs.fileListTableContainer.querySelector('.el-table__body-wrapper')
+ if (this.grid) {
+ scrollDiv = this.$refs.gridDiv.querySelector('.van-grid')
+ }
+ // 添加scroll事件
+ scrollDiv.onscroll = e => {
+ this.tableBodyScroll(null, e)
+ }
+
+ if (this.selectFile) {
+ return
+ }
+ const _this = this
+ let $$ = function(id) {
+ return document.getElementById(id)
+ }
+ let draw = $$('v-draw-rectangle')
+ let wId = 'rectangle1'
+ let startX = 0,
+ startY = 0
+ let retcLeft = 0,
+ retcTop = 0,
+ retcHeight = 0,
+ retcWidth = 0
+ _this.drawFlag = false
+ let itemClassName = 'el-table__row'
+ if (_this.grid) {
+ itemClassName =
+ 'grid-item van-grid-item__content van-grid-item__content--center van-grid-item__content--square'
+ }
+ draw.onmousedown = null
+ draw.onmousedown = function(e) {
+ let evt = window.event || e
+ const elPath = e.path || (e.composedPath && e.composedPath())
+ // 列表模式下点击表头,阻止点击事件
+ if (!_this.grid && _this.selectRowData.length > 0) {
+ const findIndex = elPath.findIndex(path => {
+ if (path.className === 'el-table__header-wrapper') {
+ return path
+ }
+ })
+ if (findIndex > -1) {
+ _this.stopSortChange = true
+ }
+ }
+ // 点击的区域是否为文件, throughRow 不为空就证明点到了文件
+ let throughRow = elPath.find(path => {
+ if (path.className === itemClassName || path.className === 'el-table__row el-table__row--striped') {
+ return path
+ }
+ })
+ if (throughRow) {
+ // 鼠标按下时就选中文件
+ if (!_this.selectRowData.includes(_this.fileList[throughRow.rowIndex])) {
+ _this.editingIndex = -1
+ if (!_this.checkCmdKey(e) && !e.shiftKey) {
+ _this.fileListTableClearSelection()
+ _this.$refs.fileListTable.toggleRowSelection([
+ { row: _this.fileList[throughRow.rowIndex], selected: true },
+ ])
+ }
+ }
+ return
+ } else {
+ _this.editingIndex = -1
+ }
+ if (evt.button !== 0) {
+ return
+ }
+ if (!_this.checkCmdKey(e) && !e.shiftKey) {
+ const index = elPath.findIndex(
+ el =>
+ el.className === itemClassName ||
+ el.className === 'el-table__row el-table__row--striped'
+ )
+ if (index < 0) {
+ _this.fileListTableClearSelection()
+ }
+ }
+ let scrollTop = draw.scrollTop || draw.scrollTop
+ let scrollLeft = draw.scrollLeft || draw.scrollLeft
+ startX = evt.clientX + scrollLeft
+ startY = evt.clientY + scrollTop
+
+ let div = document.createElement('div')
+ div.id = wId
+ div.className = 'draw-rectangle'
+ div.style.left = startX + 'px'
+ div.style.top = startY + 'px'
+ div.style.position = 'fixed'
+ div.style.border = '1px dashed #2898ff'
+ div.style.width = '0px'
+ div.style.height = '0px'
+ div.style.left = '0px'
+ div.style.top = '0px'
+ div.style.overflow = 'hidden'
+ draw.appendChild(div)
+ document.onmousemove = function(e) {
+ let evt = window.event || e
+ let scrollTop =
+ document.body.scrollTop || document.documentElement.scrollTop
+ let scrollLeft =
+ document.body.scrollLeft || document.documentElement.scrollLeft
+ retcLeft =
+ startX - evt.clientX - scrollLeft > 0
+ ? evt.clientX + scrollLeft
+ : startX
+ retcTop =
+ startY - evt.clientY - scrollTop > 0
+ ? evt.clientY + scrollTop
+ : startY
+ retcHeight = Math.abs(startY - evt.clientY - scrollTop)
+ retcWidth = Math.abs(startX - evt.clientX - scrollLeft)
+ _this.drawFlag = true
+ if (retcHeight + retcWidth < 4) {
+ return
+ }
+ const drawRectangle = document.getElementById(wId)
+ if (drawRectangle) {
+ drawRectangle.style.left = retcLeft + 'px'
+ drawRectangle.style.top = retcTop + 'px'
+ drawRectangle.style.width = retcWidth + 'px'
+ drawRectangle.style.height = retcHeight + 'px'
+ drawRectangle.style.backgroundColor = '#f2f5fa55'
+ }
+ if (_this.drawFlag && retcHeight + retcWidth > 4) {
+ if (!drawSelecting) {
+ drawSelect({
+ x: retcLeft,
+ y: retcTop + _this.fileListScrollTop,
+ w: retcWidth,
+ h: retcHeight,
+ })
+ }
+ }
+ }
+ document.onmouseup = function(e) {
+ document.onmousemove = null
+ document.onmouseup = null
+ if (_this.stopSortChange) {
+ _this.stopSortChange = false
+ setTimeout(() => {
+ _this.changeSelectedStyle(_this.selectRowData)
+ }, 200)
+ }
+ setTimeout(function() {
+ _this.drawFlag = false
+ }, 50)
+ const rectangle = document.getElementById(wId)
+ if (rectangle) {
+ draw.removeChild(rectangle)
+ }
+ if (!_this.grid) {
+ draw = document.getElementById('drag-table')
+ }
+ const dragingDivs = Array.prototype.slice.call(
+ draw.getElementsByClassName('dragingDiv')
+ )
+ dragingDivs.forEach(el => draw.removeChild(el))
+ }
+ }
+
+ let drawSelecting = false
+ let drawSelect = function(drawNode) {
+ drawSelecting = true
+ _this.dragElementList.forEach(element => {
+ if (checkTouch(element, drawNode)) {
+ _this.$refs.fileListTable.toggleRowSelection([
+ { row: _this.fileList[element.rowIndex], selected: true },
+ ])
+ } else {
+ _this.$refs.fileListTable.toggleRowSelection([
+ { row: _this.fileList[element.rowIndex], selected: false },
+ ])
+ }
+ })
+ setTimeout(() => (drawSelecting = false), 10)
+ }
+ //检查两个DIV是否有接触
+ let checkTouch = function(item, draw) {
+ //得到左上角的绝对坐标
+ let x1 = item.x
+ let y1 = item.y
+ let x2 = draw.x
+ let y2 = draw.y
+ let w1 = item.w
+ let h1 = item.h
+ let w2 = draw.w
+ let h2 = draw.h
+ return (
+ ((x1 - x2 <= 0 && x2 - x1 < w1) || (x1 - x2 >= 0 && x1 - x2 < w2)) &&
+ ((y1 - y2 <= 0 && y2 - y1 < h1) || (y1 - y2 >= 0 && y1 - y2 < h2))
+ )
+ }
+ },
+ // 行拖拽
+ rowDrop() {
+ if (this.selectFile) {
+ return
+ }
+ // 目标元素的背景颜色
+ let dragEnterBackCorlor = null
+ // 被拖拽元素的背景色
+ let dragBackCorlor = null
+ const _this = this
+ // 被拖动的元素
+ let dragged = null
+ // 被拖动的元素的索引
+ let draggedIndex = -1
+
+ let parentClassName = 'van-grid'
+ let itemClassName = 'van-grid-item van-grid-item--square'
+ let gridItemChildenClassName =
+ 'grid-item van-grid-item__content van-grid-item__content--center van-grid-item__content--square'
+ if (!_this.grid) {
+ itemClassName = 'el-table__row'
+ parentClassName = 'el-table__body'
+ }
+
+ // 正在拖动的元素
+ let dragingDiv = null
+
+ let container = document.querySelector('.dashboard-container')
+
+ // 目标元素
+ let target = document.querySelector('.el-table__body-wrapper tbody')
+ if (this.grid) {
+ target = document.querySelector('.van-checkbox-group .van-grid')
+ }
+ let draw = document.getElementById('v-draw-rectangle')
+ if (!this.grid) {
+ draw = document.getElementById('drag-table')
+ }
+ let rows = 0 //行数
+
+ let drawOffsetLeft = getElementToPageLeft(draw)
+
+ let firstOver = 0 // 是否刚开始拖动
+ let moveTitle = ''
+ setTimeout(function() {
+ rows = target.childElementCount
+ _this.dragElementList = []
+ for (let i = 0; i < target.childElementCount; i++) {
+ let child = target.children[i]
+ // 设置索引,表格自带rowIndex,这里我们设置grid的
+ if (_this.grid) {
+ if (child.rowIndex !== i) {
+ child.rowIndex = i
+ }
+ child.children[0].children[0].rowIndex = i
+ child = child.children[0].children[0]
+ }
+ // 为画矩形选取准备数据
+ let pos = getObjPos(child)
+ child.w = child.offsetWidth
+ child.h = child.offsetHeight
+ child.x = pos.x
+ child.y = pos.y
+ pos.rowIndex = child.rowIndex
+ _this.dragElementList.push(child)
+
+ // 使元素可拖动
+ child.draggable = true
+ // 给能拖动的元素加上标识,只有加上此标识才能被拖动,否则即使draggable = true,也无法拖动(在全局的ondragstart里拦截)
+ child.slot = 'jmal'
+ let childOfImg = child.querySelector('.el-avatar > img')
+ if (_this.grid) {
+ childOfImg = child.querySelector('.el-image > img')
+ }
+ if (childOfImg) {
+ childOfImg.draggable = false
+ }
+ }
+ }, 300)
+
+ // 被拖动的元素正在那个容器里
+ let dragIndex = -1
+
+ // 判断经过了那个元素
+ let judgThroughDom = function(e, d) {
+ const elPath = e.path || (e.composedPath && e.composedPath())
+ if (d === 'enter') {
+ // 这里进入其他容器后 清除上次进入的容器的状态
+ let node = null
+ const className = e.toElement.className
+ if (_this.grid) {
+ if (e.toElement.className === itemClassName) {
+ node = e.toElement
+ }
+ if (e.toElement.className === parentClassName) {
+ node = e.fromElement
+ }
+ } else {
+ // 列表模式
+ if (
+ elPath[0].id === 'v-draw-rectangle' ||
+ elPath[0].className === 'el-table__virtual-wrapper'
+ ) {
+ // 超出列表底部
+ node = e.toElement
+ } else {
+ // 超出列表顶部
+ node = elPath.find(path => {
+ if (path.className === 'el-table__header-wrapper') {
+ return path
+ }
+ })
+ }
+ }
+ if (node) {
+ // console.log(d,e,node,node.rowIndex)
+ if (dragIndex > -1) {
+ // 清除上次进入的容器的状态
+ const last = target.children[dragIndex]
+ clearClass(last)
+ }
+ dragIndex = -1
+ }
+ }
+ let throughRow = null
+ if (_this.grid) {
+ if (elPath[0].className === gridItemChildenClassName) {
+ // throughRow 表示被拖动的元素正在哪一行上
+ return throughRow
+ } else {
+ throughRow = elPath.find(path => {
+ if (path.className === gridItemChildenClassName) {
+ return path
+ }
+ })
+ }
+ return throughRow
+ } else {
+ if (elPath[0].tagName === 'TD') {
+ // throughRow 表示被拖动的元素正在哪一行上
+ throughRow = elPath.find(path => {
+ if (
+ path.className === 'el-table__row el-table__row--striped' ||
+ path.className === 'el-table__row'
+ ) {
+ return path
+ }
+ })
+ }
+ return throughRow
+ }
+ }
+
+ /***
+ * 复原拖拽的dom
+ * @param animation 是否显示动画
+ */
+ let recoverDragDom = function(animation) {
+ if (animation) {
+ _this.selectRowData.forEach(row => {
+ let dragingDiv = document.getElementById('dragingDiv' + row.index)
+ dragingDiv.style.transition = 'all 0.3s'
+ dragingDiv.style.top =
+ dragingDiv.original.top -
+ (_this.fileListScrollTop - _this.initFileListScrollTop) +
+ 'px'
+ dragingDiv.style.left = dragingDiv.original.left
+ })
+ setTimeout(() => {
+ _this.selectRowData.forEach(row => {
+ draw.removeChild(
+ document.getElementById('dragingDiv' + row.index)
+ )
+ })
+ }, 300)
+ } else {
+ _this.selectRowData.forEach(row => {
+ draw.removeChild(document.getElementById('dragingDiv' + row.index))
+ })
+ }
+ setTimeout(() => {
+ if (!_this.grid) {
+ document
+ .getElementsByClassName('el-table')[0]
+ .classList.add('el-table--enable-row-hover')
+ } else {
+ target.querySelectorAll('.grid-hover-back').forEach(e => {
+ e.classList.add('grid-hover')
+ })
+ }
+ }, 350)
+ _this.draging = 0
+ }
+
+ container.ondragend = function(e) {
+ _this.$store.dispatch('updateMessage', {
+ event: 'onDragStart',
+ data: false,
+ })
+ e.dataTransfer.effectAllowed = 'none'
+ // 清除上次进入的容器的状态
+ const last = target.children[dragIndex]
+ clearClass(last)
+ dragged.style.cursor = 'default'
+ e.target.parentNode.parentNode.title = moveTitle
+ }
+ // 开始拖拽
+ container.ondragstart = e => {
+ if (this.queryFileType === 'trash') {
+ e.preventDefault()
+ e.stopPropagation()
+ return false
+ }
+ // 正在选区获取按住关键键时禁止拖拽
+ if (_this.drawFlag || _this.checkCmdKey(e) || e.shiftKey) {
+ e.preventDefault()
+ e.stopPropagation()
+ return
+ }
+ // 判断被拖拽dom是否有slot属性并且等于'jmal'
+ if (!e.target.slot || e.target.slot !== 'jmal') {
+ return true
+ }
+ // 该文件正在重命名
+ if (e.target.rowIndex === _this.editingIndex) {
+ e.preventDefault()
+ e.stopPropagation()
+ return
+ }
+ e.target.style.cursor = 'no-drop'
+ // 复制被拖拽dom的title, 拖拽过程中移除, 拖拽完后还原
+ moveTitle = e.target.parentNode.parentNode.title
+ e.target.parentNode.parentNode.title = ''
+ // 创建拖拽时的dom, 克隆自被拖拽dom
+ _this.selectRowData.forEach((row, index) => {
+ const element = _this.dragElementList[row.index]
+ const rowIndex = element.rowIndex
+ dragingDiv = element.cloneNode(true)
+ dragingDiv.id = 'dragingDiv' + rowIndex
+ dragingDiv.classList.add('dragingDiv')
+ dragingDiv.classList.remove('el-table_row')
+ dragingDiv.style.transition = 'all 0.3s'
+ dragingDiv.style.zIndex = -1
+ dragingDiv.style.position = 'absolute'
+ const pos = _this.dragElementList[rowIndex]
+ dragingDiv.style.width = pos.w + 'px'
+ dragingDiv.style.height = pos.h + 'px'
+ dragingDiv.style.left = pos.x - drawOffsetLeft + 'px'
+ let dragingDivStyleTop = 0
+ if (!_this.grid) {
+ dragingDiv.firstChild.style.textAlign = 'center'
+ let tds = Array.prototype.slice.call(dragingDiv.childNodes)
+ tds.forEach((node, index) => {
+ if (index === 0) {
+ node.firstChild.style.margin = '0 20px'
+ }
+ if (index === 1) {
+ node.firstChild.style.width = '280px'
+ node.firstChild.style.marginRight = '20px'
+ }
+ if (index === 2) {
+ node.style.borderRadius = '0 12px 12px 0'
+ node.style.borderRight = 'solid 1px var(--apple-shadow-color)'
+ node.firstChild.style.height = '44px'
+ node.firstChild.style.lineHeight = '44px'
+ node.firstChild.style.width = '80px'
+ return true
+ }
+ if (index === 3) {
+ dragingDiv.removeChild(node)
+ }
+ })
+ dragingDivStyleTop = pos.y - _this.fileListScrollTop - 51.5
+ } else {
+ dragingDivStyleTop = pos.y - _this.fileListScrollTop - pos.h / 2 + 10
+ }
+ dragingDiv.style.top = dragingDivStyleTop + 'px'
+ if (index === 0) {
+ let numberFilesCopy = document
+ .getElementById('numberFiles')
+ .cloneNode(true)
+ numberFilesCopy.id = 'numberFilesCopy'
+ numberFilesCopy.querySelector('.number').innerHTML =
+ _this.selectRowData.length + '个文件'
+ dragingDiv.appendChild(numberFilesCopy)
+ }
+ dragingDiv.original = {
+ top: dragingDivStyleTop,
+ left: dragingDiv.style.left,
+ }
+ _this.initFileListScrollTop = _this.fileListScrollTop
+ draw.appendChild(dragingDiv)
+ })
+ firstOver = 0
+ let dragImage = document.getElementById('dragImage')
+ e.dataTransfer.setDragImage(dragImage, 10, 10)
+ _this.$store.dispatch('updateMessage', {
+ event: 'onDragStart',
+ data: true,
+ })
+ // 避免和画矩形选区冲突
+ _this.drawFlag = false
+ let rectangle = document.getElementById('rectangle1')
+ if (rectangle) {
+ document.getElementById('v-draw-rectangle').removeChild(rectangle)
+ }
+ dragged = e.target
+ draggedIndex = dragged.rowIndex
+ // 只有选中的才能拖拽
+ _this.cellMouseIndex = -1
+ dragBackCorlor = dragged.style.backgroundColor
+
+ if (!_this.grid) {
+ document
+ .getElementsByClassName('el-table--enable-row-hover')[0]
+ .classList.remove('el-table--enable-row-hover')
+ } else {
+ target.querySelectorAll('.grid-hover-back').forEach(e => {
+ e.classList.remove('grid-hover')
+ })
+ }
+ _this.draging = 1
+ }
+ container.ondragenter = function(e) {
+ clearTimeout(loop)
+ // 由于被拖动的元素 经过区域内中的每一元素都会触发该事件, 但是我们只需要它正在那一行上就行了
+ let throughRow = judgThroughDom(e, 'enter')
+ if (throughRow) {
+ if (dragIndex !== throughRow.rowIndex) {
+ if (dragIndex > -1) {
+ // 清除上次进入的容器的状态
+ const last = target.children[dragIndex]
+ clearClass(last)
+ }
+ // console.log('拖动进入目标元素'+throughRow.rowIndex,'dragIndex:',dragIndex);
+ // 不是自己或为文件夹时才改变状态
+ if (
+ draggedIndex !== throughRow.rowIndex &&
+ _this.fileList[throughRow.rowIndex].isFolder &&
+ _this.selectRowData.findIndex(
+ item => item.index === throughRow.rowIndex
+ ) === -1
+ ) {
+ // 改变本次进入的容器的状态
+ dragged.style.cursor = 'copy'
+
+ let numberFilesCopy = document.getElementById('numberFilesCopy')
+ numberFilesCopy.style.backgroundColor = '#40a9ffc9'
+ numberFilesCopy.querySelector('.number').style.display = 'none'
+ numberFilesCopy.querySelector('.icon').style.display = 'inline'
+ numberFilesCopy.querySelector('.operate').style.display = 'inline'
+ let targetFolder = numberFilesCopy.querySelector(
+ '.target .folder'
+ )
+ targetFolder.style.display = 'inline'
+ targetFolder.innerHTML = _this.fileList[throughRow.rowIndex].name
+
+ dragEnterBackCorlor = throughRow.style.backgroundColor
+ // 当拖拽文件夹上时,文件夹当背景色
+ const color = '#9fcdfc99'
+ if (_this.grid) {
+ throughRow.style.backgroundColor = color
+ } else {
+ throughRow.childNodes.forEach(
+ node => (node.style.backgroundColor = color)
+ )
+ }
+ }
+ dragIndex = throughRow.rowIndex
+ }
+ leaveIndex = -1
+ }
+ }
+
+ container.ondragover = function(e) {
+ _this.selectRowData.forEach((row, index) => {
+ const drawRectangle = document.getElementById(
+ 'dragingDiv' + row.index
+ )
+ if (drawRectangle) {
+ drawRectangle.style.left =
+ e.clientX - drawOffsetLeft + index * 3 + 10 + 'px'
+ drawRectangle.style.top = e.clientY - 50 + index * 3 + 10 + 'px'
+ if (firstOver === 0) {
+ drawRectangle.style.zIndex = 999
+ setTimeout(() => {
+ drawRectangle.style.transition = ''
+ }, 300)
+ }
+ }
+ })
+ e.preventDefault()
+ leaveIndex = -1
+ firstOver++
+ }
+
+ let loop = null
+ let leaveIndex = -1 // 是否拖出了整个table, -1表示还在table内
+
+ container.ondragleave = function(e) {
+ clearTimeout(loop)
+ let throughRow = judgThroughDom(e, 'leave')
+ if (throughRow) {
+ if (!_this.grid) {
+ if (throughRow.rowIndex === 0 || throughRow.rowIndex === rows - 1) {
+ // 离开第一行或最后一行
+ leaveIndex = throughRow.rowIndex
+ loop = setTimeout(function() {
+ if (leaveIndex > -1) {
+ const leave = target.children[leaveIndex]
+ clearClass(leave)
+ dragIndex = -1
+ }
+ }, 100)
+ }
+ }
+ }
+ }
+ container.ondrop = function() {
+ const form = _this.fileList[draggedIndex]
+ const to = _this.fileList[dragIndex]
+ if (
+ form &&
+ to &&
+ form.id !== to.id &&
+ to.isFolder &&
+ !_this.selectRowData.includes(to)
+ ) {
+ // 移动文件/文件夹
+ let forms = []
+ _this.selectRowData.forEach(row => {
+ forms.push(row.id)
+ })
+ _this
+ .$confirm(
+ `是否将选中的${_this.selectRowData.length}项移动到 ${to.name}?`,
+ '提示',
+ {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'info',
+ }
+ )
+ .then(() => {
+ _this.checkCopyOrMoveApi('move', forms, to.id, to.name)
+ recoverDragDom(false)
+ })
+ .catch(() => {
+ recoverDragDom(true)
+ })
+ } else {
+ recoverDragDom(true)
+ }
+ }
+ // 清除之前的样式
+ let clearClass = function(node) {
+ if (!dragged) {
+ return
+ }
+ if (node) {
+ if (_this.grid) {
+ node = node.children[0].children[0]
+ // #9fcdfc99
+ if (node.style.backgroundColor === 'rgba(159, 205, 252, 0.6)') {
+ node.style.backgroundColor = null
+ }
+ } else {
+ // #9fcdfc99
+ if (
+ node.firstChild.style.backgroundColor ===
+ 'rgba(159, 205, 252, 0.6)'
+ ) {
+ node.childNodes.forEach(node => {
+ node.style.backgroundColor = null
+ })
+ }
+ }
+ dragged.style.cursor = 'default'
+
+ let numberFilesCopy = document.getElementById('numberFilesCopy')
+ if (numberFilesCopy) {
+ numberFilesCopy.style.backgroundColor = '#d2eefa66'
+ numberFilesCopy.querySelector('.number').style.display = 'inline'
+ numberFilesCopy.querySelector('.icon').style.display = 'none'
+ numberFilesCopy.querySelector('.operate').style.display = 'none'
+ numberFilesCopy.querySelector('.target .folder').style.display =
+ 'none'
+ }
+ }
+ dragged.style.backgroundColor = dragBackCorlor
+ }
+
+ function getObjPos(obj) {
+ let pos = { x: 0, y: 0 }
+ while (obj) {
+ pos.x += obj.offsetLeft
+ pos.y += obj.offsetTop
+ obj = obj.offsetParent
+ }
+ return pos
+ }
+ },
+ tableBodyScroll(table, e) {
+ this.fileListScrollTop = e.target.scrollTop
+ let scrollBottom = e.target.scrollHeight - e.target.clientHeight - e.target.scrollTop
+ if (scrollBottom < (e.target.scrollHeight * 0.2)) {
+ if (!this.finished) {
+ if (!this.pageLoadCompleteList[this.pagination.pageIndex]) {
+ return
+ }
+ if (this.listModeSearch) {
+ if (this.listModeSearchOpenDir) {
+ this.searchFileAndOpenDir(this.listModeSearchOpenDir, true)
+ } else {
+ this.searchFile(this.searchFileName, true)
+ }
+ } else {
+ this.getFileListEnter(true)
+ }
+ }
+ }
+ },
+ }
+}
diff --git a/src/components/ShowFile/mixins/fileHandel.js b/src/components/ShowFile/mixins/fileHandel.js
new file mode 100644
index 0000000..8ce960c
--- /dev/null
+++ b/src/components/ShowFile/mixins/fileHandel.js
@@ -0,0 +1,876 @@
+import api from '@/api/file-api'
+import fileConfig from '@/utils/file-config'
+export default {
+ props: {
+ showUploadButton: {
+ type: Boolean,
+ default: true,
+ },
+ },
+ data() {
+ return {
+ newCreateFileDialog: false,
+ newCreateFileName: '',
+ newCreateFileDialogTitle: '',
+ createFileLoading: false,
+ renameFileName: '',
+ newFolderLoading: false,
+ renameLoading: false,
+ cellMouseIndex: -1,
+ editingIndex: -1,
+ titlePrefix: '',
+ unzipOperating: false,
+ dialogMoveOrCopyVisible: false,
+ fileTreeAndNewFolderDisabled: false,
+ directoryTreeData: [],
+ compressedFileVisible: false,
+ compressedFileData: [],
+ compressedFileName: '',
+ compressedFileTempDir: false,
+ selectTreeNode: {},
+ directoryTreeProps: {
+ label: 'name',
+ children: 'children',
+ isLeaf: 'isLeaf',
+ },
+ existsFileList: [], // 移动或复制存在的文件列表
+ copyOrMoveConfirmVisible: false, // 移动或复制警告弹出框
+ copyOrMoveParams: {
+ operating: 'copy',
+ froms: [],
+ to: '',
+ targetPath: ''
+ }, // 移动或复制要传递的参数
+ copyOrMoveToName: '', // 移动或复制到的文件夹名称
+ deleteConfirmVisible: false, // 删除确认弹窗
+ permanentDelete: false, // 是否永久删除
+ permanentDeleteDisable: false, // 是否禁用永久删除选项
+ }
+ },
+ methods: {
+ // 新建文件夹
+ newFolderNameClick() {
+ if (this.newFolderName) {
+ if (/[\[\]\/\\"<>\?\*]/gi.test(this.newFolderName)) {
+ this.$message({
+ message: '文件名不能包含以下字符:<,>,|,*,?,,/,[,]',
+ type: 'warning',
+ })
+ return
+ }
+ this.newFolderLoading = true
+ this.createFileLoading = true
+ api.uploadFolder({
+ isFolder: true,
+ filename: encodeURIComponent(this.newFolderName),
+ currentDirectory: this.getQueryPath(),
+ folder: this.$route.query.searchOpenFolder || this.$route.query.folder,
+ username: this.$store.state.user.name,
+ userId: this.$store.state.user.userId,
+ })
+ .then(res => {
+ if (res.data === 1) {
+ this.newFolderLoading = false
+ this.$message({
+ message: '该文件夹已存在',
+ type: 'warning',
+ })
+ } else {
+ this.createFileLoading = false
+ this.newCreateFileDialog = false
+ this.newFolderLoading = false
+ this.showNewFolder = false
+ this.isShowNewFolder = false
+ this.$notify({
+ title: '新建文件夹成功',
+ type: 'success',
+ duration: 1000,
+ })
+ this.getFileListEnter()
+ }
+ })
+ .catch(() => {
+ this.newFolderLoading = false
+ this.createFileLoading = false
+ })
+ } else {
+ this.newFolderLoading = false
+ this.$message({
+ message: '请输入文件夹名称',
+ type: 'warning',
+ })
+ }
+ },
+ // 新建文件
+ createFile(newFileName) {
+ if (this.newCreateFileDialogTitle === '新建文件夹') {
+ this.newFolderName = newFileName
+ this.newFolderNameClick()
+ return
+ }
+ if (newFileName) {
+ if (/[\[\]\/\\"<>\?\*]/gi.test(newFileName)) {
+ this.$message({
+ message: '文件名不能包含以下字符:<,>,|,*,?,,/,[,]',
+ type: 'warning',
+ })
+ return
+ }
+ this.createFileLoading = true
+ let parentPath = '/'
+ if (this.path) {
+ if (this.path.length > 0) {
+ parentPath = this.path
+ }
+ }
+ let suffix = newFileName.substring(newFileName.lastIndexOf('.') + 1)
+ api.addFile({
+ fileName: encodeURIComponent(newFileName),
+ isFolder: false,
+ folder: this.$route.query.searchOpenFolder || this.$route.query.folder,
+ username: this.$store.state.user.name,
+ parentPath: encodeURIComponent(parentPath),
+ })
+ .then(res => {
+ this.createFileLoading = false
+ switch (suffix && !this.$route.query.folder) {
+ case 'txt':
+ // 打开编辑器
+ this.textPreviewRow = res.data
+ this.textPreviewVisible = true
+ break
+ case 'drawio':
+ case 'mind':
+ case 'docx':
+ case 'xlsx':
+ case 'pptx':
+ this.iframePreviewRow = res.data
+ this.iframePreviewVisible = true
+ break
+ }
+ const that = this
+ this.setOnCreateFilename(newFileName)
+ setTimeout(function() {
+ that.newCreateFileDialog = false
+ }, 200)
+ })
+ .catch(() => {
+ this.createFileLoading = false
+ })
+ }
+ },
+ // 新建文件
+ createNewFile(suffix) {
+ if (this.newCreateFileDialogTitle === '新建文件夹') {
+ this.newCreateFileName = `新建文件夹`
+ } else {
+ this.newCreateFileName = `未命名文件.${suffix}`
+ }
+ this.newCreateFileName = this.getNewFileName(
+ this.fileList,
+ this.newCreateFileName
+ )
+ this.newCreateFileDialog = true
+ this.$nextTick(() => {
+ let newFileNameInput = this.$refs.newCreateFileName.$el.querySelector(
+ '.el-input__inner'
+ )
+ this.renameInputFocus(newFileNameInput, suffix)
+ })
+ },
+ newFolder() {
+ this.newFolderName = this.getNewFileName(this.fileList, '新建文件夹')
+ this.showNewFolder = true
+ this.$nextTick(() => {
+ this.$refs.newFolderName.focus()
+ this.$refs.newFolderName.select()
+ })
+ },
+ // 统计文件和文件夹
+ getShowSumFileAndFolder(fileList) {
+ let folderSize = 0
+ let fileSize = 0
+ fileList.forEach(fileInfo => {
+ if (fileInfo.isFolder) {
+ folderSize += 1
+ } else {
+ fileSize += 1
+ }
+ })
+ let folderSum = ''
+ if (folderSize > 0) {
+ folderSum = folderSize + '个文件夹'
+ }
+ let fileSum = ''
+ if (fileSize > 0) {
+ fileSum = fileSize + '个文件'
+ }
+ const stand = folderSize > 0 && fileSize > 0 ? '、' : ''
+ return folderSum + stand + fileSum
+ },
+ // 计算总大小
+ getShowSumSize(totalSize) {
+ let sizeSum = ''
+ if (totalSize < 1024) {
+ sizeSum += totalSize + 'B'
+ } else if (totalSize >= 1024 && totalSize < 1024 * 1024) {
+ sizeSum += (totalSize / 1024).toFixed(2) + 'K'
+ } else if (totalSize >= 1024 * 1024 && totalSize < 1024 * 1024 * 1024) {
+ sizeSum += (totalSize / (1024 * 1024)).toFixed(2) + 'M'
+ } else {
+ sizeSum += (totalSize / (1024 * 1024 * 1024)).toFixed(2) + 'G'
+ }
+ return sizeSum
+ },
+ // 重命名
+ rowRename(newFileName, row) {
+ //去掉回车换行
+ newFileName = newFileName.replace(/[\r\n]/g, '')
+ if (newFileName) {
+ if (/[\[\]\/\\"<>\?\*]/gi.test(newFileName)) {
+ this.$message({
+ message: '文件名不能包含以下字符:<,>,|,*,?,,/,[,]',
+ type: 'warning',
+ })
+ return
+ }
+ let strFileName = newFileName.replace(/(.*\/)*([^.]+).*/gi, '$2')
+ let newExt = newFileName.replace(/.+\./, '')
+ if (!row.isFolder) {
+ if (row.suffix !== newExt) {
+ this.$confirm(
+ `您确定要将扩展名“.${row.suffix}”更改为“.${newExt}”吗?`,
+ '提示',
+ {
+ type: 'warning',
+ showClose: false,
+ closeOnClickModal: false,
+ confirmButtonText: `保持.${row.suffix}`,
+ cancelButtonText: `使用.${newExt}`,
+ }
+ ).then(() => {
+ newFileName = strFileName + '.' + row.suffix
+ }).catch(() => {}).then(() => {
+ this.rename(row, newFileName)
+ })
+ } else {
+ this.rename(row, newFileName)
+ }
+ } else {
+ this.rename(row, newFileName)
+ }
+ } else {
+ this.editingIndex = -1
+ }
+ },
+ rename(row, newFileName) {
+ if (row.name === newFileName) {
+ this.editingIndex = -1
+ return
+ }
+ this.renameLoading = true
+ const findIndex = this.fileList.findIndex(item => {
+ if (newFileName === item.name) {
+ return item
+ }
+ })
+ if (findIndex > -1) {
+ let msg = '该文件已存在'
+ if (row.isFolder) {
+ msg = '该文件夹已存在'
+ }
+ this.$message({
+ message: msg,
+ type: 'warning',
+ })
+ this.renameLoading = false
+ return
+ }
+ api.rename({
+ newFileName: encodeURIComponent(newFileName),
+ username: this.$store.state.user.name,
+ folder: this.$route.query.searchOpenFolder || this.$route.query.folder,
+ id: row.id,
+ }).then(() => {
+ this.renameLoading = false
+ row.name = newFileName
+ row.suffix = newFileName.replace(/.+\./, '')
+ this.fileList[row.index] = row
+ this.editingIndex = -1
+ }).then(() => {
+ this.fileListTableClearSelection()
+ this.setOnCreateFilename(newFileName)
+ }).catch(() => {
+ this.renameLoading = false
+ this.editingIndex = -1
+ })
+ },
+ // 选取输入框部分内容
+ renameInputFocus(doc, suffix) {
+ this.setInputFocus()
+ doc.focus()
+ doc.selectionStart = 0
+ doc.selectionEnd = doc.value.length
+ if (suffix) {
+ doc.selectionEnd -= suffix.length + 1
+ }
+ },
+ setOnCreateFilename(newFileName) {
+ if (this.$route.query.folder) {
+ this.onCreateFilename = newFileName
+ this.getFileListEnter()
+ this.clearOnCreateFilename()
+ }
+ },
+ removeOperation() {
+ this.permanentDelete = false
+ this.selectFileList = this.getSelectFileList()
+ this.deleteConfirmVisible = true
+ },
+ onCopy(fileIdList, targetPath, targetFolder) {
+ this.checkCopyOrMoveApi('copy', fileIdList, targetFolder, undefined, targetPath)
+ },
+ onMove(fileIdList, targetPath, targetFolder) {
+ this.checkCopyOrMoveApi('move', fileIdList, targetFolder, undefined, targetPath)
+ },
+ copyOperation() {
+ this.$store.dispatch('updateFileClipboard', this.getSelectFileList())
+ },
+ // 加载下一级文件树
+ directoryTreeLoadNode(node, resolve) {
+ let fileId = null
+ if (node.level === 0) {
+ const that = this
+ setTimeout(function() {
+ that.$refs.directoryTree.setCurrentKey('0')
+ }, 0)
+ return resolve([{ id: '0', name: '根目录' }])
+ }
+ if (node.level > 1) {
+ fileId = node.data.mountFileId || node.data.id
+ }
+ api.queryFileTree({
+ userId: this.$store.state.user.userId,
+ username: this.$store.state.user.name,
+ fileId: fileId,
+ }).then(res => {
+ const nextNodes = res.data
+ return resolve(nextNodes)
+ })
+ },
+ // 点击文件树
+ treeNodeClick(row, node, event) {
+ this.fileTreeAndNewFolderDisabled = row.hasOwnProperty('newFolder')
+ this.selectTreeNode = row
+ this.selectTreeNode.showName = ' "' + row.name + '"'
+ },
+ // 节点被展开时触发
+ treeNodeExpand(row, node, event) {},
+ // 文件树里新建文件夹
+ fileTreeAndNewFolder() {
+ let newNodeId = 'newFolderNodeKey'
+ let node = this.$refs.directoryTree.getNode(newNodeId)
+ if (node !== null) {
+ this.$refs.directoryTree.remove(node)
+ }
+
+ let childNodes = this.$refs.directoryTree.store.currentNode.childNodes
+ let newFolderName = this.getNewFileName(childNodes, '新建文件夹')
+ let newNode = {
+ id: newNodeId,
+ newFolder: true,
+ name: newFolderName,
+ showName: newFolderName,
+ isLeaf: true,
+ }
+ this.$refs.directoryTree.append(newNode, this.selectTreeNode)
+ setTimeout(function() {
+ let treeInput = document.getElementById('treeInput')
+ if (treeInput) {
+ treeInput.value = newFolderName
+ treeInput.focus()
+ treeInput.select()
+ }
+ }, 100)
+ },
+ // 移动文件
+ moveFileTree() {
+ this.copyOrMove('move')
+ },
+ // 复制文件
+ copyFileTree() {
+ this.copyOrMove('copy')
+ },
+ // 解压文件
+ confirmUnzip() {
+ this.unzip(this.openingFile, this.selectTreeNode.id, false)
+ },
+ showDialogMoveOrCopyVisible() {
+ this.dialogMoveOrCopyVisible = true
+ },
+ /**
+ * 创建副本
+ */
+ duplicate() {
+ const newFilename = this.getDuplicateFileName(
+ this.fileList,
+ this.rowContextData.name
+ )
+ api
+ .duplicateFile({
+ fileId: this.rowContextData.id,
+ newFilename: newFilename,
+ })
+ .then(() => {
+ this.$message.success('创建副本成功')
+ this.setOnCreateFilename(newFilename)
+ })
+ },
+ moveOrCopy() {
+ this.showDialogMoveOrCopyVisible()
+
+ this.titlePrefix = '移动或复制到: '
+ this.unzipOperating = false
+ const that = this
+ setTimeout(function() {
+ that.selectTreeNode = that.$refs.directoryTree.getCurrentNode()
+ that.selectTreeNode.showName = ' "' + that.selectTreeNode.name + '"'
+ }, 100)
+ },
+ copyOrMove(operating) {
+ let operation = '复制'
+ if (operating === 'move') {
+ operation = '移动'
+ }
+ let selectNodePath = '/'
+ if (this.selectTreeNode.path) {
+ selectNodePath =
+ this.selectTreeNode.path + this.selectTreeNode.name + '/'
+ }
+
+ let fileIds = []
+ if (this.menusIsMultiple || this.selectRowData.length > 1) {
+ const exits = this.$refs.fileListTable.tableSelectData.some(value => {
+ fileIds.push(value.id)
+ const thisParentPath = value.path
+ if (thisParentPath === selectNodePath) {
+ this.$message({
+ message: '不能将文件' + operation + '到自身或其子目录下',
+ type: 'warning',
+ })
+ return true
+ }
+ })
+ if (exits) {
+ return
+ }
+ } else {
+ if (this.rowContextData.id) {
+ fileIds.push(this.rowContextData.id)
+ } else {
+ fileIds.push(this.rowContextData[0].id)
+ }
+ }
+ this.checkCopyOrMoveApi(operating, fileIds, this.selectTreeNode.id, this.selectTreeNode.name)
+ },
+ checkCopyOrMoveApi(operating, froms, to, toName, targetPath) {
+ if (!to && !targetPath) {
+ to = '0'
+ toName = '根目录'
+ }
+ if (targetPath) {
+ toName = path.basename(targetPath)
+ }
+ api['checkMoveOrCopy']({
+ userId: this.$store.state.user.userId,
+ username: this.$store.state.user.name,
+ froms: froms,
+ to: to,
+ targetPath: targetPath
+ }).then((res) => {
+ if (res.count > 0) {
+ this.copyOrMoveConfirmVisible = true
+ this.copyOrMoveParams = {operating: operating, froms: froms, to: to, targetPath: targetPath}
+ this.copyOrMoveToName = `${(operating === 'copy' ? '复制' : '移动')}到: "${toName}"`
+ this.existsFileList = res.data
+ } else {
+ this.copyOrMoveApi(operating, froms, to, false, targetPath)
+ }
+ })
+ },
+ copyOrMoveApi(operating, froms, to, isOverride, targetPath) {
+ this.copyOrMoveConfirmVisible = false
+ let operation = '复制'
+ if (operating === 'move') {
+ operation = '移动'
+ }
+ let copying = this.$message({
+ iconClass: 'el-icon-loading',
+ type: 'info',
+ duration: 0,
+ dangerouslyUseHTMLString: true,
+ message: operation + '中...',
+ })
+ this.dialogMoveOrCopyVisible = false
+ api[operating]({
+ userId: this.$store.state.user.userId,
+ username: this.$store.state.user.name,
+ froms: froms,
+ to: to,
+ targetPath: targetPath,
+ isOverride: isOverride
+ }).then(() => {
+ this.$refs.fileClipboard.clear()
+ copying.iconClass = null
+ copying.type = 'success'
+ copying.message = operation + '中...'
+ if (this.rowContextData.isFolder) {
+ this.$refs.directoryTree.append(this.rowContextData, to)
+ }
+ if (operating === 'move') {
+ // 移除列表
+ this.getFileListEnter()
+ }
+ setTimeout(function() {
+ copying.close()
+ }, 1000)
+ }).catch(() => {
+ copying.close()
+ })
+ },
+ renderContent(h, { node, data, store }) {
+ if (data.newFolder) {
+ return (
+
+
+
') + formatVideo(file.video, '
')
+ },
+ tooltipConfig(item) {
+ // 使用模板字符串构建更清晰的 HTML
+ const contentHTML = `
+