Enhance file transfer capabilities by introducing support for multiple source paths and recursive directory transfers in FileController and LocalFileService. Updated TransferRequest to accommodate new fields, improved error handling, and refined UI interactions in app.js for better user experience during file operations.
This commit is contained in:
@@ -273,7 +273,12 @@ function getParentPath(path) {
|
||||
function updateSelectedFiles(panelId) {
|
||||
const selected = $(`#${panelId}-file-list .file-item.selected`);
|
||||
panelState[panelId].selectedFiles = selected.map(function() {
|
||||
return $(this).data('path');
|
||||
return {
|
||||
path: $(this).data('path'),
|
||||
isDirectory: $(this).data('is-dir') === true ||
|
||||
$(this).data('is-dir') === 'true' ||
|
||||
$(this).data('is-dir') === 'True'
|
||||
};
|
||||
}).get();
|
||||
}
|
||||
|
||||
@@ -371,9 +376,10 @@ function handleFileDrop(data, targetPanelId) {
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
sourceSessionId: sourceSessionId,
|
||||
sourcePath: sourcePath,
|
||||
sourcePaths: [sourcePath],
|
||||
targetSessionId: targetSessionId,
|
||||
targetPath: targetPath
|
||||
targetPath: targetPath,
|
||||
recursive: true
|
||||
}),
|
||||
success: function(response) {
|
||||
showTransferProgress(false);
|
||||
@@ -623,8 +629,17 @@ function getFileNameFromPath(path) {
|
||||
}
|
||||
|
||||
// ========== 连接管理(模块03)==========
|
||||
function ensureBootstrap() {
|
||||
if (typeof bootstrap === 'undefined') {
|
||||
alert('Bootstrap 未加载,请检查网络连接或暂时关闭广告拦截器后刷新页面');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function showConnectionDialog() {
|
||||
loadConnectionList();
|
||||
if (!ensureBootstrap()) return;
|
||||
new bootstrap.Modal(document.getElementById('connectionModal')).show();
|
||||
}
|
||||
|
||||
@@ -758,6 +773,7 @@ function updatePanelStateWithConnection(sessionId, conn) {
|
||||
|
||||
function showAddConnectionDialog() {
|
||||
document.getElementById('connection-form').reset();
|
||||
if (!ensureBootstrap()) return;
|
||||
new bootstrap.Modal(document.getElementById('addConnectionModal')).show();
|
||||
}
|
||||
|
||||
@@ -780,7 +796,9 @@ function saveConnection() {
|
||||
data: JSON.stringify(data),
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
bootstrap.Modal.getInstance(document.getElementById('addConnectionModal')).hide();
|
||||
if (typeof bootstrap !== 'undefined') {
|
||||
bootstrap.Modal.getInstance(document.getElementById('addConnectionModal')).hide();
|
||||
}
|
||||
loadConnectionList();
|
||||
} else {
|
||||
alert('保存失败: ' + (response.message || '未知错误'));
|
||||
@@ -824,7 +842,9 @@ function connectToServer(connId) {
|
||||
updateConnectionSelect('right');
|
||||
updatePanelStateWithConnection(sessionId, conn);
|
||||
loadConnectionList();
|
||||
bootstrap.Modal.getInstance(document.getElementById('connectionModal')).hide();
|
||||
if (typeof bootstrap !== 'undefined') {
|
||||
bootstrap.Modal.getInstance(document.getElementById('connectionModal')).hide();
|
||||
}
|
||||
updateStatus('已连接到 ' + (conn.name || conn.host));
|
||||
} else {
|
||||
alert('连接失败: ' + (res.message || '未知错误'));
|
||||
@@ -1056,7 +1076,7 @@ function downloadFile(sessionId, path) {
|
||||
// 下载选中的文件
|
||||
function downloadFiles() {
|
||||
const panelId = getSourcePanelId();
|
||||
const selectedFiles = panelState[panelId].selectedFiles;
|
||||
const selectedFiles = panelState[panelId].selectedFiles || [];
|
||||
const sessionId = panelState[panelId].sessionId;
|
||||
|
||||
if (selectedFiles.length === 0) {
|
||||
@@ -1064,8 +1084,14 @@ function downloadFiles() {
|
||||
return;
|
||||
}
|
||||
|
||||
selectedFiles.forEach(function(path) {
|
||||
downloadFile(sessionId, path);
|
||||
selectedFiles.forEach(function(item) {
|
||||
if (!item || !item.path) return;
|
||||
if (item.isDirectory) {
|
||||
if (!confirm('当前选中包含文件夹,下载时将递归包含其所有子目录和文件,可能耗时较长,是否继续?')) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
downloadFile(sessionId, item.path);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1074,7 +1100,7 @@ function doTransfer(sourcePanelId, targetPanelId) {
|
||||
const sourceSessionId = panelState[sourcePanelId].sessionId;
|
||||
const targetSessionId = panelState[targetPanelId].sessionId;
|
||||
const targetPath = panelState[targetPanelId].currentPath;
|
||||
const selectedFiles = panelState[sourcePanelId].selectedFiles;
|
||||
const selectedFiles = panelState[sourcePanelId].selectedFiles || [];
|
||||
|
||||
if (selectedFiles.length === 0) {
|
||||
alert('请在' + (sourcePanelId === 'left' ? '左侧' : '右侧') + '面板选择要传输的文件');
|
||||
@@ -1093,54 +1119,43 @@ function doTransfer(sourcePanelId, targetPanelId) {
|
||||
showTransferCountProgress(0, total, '');
|
||||
updateTransferProgress(0, '传输中 (0/' + total + ')', true); // 后端无流式进度,使用动画条
|
||||
|
||||
selectedFiles.forEach(function(sourcePath) {
|
||||
$.ajax({
|
||||
url: API_BASE + 'api/files/transfer',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
sourceSessionId: sourceSessionId,
|
||||
sourcePath: sourcePath,
|
||||
targetSessionId: targetSessionId,
|
||||
targetPath: targetPath
|
||||
}),
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
completed++;
|
||||
} else {
|
||||
failed++;
|
||||
alert('传输失败: ' + (response.message || '未知错误'));
|
||||
}
|
||||
const done = completed + failed;
|
||||
showTransferCountProgress(done, total, getFileNameFromPath(sourcePath));
|
||||
updateTransferProgress(total > 0 ? Math.round((done / total) * 100) : 0, '传输中 (' + done + '/' + total + ')', false);
|
||||
if (done === total) {
|
||||
showTransferProgress(false);
|
||||
if (failed === 0) {
|
||||
updateStatus('所有文件传输成功');
|
||||
} else {
|
||||
updateStatus('传输完成:成功 ' + completed + ',失败 ' + failed);
|
||||
}
|
||||
loadFiles(targetPanelId);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
failed++;
|
||||
const errMsg = xhr.responseJSON && xhr.responseJSON.message ? xhr.responseJSON.message : error;
|
||||
alert('传输失败: ' + errMsg);
|
||||
const done = completed + failed;
|
||||
showTransferCountProgress(done, total, getFileNameFromPath(sourcePath));
|
||||
updateTransferProgress(total > 0 ? Math.round((done / total) * 100) : 0, '传输中 (' + done + '/' + total + ')', false);
|
||||
if (done === total) {
|
||||
showTransferProgress(false);
|
||||
updateStatus('传输完成:成功 ' + completed + ',失败 ' + failed);
|
||||
loadFiles(targetPanelId);
|
||||
}
|
||||
const sourcePaths = selectedFiles
|
||||
.filter(function(item) { return item && item.path; })
|
||||
.map(function(item) { return item.path; });
|
||||
|
||||
const hasDirectory = selectedFiles.some(function(item) { return item && item.isDirectory; });
|
||||
const recursive = hasDirectory; // 若包含目录,则自动递归
|
||||
|
||||
$.ajax({
|
||||
url: API_BASE + 'api/files/transfer',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
sourceSessionId: sourceSessionId,
|
||||
sourcePaths: sourcePaths,
|
||||
targetSessionId: targetSessionId,
|
||||
targetPath: targetPath,
|
||||
recursive: recursive
|
||||
}),
|
||||
success: function(response) {
|
||||
showTransferProgress(false);
|
||||
if (response.success) {
|
||||
updateStatus('传输成功');
|
||||
} else {
|
||||
alert('传输失败: ' + (response.message || '未知错误'));
|
||||
updateStatus('传输失败');
|
||||
}
|
||||
});
|
||||
loadFiles(targetPanelId);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
showTransferProgress(false);
|
||||
const errMsg = xhr.responseJSON && xhr.responseJSON.message ? xhr.responseJSON.message : error;
|
||||
alert('传输失败: ' + errMsg);
|
||||
updateStatus('传输失败');
|
||||
}
|
||||
});
|
||||
|
||||
updateStatus('正在传输 ' + total + ' 个文件...');
|
||||
updateStatus('正在传输 ' + total + ' 个项目...');
|
||||
}
|
||||
|
||||
// 传输到右侧:左侧面板选中的文件 -> 右侧面板
|
||||
|
||||
Reference in New Issue
Block a user