|
|
@ -17,7 +17,10 @@ |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
<div draggable="true" class="file-item" :class="{ |
|
|
|
<div |
|
|
|
draggable="true" |
|
|
|
class="file-item" |
|
|
|
:class="{ |
|
|
|
chosen: chosenIndexs.includes(index), |
|
|
|
'no-chosen': !chosenIndexs.includes(index), |
|
|
|
'mode-icon': mode === 'icon', |
|
|
@ -26,27 +29,52 @@ |
|
|
|
'mode-middle': mode === 'middle', |
|
|
|
'mode-detail': mode === 'detail', |
|
|
|
'drag-over': hoverIndex === index, |
|
|
|
}" :style="{ |
|
|
|
}" |
|
|
|
:style="{ |
|
|
|
'--theme-color': theme === 'light' ? '#ffffff6b' : '#3bdbff3d', |
|
|
|
}" v-for="(item, index) in fileList" :key="item.path" @dblclick="handleOnOpen(item)" |
|
|
|
}" |
|
|
|
v-for="(item, index) in fileList" |
|
|
|
:key="item.path" |
|
|
|
@dblclick="handleOnOpen(item)" |
|
|
|
@touchstart.passive="doubleTouch($event, item)" |
|
|
|
@contextmenu.stop.prevent="handleRightClick($event, item, index)" @drop="hadnleDrop($event, item.path)" |
|
|
|
@dragenter.prevent="handleDragEnter(index)" @dragover.prevent @dragleave="handleDragLeave()" |
|
|
|
@dragstart.stop="startDragApp($event, item)" @click="handleClick(index, item)" @mousedown.stop :ref="(ref: any) => { |
|
|
|
@contextmenu.stop.prevent="handleRightClick($event, item, index)" |
|
|
|
@drop="hadnleDrop($event, item.path)" |
|
|
|
@dragenter.prevent="handleDragEnter(index)" |
|
|
|
@dragover.prevent |
|
|
|
@dragleave="handleDragLeave()" |
|
|
|
@dragstart.stop="startDragApp($event, item)" |
|
|
|
@click="handleClick(index, item)" |
|
|
|
@mousedown.stop |
|
|
|
:ref="(ref: any) => { |
|
|
|
if (ref) { |
|
|
|
appPositions[index] = markRaw(ref as Element); |
|
|
|
} |
|
|
|
} |
|
|
|
"> |
|
|
|
" |
|
|
|
> |
|
|
|
<div class="file-item_img"> |
|
|
|
<FileIcon :file="item" /> |
|
|
|
</div> |
|
|
|
<span v-if="editIndex !== index" class="file-item_title"> |
|
|
|
<span |
|
|
|
v-if="editIndex !== index" |
|
|
|
class="file-item_title" |
|
|
|
> |
|
|
|
{{ getName(item) }} |
|
|
|
</span> |
|
|
|
<textarea autofocus draggable="false" @dragover.stop @dragstart.stop @dragenter.stop @mousedown.stop |
|
|
|
@dblclick.stop @click.stop @blur="onEditNameEnd" v-if="editIndex === index" |
|
|
|
class="file-item_title file-item_editing" v-model="editName"></textarea> |
|
|
|
<textarea |
|
|
|
autofocus |
|
|
|
draggable="false" |
|
|
|
@dragover.stop |
|
|
|
@dragstart.stop |
|
|
|
@dragenter.stop |
|
|
|
@mousedown.stop |
|
|
|
@dblclick.stop |
|
|
|
@click.stop |
|
|
|
@keydown.enter.prevent="onEditNameEnd" |
|
|
|
v-if="editIndex === index" |
|
|
|
class="file-item_title file-item_editing" |
|
|
|
v-model="editName" |
|
|
|
></textarea> |
|
|
|
<template v-if="mode === 'detail'"> |
|
|
|
<div class="file-item_type"> |
|
|
|
<span>{{ item.isDirectory ? "-" : dealSize(item.size) }}</span> |
|
|
@ -84,7 +112,7 @@ import { Menu } from "@/system/menu/Menu"; |
|
|
|
import { throttle } from "@/util/debounce"; |
|
|
|
import { dealSize } from "@/util/file"; |
|
|
|
import { markRaw, onMounted, ref } from "vue"; |
|
|
|
|
|
|
|
import { notifyError, notifySuccess } from "@/util/msg"; |
|
|
|
const { openPropsWindow, copyFile, createLink, deleteFile } = |
|
|
|
useContextMenu(); |
|
|
|
const sys = useSystem(); |
|
|
@ -171,28 +199,19 @@ function doubleTouch(e: TouchEvent, item: OsFileWithoutContent) { |
|
|
|
|
|
|
|
const editIndex = ref<number>(-1); |
|
|
|
const editName = ref<string>(""); |
|
|
|
|
|
|
|
async function onEditNameEnd() { |
|
|
|
const editEndName = editName.value.trim(); |
|
|
|
if (editEndName && editIndex.value >= 0) { |
|
|
|
const editpath: any = |
|
|
|
props.fileList[editIndex.value].path.toString(); |
|
|
|
let newPath: any; |
|
|
|
let sp = "/"; |
|
|
|
if (editpath.indexOf("/") === -1) { |
|
|
|
sp = "\\"; |
|
|
|
} |
|
|
|
newPath = editpath?.split(sp); |
|
|
|
newPath.pop(); |
|
|
|
newPath.push(editEndName); |
|
|
|
newPath = newPath.join(sp); |
|
|
|
await sys?.fs.rename(editpath, newPath); |
|
|
|
props.onRefresh(); |
|
|
|
if (newPath.indexOf("Desktop") !== -1) { |
|
|
|
sys.refershAppList(); |
|
|
|
if (editIndex.value >= 0) { |
|
|
|
const currentItem = props.fileList[editIndex.value]; |
|
|
|
const success = await renameFile(currentItem, editEndName); |
|
|
|
if (!success) { |
|
|
|
editName.value = basename(currentItem.path); |
|
|
|
} |
|
|
|
} |
|
|
|
editIndex.value = -1; |
|
|
|
} |
|
|
|
|
|
|
|
mountEvent("edit.end", () => { |
|
|
|
onEditNameEnd(); |
|
|
|
}); |
|
|
@ -206,7 +225,7 @@ const isMobile = ref<boolean>(false); |
|
|
|
function handleClick(index: number, item: OsFileWithoutContent) { |
|
|
|
chosenIndexs.value = [index]; |
|
|
|
if (isMobile.value) { |
|
|
|
handleOnOpen(item) |
|
|
|
handleOnOpen(item); |
|
|
|
} |
|
|
|
} |
|
|
|
onMounted(() => { |
|
|
@ -252,15 +271,12 @@ function startDragApp(mouse: DragEvent, item: OsFileWithoutContent) { |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
document.addEventListener('copy', function () { |
|
|
|
const files = chosenIndexs.value.map( |
|
|
|
(index) => props.fileList[index] |
|
|
|
) |
|
|
|
document.addEventListener("copy", function () { |
|
|
|
const files = chosenIndexs.value.map((index) => props.fileList[index]); |
|
|
|
if (files.length > 0) { |
|
|
|
copyFile(files); |
|
|
|
chosenIndexs.value = []; |
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
// document.addEventListener('keydown', function (event) { |
|
|
|
// // 检测 Control + C |
|
|
@ -369,9 +385,9 @@ function handleRightClick( |
|
|
|
menuArr.push({ |
|
|
|
label: "加入知识库", |
|
|
|
click: () => { |
|
|
|
console.log(item) |
|
|
|
console.log(item); |
|
|
|
addKnowledge(item.path).then((res: any) => { |
|
|
|
console.log(res) |
|
|
|
console.log(res); |
|
|
|
if (res.code != 0) { |
|
|
|
new Notify({ |
|
|
|
title: t("tips"), |
|
|
@ -384,7 +400,7 @@ function handleRightClick( |
|
|
|
}); |
|
|
|
props.onRefresh(); |
|
|
|
} |
|
|
|
}) |
|
|
|
}); |
|
|
|
}, |
|
|
|
}); |
|
|
|
} else { |
|
|
@ -406,7 +422,6 @@ function handleRightClick( |
|
|
|
}, |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
if (choose.ifShow) { |
|
|
|
menuArr.push({ |
|
|
@ -551,6 +566,49 @@ function handleDragLeave() { |
|
|
|
// function dealtName(name: string) { |
|
|
|
// return name; |
|
|
|
// } |
|
|
|
|
|
|
|
function getPathSeparator(path: string): string { |
|
|
|
return path.indexOf("/") === -1 ? "\\" : "/"; |
|
|
|
} |
|
|
|
|
|
|
|
function buildNewPath(editpath: string, editEndName: string): string { |
|
|
|
const sp = getPathSeparator(editpath); |
|
|
|
const pathParts = editpath.split(sp); |
|
|
|
pathParts.pop(); |
|
|
|
pathParts.push(editEndName); |
|
|
|
return pathParts.join(sp); |
|
|
|
} |
|
|
|
|
|
|
|
async function renameFile( |
|
|
|
currentItem: OsFileWithoutContent, |
|
|
|
newName: string |
|
|
|
) { |
|
|
|
const currentName = basename(currentItem.path); |
|
|
|
if (newName && newName !== currentName) { |
|
|
|
const editpath = currentItem.path.toString(); |
|
|
|
const newPath = buildNewPath(editpath, newName); |
|
|
|
|
|
|
|
if (await sys?.fs.exists(newPath)) { |
|
|
|
notifyError("文件名已存在,请选择其他名称。"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
await sys?.fs.rename(editpath, newPath); |
|
|
|
props.onRefresh(); |
|
|
|
if (newPath.includes("Desktop")) { |
|
|
|
sys.refershAppList(); |
|
|
|
} |
|
|
|
notifySuccess("重命名成功"); |
|
|
|
return true; |
|
|
|
} catch (error) { |
|
|
|
console.error("重命名失败:", error); |
|
|
|
notifyError("重命名失败,请重试。"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
</script> |
|
|
|
<style lang="scss" scoped> |
|
|
|
.file-item { |
|
|
@ -585,13 +643,28 @@ function handleDragLeave() { |
|
|
|
display: inline-block !important; |
|
|
|
outline: none; |
|
|
|
pointer-events: all; |
|
|
|
padding: 0; |
|
|
|
padding: 6px 10px; |
|
|
|
margin: 0; |
|
|
|
min-width: 0; |
|
|
|
height: min-content !important; |
|
|
|
width: min-content !important; |
|
|
|
min-width: 120px; |
|
|
|
max-width: 100%; |
|
|
|
height: auto !important; |
|
|
|
width: auto !important; |
|
|
|
resize: none; |
|
|
|
border-radius: 0; |
|
|
|
border-radius: 6px; |
|
|
|
border: 1px solid var(--border-color, #ccc); |
|
|
|
background-color: var(--input-bg-color, #f9f9f9); |
|
|
|
color: var(--input-text-color, #333); |
|
|
|
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15); |
|
|
|
transition: border-color 0.3s, box-shadow 0.3s, |
|
|
|
background-color 0.3s; |
|
|
|
overflow-x: auto; |
|
|
|
white-space: nowrap; |
|
|
|
} |
|
|
|
|
|
|
|
.file-item_editing:focus { |
|
|
|
border-color: var(--focus-border-color, #0056b3); |
|
|
|
box-shadow: 0 3px 8px rgba(0, 86, 179, 0.3); |
|
|
|
background-color: var(--focus-bg-color, #e6f7ff); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -751,6 +824,5 @@ function handleDragLeave() { |
|
|
|
background-color: transparent; |
|
|
|
border: 1px solid transparent; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
</style> |
|
|
|