update
This commit is contained in:
@@ -268,8 +268,25 @@ const sidebarProps = computed(() => (paneName: PaneName | null) => {
|
|||||||
// We might not need 'request-add-connection' from the sidebar context
|
// We might not need 'request-add-connection' from the sidebar context
|
||||||
// onRequestAddConnection: () => emit('request-add-connection')
|
// onRequestAddConnection: () => emit('request-add-connection')
|
||||||
};
|
};
|
||||||
|
case 'fileManager':
|
||||||
|
// Only provide props if there's an active session
|
||||||
|
if (activeSession.value) {
|
||||||
|
return {
|
||||||
|
...baseProps,
|
||||||
|
sessionId: activeSession.value.sessionId, // Corrected: Use sessionId
|
||||||
|
dbConnectionId: activeSession.value.connectionId,
|
||||||
|
sftpManager: activeSession.value.sftpManager,
|
||||||
|
wsDeps: {
|
||||||
|
sendMessage: activeSession.value.wsManager.sendMessage,
|
||||||
|
onMessage: activeSession.value.wsManager.onMessage,
|
||||||
|
isConnected: activeSession.value.wsManager.isConnected,
|
||||||
|
isSftpReady: activeSession.value.wsManager.isSftpReady
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return baseProps; // Return only base props if no active session
|
||||||
|
}
|
||||||
// Add cases for other components if they need specific props or event forwarding in the sidebar
|
// Add cases for other components if they need specific props or event forwarding in the sidebar
|
||||||
// case 'fileManager': return { ...baseProps, ... };
|
|
||||||
// case 'commandHistory': return { ...baseProps, onExecuteCommand: (cmd: string) => emit('sendCommand', cmd) };
|
// case 'commandHistory': return { ...baseProps, onExecuteCommand: (cmd: string) => emit('sendCommand', cmd) };
|
||||||
// case 'quickCommands': return { ...baseProps, onExecuteCommand: (cmd: string) => emit('sendCommand', cmd) };
|
// case 'quickCommands': return { ...baseProps, onExecuteCommand: (cmd: string) => emit('sendCommand', cmd) };
|
||||||
default:
|
default:
|
||||||
@@ -517,22 +534,38 @@ const getIconClasses = (paneName: PaneName): string[] => {
|
|||||||
<div :class="['sidebar-panel', 'left-sidebar-panel', { active: !!activeLeftSidebarPane }]">
|
<div :class="['sidebar-panel', 'left-sidebar-panel', { active: !!activeLeftSidebarPane }]">
|
||||||
<button class="close-sidebar-btn" @click="closeSidebars" title="Close Sidebar">×</button>
|
<button class="close-sidebar-btn" @click="closeSidebars" title="Close Sidebar">×</button>
|
||||||
<component
|
<component
|
||||||
v-if="currentLeftSidebarComponent"
|
v-if="currentLeftSidebarComponent && (activeLeftSidebarPane !== 'fileManager' || activeSession)"
|
||||||
:is="currentLeftSidebarComponent"
|
:is="currentLeftSidebarComponent"
|
||||||
:key="`left-panel-${activeLeftSidebarPane}`"
|
:key="`left-panel-${activeLeftSidebarPane}`"
|
||||||
v-bind="sidebarProps(activeLeftSidebarPane)"
|
v-bind="sidebarProps(activeLeftSidebarPane)"
|
||||||
/>
|
/>
|
||||||
|
<!-- Placeholder if FileManager is selected but no active session -->
|
||||||
|
<div v-else-if="activeLeftSidebarPane === 'fileManager' && !activeSession" class="sidebar-pane-content pane-placeholder empty-session">
|
||||||
|
<div class="empty-session-content">
|
||||||
|
<i class="fas fa-plug"></i>
|
||||||
|
<span>无活动会话</span>
|
||||||
|
<div class="empty-session-tip">文件管理器需要活动会话</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Right Sidebar Panel -->
|
<!-- Right Sidebar Panel -->
|
||||||
<div :class="['sidebar-panel', 'right-sidebar-panel', { active: !!activeRightSidebarPane }]">
|
<div :class="['sidebar-panel', 'right-sidebar-panel', { active: !!activeRightSidebarPane }]">
|
||||||
<button class="close-sidebar-btn" @click="closeSidebars" title="Close Sidebar">×</button>
|
<button class="close-sidebar-btn" @click="closeSidebars" title="Close Sidebar">×</button>
|
||||||
<component
|
<component
|
||||||
v-if="currentRightSidebarComponent"
|
v-if="currentRightSidebarComponent && (activeRightSidebarPane !== 'fileManager' || activeSession)"
|
||||||
:is="currentRightSidebarComponent"
|
:is="currentRightSidebarComponent"
|
||||||
:key="`right-panel-${activeRightSidebarPane}`"
|
:key="`right-panel-${activeRightSidebarPane}`"
|
||||||
v-bind="sidebarProps(activeRightSidebarPane)"
|
v-bind="sidebarProps(activeRightSidebarPane)"
|
||||||
/>
|
/>
|
||||||
|
<!-- Placeholder if FileManager is selected but no active session -->
|
||||||
|
<div v-else-if="activeRightSidebarPane === 'fileManager' && !activeSession" class="sidebar-pane-content pane-placeholder empty-session">
|
||||||
|
<div class="empty-session-content">
|
||||||
|
<i class="fas fa-plug"></i>
|
||||||
|
<span>无活动会话</span>
|
||||||
|
<div class="empty-session-tip">文件管理器需要活动会话</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Right Sidebar Buttons (Only render if root) -->
|
<!-- Right Sidebar Buttons (Only render if root) -->
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ export function createSftpActionsManager(
|
|||||||
|
|
||||||
// const fileList = ref<FileListItem[]>([]); // 不再直接使用 fileList ref
|
// const fileList = ref<FileListItem[]>([]); // 不再直接使用 fileList ref
|
||||||
const isLoading = ref<boolean>(false);
|
const isLoading = ref<boolean>(false);
|
||||||
|
const loadingRequestId = ref<string | null>(null); // 新增:跟踪当前加载请求 ID
|
||||||
// const error = ref<string | null>(null); // 不再使用本地 error ref
|
// const error = ref<string | null>(null); // 不再使用本地 error ref
|
||||||
const instanceSessionId = sessionId; // 保存会话 ID 用于日志
|
const instanceSessionId = sessionId; // 保存会话 ID 用于日志
|
||||||
const uiNotificationsStore = useUiNotificationsStore(); // 初始化 UI 通知 store
|
const uiNotificationsStore = useUiNotificationsStore(); // 初始化 UI 通知 store
|
||||||
@@ -232,6 +233,7 @@ export function createSftpActionsManager(
|
|||||||
// error.value = null; // 不再需要
|
// error.value = null; // 不再需要
|
||||||
currentPathRef.value = path; // 更新外部 ref
|
currentPathRef.value = path; // 更新外部 ref
|
||||||
const requestId = generateRequestId();
|
const requestId = generateRequestId();
|
||||||
|
loadingRequestId.value = requestId; // 记录当前加载请求 ID
|
||||||
sendMessage({ type: 'sftp:readdir', requestId: requestId, payload: { path } });
|
sendMessage({ type: 'sftp:readdir', requestId: requestId, payload: { path } });
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -412,10 +414,20 @@ export function createSftpActionsManager(
|
|||||||
|
|
||||||
if (!path) {
|
if (!path) {
|
||||||
console.error(`[SFTP ${instanceSessionId}] Received readdir success without path!`);
|
console.error(`[SFTP ${instanceSessionId}] Received readdir success without path!`);
|
||||||
|
// 如果收到的消息没有路径,但请求 ID 匹配,仍然需要重置加载状态
|
||||||
|
if (message.requestId === loadingRequestId.value) {
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
|
loadingRequestId.value = null;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查请求 ID 是否匹配当前加载请求
|
||||||
|
if (message.requestId !== loadingRequestId.value) {
|
||||||
|
console.log(`[SFTP ${instanceSessionId}] Received stale readdir success for ${path} (ID: ${message.requestId}, expected: ${loadingRequestId.value}). Ignoring.`);
|
||||||
|
return; // 忽略过时的响应
|
||||||
|
}
|
||||||
|
|
||||||
console.log(`[SFTP ${instanceSessionId}] Received file list for directory ${path}`);
|
console.log(`[SFTP ${instanceSessionId}] Received file list for directory ${path}`);
|
||||||
|
|
||||||
// Find or create the node for the directory itself (e.g., /root)
|
// Find or create the node for the directory itself (e.g., /root)
|
||||||
@@ -482,21 +494,31 @@ export function createSftpActionsManager(
|
|||||||
targetNode.childrenLoaded = true;
|
targetNode.childrenLoaded = true;
|
||||||
console.log(`[SFTP ${instanceSessionId}] File tree node ${path}'s children updated after merge.`);
|
console.log(`[SFTP ${instanceSessionId}] File tree node ${path}'s children updated after merge.`);
|
||||||
|
|
||||||
// If the updated path is the currently viewed path, stop loading
|
// 重置加载状态,因为这是匹配的响应
|
||||||
if (path === currentPathRef.value) {
|
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
}
|
loadingRequestId.value = null;
|
||||||
|
console.log(`[SFTP ${instanceSessionId}] isLoading reset after successful readdir for ${path}.`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSftpReaddirError = (payload: MessagePayload, message: WebSocketMessage) => {
|
const onSftpReaddirError = (payload: MessagePayload, message: WebSocketMessage) => {
|
||||||
// 类型断言,因为我们知道 readdir:error 的 payload 是 string
|
// 类型断言,因为我们知道 readdir:error 的 payload 是 string
|
||||||
const errorPayload = payload as string;
|
const errorPayload = payload as string;
|
||||||
if (message.path === currentPathRef.value) {
|
const errorPath = message.path;
|
||||||
console.error(`[SFTP ${instanceSessionId}] 加载目录 ${message.path} 出错:`, errorPayload); // 日志改为中文
|
|
||||||
|
// 检查请求 ID 是否匹配当前加载请求
|
||||||
|
if (message.requestId !== loadingRequestId.value) {
|
||||||
|
console.log(`[SFTP ${instanceSessionId}] Received stale readdir error for ${errorPath} (ID: ${message.requestId}, expected: ${loadingRequestId.value}). Ignoring.`);
|
||||||
|
return; // 忽略过时的错误响应
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error(`[SFTP ${instanceSessionId}] 加载目录 ${errorPath} 出错:`, errorPayload); // 日志改为中文
|
||||||
// error.value = errorPayload; // 使用通知
|
// error.value = errorPayload; // 使用通知
|
||||||
uiNotificationsStore.showError(`${t('fileManager.errors.loadDirectoryFailed')}: ${errorPayload}`, { timeout: 5000 }); // 使用 uiNotificationsStore, 添加 i18n key
|
uiNotificationsStore.showError(`${t('fileManager.errors.loadDirectoryFailed')}: ${errorPayload}`, { timeout: 5000 }); // 使用 uiNotificationsStore, 添加 i18n key
|
||||||
|
|
||||||
|
// 重置加载状态,因为这是匹配的响应
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
}
|
loadingRequestId.value = null;
|
||||||
|
console.log(`[SFTP ${instanceSessionId}] isLoading reset after failed readdir for ${errorPath}.`);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 移除通用的 onActionSuccessRefresh
|
// 移除通用的 onActionSuccessRefresh
|
||||||
|
|||||||
Reference in New Issue
Block a user