Browse Source

fix:修复文件夹重命名后会被删除问题

master
秋田弘 5 months ago
parent
commit
beaeedec39
  1. 352
      frontend/src/components/builtin/FileList.vue

352
frontend/src/components/builtin/FileList.vue

@ -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>
@ -64,33 +92,33 @@
</div>
</template>
<script lang="ts" setup>
import { useAppMenu } from "@/hook/useAppMenu";
import { useContextMenu } from "@/hook/useContextMenu.ts";
import { useFileDrag } from "@/hook/useFileDrag";
import { Rect } from "@/hook/useRectChosen";
import { dealSystemName, t } from "@/i18n";
import { useChooseStore } from "@/stores/choose";
import { getSystemKey } from "@/system/config";
import { emitEvent, mountEvent } from "@/system/event";
import { addKnowledge } from "@/hook/useAi";
import {
import { useAppMenu } from "@/hook/useAppMenu";
import { useContextMenu } from "@/hook/useContextMenu.ts";
import { useFileDrag } from "@/hook/useFileDrag";
import { Rect } from "@/hook/useRectChosen";
import { dealSystemName, t } from "@/i18n";
import { useChooseStore } from "@/stores/choose";
import { getSystemKey } from "@/system/config";
import { emitEvent, mountEvent } from "@/system/event";
import { addKnowledge } from "@/hook/useAi";
import {
basename,
BrowserWindow,
Notify,
OsFileWithoutContent,
useSystem,
} from "@/system/index.ts";
import { Menu } from "@/system/menu/Menu";
import { throttle } from "@/util/debounce";
import { dealSize } from "@/util/file";
import { markRaw, onMounted, ref } from "vue";
const { openPropsWindow, copyFile, createLink, deleteFile } =
} from "@/system/index.ts";
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();
const { startDrag, folderDrop } = useFileDrag(sys);
const choose = useChooseStore();
const props = defineProps({
const sys = useSystem();
const { startDrag, folderDrop } = useFileDrag(sys);
const choose = useChooseStore();
const props = defineProps({
onChosen: {
type: Function,
required: true,
@ -119,9 +147,9 @@ const props = defineProps({
type: String,
default: "icon",
},
});
});
function getName(item: any) {
function getName(item: any) {
const name = dealSystemName(basename(item.path));
// console.log(name)
// console.log(item.path)
@ -130,9 +158,9 @@ function getName(item: any) {
} else {
return name;
}
}
}
function handleOnOpen(item: OsFileWithoutContent) {
function handleOnOpen(item: OsFileWithoutContent) {
// props.onOpen(item);
// emitEvent('desktop.app.open');
chosenIndexs.value = [];
@ -145,14 +173,14 @@ function handleOnOpen(item: OsFileWithoutContent) {
props.onOpen(item);
emitEvent("desktop.app.open");
}
}
function hadnleDrop(mouse: DragEvent, path: string) {
}
function hadnleDrop(mouse: DragEvent, path: string) {
hoverIndex.value = -1;
folderDrop(mouse, path);
chosenIndexs.value = [];
}
let expired: number | null = null;
function doubleTouch(e: TouchEvent, item: OsFileWithoutContent) {
}
let expired: number | null = null;
function doubleTouch(e: TouchEvent, item: OsFileWithoutContent) {
if (e.touches.length === 1) {
if (!expired) {
expired = e.timeStamp + 400;
@ -167,49 +195,40 @@ function doubleTouch(e: TouchEvent, item: OsFileWithoutContent) {
expired = e.timeStamp + 400;
}
}
}
}
const editIndex = ref<number>(-1);
const editName = ref<string>("");
async function onEditNameEnd() {
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", () => {
}
mountEvent("edit.end", () => {
onEditNameEnd();
});
});
const hoverIndex = ref<number>(-1);
const appPositions = ref<Array<Element>>([]);
const hoverIndex = ref<number>(-1);
const appPositions = ref<Array<Element>>([]);
const chosenIndexs = ref<Array<number>>([]);
import { isMobileDevice } from "@/util/device";
const isMobile = ref<boolean>(false);
function handleClick(index: number, item: OsFileWithoutContent) {
const chosenIndexs = ref<Array<number>>([]);
import { isMobileDevice } from "@/util/device";
const isMobile = ref<boolean>(false);
function handleClick(index: number, item: OsFileWithoutContent) {
chosenIndexs.value = [index];
if (isMobile.value) {
handleOnOpen(item)
handleOnOpen(item);
}
}
onMounted(() => {
}
onMounted(() => {
isMobile.value = isMobileDevice();
chosenIndexs.value = [];
props.onChosen(
@ -233,9 +252,9 @@ onMounted(() => {
chosenIndexs.value = tempChosen;
}, 100)
);
});
});
function startDragApp(mouse: DragEvent, item: OsFileWithoutContent) {
function startDragApp(mouse: DragEvent, item: OsFileWithoutContent) {
if (chosenIndexs.value.length) {
startDrag(
mouse,
@ -251,34 +270,31 @@ function startDragApp(mouse: DragEvent, item: OsFileWithoutContent) {
chosenIndexs.value = [];
});
}
}
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
// if (event.ctrlKey && event.key === 'c') {
// //console.log('Control + C ');
// copyFile(
// chosenIndexs.value.map(
// (index) => props.fileList[index]
// )
// );
// chosenIndexs.value = [];
// }
// });
function handleRightClick(
});
// document.addEventListener('keydown', function (event) {
// // Control + C
// if (event.ctrlKey && event.key === 'c') {
// //console.log('Control + C ');
// copyFile(
// chosenIndexs.value.map(
// (index) => props.fileList[index]
// )
// );
// chosenIndexs.value = [];
// }
// });
function handleRightClick(
mouse: MouseEvent,
item: OsFileWithoutContent,
index: number
) {
) {
if (chosenIndexs.value.length <= 1) {
chosenIndexs.value = [
props.fileList.findIndex((app) => app.path === item.path),
@ -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({
@ -538,22 +553,65 @@ function handleRightClick(
//console.log(ext)
Menu.buildFromTemplate(menuArr).popup(mouse);
}
}
function handleDragEnter(index: number) {
function handleDragEnter(index: number) {
hoverIndex.value = index;
}
}
function handleDragLeave() {
function handleDragLeave() {
hoverIndex.value = -1;
}
}
// function dealtName(name: string) {
// return name;
// }
// 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 {
.file-item {
position: relative;
display: flex;
flex-direction: column;
@ -585,21 +643,36 @@ 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:hover {
.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);
}
}
.file-item:hover {
background-color: #b1f1ff4c;
}
}
.chosen {
.chosen {
border: 1px dashed #3bdbff3d;
// background-color: #ffffff6b;
background-color: var(--theme-color);
@ -612,9 +685,9 @@ function handleDragLeave() {
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
}
}
.no-chosen {
.no-chosen {
.file-item_title {
overflow: hidden;
text-overflow: ellipsis;
@ -623,15 +696,15 @@ function handleDragLeave() {
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
}
}
.drag-over {
.drag-over {
border: 1px dashed #3bdbff3d;
// background-color: #ffffff6b;
background-color: var(--theme-color);
}
}
.mode-icon {
.mode-icon {
.file-item_img {
width: 60%;
height: calc(0.6 * var(--desk-item-size));
@ -648,9 +721,9 @@ function handleDragLeave() {
word-break: break-all;
flex-grow: 0;
}
}
}
.mode-list {
.mode-list {
display: flex;
flex-direction: row;
justify-content: flex-start;
@ -669,24 +742,24 @@ function handleDragLeave() {
height: min-content;
word-break: break-all;
}
}
}
.mode-icon {
.mode-icon {
width: var(--desk-item-size);
height: var(--desk-item-size);
}
}
.mode-big {
.mode-big {
width: calc(var(--desk-item-size) * 2.5);
height: calc(var(--desk-item-size) * 2.5);
}
}
.mode-middle {
.mode-middle {
width: calc(var(--desk-item-size) * 1.5);
height: calc(var(--desk-item-size) * 1.5);
}
}
.mode-detail {
.mode-detail {
display: flex;
flex-direction: row;
justify-content: flex-start;
@ -716,14 +789,14 @@ function handleDragLeave() {
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.file-bar:hover {
.file-bar:hover {
background-color: unset;
user-select: none;
}
}
@media screen and (max-width: 768px) {
@media screen and (max-width: 768px) {
.file-item {
height: vh(70);
display: flex;
@ -751,6 +824,5 @@ function handleDragLeave() {
background-color: transparent;
border: 1px solid transparent;
}
}
}
</style>

Loading…
Cancel
Save