<template>
|
<div class="file_grid" @mousedown="startSelection">
|
<a-empty v-if="fileList.length == 0" :image="simpleImage"></a-empty>
|
|
<ul v-else class="file-list" ref="gridListRef">
|
<li class="file-item draggable selectable" v-for="(item, index) in fileListSorted"
|
:class="{ dragging: item.dragging }" :title="$file.getFileNameComplete(item)" :key="index"
|
:style="`width: ${gridSize + 40}px;`" @click="handleClickFileName(item)"
|
@contextmenu.prevent="handleContextMenu(item, index, $event)" @dragstart="handleDragStart(item, $event)"
|
@dblclick="handDbclickFileName(item)" @dragover="handleDragOver(item)" @mousedown.stop="fileMouseDown">
|
<img class="file-img" :src="$file.setFileImg(item)" :style="`width: ${gridSize}px; height: ${gridSize}px;`" />
|
<div class="file-name" v-html="$file.getFileNameComplete(item)"></div>
|
|
<div class="file-checked-wrapper" draggable :class="{ checked: item.checked }" v-show="isBatchOperation"
|
@click.stop.self="item.checked = !item.checked">
|
<a-checkbox class="file-checked" :checked="item.checked"
|
@click.stop="item.checked = !item.checked"></a-checkbox>
|
</div>
|
|
</li>
|
</ul>
|
<div v-if="selecting" class="selection-box" :style="selectionBoxStyles"></div>
|
</div>
|
</template>
|
|
<script>
|
import { Empty } from 'ant-design-vue';
|
export default {
|
props: ['fileList', 'searchStr'],
|
data() {
|
return {
|
gridSize: 70,
|
fileListSorted: [],
|
timer: null,
|
startX: 0,
|
startY: 0,
|
endX: 0,
|
endY: 0,
|
selecting: false,
|
|
}
|
},
|
beforeCreate() {
|
this.simpleImage = Empty.PRESENTED_IMAGE_SIMPLE;
|
|
},
|
methods: {
|
// 文件名点击事件
|
handleClickFileName(record) {
|
this.timer = setTimeout(() => {
|
console.log("fileNameclick", record)
|
this.$emit('fileClick', record)
|
let ele = document.getElementById(record.filePath + '/' + record.fileName);
|
ele && ele.scrollIntoView({ block: 'end', behavior: 'smooth' });
|
}, 250)
|
|
},
|
|
handDbclickFileName(record) {
|
clearTimeout(this.timer)
|
this.timer = null;
|
console.log(`output->双击`)
|
this.$emit('fileDbclick', record)
|
|
},
|
/**
|
* 文件鼠标右键事件
|
* @param {object} item 文件信息
|
* @param {number} index 文件索引
|
* @param {object} event 鼠标事件信息
|
*/
|
handleContextMenu(item, index, event) {
|
// 阻止右键事件冒泡
|
event.cancelBubble = true
|
// xs 以上的屏幕
|
this.selectedFile = item
|
if (!this.isBatchOperation) {
|
event.preventDefault()
|
this.$openBox
|
.contextMenu({
|
selectedFile: item,
|
domEvent: event
|
})
|
.then((res) => {
|
this.selectedFile = {}
|
console.log("CALLBACK::::", res);
|
if (res === 'confirm') {
|
this.$emit('reloadPathTree', this.searchStr) // 刷新文件列表
|
} else if (res === 'open') {
|
this.handleClickFileName(item)
|
} else if (res === 'refreshFavorite') {
|
this.$emit("refreshFavorite")
|
this.$message('收藏成功')
|
}
|
|
})
|
}
|
},
|
|
|
handleDragStart(item, event) {
|
item.dragging = true;
|
//console.log(`output->this.selectedFileList`, this.selectedFileList)
|
var dragData;
|
dragData = item.pathId
|
if (this.selectedFileList && this.selectedFileList.length > 0) {
|
event.dataTransfer.setData("text/plain", "Dragged element");
|
var img = new Image();
|
img.src = require('@/assets/file/files1.png')
|
img.width = 100
|
img.height = 100
|
//console.log(`output->img`, img)
|
// img.src = 'example.gif';
|
event.dataTransfer.setDragImage(img, 50, 50);
|
dragData = this.selectedFileList
|
localStorage.setItem("isBatch", true);
|
}
|
|
//event.preventDefault();
|
|
|
// document.addEventListener("mousemove", (e) => this.moveDrag(item, e));
|
// document.addEventListener("mouseup", this.stopDrag(item));
|
// event.preventDefault();
|
// console.log(`output->item`, item)
|
this.$emit('fileDragStart', dragData)
|
// console.log(`output->event`, event)
|
|
// console.log(`output->event.`, event.dataTransfer.getData("text/plain"))
|
// event.dataTransfer.setDragImage(img, 10, 10)
|
},
|
|
handleDragOver(item, event) {
|
// console.log(`output->item`, item)
|
},
|
|
fileMouseDown(event) {
|
return;
|
},
|
startSelection(event) {
|
event.preventDefault();
|
this.startX = event.clientX;
|
this.startY = event.clientY;
|
this.endX = this.startX;
|
this.endY = this.startY;
|
this.selecting = true;
|
|
document.addEventListener("mousemove", this.moveSelection);
|
document.addEventListener("mouseup", this.stopSelection);
|
},
|
|
// moveDrag(item, event) {
|
|
// if (item && item.dragging) {
|
// const endX = event.clientX;
|
// const endY = event.clientY;
|
|
|
// console.log(`output->endX`, endX)
|
// console.log(`output->endY`, endY)
|
// console.log(`output->item`, item)
|
// console.log(`output->event`, event)
|
// }
|
|
// },
|
|
// stopDrag(item) {
|
// item.dragging = false;
|
// document.removeEventListener("mousemove", this.moveDrag(item));
|
// document.removeEventListener("mouseup", this.stopDrag(item));
|
// },
|
|
|
moveSelection(event) {
|
if (this.selecting) {
|
this.endX = event.clientX;
|
this.endY = event.clientY;
|
const minX = Math.min(this.startX, this.endX);
|
const maxX = Math.max(this.startX, this.endX);
|
const minY = Math.min(this.startY, this.endY);
|
const maxY = Math.max(this.startY, this.endY);
|
|
this.fileListSorted.forEach((item, index) => {
|
const rect = this.$refs.gridListRef.children[index].getBoundingClientRect();
|
const itemX = rect.left + rect.width / 2;
|
const itemY = rect.top + rect.height / 2;
|
|
item.checked =
|
itemX >= minX && itemX <= maxX && itemY >= minY && itemY <= maxY;
|
});
|
}
|
},
|
stopSelection(event) {
|
this.selecting = false;
|
document.removeEventListener("mousemove", this.moveSelection);
|
document.removeEventListener("mouseup", this.stopSelection);
|
}
|
},
|
computed: {
|
|
|
// 是否批量操作
|
isBatchOperation() {
|
return this.$store.state.fileList.isBatchOperation
|
},
|
// 批量操作模式 - 被选中的文件
|
selectedFileList() {
|
console.log("fileList:::", this.fileList);
|
this.fileListSorted = this.fileListSorted.length == 0 ? [...this.fileList].map((item) => {
|
return { ...item, checked: false }
|
}) : this.fileListSorted
|
let res = this.fileListSorted.filter((item) => item.checked)
|
return res
|
},
|
|
selectionBoxStyles() {
|
const minX = Math.min(this.startX, this.endX);
|
const minY = Math.min(this.startY, this.endY);
|
const width = Math.abs(this.startX - this.endX);
|
const height = Math.abs(this.startY - this.endY);
|
|
return {
|
left: minX + 'px',
|
top: minY + 'px',
|
width: width + 'px',
|
height: height + 'px'
|
};
|
}
|
},
|
watch: {
|
fileList(newValue) {
|
console.log("watchFileList:::");
|
this.fileListSorted = [...newValue].map((item) => {
|
return { ...item, checked: false }
|
})
|
},
|
// 批量操作模式 - 监听被选中的文件
|
selectedFileList(newValue) {
|
console.log("new value:::", newValue);
|
this.$store.commit('changeSelectedFiles', newValue)
|
this.$store.commit('changeIsBatchOperation', newValue.length !== 0)
|
},
|
}
|
|
|
}
|
</script>
|
|
<style lang="less" scoped>
|
@import '~@assets/file/less/varibles.less';
|
@import '~@assets/file/less/mixins.less';
|
|
.file_grid {
|
height: calc(100vh - 265px);
|
overflow: auto;
|
}
|
|
.file-list {
|
|
overflow-y: auto;
|
display: flex;
|
flex-wrap: wrap;
|
align-items: flex-start;
|
align-content: flex-start;
|
list-style: none;
|
|
|
.file-item {
|
margin: 0 16px 16px 0;
|
position: relative;
|
padding: 8px;
|
text-align: center;
|
cursor: pointer;
|
z-index: 1;
|
|
&:hover {
|
background: #F5F7FA;
|
|
.file-name {
|
font-weight: 550;
|
}
|
}
|
|
.file-name {
|
margin-top: 8px;
|
height: 44px;
|
line-height: 22px;
|
font-size: 12px;
|
word-break: break-all;
|
/* autoprefixer: off */
|
-webkit-box-orient: vertical;
|
/* autoprefixer: on */
|
.setEllipsis(2);
|
|
/deep/ .keyword {
|
color: @Danger;
|
}
|
|
}
|
|
.file-checked-wrapper {
|
position: absolute;
|
top: 0;
|
left: 0;
|
z-index: 2;
|
background: rgba(245, 247, 250, 0.5);
|
width: 100%;
|
height: 100%;
|
|
.file-checked {
|
position: absolute;
|
top: 16px;
|
left: 24px;
|
}
|
}
|
|
.file-checked-wrapper.checked {
|
background: rgba(245, 247, 250, 0);
|
}
|
}
|
|
.file-item.active {
|
background: #F5F7FA;
|
}
|
}
|
|
.draggable {
|
cursor: grab;
|
}
|
|
.selection-box {
|
position: absolute;
|
border: 2px dashed rgb(0, 153, 255);
|
background-color: rgba(0, 119, 255, 0.3);
|
pointer-events: none;
|
z-index: 999;
|
}
|
</style>
|