Skip to content

Commit e713507

Browse files
committed
实现桌面图标拖动和文件拖入文件夹功能
1 parent b6fcc5b commit e713507

2 files changed

Lines changed: 88 additions & 3 deletions

File tree

src/components/Desktop.jsx

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,30 @@ const DesktopIcon = styled.div`
6060
}
6161
`;
6262

63+
const DragOverlay = styled.div`
64+
position: fixed;
65+
pointer-events: none;
66+
z-index: 9999;
67+
opacity: 0.8;
68+
display: flex;
69+
flex-direction: column;
70+
align-items: center;
71+
color: white;
72+
text-shadow: 1px 1px 2px black;
73+
`;
74+
6375
const Desktop = () => {
6476
const { t } = useTranslation();
65-
const { fs } = useFileSystem();
77+
const { fs, moveFile } = useFileSystem();
6678
const { windows, openWindow, focusWindow } = useWindowManager();
6779
const { showModal } = useModal();
6880

6981
const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0 });
7082
const [refreshKey, setRefreshKey] = useState(0);
7183
const [isRefreshing, setIsRefreshing] = useState(false);
7284
const [pasteDisabled, setPasteDisabled] = useState(true);
85+
const [draggedItem, setDraggedItem] = useState(null);
86+
const [dragPosition, setDragPosition] = useState({ x: 0, y: 0 });
7387

7488
const handleIconDoubleClick = (key, item) => {
7589
const resolved = resolveFileOpen(key, item);
@@ -80,6 +94,27 @@ const Desktop = () => {
8094
openWindow(resolved.appId, item.name, resolved.component, resolved.icon, resolved.windowProps);
8195
};
8296

97+
const handleDragStart = (e, key, item) => {
98+
setDraggedItem({ key, item });
99+
setDragPosition({ x: e.clientX, y: e.clientY });
100+
};
101+
102+
const handleDrag = (e) => {
103+
setDragPosition({ x: e.clientX, y: e.clientY });
104+
};
105+
106+
const handleDragEnd = (e, targetKey) => {
107+
// 如果拖拽到了另一个文件夹上
108+
if (targetKey && targetKey !== draggedItem?.key) {
109+
const targetItem = fs.root.children[targetKey];
110+
if (targetItem && targetItem.type === 'folder') {
111+
// 将文件移动到目标文件夹
112+
moveFile([], draggedItem.key, [targetKey]);
113+
}
114+
}
115+
setDraggedItem(null);
116+
};
117+
83118
const handleContextMenu = async (e) => {
84119
e.preventDefault();
85120
try {
@@ -134,7 +169,17 @@ const Desktop = () => {
134169
? 'recycle_bin_full'
135170
: item.icon;
136171
return (
137-
<DesktopIcon key={key} data-testid={`desktop-icon-${key}`} onDoubleClick={() => handleIconDoubleClick(key, item)}>
172+
<DesktopIcon
173+
key={key}
174+
data-testid={`desktop-icon-${key}`}
175+
onDoubleClick={() => handleIconDoubleClick(key, item)}
176+
draggable
177+
onDragStart={(e) => handleDragStart(e, key, item)}
178+
onDrag={(e) => handleDrag(e)}
179+
onDragEnd={(e) => handleDragEnd(e, null)}
180+
onDragOver={(e) => e.preventDefault()} // 允许放置
181+
onDrop={(e) => handleDragEnd(e, key)}
182+
>
138183
<div className="icon-wrapper">
139184
<XPIcon name={iconName} size={32} />
140185
</div>

src/context/FileSystemContext.jsx

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,45 @@ export const FileSystemProvider = ({ children }) => {
142142
});
143143
};
144144

145+
const moveFile = (sourcePath, fileName, destinationPath, newName = fileName) => {
146+
setFs(prevFs => {
147+
const newFs = JSON.parse(JSON.stringify(prevFs));
148+
149+
let sourceParent = newFs.root;
150+
for (let part of sourcePath) {
151+
if (sourceParent.children && sourceParent.children[part]) {
152+
sourceParent = sourceParent.children[part];
153+
} else {
154+
return prevFs;
155+
}
156+
}
157+
158+
if (!sourceParent.children || !sourceParent.children[fileName]) {
159+
return prevFs;
160+
}
161+
162+
let destinationParent = newFs.root;
163+
for (let part of destinationPath) {
164+
if (destinationParent.children && destinationParent.children[part]) {
165+
destinationParent = destinationParent.children[part];
166+
} else {
167+
return prevFs;
168+
}
169+
}
170+
171+
if (!destinationParent.children) {
172+
destinationParent.children = {};
173+
}
174+
175+
// 移动文件
176+
destinationParent.children[newName] = JSON.parse(JSON.stringify(sourceParent.children[fileName]));
177+
destinationParent.children[newName].name = newName;
178+
delete sourceParent.children[fileName];
179+
180+
return newFs;
181+
});
182+
};
183+
145184
const copyFile = (sourcePath, fileName, destinationPath, newName = fileName) => {
146185
setFs(prevFs => {
147186
const newFs = JSON.parse(JSON.stringify(prevFs));
@@ -300,7 +339,8 @@ export const FileSystemProvider = ({ children }) => {
300339
pasteFile,
301340
searchFiles,
302341
getFileProperties,
303-
clipboard
342+
clipboard,
343+
moveFile
304344
}}
305345
>
306346
{children}

0 commit comments

Comments
 (0)