This commit is contained in:
Baobhan Sith
2025-04-16 17:16:13 +08:00
parent 041168194b
commit 722e0dbc10
2 changed files with 32 additions and 27 deletions
@@ -49,10 +49,11 @@ const route = useRoute(); // Keep for download URL generation for now
// const currentPath = ref<string>('.'); // const currentPath = ref<string>('.');
// Access SFTP state and methods from the injected manager instance // Access SFTP state and methods from the injected manager instance
// Note: 'error' and 'clearSftpError' are handled by the UI notification store via useSftpActions
const { const {
fileList, fileList,
isLoading, isLoading,
error, // error, // Removed, handled by UI notification store
loadDirectory, loadDirectory,
createDirectory, createDirectory,
createFile, createFile,
@@ -63,7 +64,7 @@ const {
writeFile, // Provided by the manager writeFile, // Provided by the manager
joinPath, joinPath,
currentPath, // 从 sftpManager 获取 currentPath currentPath, // 从 sftpManager 获取 currentPath
clearSftpError, // clearSftpError, // Removed, handled by UI notification store
cleanup: cleanupSftpHandlers, // Get the cleanup function from the manager cleanup: cleanupSftpHandlers, // Get the cleanup function from the manager
} = props.sftpManager; // 直接从 props 获取 } = props.sftpManager; // 直接从 props 获取
@@ -77,9 +78,9 @@ const {
currentPath, // 使用从 sftpManager 获取的 currentPath currentPath, // 使用从 sftpManager 获取的 currentPath
fileList, // 传递来自 sftpManager 的 fileList ref fileList, // 传递来自 sftpManager 的 fileList ref
() => loadDirectory(currentPath.value), // Refresh function uses manager's loadDirectory () => loadDirectory(currentPath.value), // Refresh function uses manager's loadDirectory
props.sessionId, // 传递 sessionId // props.sessionId, // 不再传递 sessionId
props.dbConnectionId // 传递 dbConnectionId // props.dbConnectionId // 不再传递 dbConnectionId
// useFileUploader 内部创建自己的 ws 连接, 不需要 wsDeps props.wsDeps // 传递注入的 WebSocket 依赖项
); );
// 实例化新的文件编辑器 Store // 实例化新的文件编辑器 Store
@@ -628,6 +629,7 @@ const stopResize = () => {
// --- 路径编辑逻辑 --- // --- 路径编辑逻辑 ---
const startPathEdit = () => { const startPathEdit = () => {
// 恢复使用 props.sftpManager.isLoading 和 props.wsDeps.isConnected // 恢复使用 props.sftpManager.isLoading 和 props.wsDeps.isConnected
// 注意:这里仍然使用从 sftpManager 解构的 isLoading
if (isLoading.value || !props.wsDeps.isConnected.value) return; if (isLoading.value || !props.wsDeps.isConnected.value) return;
editablePath.value = currentPath.value; // 使用 sftpManager 的 currentPath 初始化编辑框 editablePath.value = currentPath.value; // 使用 sftpManager 的 currentPath 初始化编辑框
isEditingPath.value = true; isEditingPath.value = true;
@@ -655,10 +657,10 @@ const cancelPathEdit = () => {
isEditingPath.value = false; isEditingPath.value = false;
}; };
// 清除错误消息的函数 - 调用 props 中的 clearSftpError // 清除错误消息的函数 - 不再需要,错误由 UI 通知处理
const clearError = () => { // const clearError = () => {
clearSftpError(); // clearSftpError();
}; // };
</script> </script>
@@ -705,17 +707,17 @@ const clearError = () => {
@dragleave.prevent="handleDragLeave" @dragleave.prevent="handleDragLeave"
@drop.prevent="handleDrop" @drop.prevent="handleDrop"
> >
<!-- 移除内联错误提示框 --> <!-- Error display is handled globally by UINotificationDisplay -->
<!-- <div v-if="error" class="error-alert"> ... </div> -->
<!-- 1. Initial Loading Indicator --> <!-- 1. Loading Indicator -->
<div v-if="isLoading && !initialLoadDone" class="loading">{{ t('fileManager.loading') }}</div> <div v-if="isLoading" class="loading">{{ t('fileManager.loading') }}</div>
<!-- 2. File Table (Show if not initial loading) --> <!-- 2. Content when not loading -->
<!-- Removed the error condition here, table shows regardless of error --> <template v-else>
<table v-else-if="sortedFileList.length > 0 || currentPath !== '/'" ref="tableRef" class="resizable-table" @contextmenu.prevent> <!-- File Table (Show if list has items OR not at root to show '..') -->
<colgroup> <table v-if="sortedFileList.length > 0 || currentPath !== '/'" ref="tableRef" class="resizable-table" @contextmenu.prevent>
<col :style="{ width: `${colWidths.type}px` }"> <colgroup>
<col :style="{ width: `${colWidths.type}px` }">
<col :style="{ width: `${colWidths.name}px` }"> <col :style="{ width: `${colWidths.name}px` }">
<col :style="{ width: `${colWidths.size}px` }"> <col :style="{ width: `${colWidths.size}px` }">
<col :style="{ width: `${colWidths.permissions}px` }"> <col :style="{ width: `${colWidths.permissions}px` }">
@@ -774,11 +776,10 @@ const clearError = () => {
</table> </table>
<!-- 4. Empty Directory Message (Show if not initial loading, no error, list is empty, and at root) --> <!-- 4. Empty Directory Message (Show if not initial loading, no error, list is empty, and at root) -->
<!-- 3. Empty Directory Message (Show only if not loading AND list is empty AND not at root) --> <!-- Empty Directory Message (Show only if at root AND list is empty) -->
<div v-else-if="!isLoading && sortedFileList.length === 0 && currentPath === '/'" class="no-files">{{ t('fileManager.emptyDirectory') }}</div> <div v-else-if="currentPath === '/'" class="no-files">{{ t('fileManager.emptyDirectory') }}</div>
<!-- Note: If there's an error, the table will still render (potentially empty if initial load failed), <!-- Note: The table above handles the case where the directory is not root but empty (shows '..') -->
but the error message will be shown above. The "Empty Directory" message </template> <!-- Add missing end tag for v-else template -->
is now only shown if explicitly empty and not loading. -->
</div> </div>
<!-- 使用 FileUploadPopup 组件 --> <!-- 使用 FileUploadPopup 组件 -->
@@ -7,6 +7,8 @@ import type { WebSocketMessage, MessagePayload } from '../types/websocket.types'
// --- 接口定义 (已移至 upload.types.ts) --- // --- 接口定义 (已移至 upload.types.ts) ---
import type { WebSocketDependencies } from './useSftpActions'; // 导入 WebSocketDependencies 类型
// 辅助函数 (从 FileManager.vue 复制) // 辅助函数 (从 FileManager.vue 复制)
const generateUploadId = (): string => { const generateUploadId = (): string => {
// 如果需要,可以使用稍微不同的格式作为上传 ID // 如果需要,可以使用稍微不同的格式作为上传 ID
@@ -24,12 +26,14 @@ export function useFileUploader(
currentPathRef: Ref<string>, currentPathRef: Ref<string>,
fileListRef: Readonly<Ref<readonly FileListItem[]>>, // 使用 Readonly 类型 fileListRef: Readonly<Ref<readonly FileListItem[]>>, // 使用 Readonly 类型
refreshDirectory: () => void, // 上传成功后刷新目录的回调函数 refreshDirectory: () => void, // 上传成功后刷新目录的回调函数
sessionId: string, // sessionId: string, // 不再需要,因为 wsDeps 包含了会话上下文
dbConnectionId: string // dbConnectionId: string, // 不再需要
wsDeps: WebSocketDependencies // 注入 WebSocket 依赖项
) { ) {
const { t } = useI18n(); const { t } = useI18n();
// 使用工厂函数创建WebSocket连接管理器,并传入t函数 // 不再创建独立的连接管理器,而是使用注入的依赖项
const { sendMessage, onMessage, isConnected } = createWebSocketConnectionManager(sessionId, dbConnectionId, t); // const { sendMessage, onMessage, isConnected } = createWebSocketConnectionManager(sessionId, dbConnectionId, t);
const { sendMessage, onMessage, isConnected } = wsDeps; // 使用注入的依赖项
// 对 uploads 字典使用 reactive 以获得更好的深度响应性 // 对 uploads 字典使用 reactive 以获得更好的深度响应性
const uploads = reactive<Record<string, UploadItem>>({}); const uploads = reactive<Record<string, UploadItem>>({});