commit
8d4162426a
File diff suppressed because it is too large
Load Diff
48
src/components/ShowFile/mixins/clipboard.js
Normal file
48
src/components/ShowFile/mixins/clipboard.js
Normal file
@ -0,0 +1,48 @@
|
||||
import store from '@/store'
|
||||
import fileConfig from '@/utils/file-config'
|
||||
|
||||
export default {
|
||||
|
||||
computed: {
|
||||
fileClipboard() {
|
||||
return store.getters.fileClipboard
|
||||
},
|
||||
getClipboardFileIdList() {
|
||||
return store.getters.fileClipboard.map(file => file.id)
|
||||
},
|
||||
},
|
||||
props: {
|
||||
showClipboard: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 复制下载链接
|
||||
copyDownloadLink(row, elName) {
|
||||
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(elName, {
|
||||
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()
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
23
src/components/ShowFile/mixins/common.js
Normal file
23
src/components/ShowFile/mixins/common.js
Normal file
@ -0,0 +1,23 @@
|
||||
import { formatSize, formatTime } from '@/utils/number'
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
imageUrl() {
|
||||
return `${process.env.VUE_APP_BASE_API}/view/thumbnail?jmal-token=${this.$store.state.user.token}&name=${this.$store.state.user.name}&id=`
|
||||
},
|
||||
audioCoverUrl() {
|
||||
return `${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)
|
||||
},
|
||||
}
|
||||
}
|
||||
452
src/components/ShowFile/mixins/fileContextmenu.js
Normal file
452
src/components/ShowFile/mixins/fileContextmenu.js
Normal file
@ -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, '.file-contextmenu')
|
||||
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
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
740
src/components/ShowFile/mixins/fileDrag.js
Normal file
740
src/components/ShowFile/mixins/fileDrag.js
Normal file
@ -0,0 +1,740 @@
|
||||
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
|
||||
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 = ''
|
||||
|
||||
this.$nextTick(() => {
|
||||
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
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// 被拖动的元素正在那个容器里
|
||||
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 (className === itemClassName) {
|
||||
node = e.toElement
|
||||
}
|
||||
if (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)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
882
src/components/ShowFile/mixins/fileHandle.js
Normal file
882
src/components/ShowFile/mixins/fileHandle.js
Normal file
@ -0,0 +1,882 @@
|
||||
import api from '@/api/file-api'
|
||||
import fileConfig from '@/utils/file-config'
|
||||
import path from 'path'
|
||||
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(() => {
|
||||
const finalFileName = strFileName + '.' + row.suffix
|
||||
this.rename(row, finalFileName)
|
||||
}).catch(() => {
|
||||
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 (
|
||||
<span class="custom-tree-node">
|
||||
<span>
|
||||
<svg-icon icon-class="folder" />
|
||||
</span>
|
||||
<span>
|
||||
<div class="el-input el-input--mini el-input-tree">
|
||||
<input
|
||||
type="text"
|
||||
autocomplete="on"
|
||||
value="新建文件夹"
|
||||
id="treeInput"
|
||||
class="el-input__inner"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
on-click={() => {
|
||||
let path = '/'
|
||||
let parentData = node.parent.data
|
||||
if (parentData.path) {
|
||||
path = parentData.path + parentData.name + path
|
||||
}
|
||||
let newFolderName = document.getElementById('treeInput').value
|
||||
api
|
||||
.newFolder({
|
||||
isFolder: true,
|
||||
filename: encodeURIComponent(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 => {
|
||||
data.newFolder = false
|
||||
data.name = newFolderName
|
||||
data.id = res.data
|
||||
})
|
||||
.catch(() => {
|
||||
window.event.preventDefault()
|
||||
window.event.stopPropagation()
|
||||
})
|
||||
}}
|
||||
class="el-button el-icon-check el-button--mini el-input-tree-button"
|
||||
element-loading-spinner="el-icon-loading"
|
||||
element-loading-background="#f6f7fa88"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
on-click={() => {
|
||||
this.$refs.directoryTree.remove(node)
|
||||
window.event.preventDefault()
|
||||
window.event.stopPropagation()
|
||||
}}
|
||||
class="el-button el-icon-close el-button--mini el-input-tree-button"
|
||||
element-loading-spinner="el-icon-loading"
|
||||
element-loading-background="#f6f7fa88"
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
if (node.expanded) {
|
||||
return (
|
||||
<span class="custom-tree-node">
|
||||
<svg-icon icon-class="open-folder" />
|
||||
<span style="margin-left: 5px;">{node.label}</span>
|
||||
<span />
|
||||
</span>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<span class="custom-tree-node">
|
||||
<svg-icon icon-class="folder" />
|
||||
<span style="margin-left: 5px;">{node.label}</span>
|
||||
<span />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
},
|
||||
allocateTag() {
|
||||
// 将this.$refs.fileListTable.tableSelectData拷贝给tagDialogObjectList而不是赋值
|
||||
this.tagDialogObjectList = JSON.parse(
|
||||
JSON.stringify(this.$refs.fileListTable.tableSelectData)
|
||||
)
|
||||
this.tagDialogVisible = true
|
||||
},
|
||||
allocateTagSuccess() {
|
||||
this.getFileListEnter()
|
||||
},
|
||||
share(row) {
|
||||
if (!row || !row.id) {
|
||||
if (this.rowContextData.id) {
|
||||
row = this.rowContextData
|
||||
} else {
|
||||
row = this.$refs.fileListTable.tableSelectData[0]
|
||||
}
|
||||
}
|
||||
this.shareDialogObject = row
|
||||
this.shareDialogObject.fileId = row.id
|
||||
this.shareDialogObject.shareBase = row.shareBase
|
||||
this.shareDialogObject.subShare = row.subShare
|
||||
this.shareDialogVisible = true
|
||||
},
|
||||
shareSuccess(shareBase, subShare) {
|
||||
this.updateRowContextData()
|
||||
this.rowContextData.shareBase = shareBase
|
||||
this.rowContextData.subShare = subShare
|
||||
this.rowContextData.isShare = true
|
||||
},
|
||||
onCancelShare() {
|
||||
this.updateRowContextData()
|
||||
delete this.rowContextData.shareBase
|
||||
delete this.rowContextData.subShare
|
||||
delete this.rowContextData.isShare
|
||||
},
|
||||
updateRowContextData() {
|
||||
// 这3行代码是为了让vue刷新数据
|
||||
const isFavorite = this.rowContextData.isFavorite
|
||||
this.rowContextData.isFavorite = !isFavorite
|
||||
this.rowContextData.isFavorite = isFavorite
|
||||
},
|
||||
downloadFile() {
|
||||
let fileIds = []
|
||||
if (this.$refs.fileListTable.tableSelectData.length > 0) {
|
||||
this.$refs.fileListTable.tableSelectData.forEach(value => {
|
||||
fileIds.push(value.id)
|
||||
})
|
||||
} else {
|
||||
fileIds.push(this.rowContextData.id)
|
||||
}
|
||||
if (fileIds.length > 1 || this.rowContextData.isFolder) {
|
||||
fileConfig.packageDownload(fileIds)
|
||||
return
|
||||
}
|
||||
fileConfig.download(
|
||||
this.$store.state.user.name,
|
||||
this.rowContextData,
|
||||
this.$store.getters.token
|
||||
)
|
||||
},
|
||||
// 收藏/取消收藏
|
||||
favoriteOperating(isFavorite) {
|
||||
const fileIds = this.getSelectIdList()
|
||||
this.rowContextData.isFavorite = isFavorite
|
||||
this.highlightFavorite(isFavorite, true)
|
||||
api
|
||||
.favoriteUrl({
|
||||
fileIds: fileIds,
|
||||
isFavorite: isFavorite,
|
||||
})
|
||||
.then(() => {
|
||||
// 收藏页面
|
||||
const homePage =
|
||||
!this.$route.query.path || this.$route.query.length <= 1
|
||||
if (!isFavorite && this.isCollectView && homePage) {
|
||||
// 移除列表
|
||||
this.removeSelectItem()
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.rowContextData.isFavorite = !isFavorite
|
||||
})
|
||||
},
|
||||
// 移动至回收站
|
||||
moveToRecycle() {
|
||||
this.permanentDelete = false
|
||||
this.deleteFile()
|
||||
},
|
||||
// 彻底删除
|
||||
sweepDeleteFile() {
|
||||
this.permanentDelete = true
|
||||
this.deleteFile()
|
||||
},
|
||||
// 删除
|
||||
deleteFile() {
|
||||
// 提取出selectFileList中的id
|
||||
const fileIds = this.selectFileList.map(item => item.id)
|
||||
this.deleteLoading = true
|
||||
api.delete({
|
||||
currentDirectory: this.getQueryPath(),
|
||||
username: this.$store.state.user.name,
|
||||
fileIds: fileIds,
|
||||
sweep: this.permanentDelete,
|
||||
}).then(() => {
|
||||
this.deleteLoading = false
|
||||
this.deleteConfirmVisible = false
|
||||
// 刷新列表
|
||||
if (this.$route.query.folder) {
|
||||
this.getFileListEnter()
|
||||
}
|
||||
}).catch(() => {
|
||||
this.deleteLoading = false
|
||||
this.deleteConfirmVisible = false
|
||||
})
|
||||
},
|
||||
restoreFile() {
|
||||
const fileIds = this.getSelectIdList()
|
||||
api.restore({fileIds: fileIds}).then()
|
||||
},
|
||||
sweepFile() {
|
||||
const fileIds = this.getSelectIdList()
|
||||
this.$confirm(`此操作将永久删除 ${fileIds.length}个文件, 是否继续?`, '提示', {
|
||||
confirmButtonText: '彻底删除',
|
||||
confirmButtonClass: 'el-button--danger',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
api.sweep({fileIds: fileIds}).then()
|
||||
})
|
||||
},
|
||||
clearTrash() {
|
||||
this.$confirm(`是否清空回收站? 此操作将无法还原!!!`, '提示', {
|
||||
confirmButtonText: '清空',
|
||||
confirmButtonClass: 'el-button--danger',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
api.clearTrash().then()
|
||||
})
|
||||
},
|
||||
// 移除选中项
|
||||
removeSelectItem() {
|
||||
let removeFileIndexList = []
|
||||
if (this.$refs.fileListTable.tableSelectData.length > 0) {
|
||||
this.$refs.fileListTable.tableSelectData.forEach(item => {
|
||||
let fileIndex = this.fileList.findIndex(file => file.id === item.id)
|
||||
if (fileIndex > -1) {
|
||||
removeFileIndexList.push(fileIndex)
|
||||
}
|
||||
})
|
||||
}
|
||||
// 先清空之前选择的数据
|
||||
this.$refs.fileListTable.doLayout()
|
||||
this.fileListTableClearSelection()
|
||||
this.$refs.fileListTable.tableSelectData = []
|
||||
// 倒序
|
||||
removeFileIndexList = removeFileIndexList.sort((a, b) => b - a)
|
||||
setTimeout(() => {
|
||||
// 再执行移除
|
||||
for (let i = 0; i < removeFileIndexList.length; i++) {
|
||||
this.fileList.splice(removeFileIndexList[i], 1)
|
||||
}
|
||||
this.fileList.map((item, index) => {
|
||||
item.index = index
|
||||
})
|
||||
// 改变拖拽目标
|
||||
this.rowDrop()
|
||||
// 画矩形选取
|
||||
this.drawRectangle()
|
||||
}, 300)
|
||||
},
|
||||
// 获取选中项id列表
|
||||
getSelectIdList() {
|
||||
const fileIds = []
|
||||
if (this.selectRowData.length > 1 || this.menusIsMultiple) {
|
||||
this.$refs.fileListTable.tableSelectData.forEach(value => {
|
||||
fileIds.push(value.id)
|
||||
})
|
||||
} else {
|
||||
fileIds.push(this.rowContextData.id)
|
||||
}
|
||||
return fileIds
|
||||
},
|
||||
getSelectFileList() {
|
||||
this.permanentDeleteDisable = false;
|
||||
let selectedSource = [];
|
||||
if (this.selectRowData.length > 1 || this.menusIsMultiple) {
|
||||
selectedSource = this.$refs.fileListTable.tableSelectData;
|
||||
} else if (this.rowContextData) {
|
||||
selectedSource = [this.rowContextData];
|
||||
}
|
||||
|
||||
if (selectedSource.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const fileList = selectedSource.map(({ id, suffix, name, mountFileId, contentType, isFolder, music, video }) => {
|
||||
return { id, suffix, name, mountFileId, contentType, isFolder, music, video };
|
||||
});
|
||||
|
||||
if (fileList.length > 0) {
|
||||
this.checkPermanentDelete(fileList[0]);
|
||||
}
|
||||
return fileList;
|
||||
},
|
||||
checkPermanentDelete(file) {
|
||||
if (/\//.test(file.id) || file.mountFileId) {
|
||||
this.permanentDeleteDisable = true
|
||||
this.permanentDelete = true
|
||||
}
|
||||
},
|
||||
// 解压文件
|
||||
unzip(file, destFileId, tempDir) {
|
||||
let status = '解压'
|
||||
let decompressing = this.$message({
|
||||
iconClass: 'el-icon-loading',
|
||||
type: 'info',
|
||||
duration: 0,
|
||||
dangerouslyUseHTMLString: true,
|
||||
message: '<span> 正在' + status + '</span>',
|
||||
})
|
||||
api.unzip({
|
||||
fileId: file.id,
|
||||
destFileId: destFileId,
|
||||
})
|
||||
.then(res => {
|
||||
decompressing.iconClass = null
|
||||
decompressing.type = 'success'
|
||||
decompressing.message = status + '成功'
|
||||
|
||||
if (tempDir) {
|
||||
this.compressedFileData = res.data
|
||||
this.compressedFileVisible = true
|
||||
this.compressedFileName = file.name
|
||||
this.compressedFileTempDir = tempDir
|
||||
}
|
||||
|
||||
const that = this
|
||||
setTimeout(function() {
|
||||
decompressing.close()
|
||||
that.openCompressionVisible = false
|
||||
if (file.id === destFileId) {
|
||||
that.getFileListEnter()
|
||||
}
|
||||
if (destFileId && file.id !== destFileId && !tempDir) {
|
||||
that.dialogMoveOrCopyVisible = false
|
||||
}
|
||||
}, 1000)
|
||||
})
|
||||
.catch(() => {
|
||||
decompressing.close()
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
477
src/components/ShowFile/mixins/fileList.js
Normal file
477
src/components/ShowFile/mixins/fileList.js
Normal file
@ -0,0 +1,477 @@
|
||||
import api from '@/api/file-api'
|
||||
import _ from 'lodash'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
debounceGetFileList: null,// 获取文件列表防抖
|
||||
fileList: [],
|
||||
pageLoadCompleteList: [],
|
||||
pagination: {
|
||||
pageIndex: 1,
|
||||
pageSize: 50,
|
||||
total: 0,
|
||||
pageSizes: [10, 20, 30, 40, 50],
|
||||
},
|
||||
clientHeight: 500,
|
||||
tableHeadNameWidth: 500,
|
||||
// 表头数据
|
||||
tableHead: [
|
||||
{
|
||||
name: '',
|
||||
label: '',
|
||||
index: 0,
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
label: '',
|
||||
index: 1,
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
label: '名称',
|
||||
sortable: true,
|
||||
index: 2,
|
||||
},
|
||||
{
|
||||
name: 'size',
|
||||
label: '大小',
|
||||
sortable: true,
|
||||
index: 3,
|
||||
},
|
||||
{
|
||||
name: 'updateDate',
|
||||
label: '修改日期',
|
||||
sortable: true,
|
||||
index: 4,
|
||||
},
|
||||
],
|
||||
tableLoading: true,
|
||||
finished: false,
|
||||
grid: this.defaultGrid,
|
||||
vmode: this.defaultGrid ? 'grid' : 'list',
|
||||
gridColumnNum: -1,
|
||||
gridPaddingRight: 0,
|
||||
gridItemWidth: 125,
|
||||
gridMinHeight: 125,
|
||||
onCreateFilename: '',
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.debounceGetFileList = _.debounce((onLoad) => {
|
||||
this.getFileList(onLoad)
|
||||
}, 200)
|
||||
},
|
||||
mounted() {
|
||||
// 加载布局
|
||||
if (this.$route.query.vmode) {
|
||||
this.vmode = this.$route.query.vmode
|
||||
} else {
|
||||
if (this.defaultGrid) {
|
||||
this.vmode = 'grid'
|
||||
} else {
|
||||
this.vmode = 'list'
|
||||
}
|
||||
}
|
||||
if (this.vmode === 'list') {
|
||||
this.grid = false
|
||||
if (!this.selectFile) {
|
||||
this.lessClientHeight = 140
|
||||
}
|
||||
} else {
|
||||
this.grid = true
|
||||
if (!this.selectFile) {
|
||||
this.lessClientHeight = 106
|
||||
}
|
||||
this.containerResize()
|
||||
}
|
||||
// 加载url上的path
|
||||
if (this.$route.query.path !== '/') {
|
||||
const path = decodeURI(this.$route.query.path)
|
||||
this.pathList.splice(1, 1)
|
||||
path.split('/').forEach((pathName, index) => {
|
||||
if (index > 0) {
|
||||
const item = {}
|
||||
item['folder'] = pathName
|
||||
this.pathList.push(item)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (this.$route.query.searchOpenFolder && this.path && !this.$route.query.keyword) {
|
||||
localStorage.setItem(this.path, this.$route.query.searchOpenFolder)
|
||||
}
|
||||
if (this.$route.query.highlight) {
|
||||
this.onCreateFilename = this.$route.query.highlight
|
||||
this.clearOnCreateFilename()
|
||||
}
|
||||
// remove query.basePath
|
||||
if (this.$route.query.basePath) {
|
||||
this.basePath = this.$route.query.basePath
|
||||
}
|
||||
|
||||
// remove query.folder
|
||||
if (this.$route.query.searchOpenFolder && this.$route.query.keyword) {
|
||||
const query = { ...this.$route.query }
|
||||
delete query.searchOpenFolder
|
||||
this.$router.replace({ query })
|
||||
}
|
||||
|
||||
if (this.$route.query.keyword) {
|
||||
this.filterOption = localStorage.getItem('searchFilterOption') ? JSON.parse(localStorage.getItem('searchFilterOption')) : {}
|
||||
this.$refs.searchOption.setFilterOption(this.filterOption)
|
||||
}
|
||||
|
||||
let that = this
|
||||
window.onresize = function() {
|
||||
that.clientHeight = document.documentElement.clientHeight - that.lessClientHeight
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
if (!this.getFileListed) {
|
||||
this.getFileListEnter()
|
||||
}
|
||||
}, 50)
|
||||
},
|
||||
methods: {
|
||||
onmessage(msg) {
|
||||
let fileDoc = msg.body
|
||||
const url = msg.url
|
||||
let index = this.fileList.findIndex(file => file.id === fileDoc.id)
|
||||
if ('updateFile' === url) {
|
||||
if (index > -1) {
|
||||
if (fileDoc.m3u8) {
|
||||
this.fileList[index].m3u8 = fileDoc.m3u8
|
||||
}
|
||||
this.fileList[index].size = fileDoc.size
|
||||
this.fileList[index].agoTime = 1
|
||||
this.fileList[index].updateDate = fileDoc.updateDate
|
||||
}
|
||||
}
|
||||
let thisPath = this.path
|
||||
if (this.listModeSearchOpenDir) {
|
||||
const row = this.pathList[this.pathList.length - 1]
|
||||
thisPath = `${row.row.path}${row.folder}`
|
||||
}
|
||||
const isCurrentPath = (thisPath + '/') === fileDoc
|
||||
if ('deleteFile' === url && (isCurrentPath || this.$route.path.startsWith('/recently'))) {
|
||||
this.getFileListEnter()
|
||||
}
|
||||
if ('createFile' === url) {
|
||||
if (fileDoc.$set) {
|
||||
this.onCreateFilename = fileDoc.$set.name
|
||||
}
|
||||
if (fileDoc && fileDoc.name) {
|
||||
this.onCreateFilename = fileDoc.name
|
||||
}
|
||||
if (!thisPath) {
|
||||
thisPath = ''
|
||||
}
|
||||
if (fileDoc) {
|
||||
if (fileDoc.$set) {
|
||||
let path = fileDoc.$set.path
|
||||
path = path.replace(/\\/g, '/')
|
||||
if (thisPath + '/' === path) {
|
||||
this.getFileListEnter()
|
||||
}
|
||||
} else {
|
||||
if (thisPath + '/' === fileDoc.path) {
|
||||
this.getFileListEnter()
|
||||
}
|
||||
}
|
||||
}
|
||||
this.clearOnCreateFilename()
|
||||
}
|
||||
if (this.$route.path.startsWith('/trash') && msg.url === 'operationTips') {
|
||||
this.getFileListEnter()
|
||||
}
|
||||
},
|
||||
// 延时清空onCreateFilename
|
||||
clearOnCreateFilename() {
|
||||
setTimeout(() => {
|
||||
this.onCreateFilename = ''
|
||||
}, 2000)
|
||||
},
|
||||
gridItemClick(row, event) {
|
||||
if (this.selectFile) {
|
||||
this.fileClick(row, event)
|
||||
}
|
||||
if (this.checkCmdKey(event)) {
|
||||
this.pinSelect(row, event)
|
||||
this.$refs.fileListTable.toggleRowSelection([{ row: row }])
|
||||
return
|
||||
}
|
||||
this.pinSelect(row, event)
|
||||
},
|
||||
containerResize() {
|
||||
// gird视图
|
||||
const container = document.querySelector('.dashboard-container')
|
||||
let clientWidth = container.clientWidth
|
||||
this.clientHeight = document.documentElement.clientHeight - this.lessClientHeight
|
||||
this.gridItemWidth = 125
|
||||
if (this.queryFileType === 'image') {
|
||||
this.gridItemWidth = 165
|
||||
this.gridColumnNum = Math.trunc((clientWidth - 10) / this.gridItemWidth)
|
||||
} else {
|
||||
this.gridColumnNum = Math.trunc((clientWidth - 10) / this.gridItemWidth)
|
||||
}
|
||||
const gridWidth = (clientWidth - 10) / this.gridColumnNum
|
||||
this.gridPaddingRight = gridWidth - this.gridItemWidth + 10
|
||||
this.showUpdateDateItem = clientWidth >= 900;
|
||||
this.showSizeItem = clientWidth >= 500;
|
||||
let gridRowNum = Math.round(
|
||||
this.clientHeight / (clientWidth / this.gridColumnNum)
|
||||
)
|
||||
|
||||
if (this.finished && this.pagination.pageIndex === 1) {
|
||||
const actualRows = Math.ceil(this.fileList.length / this.gridColumnNum)
|
||||
const gridMinHeight = actualRows * this.gridItemWidth + (actualRows - 1) * 10
|
||||
if (gridMinHeight < this.clientHeight) {
|
||||
this.gridMinHeight = gridMinHeight
|
||||
}
|
||||
}
|
||||
|
||||
const lastPageSize = this.pagination.pageSize
|
||||
const thisPageSize = gridRowNum * this.gridColumnNum + this.gridColumnNum
|
||||
if (thisPageSize !== lastPageSize) {
|
||||
this.pagination.pageSize = thisPageSize
|
||||
if (this.$route.query.tagId) {
|
||||
this.queryCondition.tagId = this.$route.query.tagId
|
||||
}
|
||||
this.getFileListEnter()
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
// list 视图
|
||||
const fileListTableWidth = this.$refs.fileListTableContainer.offsetWidth
|
||||
this.tableHeadNameWidth = fileListTableWidth - (80 + 200 + 250) - 90
|
||||
})
|
||||
|
||||
// 使列表可拖拽
|
||||
this.rowDrop()
|
||||
this.drawRectangle()
|
||||
},
|
||||
// 切换布局
|
||||
changeVmode() {
|
||||
this.grid = !this.grid
|
||||
this.vmode = 'list'
|
||||
if (this.grid) {
|
||||
this.vmode = 'grid'
|
||||
this.lessClientHeight = 106
|
||||
} else {
|
||||
this.lessClientHeight = 140
|
||||
this.$refs.fileListTable.setHeight()
|
||||
}
|
||||
this.clientHeight =
|
||||
document.documentElement.clientHeight - this.lessClientHeight
|
||||
if (!this.path) {
|
||||
this.path = ''
|
||||
}
|
||||
this.editingIndex = -1
|
||||
const queryTagId = this.$route.query.tagId ? `&tagId=${this.$route.query.tagId}` : ''
|
||||
const basePath = this.getBasePath().replace(/#/g, '%23')
|
||||
const keyword = this.$route.query.keyword ? `&keyword=${this.$route.query.keyword}` : ''
|
||||
const folder = this.$route.query.folder ? `&folder=${this.$route.query.folder}` : ''
|
||||
const searchOpenFolder = this.$route.query.searchOpenFolder ? `&searchOpenFolder=${this.$route.query.searchOpenFolder}` : ''
|
||||
this.$router.push(`?vmode=${this.vmode}&path=${this.path.replace(/#/g, '%23')}${folder}${queryTagId}${basePath}${keyword}${searchOpenFolder}`)
|
||||
// 改变拖拽目标
|
||||
this.rowDrop()
|
||||
// 画矩形选取
|
||||
this.drawRectangle()
|
||||
this.loadContextMenus()
|
||||
// 使列表滑到顶部
|
||||
if (!this.grid) {
|
||||
if (this.fileListScrollTop > 0) {
|
||||
this.$refs.fileListTable.pagingScrollTopLeft()
|
||||
}
|
||||
}
|
||||
this.fileListScrollTop = 0
|
||||
},
|
||||
// 请求之前的准备
|
||||
beforeLoadData(onLoad) {
|
||||
if (onLoad) {
|
||||
this.pagination.pageIndex++
|
||||
} else {
|
||||
this.pagination.pageIndex = 1
|
||||
}
|
||||
this.currentDirectory = decodeURIComponent(this.getQueryPath())
|
||||
this.pageLoadCompleteList[this.pagination.pageIndex] = false
|
||||
this.tableLoading = true
|
||||
this.finished = false
|
||||
},
|
||||
// 填充数据
|
||||
loadData(res, onLoad) {
|
||||
if (!this.$refs.fileListTable) {
|
||||
return
|
||||
}
|
||||
if (onLoad) {
|
||||
res.data.forEach((file, number) => {
|
||||
file['index'] =
|
||||
(this.pagination.pageIndex - 1) * this.pagination.pageSize + number
|
||||
this.fileList.push(file)
|
||||
})
|
||||
} else {
|
||||
this.fileList = res.data
|
||||
this.fileList.map((item, index) => {
|
||||
item.index = index
|
||||
})
|
||||
this.$refs.fileListTable.reloadData(this.fileList)
|
||||
setTimeout(() => {
|
||||
if (this.$refs.fileListTable) {
|
||||
this.$refs.fileListTable.reloadData(this.fileList)
|
||||
}
|
||||
}, 0)
|
||||
}
|
||||
// 数据全部加载完成
|
||||
if (this.fileList.length >= res.count) {
|
||||
this.finished = true
|
||||
}
|
||||
this.tableLoading = false
|
||||
this.clientHeight =
|
||||
document.documentElement.clientHeight - this.lessClientHeight
|
||||
this.listModeSearch = false
|
||||
this.pagination['total'] = res.count
|
||||
this.$nextTick(() => {
|
||||
this.containerResize()
|
||||
this.tableLoading = false
|
||||
this.pageLoadCompleteList[this.pagination.pageIndex] = true
|
||||
})
|
||||
// 加载菜单状态
|
||||
this.loadContextMenus()
|
||||
// 高亮新增的文件
|
||||
this.highlightNewFile()
|
||||
// 设置挂载文件的用户名(文件的所有者)
|
||||
this.fileUsername = ''
|
||||
this.setMountFileOwner(res.props)
|
||||
const path = this.$route.query.path ? this.$route.query.path : '/'
|
||||
const basePath = this.$route.query.basePath
|
||||
? this.$route.query.basePath
|
||||
: '/'
|
||||
this.path = basePath + path
|
||||
this.path = this.path.replace(/\\/g, '/')
|
||||
this.path = this.path.replace(/\/\//g, '/')
|
||||
if (this.path === '/') {
|
||||
this.path = ''
|
||||
}
|
||||
},
|
||||
// 设置挂载文件的用户名(文件的所有者)
|
||||
setMountFileOwner(props) {
|
||||
localStorage.removeItem('mountFileOwner')
|
||||
if (this.$route.query.folder) {
|
||||
if (props && props.fileUsername && props.fileUsername !== this.$store.getters.name) {
|
||||
this.fileUsername = props.fileUsername
|
||||
localStorage.setItem('mountFileOwner', props.fileUsername)
|
||||
}
|
||||
}
|
||||
},
|
||||
// 高亮新增文件
|
||||
highlightNewFile() {
|
||||
if (this.onCreateFilename) {
|
||||
let index = this.fileList.findIndex(
|
||||
item => item.name === this.onCreateFilename
|
||||
)
|
||||
if (index > -1) {
|
||||
let row = this.fileList[index]
|
||||
setTimeout(() => {
|
||||
this.fileListTableClearSelection()
|
||||
this.$refs.fileListTable.toggleRowSelection([
|
||||
{ row: row, selected: true },
|
||||
])
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
},
|
||||
getFileListEnter(onLoad) {
|
||||
this.debounceGetFileList(onLoad)
|
||||
},
|
||||
getFileList(onLoad) {
|
||||
if (this.$route.query.keyword) {
|
||||
if (this.$route.query.keyword !== 'undefined') {
|
||||
this.searchFileName = this.$route.query.keyword
|
||||
}
|
||||
this.searchInputBlur()
|
||||
const searchPathIndex = this.pathList.findIndex(item => item.search)
|
||||
if (this.$route.query.searchOpenFolder && searchPathIndex > -1) {
|
||||
this.searchFileAndOpenDir(this.$route.query.searchOpenFolder, onLoad)
|
||||
} else {
|
||||
this.searchFile(this.searchFileName)
|
||||
}
|
||||
} else {
|
||||
this.searchFileName = ''
|
||||
this.getFileListed = true
|
||||
this.beforeLoadData(onLoad)
|
||||
api.fileList({
|
||||
userId: this.$store.state.user.userId,
|
||||
username: this.$store.state.user.name,
|
||||
currentDirectory: this.getQueryPath(),
|
||||
folder: this.$route.query.folder,
|
||||
queryFileType: this.queryFileType,
|
||||
sortableProp: this.sortable.prop,
|
||||
order: this.sortable.order,
|
||||
isFolder: this.queryCondition.isFolder,
|
||||
isFavorite: this.queryCondition.isFavorite,
|
||||
isMount: this.queryCondition.isMount,
|
||||
isTrash: this.queryCondition.isTrash,
|
||||
tagId: this.queryCondition.tagId,
|
||||
queryCondition: this.queryCondition,
|
||||
pageIndex: this.pagination.pageIndex,
|
||||
pageSize: this.pagination.pageSize,
|
||||
})
|
||||
.then(res => {
|
||||
this.loadData(res, onLoad)
|
||||
}).catch(() => {
|
||||
this.tableLoading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
pinSelect(row, event) {
|
||||
if (event.shiftKey && this.selectOrigin > -1) {
|
||||
const origin = this.selectOrigin
|
||||
this.selectEnd = row.index
|
||||
let diff = this.selectEnd - origin
|
||||
// 先清除选中
|
||||
this.fileListTableClearSelection()
|
||||
if (diff === 0) {
|
||||
this.selectOrigin = -1
|
||||
}
|
||||
if (diff > 0) {
|
||||
for (let i = origin; i <= this.selectEnd; i++) {
|
||||
this.$refs.fileListTable.toggleRowSelection([{ row: this.fileList[i], selected: true }])
|
||||
}
|
||||
}
|
||||
if (diff < 0) {
|
||||
for (let i = this.selectEnd; i <= origin; i++) {
|
||||
this.$refs.fileListTable.toggleRowSelection([{ row: this.fileList[i], selected: true }])
|
||||
}
|
||||
}
|
||||
}
|
||||
this.changeSelectedStyle(this.$refs.fileListTable.tableSelectData)
|
||||
},
|
||||
//双击
|
||||
dblclick(row, column, cell, event) {
|
||||
this.fileClick(row, event)
|
||||
},
|
||||
// 单元格点击事件
|
||||
cellClick(row, column, cell, event) {
|
||||
if (this.selectFile) {
|
||||
this.fileClick(row, event)
|
||||
return
|
||||
}
|
||||
clearTimeout(this.Loop)
|
||||
if (this.editingIndex === -1) {
|
||||
const columnIndex = column.index
|
||||
if (columnIndex === 2) {
|
||||
if (this.selectRowData.length < 1) {
|
||||
if (row.index !== this.editingIndex) {
|
||||
this.editingIndex = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.checkCmdKey(event)) {
|
||||
this.pinSelect(row, event)
|
||||
this.$refs.fileListTable.toggleRowSelection([{ row: row }])
|
||||
return
|
||||
}
|
||||
this.pinSelect(row, event)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
56
src/components/ShowFile/mixins/fileTooltip.js
Normal file
56
src/components/ShowFile/mixins/fileTooltip.js
Normal file
@ -0,0 +1,56 @@
|
||||
import { formatExif, formatVideo } from '@/utils/media'
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
extendedInfo(file) {
|
||||
if (!file.exif && !file.video) {
|
||||
return ''
|
||||
}
|
||||
return formatExif(file.exif, '<br>') + formatVideo(file.video, '<br>')
|
||||
},
|
||||
tooltipConfig(item) {
|
||||
// 使用模板字符串构建更清晰的 HTML
|
||||
const contentHTML = `
|
||||
<div class="apple-tooltip-content">
|
||||
<div class="tooltip-row">
|
||||
<span class="tooltip-label">大小:</span>
|
||||
<span class="tooltip-value">${this.formatSize(item.size)}</span>
|
||||
</div>
|
||||
${item.w && item.h ? `
|
||||
<div class="tooltip-row">
|
||||
<span class="tooltip-label">尺寸:</span>
|
||||
<span class="tooltip-value">${item.w}×${item.h}</span>
|
||||
</div>` : ''}
|
||||
<div class="tooltip-row">
|
||||
<span class="tooltip-label">名称:</span>
|
||||
<span class="tooltip-value tooltip-value-name">${item.name}</span>
|
||||
</div>
|
||||
<div class="tooltip-row">
|
||||
<span class="tooltip-label">上传时间:</span>
|
||||
<span class="tooltip-value tooltip-value-date">${item.uploadDate}</span>
|
||||
</div>
|
||||
<div class="tooltip-row">
|
||||
<span class="tooltip-label">修改时间:</span>
|
||||
<span class="tooltip-value tooltip-value-date">${item.updateDate}</span>
|
||||
</div>
|
||||
<div class="tooltip-row">
|
||||
<span class="tooltip-label">路径:</span>
|
||||
<span class="tooltip-value tooltip-value-path">${item.path}</span>
|
||||
</div>
|
||||
${this.extendedInfo(item)}
|
||||
</div>
|
||||
`;
|
||||
|
||||
return {
|
||||
content: contentHTML,
|
||||
// trigger: 'click',
|
||||
delay: 0,
|
||||
placement: 'left',
|
||||
allowHTML: true,
|
||||
theme: 'light',
|
||||
// appendTo: 'parent',
|
||||
arrow: true
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
159
src/components/ShowFile/mixins/filenameHandle.js
Normal file
159
src/components/ShowFile/mixins/filenameHandle.js
Normal file
@ -0,0 +1,159 @@
|
||||
export default {
|
||||
computed: {
|
||||
gridFilename() {
|
||||
// 优化文件名,如果文件名过长,则进行截取
|
||||
return function(item) {
|
||||
let filename = item.name;
|
||||
// 如果是文件夹,直接返回文件夹名
|
||||
if (item.isFolder || !this.grid) {
|
||||
return filename;
|
||||
}
|
||||
const verticalImage = item.w && item.h && (item.w / item.h < 1.6)
|
||||
const verticalVideo = item.video && (item.video.width / item.video.height < 1.6)
|
||||
const singleLine = verticalImage || verticalVideo || item.showCover
|
||||
const gridFilenameLength = singleLine ? 13 : 28
|
||||
// 分离文件名和后缀
|
||||
let parts = filename.split('.');
|
||||
let suffix = parts.length > 1 ? parts.pop() : '';
|
||||
let base = parts.join('.');
|
||||
// 获取文件名的有效长度
|
||||
let effectiveLength = this.getEffectiveLength(base, suffix);
|
||||
// 如果有效长度小于或等于规定的长度,则直接返回文件名
|
||||
if (effectiveLength <= gridFilenameLength) {
|
||||
return filename;
|
||||
}
|
||||
// 根据是否有后缀来确定需要截取的长度
|
||||
let sliceLength = gridFilenameLength - (suffix ? suffix.length + 2 : 1); // +2 是为了“…”和分隔符
|
||||
let prev = '';
|
||||
let currentLength = 0;
|
||||
// 截取字符串,确保不会在中文字符中间断开
|
||||
for (let char of Array.from(base)) {
|
||||
let charLength = this.getCharLength(char);
|
||||
if (currentLength + charLength > sliceLength) {
|
||||
break;
|
||||
}
|
||||
currentLength += charLength;
|
||||
prev += char;
|
||||
}
|
||||
// 根据是否有后缀返回相应的格式
|
||||
if (suffix) {
|
||||
return prev + '…' + suffix;
|
||||
}
|
||||
return prev + '…';
|
||||
};
|
||||
},
|
||||
getSummaries3() {
|
||||
let totalSize = 0
|
||||
this.fileList.forEach(file => {
|
||||
totalSize += file.size
|
||||
})
|
||||
return totalSize > 0
|
||||
? this.fileList.length + '项 ' + this.getShowSumSize(totalSize)
|
||||
: ''
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 获取字符的长度。中文字符长度为2,其他字符长度为1
|
||||
getCharLength(char) {
|
||||
// 优化的字符长度计算函数
|
||||
// 使用 Unicode 范围来判断字符宽度,更准确且性能更好
|
||||
|
||||
if (!char) return 0; // 处理空字符或 undefined
|
||||
|
||||
const code = char.codePointAt(0);
|
||||
|
||||
// 全角字符范围判断(长度为2)
|
||||
if (
|
||||
// 中日韩统一表意文字 (CJK Unified Ideographs)
|
||||
(code >= 0x4E00 && code <= 0x9FFF) ||
|
||||
// 中日韩扩展A区
|
||||
(code >= 0x3400 && code <= 0x4DBF) ||
|
||||
// 中日韩符号和标点
|
||||
(code >= 0x3000 && code <= 0x303F) ||
|
||||
// 全角ASCII、全角标点
|
||||
(code >= 0xFF00 && code <= 0xFFEF) ||
|
||||
// 平假名
|
||||
(code >= 0x3040 && code <= 0x309F) ||
|
||||
// 片假名
|
||||
(code >= 0x30A0 && code <= 0x30FF) ||
|
||||
// 韩文字母
|
||||
(code >= 0xAC00 && code <= 0xD7AF) ||
|
||||
// 其他可能的宽字符
|
||||
(code >= 0x1100 && code <= 0x11FF) || // 韩文字母扩展
|
||||
(code >= 0x2E80 && code <= 0x2EFF) || // 中日韩部首补充
|
||||
(code >= 0x2F00 && code <= 0x2FDF) || // 康熙部首
|
||||
(code >= 0x31C0 && code <= 0x31EF) || // 中日韩笔画
|
||||
(code >= 0xF900 && code <= 0xFAFF) || // 中日韩兼容表意文字
|
||||
(code >= 0xFE30 && code <= 0xFE4F) || // 中日韩兼容形式
|
||||
// 表情符号和其他宽字符
|
||||
(code >= 0x1F300 && code <= 0x1F9FF) ||
|
||||
// 全角空格
|
||||
code === 0x3000
|
||||
) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
// 半角字符(包括普通空格、ASCII字符等)
|
||||
return 1;
|
||||
},
|
||||
// 获取有效长度。如果有后缀,则包括后缀和点的长度;否则是基础名称和后7位的长度
|
||||
getEffectiveLength(base, suffix) {
|
||||
let chineseLength = Array.from(base).reduce((count, char) => count + this.getCharLength(char), 0)
|
||||
return suffix ? chineseLength + suffix.length + 1 : chineseLength
|
||||
},
|
||||
getNewFileName(fileList, newFileName) {
|
||||
let append = 0
|
||||
let filenameList = []
|
||||
fileList.forEach(file => {
|
||||
let fileName = file.name || file.label
|
||||
filenameList.push(fileName)
|
||||
})
|
||||
const newName = newFileName
|
||||
while (filenameList.includes(newFileName)) {
|
||||
append += 1
|
||||
if (newName.indexOf('.') > 0) {
|
||||
const name = newName.substring(0, newName.lastIndexOf('.'))
|
||||
const suffix = newName.substring(newName.lastIndexOf('.'))
|
||||
newFileName = `${name}${append}${suffix}`
|
||||
} else {
|
||||
newFileName = `${newName}${append}`
|
||||
}
|
||||
}
|
||||
return newFileName
|
||||
},
|
||||
getDuplicateFileName(fileList, filename) {
|
||||
let append = 0
|
||||
let filenameList = []
|
||||
fileList.forEach(file => {
|
||||
let fileName = file.name || file.label
|
||||
filenameList.push(fileName)
|
||||
})
|
||||
let newName = filename
|
||||
while (filenameList.includes(filename)) {
|
||||
append += 1
|
||||
if (newName.indexOf('.') > 0) {
|
||||
let name = newName.substring(0, newName.lastIndexOf('.'))
|
||||
if (name.indexOf(' 副本') > 0) {
|
||||
name = name.substring(0, name.lastIndexOf(' 副本'))
|
||||
}
|
||||
const suffix = newName.substring(newName.lastIndexOf('.'))
|
||||
if (append === 1) {
|
||||
filename = `${name} 副本${suffix}`
|
||||
} else {
|
||||
filename = `${name} 副本${append}${suffix}`
|
||||
}
|
||||
} else {
|
||||
if (newName.indexOf(' 副本') > 0) {
|
||||
newName = newName.substring(0, newName.lastIndexOf(' 副本'))
|
||||
}
|
||||
if (append === 1) {
|
||||
filename = `${newName} 副本`
|
||||
} else {
|
||||
filename = `${newName} 副本${append}`
|
||||
}
|
||||
}
|
||||
}
|
||||
return filename
|
||||
},
|
||||
}
|
||||
}
|
||||
144
src/components/ShowFile/mixins/filepathHandle.js
Normal file
144
src/components/ShowFile/mixins/filepathHandle.js
Normal file
@ -0,0 +1,144 @@
|
||||
import api from '@/api/file-api'
|
||||
export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
basePath: '/',
|
||||
pathList: [{ folder: '' }],
|
||||
currentDirectory: '/', // 当前路径
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 监听返回
|
||||
if (window.history && window.history.pushState) {
|
||||
history.pushState(null, null, document.URL)
|
||||
window.addEventListener('popstate', this.goBack, false)
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('popstate', this.goBack, false)
|
||||
},
|
||||
methods: {
|
||||
// 浏览器的返回事件
|
||||
goBack() {
|
||||
if (this.pathList.length <= 1) {
|
||||
const queryTagId = this.$route.query.tagId
|
||||
? `&tagId=${this.$route.query.tagId}`
|
||||
: ''
|
||||
const keyword = this.$route.query.keyword
|
||||
? `&keyword=${this.$route.query.keyword}`
|
||||
: ''
|
||||
const basePath = this.getBasePath()
|
||||
this.$router.push(
|
||||
`/?vmode=${this.vmode}&path=${encodeURIComponent(
|
||||
this.path
|
||||
)}${queryTagId}${basePath}${keyword}`
|
||||
)
|
||||
return
|
||||
}
|
||||
this.lastLink()
|
||||
},
|
||||
lastLink() {
|
||||
let keywordQuery = ''
|
||||
const searchPathIndex = this.pathList.findIndex(item => item.search)
|
||||
if (searchPathIndex === this.pathList.length - 1) {
|
||||
keywordQuery = '&keyword='
|
||||
}
|
||||
this.handleLink(
|
||||
this.pathList[this.pathList.length - 2],
|
||||
this.pathList.length - 2,
|
||||
undefined,
|
||||
undefined,
|
||||
keywordQuery
|
||||
).then(r => {})
|
||||
},
|
||||
async handleLink(item, index, unPushLink, unRefresh, keywordQuery) {
|
||||
this.pathList.splice(
|
||||
this.pathList.findIndex((v, i) => i === index + 1),
|
||||
this.pathList.length - (index + 1)
|
||||
)
|
||||
if (item && item.search) {
|
||||
if (item.searchKey) {
|
||||
this.searchFileByKeyword(item.searchKey)
|
||||
} else if (item.row) {
|
||||
this.searchFileAndOpenDir(item.row.id)
|
||||
}
|
||||
} else {
|
||||
this.pathList.forEach((p, number) => {
|
||||
if (number === 0) {
|
||||
this.path = ''
|
||||
} else if (number === this.pathList.length) {
|
||||
} else {
|
||||
this.path += '/' + this.pathList[number].folder
|
||||
}
|
||||
this.path = this.path.replace(/\\/g, '/')
|
||||
})
|
||||
let queryFolder = localStorage.getItem('mountFileOwner') ? localStorage.getItem(this.path) : this.$route.query.folder
|
||||
if (localStorage.getItem('mountFileOwner') && !queryFolder) {
|
||||
queryFolder = await this.getMountFolderId(this.$route.query.folder, localStorage.getItem('mountFileOwner'), this.path)
|
||||
}
|
||||
let searchOpenFolder = this.$route.query.searchOpenFolder ? `&searchOpenFolder=${this.$route.query.searchOpenFolder}` : ''
|
||||
if (!unPushLink) {
|
||||
const queryTagId = this.$route.query.tagId
|
||||
? `&tagId=${this.$route.query.tagId}`
|
||||
: ''
|
||||
const basePath = this.getBasePath()
|
||||
if (keywordQuery !== '&keyword=') {
|
||||
keywordQuery = this.$route.query.keyword
|
||||
? `&keyword=${this.$route.query.keyword}`
|
||||
: ''
|
||||
} else {
|
||||
keywordQuery = ''
|
||||
}
|
||||
const searchPathIndex = this.pathList.findIndex(item => item.search)
|
||||
if (searchPathIndex < 0) {
|
||||
keywordQuery = ''
|
||||
searchOpenFolder = ''
|
||||
}
|
||||
this.$router.push(`?vmode=${this.vmode}&path=${encodeURIComponent(this.path)}${queryFolder ? '&folder=' + queryFolder : ''}${queryTagId}${basePath}${keywordQuery}${searchOpenFolder}`)
|
||||
}
|
||||
if (!unRefresh) {
|
||||
this.pagination.pageIndex = 1
|
||||
this.getFileListEnter()
|
||||
}
|
||||
}
|
||||
},
|
||||
getMountFolderId(currentFolder, fileUsername, path) {
|
||||
return new Promise((resolve, reject) => {
|
||||
api.getMountFolderId({
|
||||
otherFileId: currentFolder,
|
||||
fileUsername: fileUsername,
|
||||
path: path
|
||||
})
|
||||
.then(res => {
|
||||
if (res.data) {
|
||||
resolve(res.data)
|
||||
} else {
|
||||
resolve('')
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
reject('')
|
||||
})
|
||||
})
|
||||
},
|
||||
getBasePath() {
|
||||
let basePath = this.$route.query.basePath ? `&basePath=${this.$route.query.basePath}` : ''
|
||||
if (!this.path || this.path.length < 2) {
|
||||
this.basePath = '/'
|
||||
return ''
|
||||
}
|
||||
return basePath
|
||||
},
|
||||
getQueryPath() {
|
||||
// 去掉this.$route.query.basePath最后的/
|
||||
let basePath = this.$route.query.basePath ? this.$route.query.basePath : '/'
|
||||
if (basePath) {
|
||||
if (basePath.lastIndexOf('/') === basePath.length - 1) {
|
||||
basePath = basePath.substring(0, basePath.length - 1)
|
||||
}
|
||||
}
|
||||
return encodeURIComponent(basePath + this.$route.query.path)
|
||||
},
|
||||
}
|
||||
}
|
||||
140
src/components/ShowFile/mixins/globalContextmenu.js
Normal file
140
src/components/ShowFile/mixins/globalContextmenu.js
Normal file
@ -0,0 +1,140 @@
|
||||
// 全局右键菜单操作
|
||||
export default {
|
||||
props: {
|
||||
contextMenus: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
contextmenuDisabled: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
contextmenuClick(operation) {
|
||||
this.fileListTableClearSelection()
|
||||
if (operation.startsWith('order')) {
|
||||
const [prop, order] = operation.split('-')
|
||||
this.handleSortChange(prop, order)
|
||||
return
|
||||
}
|
||||
switch (operation) {
|
||||
case 'vmode-list':
|
||||
this.grid = true
|
||||
this.changeVmode()
|
||||
break
|
||||
case 'vmode-grid':
|
||||
this.grid = false
|
||||
this.changeVmode()
|
||||
break
|
||||
case 'refresh':
|
||||
this.getFileListEnter()
|
||||
break
|
||||
case 'createTextFile':
|
||||
this.newCreateFileDialogTitle = '新建文本文件'
|
||||
this.createNewFile('txt')
|
||||
break
|
||||
case 'createFolder':
|
||||
this.newCreateFileDialogTitle = '新建文件夹'
|
||||
this.createNewFile('')
|
||||
break
|
||||
case 'createDrawioFile':
|
||||
this.newCreateFileDialogTitle = '新建流程图'
|
||||
this.createNewFile('drawio')
|
||||
break
|
||||
case 'createMinderFile':
|
||||
this.newCreateFileDialogTitle = '新建思维导图'
|
||||
this.createNewFile('mind')
|
||||
break
|
||||
case 'createWordFile':
|
||||
this.newCreateFileDialogTitle = '新建Word文档'
|
||||
this.createNewFile('docx')
|
||||
break
|
||||
case 'createExcalidrawFile':
|
||||
this.newCreateFileDialogTitle = '新建白板'
|
||||
this.createNewFile('excalidraw')
|
||||
break
|
||||
case 'createExcelFile':
|
||||
this.newCreateFileDialogTitle = '新建Excel工作表'
|
||||
this.createNewFile('xlsx')
|
||||
break
|
||||
case 'createPPTFile':
|
||||
this.newCreateFileDialogTitle = '新建PPT演示文档'
|
||||
this.createNewFile('pptx')
|
||||
break
|
||||
case 'createMarkdownFile':
|
||||
this.newDocument()
|
||||
break
|
||||
case 'clearTrash':
|
||||
this.clearTrash()
|
||||
break
|
||||
}
|
||||
},
|
||||
// 加载菜单查看状态
|
||||
loadContextMenus() {
|
||||
if (this.contextMenus.length < 1) {
|
||||
this.contextmenuDisabled = true
|
||||
return
|
||||
}
|
||||
let container = document.querySelector('.dashboard-container')
|
||||
if (this.$refs.homeContextmenu.references.length === 0) {
|
||||
this.$refs.homeContextmenu.addRef({ el: container, vnode: container })
|
||||
}
|
||||
const viewModeIndex = this.contextMenus.findIndex(
|
||||
item => item.operation === 'viewMode'
|
||||
)
|
||||
const arrangementModeIndex = this.contextMenus.findIndex(
|
||||
item => item.operation === 'arrangement'
|
||||
)
|
||||
if (viewModeIndex > -1) {
|
||||
const child = this.contextMenus[viewModeIndex].child
|
||||
if (this.grid) {
|
||||
child[0].iconClass = 'menu-empty'
|
||||
child[1].iconClass = 'menu-point'
|
||||
} else {
|
||||
child[0].iconClass = 'menu-point'
|
||||
child[1].iconClass = 'menu-empty'
|
||||
}
|
||||
}
|
||||
if (arrangementModeIndex > -1) {
|
||||
const child = this.contextMenus[arrangementModeIndex].child
|
||||
const prop = this.sortable.prop
|
||||
child.forEach(item => {
|
||||
const orderProp = item.orderProp
|
||||
if (orderProp === prop) {
|
||||
child.map(item => {
|
||||
if (orderProp === item.orderProp && this.sortable.order === item.order) {
|
||||
item.iconClass = 'menu-' + this.sortable.order
|
||||
} else {
|
||||
item.iconClass = 'menu-null'
|
||||
}
|
||||
return item
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
// 新建文档
|
||||
newDocument() {
|
||||
window.open(`/setting/website/manager-articles?operation=new`, '_blank')
|
||||
},
|
||||
handleSortChange(command, order) {
|
||||
this.sortable.order = order
|
||||
switch (command) {
|
||||
case 'orderName':
|
||||
this.sortChangeOfMenu('name', 1)
|
||||
break
|
||||
case 'orderSize':
|
||||
this.sortChangeOfMenu('size', 2)
|
||||
break
|
||||
case 'orderUpdateDate':
|
||||
this.sortChangeOfMenu('updateDate', 3)
|
||||
break
|
||||
case 'orderUploadDate':
|
||||
this.sortChangeOfMenu('uploadDate', -1)
|
||||
break
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
316
src/components/ShowFile/mixins/searchFile.js
Normal file
316
src/components/ShowFile/mixins/searchFile.js
Normal file
@ -0,0 +1,316 @@
|
||||
import api from '@/api/file-api'
|
||||
import _ from 'lodash'
|
||||
|
||||
export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
showNewFolder: false,
|
||||
isShowNewFolder: false,
|
||||
listModeSearch: false,
|
||||
listModeSearchOpenDir: false,
|
||||
newFolderName: '新建文件夹',
|
||||
searchFileName: '',
|
||||
debounceSearch: null,// 搜索防抖
|
||||
filterOption: {}, // 搜索选项
|
||||
searchSuggestions: [],// 搜索历史列表
|
||||
_isSuggestionHandledBySelect: false,
|
||||
_originalSearchFileNameBeforeSelect: '',
|
||||
hasSearchFilterOption: false, // 是否有搜索选项
|
||||
fileUsername: '', // 一般用于挂载文件
|
||||
searchInputClass: 'search-input' // 搜索输入框样式
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
searchOptionBtnClass() {
|
||||
return this.hasSearchFilterOption ? 'search-option-btn search-option-btn-active' : 'search-option-btn'
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
searchFileName(newValue) {
|
||||
if (!newValue) {
|
||||
this.hasSearchFilterOption = false
|
||||
this.$refs.searchOption.clearFilterOption()
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.debounceSearch = _.debounce((key, onLoad) => {
|
||||
this.searchFile(key, onLoad)
|
||||
}, 200)
|
||||
},
|
||||
methods: {
|
||||
hideNewFolderName() {
|
||||
this.showNewFolder = false
|
||||
this.isShowNewFolder = false
|
||||
},
|
||||
showNewFolderClick() {
|
||||
this.isShowNewFolder = true
|
||||
},
|
||||
upload() {
|
||||
// 打开文件选择框
|
||||
this.$store.dispatch('updateMessage', {event: 'openUploader'})
|
||||
},
|
||||
uploadFolder() {
|
||||
if (window.uploader.supportDirectory) {
|
||||
this.$store.dispatch('updateMessage', {event: 'uploadFolder'})
|
||||
} else {
|
||||
this.$message({
|
||||
message: '该浏览器不支持上传文件夹',
|
||||
type: 'warning',
|
||||
})
|
||||
}
|
||||
},
|
||||
getUploadParams() {
|
||||
return {
|
||||
folder: this.$route.query.searchOpenFolder || this.$route.query.folder,
|
||||
currentDirectory: this.getQueryPath(),
|
||||
username: this.$store.state.user.name,
|
||||
userId: this.$store.state.user.userId,
|
||||
}
|
||||
},
|
||||
newFolderNameClickEnter() {
|
||||
this.newFolderNameClick()
|
||||
},
|
||||
searchFileByKeyword(key) {
|
||||
this.searchFile(key)
|
||||
},
|
||||
searchFileEnter() {
|
||||
if (this._isSuggestionHandledBySelect) {
|
||||
return
|
||||
}
|
||||
this.debounceSearch(this.searchFileName)
|
||||
this.$refs.searchInput.close()
|
||||
},
|
||||
searchFile(key, onLoad) {
|
||||
if (key) {
|
||||
this.beforeLoadData(onLoad)
|
||||
// this.pathList = [{ folder: "" }]
|
||||
// 查找this.pathList中是否已经有搜索的路径
|
||||
|
||||
const item = {}
|
||||
item['folder'] = `搜索: ${key}`
|
||||
item['search'] = true
|
||||
item['searchKey'] = key
|
||||
|
||||
let searchOpenFolder = this.$route.query.searchOpenFolder ? `&searchOpenFolder=${this.$route.query.searchOpenFolder}` : ''
|
||||
|
||||
const searchPathIndex = this.pathList.findIndex(item => item.search)
|
||||
if (searchPathIndex < 0) {
|
||||
this.pathList.push(item)
|
||||
} else {
|
||||
this.pathList.splice(searchPathIndex,this.pathList.length - searchPathIndex)
|
||||
this.pathList.push(item)
|
||||
searchOpenFolder = ''
|
||||
}
|
||||
const queryTagId = this.$route.query.tagId ? `&tagId=${this.$route.query.tagId}` : ''
|
||||
const folder = this.$route.query.folder ? `&folder=${this.$route.query.folder}` : ''
|
||||
const basePath = this.getBasePath()
|
||||
const keyword = key ? `&keyword=${key}` : ''
|
||||
const path = this.path ? encodeURIComponent(this.path.replace(this.basePath, '/')) : '/'
|
||||
this.$router.push(`?vmode=${this.vmode}&path=${path}${keyword}${searchOpenFolder}${queryTagId}${basePath}${folder}`)
|
||||
|
||||
api.searchFile({
|
||||
userId: this.$store.state.user.userId,
|
||||
username: this.$store.state.user.name,
|
||||
keyword: key,
|
||||
sortableProp: this.sortable.prop,
|
||||
order: this.sortable.order,
|
||||
currentDirectory: this.getQueryPath(),
|
||||
folder: this.$route.query.folder,
|
||||
tagId: this.$route.query.tagId,
|
||||
isFolder: this.queryCondition.isFolder,
|
||||
isFavorite: this.queryCondition.isFavorite,
|
||||
queryFileType: this.filterOption.type || this.queryFileType,
|
||||
pageIndex: this.pagination.pageIndex,
|
||||
pageSize: this.pagination.pageSize,
|
||||
type: this.filterOption.type,
|
||||
queryModifyStart: this.filterOption.modifyStart,
|
||||
queryModifyEnd: this.filterOption.modifyEnd,
|
||||
querySizeMin: this.filterOption.sizeMin,
|
||||
querySizeMax: this.filterOption.sizeMax,
|
||||
searchMount: this.filterOption.searchMount,
|
||||
isMount: this.queryCondition.isMount,
|
||||
searchOverall: this.filterOption.searchOverall,
|
||||
exactSearch: this.filterOption.exactSearch,
|
||||
includeTagName: this.filterOption.includeTagName,
|
||||
includeFileName: this.filterOption.includeFileName,
|
||||
includeFileContent: this.filterOption.includeFileContent,
|
||||
}).then(res => {
|
||||
this.loadData(res, onLoad)
|
||||
this.listModeSearch = true
|
||||
this.listModeSearchOpenDir = false
|
||||
}).catch(() => {
|
||||
this.tableLoading = false
|
||||
})
|
||||
} else {
|
||||
if (this.listModeSearch) {
|
||||
this.listModeSearch = false
|
||||
this.lastLink()
|
||||
}
|
||||
}
|
||||
},
|
||||
searchFileAndOpenDir(fileId, onLoad) {
|
||||
this.beforeLoadData(onLoad)
|
||||
|
||||
const queryTagId = this.$route.query.tagId ? `&tagId=${this.$route.query.tagId}` : ''
|
||||
const path = this.$route.query.path ? `&path=${this.$route.query.path}`.replace(/#/g, '%23') : ''
|
||||
const keyword = this.$route.query.keyword ? `&keyword=${this.$route.query.keyword}` : ''
|
||||
const basePath = this.getBasePath()
|
||||
const searchOpenFolder = `&searchOpenFolder=${fileId}`
|
||||
const folder = this.$route.query.folder ? `&folder=${this.$route.query.folder}` : ''
|
||||
this.$router.push(`?vmode=${this.vmode}${path}${keyword}${searchOpenFolder}${queryTagId}${basePath}${folder}`)
|
||||
|
||||
api.searchFileAndOpenDir({
|
||||
userId: this.$store.state.user.userId,
|
||||
username: this.$store.getters.name,
|
||||
id: fileId,
|
||||
currentDirectory: this.getQueryPath(),
|
||||
pageIndex: this.pagination.pageIndex,
|
||||
pageSize: this.pagination.pageSize,
|
||||
folder: this.$route.query.folder,
|
||||
})
|
||||
.then(res => {
|
||||
this.loadData(res, onLoad)
|
||||
this.listModeSearch = true
|
||||
this.listModeSearchOpenDir = fileId
|
||||
}).catch(() => {
|
||||
this.tableLoading = false
|
||||
})
|
||||
},
|
||||
openDir(row, onLoad) {
|
||||
this.beforeLoadData(onLoad)
|
||||
api.searchFileAndOpenDir({
|
||||
userId: this.$store.state.user.userId,
|
||||
username: this.$store.getters.name,
|
||||
id: row.mountFileId || row.id,
|
||||
currentDirectory: this.getQueryPath(),
|
||||
pageIndex: this.pagination.pageIndex,
|
||||
pageSize: this.pagination.pageSize,
|
||||
folder: this.$route.query.folder,
|
||||
})
|
||||
.then(res => {
|
||||
this.loadData(res, onLoad)
|
||||
}).catch(() => {
|
||||
this.tableLoading = false
|
||||
})
|
||||
},
|
||||
searchClose() {
|
||||
this.searchFileName = ''
|
||||
this.searchInputBlur()
|
||||
this.searchFileEnter()
|
||||
},
|
||||
searchInputFocus() {
|
||||
this.searchInputClass = 'search-input search-input-focus'
|
||||
this.setInputFocus()
|
||||
},
|
||||
searchInputBlur() {
|
||||
this.searchInputClass = this.searchFileName ? 'search-input search-input-focus' : 'search-input'
|
||||
this.setInputBlur()
|
||||
},
|
||||
searchFilterChange() {
|
||||
this.debounceSearch(this.searchFileName, false)
|
||||
},
|
||||
showSearchOption() {
|
||||
},
|
||||
async fetchDynamicSuggestions(queryString, cb) {
|
||||
this._originalSearchFileNameBeforeSelect = queryString
|
||||
this.searchSuggestions = []
|
||||
const recentlySearch =
|
||||
{
|
||||
sugType: 'clearAllHistory',
|
||||
keyword: '',
|
||||
value: `__READONLY_DIVIDER_${Date.now()}__`,
|
||||
id: 'recently_search_id'
|
||||
}
|
||||
if (!queryString) {
|
||||
this.queryRecentlySearchHistory(queryString, recentlySearch, cb)
|
||||
} else {
|
||||
const fixedActionItems = [
|
||||
{
|
||||
sugType: 'action_current_path_search',
|
||||
keyword: queryString,
|
||||
value: queryString,
|
||||
id: 'action_current_path_search_id'
|
||||
},
|
||||
{
|
||||
sugType: 'action_global_search',
|
||||
keyword: queryString,
|
||||
value: queryString,
|
||||
id: 'action_global_search_id'
|
||||
},
|
||||
]
|
||||
this.searchSuggestions.push(...fixedActionItems)
|
||||
this.queryRecentlySearchHistory(queryString, recentlySearch, cb)
|
||||
}
|
||||
},
|
||||
queryRecentlySearchHistory(queryString = '', recentlySearch, cb) {
|
||||
api.getRecentlySearchHistory({keyword: queryString}).then(res => {
|
||||
const historyItems = res.data.map(item => ({
|
||||
...item,
|
||||
value: item.keyword,
|
||||
sugType: 'history'
|
||||
}))
|
||||
if (historyItems.length > 0) {
|
||||
this.searchSuggestions.push(recentlySearch)
|
||||
}
|
||||
this.searchSuggestions.push(...historyItems)
|
||||
cb(this.searchSuggestions)
|
||||
}).catch(error => {
|
||||
console.error("Error fetching search history:", error)
|
||||
cb(this.searchSuggestions.length > 0 ? this.searchSuggestions : [])
|
||||
})
|
||||
},
|
||||
handleSelectSuggestion(item) {
|
||||
this._isSuggestionHandledBySelect = true
|
||||
if (item.id === "recently_search_id") {
|
||||
this.$nextTick(() => {
|
||||
if (this.searchFileName !== this._originalSearchFileNameBeforeSelect) {
|
||||
this.searchFileName = this._originalSearchFileNameBeforeSelect
|
||||
}
|
||||
this._isSuggestionHandledBySelect = false
|
||||
})
|
||||
return
|
||||
}
|
||||
if ( item.sugType === 'history') {
|
||||
this.searchFileName = item.keyword
|
||||
}
|
||||
if ( item.sugType === 'action_global_search') {
|
||||
item.searchOverall = true
|
||||
}
|
||||
if ( item.sugType === 'action_current_path_search') {
|
||||
item.searchOverall = false
|
||||
}
|
||||
this.debounceSearch(this.searchFileName, false)
|
||||
this.$refs.searchOption.setFilterOption(item)
|
||||
this.$nextTick(() => {
|
||||
this._isSuggestionHandledBySelect = false
|
||||
})
|
||||
},
|
||||
clearSearchHistoryForItem(itemToDelete, event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
const idToDelete = itemToDelete.id
|
||||
api.removeSearchHistory({id: idToDelete}).then(() => {
|
||||
const index = this.searchSuggestions.findIndex(item => item.id === idToDelete)
|
||||
this.searchSuggestions.splice(index, 1)
|
||||
})
|
||||
},
|
||||
clearAllSearchHistory(event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
this.$confirm('确定要清除所有搜索记录吗', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
api.removeAllSearchHistory({userId: this.$store.getters.userId}).then(() => {
|
||||
this.searchSuggestions = this.searchSuggestions.filter(
|
||||
item => item.sugType === 'action_current_path_search' || item.sugType === 'action_global_search'
|
||||
);
|
||||
})
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
109
src/components/ShowFile/mixins/shortcutKey.js
Normal file
109
src/components/ShowFile/mixins/shortcutKey.js
Normal file
@ -0,0 +1,109 @@
|
||||
// 快捷键处理
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
drawer: false,
|
||||
drawerShowTime: 0,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 获取键盘事件
|
||||
window.addEventListener('keydown', this.keydown)
|
||||
window.addEventListener('keyup', this.keyup)
|
||||
},
|
||||
beforeDestroy() {
|
||||
// 移除事件监听
|
||||
window.removeEventListener('keydown', this.keydown, false)
|
||||
window.removeEventListener('keyup', this.keyup, false)
|
||||
},
|
||||
computed: {
|
||||
cmdKey() {
|
||||
return navigator.platform.startsWith('Mac') ? '⌘' : 'Ctrl'
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
checkCmdKey(event) {
|
||||
const isMac = navigator.platform.startsWith('Mac')
|
||||
const { ctrlKey, metaKey } = event
|
||||
return (isMac && metaKey) || (!isMac && ctrlKey)
|
||||
},
|
||||
keydown(event) {
|
||||
const { keyCode } = event
|
||||
const isCmd = this.checkCmdKey(event)
|
||||
const checkPreviewVisible = this.checkPreviewVisible()
|
||||
// space
|
||||
if (keyCode === 32 && this.selectRowData.length > 0 && !checkPreviewVisible) {
|
||||
if (!this.drawer) {
|
||||
this.drawer = true
|
||||
this.drawerShowTime = Date.now()
|
||||
} else {
|
||||
this.drawer = false
|
||||
}
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
// F2
|
||||
if (keyCode === 113 && this.selectRowData.length > 0 && !checkPreviewVisible) {
|
||||
this.renameFileName = this.rowContextData.name
|
||||
this.editingIndex = this.rowContextData.index
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
// Del
|
||||
if (keyCode === 8 && !this.inputting && this.selectRowData.length > 0 && !checkPreviewVisible) {
|
||||
this.removeOperation()
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
// ctrl + A / cmd + A
|
||||
if (isCmd && keyCode === 65 && !checkPreviewVisible) {
|
||||
if (this.inputting || this.editingIndex !== -1) {
|
||||
event.target.select()
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.fileListTable) {
|
||||
this.$refs.fileListTable.toggleAllSelection()
|
||||
}
|
||||
})
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
}
|
||||
// ctrl + C / cmd + C
|
||||
if (isCmd && keyCode === 67 && !checkPreviewVisible && !this.inputting && this.selectRowData.length > 0) {
|
||||
this.copyOperation()
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
// ctrl + V / cmd + V
|
||||
if (isCmd && keyCode === 86 && !checkPreviewVisible && !this.inputting && this.fileClipboard.length > 0) {
|
||||
// copy
|
||||
this.onCopy(this.getClipboardFileIdList, this.path, this.currentFolder)
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
// ctrl + X / cmd + X
|
||||
if (isCmd && keyCode === 88 && !checkPreviewVisible && !this.inputting && this.fileClipboard.length > 0) {
|
||||
// move
|
||||
this.onMove(this.getClipboardFileIdList, this.path, this.currentFolder)
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
// ctrl + P / cmd + P
|
||||
if (isCmd && keyCode === 80 && !checkPreviewVisible) {
|
||||
this.$refs.searchInput.focus()
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
},
|
||||
keyup(event) {
|
||||
const { keyCode } = event
|
||||
// space
|
||||
if (keyCode === 32) {
|
||||
if (this.drawer && Date.now() - this.drawerShowTime >= 500) {
|
||||
this.drawer = false
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
179
src/components/ShowFile/mixins/styleControl.js
Normal file
179
src/components/ShowFile/mixins/styleControl.js
Normal file
@ -0,0 +1,179 @@
|
||||
export default {
|
||||
props: {
|
||||
lessClientHeight: {
|
||||
type: Number,
|
||||
default: 106,
|
||||
},
|
||||
showSearchButton: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
isCollectView: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
showNavigation: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedRowIndices: new Set()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sortChangeOfMenu(prop, headerIndex) {
|
||||
let tableHeader = document.querySelector('.el-table__header thead tr')
|
||||
// 去掉table-header上所有排序高亮
|
||||
tableHeader.childNodes.forEach(el => {
|
||||
if (el.className.indexOf('is-sortable') > -1) {
|
||||
this.removeClass(el, 'descending')
|
||||
this.removeClass(el, 'ascending')
|
||||
}
|
||||
})
|
||||
// 重新加上排序高亮
|
||||
let order = this.sortable.order
|
||||
if (headerIndex > -1) {
|
||||
this.addClass(tableHeader.children[headerIndex], order)
|
||||
}
|
||||
this.orderCustom = true
|
||||
this.sortChange({ prop: prop, order: order })
|
||||
},
|
||||
sortChange(column) {
|
||||
let { prop, order } = column
|
||||
if (this.orderCustom || this.listModeSearch) {
|
||||
this.sortable.prop = prop
|
||||
this.sortable.order = order
|
||||
this.pagination.pageIndex = 1
|
||||
if (this.listModeSearch) {
|
||||
this.searchFile(this.searchFileName)
|
||||
} else {
|
||||
this.getFileListEnter()
|
||||
}
|
||||
}
|
||||
},
|
||||
removeClass(el, className) {
|
||||
const str = el.className
|
||||
if (str.indexOf(className) > -1) {
|
||||
el.className = str.replace(className, '')
|
||||
}
|
||||
},
|
||||
addClass(el, className) {
|
||||
if (el) {
|
||||
el.classList.add(className)
|
||||
}
|
||||
},
|
||||
// 收集选中的index值作为数组 传递给rowRed判断变换样式
|
||||
handleSelectionChange(rows) {
|
||||
// 起点
|
||||
if (rows.length > 0) {
|
||||
this.selectOrigin = rows[0].index
|
||||
this.rowContextData = rows[0]
|
||||
}
|
||||
this.selectedRowIndices = new Set(rows.map(row => row.index));
|
||||
this.$refs.fileListTable.tableSelectData = rows
|
||||
this.selectRowData = rows
|
||||
this.changeSelectedStyle(rows)
|
||||
},
|
||||
changeSelectedStyle(rows) {
|
||||
if (this.stopSortChange) {
|
||||
return
|
||||
}
|
||||
let selectTotalSize = 0
|
||||
rows.forEach(item => {
|
||||
selectTotalSize += item.size
|
||||
})
|
||||
const item_name = this.tableHead[2]
|
||||
const item_size = this.tableHead[3]
|
||||
const item_date = this.tableHead[4]
|
||||
if (rows.length > 0) {
|
||||
const sumFileAndFolder = this.getShowSumFileAndFolder(rows)
|
||||
const sizeSum = this.getShowSumSize(selectTotalSize)
|
||||
item_name.label = sumFileAndFolder
|
||||
item_name.sortable = false
|
||||
item_size.label = sizeSum
|
||||
item_size.sortable = false
|
||||
item_date.label = ''
|
||||
item_date.sortable = false
|
||||
} else {
|
||||
item_name.label = '名称'
|
||||
item_name.sortable = true
|
||||
item_size.label = '大小'
|
||||
item_size.sortable = true
|
||||
item_date.label = '修改日期'
|
||||
item_date.sortable = true
|
||||
}
|
||||
},
|
||||
// cell-style 通过返回值可以实现样式变换利用传递过来的数组index循环改变样式
|
||||
rowStyle({ row, column, rowIndex, columnIndex }) {
|
||||
if (this.selectedRowIndices.has(rowIndex)) {
|
||||
if (columnIndex === 0) {
|
||||
return {
|
||||
backgroundColor: '#e0f3fc !important',
|
||||
borderRadius: '12px 0 0 12px',
|
||||
borderLeft: 'solid 1px var(--apple-shadow-color)',
|
||||
borderTop: 'solid 1px var(--apple-shadow-color)',
|
||||
borderBottom: 'solid 1px var(--apple-shadow-color)',
|
||||
}
|
||||
}
|
||||
if (columnIndex === 3) {
|
||||
return {
|
||||
backgroundColor: '#e0f3fc !important',
|
||||
borderRadius: '0 12px 12px 0',
|
||||
borderRight: 'solid 1px var(--apple-shadow-color)',
|
||||
borderTop: 'solid 1px var(--apple-shadow-color)',
|
||||
borderBottom: 'solid 1px var(--apple-shadow-color)',
|
||||
}
|
||||
}
|
||||
return {
|
||||
backgroundColor: '#e0f3fc !important',
|
||||
borderTop: 'solid 1px var(--apple-shadow-color)',
|
||||
borderBottom: 'solid 1px var(--apple-shadow-color)',
|
||||
}
|
||||
} else {
|
||||
if (columnIndex === 0) {
|
||||
return {
|
||||
borderRadius: '12px 0 0 12px',
|
||||
}
|
||||
}
|
||||
if (columnIndex === 3) {
|
||||
return {
|
||||
borderRadius: '0 12px 12px 0',
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 选择某行预备数据
|
||||
preliminaryRowData(row) {
|
||||
if (row) {
|
||||
this.rowContextData = row
|
||||
}
|
||||
const isFavorite = this.rowContextData.isFavorite
|
||||
this.highlightFavorite(isFavorite, false)
|
||||
},
|
||||
// 是否高亮收藏图标
|
||||
highlightFavorite(isFavorite, isHover) {
|
||||
const item_menu = this.menus.find(item => {
|
||||
if (item.operation === 'favorite' || item.operation === 'unFavorite') {
|
||||
return item
|
||||
}
|
||||
})
|
||||
if (item_menu) {
|
||||
if (isFavorite) {
|
||||
item_menu.label = '取消收藏'
|
||||
item_menu.iconClass = 'menu-unfavorite-hover'
|
||||
item_menu.operation = 'unFavorite'
|
||||
} else {
|
||||
if (isHover) {
|
||||
item_menu.iconClass = 'menu-favorite-hover'
|
||||
} else {
|
||||
item_menu.iconClass = 'menu-favorite'
|
||||
}
|
||||
item_menu.label = '收藏'
|
||||
item_menu.operation = 'favorite'
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
343
src/components/ShowFile/style/index.scss
Normal file
343
src/components/ShowFile/style/index.scss
Normal file
@ -0,0 +1,343 @@
|
||||
.dashboard-container {
|
||||
min-width: 498px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
>>> .app-wrapper {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
>>> :focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.table-file-name:hover {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
>>> .plTableBox .el-table .el-table__header {
|
||||
th {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.is-sortable:hover {
|
||||
background-color: #e0f3fc;
|
||||
border-radius: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
>>> table {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 1px;
|
||||
}
|
||||
|
||||
>>> .el-table td {
|
||||
padding: 0;
|
||||
height: 50px !important;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.home-link:hover {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.info-statistics {
|
||||
padding: 5px 15px;
|
||||
float: right;
|
||||
width: 30%;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-pack: end;
|
||||
-ms-flex-pack: end;
|
||||
justify-content: flex-end;
|
||||
|
||||
span {
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
>>> .el-input-tree {
|
||||
width: 50% !important;
|
||||
}
|
||||
|
||||
>>> .el-input-tree-button {
|
||||
margin-left: 5px !important;
|
||||
}
|
||||
|
||||
>>> .open-file-dialog {
|
||||
.el-dialog {
|
||||
width: 420px;
|
||||
}
|
||||
|
||||
.svg-icon {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.dialog-msg {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
>>> .v-contextmenu-item {
|
||||
.svg-icon {
|
||||
font-size: 14px;
|
||||
}
|
||||
&:hover {
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
>>> .new-text-file-dialog {
|
||||
height: 350px;
|
||||
top: calc(50% - 175px);
|
||||
|
||||
.el-dialog {
|
||||
width: 420px;
|
||||
|
||||
.el-dialog__header {
|
||||
padding: 15px 20px 15px;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
.el-loading-spinner {
|
||||
margin-top: -13px;
|
||||
|
||||
.circular {
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-footer-delete {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.shadow-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.shadow-container::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.05), transparent 4px);
|
||||
pointer-events: none;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
>>> .van-grid-item__content {
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
border-radius: $dialogBorderRadius !important;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.vmode {
|
||||
padding: 5px 10px;
|
||||
margin-left: -5px;
|
||||
}
|
||||
|
||||
.number-files {
|
||||
position: absolute;
|
||||
top: -42px;
|
||||
left: 0;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
-webkit-backdrop-filter: saturate(180%) blur(20px);
|
||||
backdrop-filter: saturate(180%) blur(20px);
|
||||
background: #d2eefa66;
|
||||
border-radius: 40px;
|
||||
display: flex;
|
||||
|
||||
.icon {
|
||||
padding: 5px;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.number {
|
||||
padding: 0 15px 0 15px;
|
||||
}
|
||||
|
||||
.target {
|
||||
.folder {
|
||||
background-color: #1d8cff;
|
||||
color: #ffffff;
|
||||
padding: 8px;
|
||||
border-radius: 32px;
|
||||
margin-right: 5px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
>>> .el-table--enable-row-hover {
|
||||
.el-table__body tr:hover > td {
|
||||
background-color: #e0f3fc;
|
||||
}
|
||||
}
|
||||
|
||||
>>> .el-table::before {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
>>> .el-table {
|
||||
padding-left: 40px;
|
||||
th.gutter {
|
||||
display: table-cell !important;
|
||||
}
|
||||
}
|
||||
.dialog-file-list {
|
||||
padding: 10px 0;
|
||||
}
|
||||
.delete-attention {
|
||||
padding: 10px 10px;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 10px;
|
||||
.el-checkbox {
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
.mt-5 {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 250px;
|
||||
transition: width 0.3s ease-in-out;
|
||||
>>> .el-input--suffix .el-input__inner {
|
||||
padding-right: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
.search-input-focus {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.search-close-btn {
|
||||
padding: 4px;
|
||||
color: #C0C4CC;
|
||||
:hover {
|
||||
color: #409EFF;
|
||||
}
|
||||
}
|
||||
|
||||
.search-option-btn {
|
||||
padding: 4px;
|
||||
margin-right: 4px;
|
||||
color: #606266;
|
||||
:hover {
|
||||
color: #409EFF;
|
||||
}
|
||||
}
|
||||
|
||||
.search-option-btn-active {
|
||||
background: #409EFF;
|
||||
color: #fff;
|
||||
:hover {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
>>> .el-autocomplete-suggestion {
|
||||
margin-top: 0 !important;
|
||||
|
||||
.popper__arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
li {
|
||||
padding: 0 5px 0 15px;
|
||||
}
|
||||
|
||||
.suggestion-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.suggestion-item-title {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
justify-content: flex-start;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
.suggestion-item-text {
|
||||
width: 168px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.clear-search-history-btn {
|
||||
padding: 8px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.clear-search-history-btn {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.suggestion-item.action-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.suggestion-action-item-title {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
justify-content: flex-start;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
|
||||
.suggestion-action-item-text {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.suggestion-item-keyword {
|
||||
line-height: normal;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.suggestion-item-hint {
|
||||
color: #c8c9cc;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -322,7 +322,6 @@ export default {
|
||||
return {
|
||||
prompt: '文件分享已被撤销',// 文件分享已被撤销
|
||||
isLoading: true,
|
||||
fileMenuActive: '',
|
||||
path: this.$route.query.path,
|
||||
showNewFolder: false,
|
||||
isShowNewFolder: false,
|
||||
@ -401,10 +400,6 @@ export default {
|
||||
children: 'children',
|
||||
isLeaf: 'isLeaf'
|
||||
},
|
||||
|
||||
dragLoop: null,
|
||||
positionX: 0,
|
||||
positionY: 0,
|
||||
grid: false,
|
||||
vmode: 'list',
|
||||
gridColumnNum: -1,
|
||||
@ -415,7 +410,6 @@ export default {
|
||||
summaries: '',
|
||||
shareDialog: false,
|
||||
shareLink: '',
|
||||
shareFileName: '',
|
||||
generateShareLinkLoading: true,
|
||||
shareId: '',
|
||||
shortId: this.$route.params.id,
|
||||
@ -430,7 +424,6 @@ export default {
|
||||
iframePreviewRow: {},
|
||||
iframePreviewVisible: false,
|
||||
fileHandler: {},
|
||||
audioPreviewRow: {},
|
||||
audioPreviewVisible: false,
|
||||
showUpdateDateItem: this.$pc,// 列表模式下是否显示修改时间
|
||||
showSizeItem: this.$pc,// 列表模式下是否显示文件大小
|
||||
|
||||
@ -215,7 +215,6 @@
|
||||
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=`,
|
||||
fileMenuActive: '',
|
||||
path: this.$route.query.path,
|
||||
pathList: [
|
||||
{ 'folder': '', index: 0 },
|
||||
@ -265,7 +264,6 @@
|
||||
finished: false,
|
||||
cellMouseIndex: -1,
|
||||
shareDialog: false,
|
||||
shareFileName: '',
|
||||
sumFileAndFolder: '',
|
||||
shareDialogVisible: false,
|
||||
shareDialogObject: {},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user