修改远程文件无法显示的问题
This commit is contained in:
		
							parent
							
								
									80d0ad288c
								
							
						
					
					
						commit
						06a2ab71e6
					
				
							
								
								
									
										6
									
								
								.idea/vcs.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.idea/vcs.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="VcsDirectoryMappings">
 | 
				
			||||||
 | 
					    <mapping directory="$PROJECT_DIR$" vcs="Git" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										199
									
								
								CloudSync/FOLDER_MANAGEMENT.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								CloudSync/FOLDER_MANAGEMENT.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,199 @@
 | 
				
			|||||||
 | 
					# 📁 本地文件夹管理功能
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CloudSync 现在支持管理多个本地文件夹,并自动保存使用历史记录!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## ✨ 主要功能
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 1. 多文件夹管理
 | 
				
			||||||
 | 
					- ✅ 同时管理多个本地同步文件夹
 | 
				
			||||||
 | 
					- ✅ 每个文件夹独立配置远程路径
 | 
				
			||||||
 | 
					- ✅ 可以启用/禁用特定文件夹的同步
 | 
				
			||||||
 | 
					- ✅ 批量同步所有启用的文件夹
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 2. 历史记录
 | 
				
			||||||
 | 
					- 📊 自动记录文件夹访问时间
 | 
				
			||||||
 | 
					- 📈 统计文件夹使用次数
 | 
				
			||||||
 | 
					- 🕐 按最近使用时间排序
 | 
				
			||||||
 | 
					- 🔥 按使用频率排序
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 3. 配置持久化
 | 
				
			||||||
 | 
					- 💾 自动保存文件夹列表到 `~/.cloudsync/folders.json`
 | 
				
			||||||
 | 
					- 🔄 下次启动自动加载历史文件夹
 | 
				
			||||||
 | 
					- 📤 支持导出配置到文件
 | 
				
			||||||
 | 
					- 📥 支持从文件导入配置(合并或替换)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 4. 智能管理
 | 
				
			||||||
 | 
					- 🧹 一键清理无效文件夹(路径不存在的)
 | 
				
			||||||
 | 
					- 🔍 文件夹状态显示(启用/禁用/最后访问时间)
 | 
				
			||||||
 | 
					- ✏️ 可以编辑文件夹的远程路径
 | 
				
			||||||
 | 
					- ❌ 移除文件夹不会删除本地文件
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 🎮 使用方法
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 添加文件夹
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. **方法一:点击"浏览"按钮**
 | 
				
			||||||
 | 
					   - 在"当前文件夹"旁边点击"浏览"
 | 
				
			||||||
 | 
					   - 选择要同步的本地文件夹
 | 
				
			||||||
 | 
					   - 文件夹会自动添加到列表
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2. **方法二:点击"➕ 添加文件夹"按钮**
 | 
				
			||||||
 | 
					   - 在文件夹列表下方点击"➕ 添加文件夹"
 | 
				
			||||||
 | 
					   - 选择要同步的本地文件夹
 | 
				
			||||||
 | 
					   - 文件夹会添加到列表并自动选中
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 管理文件夹
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					在文件夹列表中显示的信息:
 | 
				
			||||||
 | 
					- **本地路径**:文件夹在本地的完整路径
 | 
				
			||||||
 | 
					- **远程路径**:同步到云盘的目标路径
 | 
				
			||||||
 | 
					- **状态**:✅ 启用 或 ❌ 禁用
 | 
				
			||||||
 | 
					- **最后访问**:最后一次访问该文件夹的时间
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 文件夹操作
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- **➖ 移除选中**:从列表中移除选中的文件夹(不删除本地文件)
 | 
				
			||||||
 | 
					- **🔄 刷新列表**:重新加载文件夹列表
 | 
				
			||||||
 | 
					- **🧹 清理无效**:自动移除路径不存在的文件夹
 | 
				
			||||||
 | 
					- **📤 导出配置**:将文件夹列表导出为JSON文件
 | 
				
			||||||
 | 
					- **📥 导入配置**:从JSON文件导入文件夹列表
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 开始同步
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. 添加一个或多个文件夹
 | 
				
			||||||
 | 
					2. 确保要同步的文件夹状态为"✅ 启用"
 | 
				
			||||||
 | 
					3. 点击"开始同步"按钮
 | 
				
			||||||
 | 
					4. 系统会依次同步所有启用的文件夹
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 📊 配置文件格式
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					配置文件保存在:`~/.cloudsync/folders.json`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```json
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "folders": [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "path": "/home/user/Documents",
 | 
				
			||||||
 | 
					      "remote_path": "/CloudSync/Documents",
 | 
				
			||||||
 | 
					      "enabled": true,
 | 
				
			||||||
 | 
					      "added_at": "2025-10-11T12:00:00",
 | 
				
			||||||
 | 
					      "last_accessed": "2025-10-11T15:30:00",
 | 
				
			||||||
 | 
					      "access_count": 5
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "path": "/home/user/Pictures",
 | 
				
			||||||
 | 
					      "remote_path": "/CloudSync/Pictures",
 | 
				
			||||||
 | 
					      "enabled": true,
 | 
				
			||||||
 | 
					      "added_at": "2025-10-11T12:05:00",
 | 
				
			||||||
 | 
					      "last_accessed": "2025-10-11T14:20:00",
 | 
				
			||||||
 | 
					      "access_count": 3
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "last_updated": "2025-10-11T15:30:00"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 🔧 高级功能
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 编程式使用
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```python
 | 
				
			||||||
 | 
					from cloudsync.utils.folder_manager import get_folder_manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 获取文件夹管理器实例
 | 
				
			||||||
 | 
					fm = get_folder_manager()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 添加文件夹
 | 
				
			||||||
 | 
					fm.add_folder(
 | 
				
			||||||
 | 
					    path="/path/to/folder",
 | 
				
			||||||
 | 
					    remote_path="/CloudSync/MyFolder",
 | 
				
			||||||
 | 
					    enabled=True
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 获取所有文件夹
 | 
				
			||||||
 | 
					all_folders = fm.get_all_folders()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 获取启用的文件夹
 | 
				
			||||||
 | 
					enabled_folders = fm.get_all_folders(enabled_only=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 获取最近使用的5个文件夹
 | 
				
			||||||
 | 
					recent_folders = fm.get_recent_folders(limit=5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 获取最常用的10个文件夹
 | 
				
			||||||
 | 
					popular_folders = fm.get_most_used_folders(limit=10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 更新文件夹状态
 | 
				
			||||||
 | 
					fm.update_folder_enabled("/path/to/folder", enabled=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 更新远程路径
 | 
				
			||||||
 | 
					fm.update_folder_remote_path("/path/to/folder", "/NewPath")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 清理无效文件夹
 | 
				
			||||||
 | 
					removed_count = fm.clean_invalid_folders()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 导出配置
 | 
				
			||||||
 | 
					fm.export_config("/path/to/backup.json")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 导入配置(合并)
 | 
				
			||||||
 | 
					fm.import_config("/path/to/backup.json", merge=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 导入配置(替换)
 | 
				
			||||||
 | 
					fm.import_config("/path/to/backup.json", merge=False)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 💡 使用技巧
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. **首次使用**
 | 
				
			||||||
 | 
					   - 添加常用的同步文件夹
 | 
				
			||||||
 | 
					   - 系统会记住这些文件夹,下次打开自动加载
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2. **批量管理**
 | 
				
			||||||
 | 
					   - 导出配置文件保存到云盘或U盘
 | 
				
			||||||
 | 
					   - 在另一台电脑上导入配置,快速恢复同步设置
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					3. **性能优化**
 | 
				
			||||||
 | 
					   - 禁用暂时不需要同步的文件夹
 | 
				
			||||||
 | 
					   - 定期清理无效文件夹
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					4. **备份建议**
 | 
				
			||||||
 | 
					   - 定期导出文件夹配置
 | 
				
			||||||
 | 
					   - 配置文件很小,可以包含在系统备份中
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 🚀 升级说明
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					从旧版本升级:
 | 
				
			||||||
 | 
					- 旧版本的单文件夹配置会自动迁移
 | 
				
			||||||
 | 
					- 不需要重新配置,所有设置都会保留
 | 
				
			||||||
 | 
					- 配置文件兼容性:向后兼容
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## ❓ 常见问题
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Q: 移除文件夹会删除本地文件吗?**
 | 
				
			||||||
 | 
					A: 不会!移除只是从同步列表中删除,不会删除任何本地文件。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Q: 文件夹的访问记录有什么用?**
 | 
				
			||||||
 | 
					A: 帮助你了解文件夹使用频率,下次打开时自动选中最近使用的文件夹。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Q: 如何临时禁用某个文件夹的同步?**
 | 
				
			||||||
 | 
					A: 在文件夹列表中右键(或双击)可以切换启用状态(功能开发中)。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Q: 配置文件丢失了怎么办?**
 | 
				
			||||||
 | 
					A: 如果有导出的备份文件,可以导入恢复。否则需要重新添加文件夹。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Q: 可以同步网络驱动器吗?**
 | 
				
			||||||
 | 
					A: 可以!只要路径有效,支持任何可访问的目录。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 📝 开发计划
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [ ] 文件夹分组功能
 | 
				
			||||||
 | 
					- [ ] 文件夹标签和颜色标记
 | 
				
			||||||
 | 
					- [ ] 同步策略自定义(文件过滤、排除规则)
 | 
				
			||||||
 | 
					- [ ] 文件夹右键菜单
 | 
				
			||||||
 | 
					- [ ] 文件夹拖拽排序
 | 
				
			||||||
 | 
					- [ ] 批量操作(批量启用/禁用/移除)
 | 
				
			||||||
 | 
					- [ ] 文件夹搜索和过滤
 | 
				
			||||||
 | 
					- [ ] 同步历史记录查看
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 🤝 反馈建议
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					如果您有任何建议或发现问题,欢迎反馈!
 | 
				
			||||||
							
								
								
									
										278
									
								
								CloudSync/REMOTE_FILES_FIX.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										278
									
								
								CloudSync/REMOTE_FILES_FIX.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,278 @@
 | 
				
			|||||||
 | 
					# 远程文件显示功能修复说明
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 问题描述
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					用户报告:主页面中远程同步文件夹无法显示
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 根本原因
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`SyncTab` 类中缺少 `_refresh_remote_tree()` 方法的实现。虽然在文件夹选择事件中调用了该方法,但实际方法并不存在,导致远程文件无法加载和显示。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 解决方案
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 1. 实现 `_refresh_remote_tree()` 方法
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**位置**: `cloudsync/ui/sync_tab.py:391-474`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**功能特性**:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- ✅ 异步加载远程文件,避免UI阻塞
 | 
				
			||||||
 | 
					- ✅ 支持多云盘服务并行查询
 | 
				
			||||||
 | 
					- ✅ 智能解析不同云盘的文件列表格式
 | 
				
			||||||
 | 
					- ✅ 按云盘分类显示文件结构
 | 
				
			||||||
 | 
					- ✅ 显示加载进度和错误信息
 | 
				
			||||||
 | 
					- ✅ 自动区分文件和文件夹
 | 
				
			||||||
 | 
					- ✅ 显示文件大小信息
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 2. 方法实现详解
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```python
 | 
				
			||||||
 | 
					def _refresh_remote_tree(self, remote_path=None):
 | 
				
			||||||
 | 
					    """刷新远程文件树"""
 | 
				
			||||||
 | 
					    # 1. 获取远程路径
 | 
				
			||||||
 | 
					    if remote_path is None:
 | 
				
			||||||
 | 
					        remote_path = self.remote_dir_var.get()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if not remote_path:
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # 2. 清空现有显示
 | 
				
			||||||
 | 
					    self.remote_tree.delete(*self.remote_tree.get_children())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # 3. 显示加载提示
 | 
				
			||||||
 | 
					    self.log_queue.put(f"🔄 正在加载远程文件: {remote_path}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # 4. 在后台线程中加载文件列表
 | 
				
			||||||
 | 
					    def load_worker():
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            all_files = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # 从所有云盘服务获取文件列表
 | 
				
			||||||
 | 
					            for cloud in self.clouds:
 | 
				
			||||||
 | 
					                try:
 | 
				
			||||||
 | 
					                    self.log_queue.put(f"  正在从 {cloud.name} 获取文件列表...")
 | 
				
			||||||
 | 
					                    files = cloud.list_files(remote_path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if files:
 | 
				
			||||||
 | 
					                        all_files[cloud.name] = files
 | 
				
			||||||
 | 
					                        self.log_queue.put(f"  ✅ {cloud.name}: 找到 {len(files)} 个文件")
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        self.log_queue.put(f"  ℹ️ {cloud.name}: 目录为空或不存在")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                except Exception as e:
 | 
				
			||||||
 | 
					                    self.logger.error(f"Failed to list files from {cloud.name}: {e}")
 | 
				
			||||||
 | 
					                    self.log_queue.put(f"  ❌ {cloud.name}: 获取失败 - {str(e)[:50]}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # 5. 在UI线程中更新树形视图
 | 
				
			||||||
 | 
					            def update_tree():
 | 
				
			||||||
 | 
					                if not all_files:
 | 
				
			||||||
 | 
					                    self.remote_tree.insert("", "end", text="📭 远程目录为空或不存在")
 | 
				
			||||||
 | 
					                    return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # 为每个云盘创建分类节点
 | 
				
			||||||
 | 
					                for cloud_name, files in all_files.items():
 | 
				
			||||||
 | 
					                    cloud_node = self.remote_tree.insert("", "end",
 | 
				
			||||||
 | 
					                                                         text=f"☁️ {cloud_name}",
 | 
				
			||||||
 | 
					                                                         open=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # 解析并添加文件
 | 
				
			||||||
 | 
					                    for file_info in files:
 | 
				
			||||||
 | 
					                        file_info = file_info.strip()
 | 
				
			||||||
 | 
					                        if not file_info:
 | 
				
			||||||
 | 
					                            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        # 解析百度网盘格式:
 | 
				
			||||||
 | 
					                        # "D 文件夹名" - 目录
 | 
				
			||||||
 | 
					                        # "F 文件名 (大小)" - 文件
 | 
				
			||||||
 | 
					                        if file_info.startswith('D '):
 | 
				
			||||||
 | 
					                            name = file_info[2:].strip()
 | 
				
			||||||
 | 
					                            self.remote_tree.insert(cloud_node, "end",
 | 
				
			||||||
 | 
					                                                   text=f"📁 {name}")
 | 
				
			||||||
 | 
					                        elif file_info.startswith('F '):
 | 
				
			||||||
 | 
					                            parts = file_info[2:].split('(')
 | 
				
			||||||
 | 
					                            name = parts[0].strip()
 | 
				
			||||||
 | 
					                            size = parts[1].rstrip(')').strip() if len(parts) > 1 else ""
 | 
				
			||||||
 | 
					                            display_text = f"📄 {name}" + (f" ({size})" if size else "")
 | 
				
			||||||
 | 
					                            self.remote_tree.insert(cloud_node, "end",
 | 
				
			||||||
 | 
					                                                   text=display_text)
 | 
				
			||||||
 | 
					                        else:
 | 
				
			||||||
 | 
					                            # 未知格式,直接显示
 | 
				
			||||||
 | 
					                            self.remote_tree.insert(cloud_node, "end",
 | 
				
			||||||
 | 
					                                                   text=f"📄 {file_info}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                self.log_queue.put("✅ 远程文件列表加载完成")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.frame.after(0, update_tree)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            self.logger.error(f"Error loading remote files: {e}")
 | 
				
			||||||
 | 
					            self.log_queue.put(f"❌ 加载远程文件失败: {e}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            def show_error():
 | 
				
			||||||
 | 
					                self.remote_tree.insert("", "end",
 | 
				
			||||||
 | 
					                                       text=f"❌ 加载失败: {str(e)[:50]}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.frame.after(0, show_error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # 启动后台线程
 | 
				
			||||||
 | 
					    threading.Thread(target=load_worker, daemon=True).start()
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 3. 触发机制
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					方法在以下情况下自动触发:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. **文件夹选择事件** (`_on_folder_select()`)
 | 
				
			||||||
 | 
					   - 用户在文件夹列表中选择某个文件夹时
 | 
				
			||||||
 | 
					   - 自动刷新该文件夹对应的远程路径
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```python
 | 
				
			||||||
 | 
					def _on_folder_select(self, event):
 | 
				
			||||||
 | 
					    """文件夹选择事件"""
 | 
				
			||||||
 | 
					    selection = self.folder_tree.selection()
 | 
				
			||||||
 | 
					    if selection:
 | 
				
			||||||
 | 
					        item = self.folder_tree.item(selection[0])
 | 
				
			||||||
 | 
					        values = item['values']
 | 
				
			||||||
 | 
					        if values:
 | 
				
			||||||
 | 
					            folder_path = values[0]
 | 
				
			||||||
 | 
					            remote_path = values[1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # 更新当前选中的文件夹
 | 
				
			||||||
 | 
					            self.current_folder_var.set(folder_path)
 | 
				
			||||||
 | 
					            self.remote_dir_var.set(remote_path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # 刷新本地文件预览
 | 
				
			||||||
 | 
					            self._refresh_local_tree(folder_path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # 刷新远程文件预览
 | 
				
			||||||
 | 
					            self._refresh_remote_tree(remote_path)  # ← 自动触发
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # 更新访问记录
 | 
				
			||||||
 | 
					            self.folder_manager.update_folder_access(folder_path)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 用户体验改进
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 🎯 加载过程可视化
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- 实时显示加载状态:"🔄 正在加载远程文件"
 | 
				
			||||||
 | 
					- 显示每个云盘的查询进度
 | 
				
			||||||
 | 
					- 成功/失败/空目录都有清晰的提示
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 📁 文件分类显示
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					☁️ baidu
 | 
				
			||||||
 | 
					  📁 Documents
 | 
				
			||||||
 | 
					  📁 Pictures
 | 
				
			||||||
 | 
					  📄 readme.txt (1.2KB)
 | 
				
			||||||
 | 
					  📄 photo.jpg (3.5MB)
 | 
				
			||||||
 | 
					☁️ quark
 | 
				
			||||||
 | 
					  📁 Backup
 | 
				
			||||||
 | 
					  📄 data.zip (50MB)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### ⚡ 性能优化
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- 使用后台线程加载,不阻塞UI
 | 
				
			||||||
 | 
					- 并行查询多个云盘服务
 | 
				
			||||||
 | 
					- 异步更新UI,保持界面响应
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 🛡️ 错误处理
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- 单个云盘失败不影响其他云盘
 | 
				
			||||||
 | 
					- 详细的错误日志记录
 | 
				
			||||||
 | 
					- 友好的错误提示信息
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 支持的云盘格式
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 百度网盘 (bypy)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bypy的list命令输出格式:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					D folder_name
 | 
				
			||||||
 | 
					F file_name.txt (1024)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					解析规则:
 | 
				
			||||||
 | 
					- `D` 开头:目录,显示为 📁
 | 
				
			||||||
 | 
					- `F` 开头:文件,显示为 📄,括号中为大小
 | 
				
			||||||
 | 
					- 其他格式:作为文件显示
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 夸克网盘
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					将根据实际API返回格式进行解析
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 测试建议
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 1. 基本功能测试
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```python
 | 
				
			||||||
 | 
					# 测试场景1:选择文件夹后自动加载远程文件
 | 
				
			||||||
 | 
					1. 启动应用
 | 
				
			||||||
 | 
					2. 在文件夹列表中选择一个文件夹
 | 
				
			||||||
 | 
					3. 观察右侧"远程文件"面板是否显示文件
 | 
				
			||||||
 | 
					4. 检查日志中是否有加载进度信息
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 测试场景2:空目录显示
 | 
				
			||||||
 | 
					1. 选择一个远程不存在的文件夹
 | 
				
			||||||
 | 
					2. 应显示 "📭 远程目录为空或不存在"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 测试场景3:错误处理
 | 
				
			||||||
 | 
					1. 断开网络连接
 | 
				
			||||||
 | 
					2. 选择文件夹触发加载
 | 
				
			||||||
 | 
					3. 应显示错误信息并记录到日志
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 2. 性能测试
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```python
 | 
				
			||||||
 | 
					# 大文件列表测试
 | 
				
			||||||
 | 
					1. 创建包含大量文件的远程目录(100+文件)
 | 
				
			||||||
 | 
					2. 选择该文件夹
 | 
				
			||||||
 | 
					3. 观察加载时间和UI响应性
 | 
				
			||||||
 | 
					4. 验证所有文件都正确显示
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 3. 多云盘测试
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```python
 | 
				
			||||||
 | 
					# 多云盘并行查询
 | 
				
			||||||
 | 
					1. 配置多个云盘服务(百度+夸克)
 | 
				
			||||||
 | 
					2. 在不同云盘创建相同路径的文件夹
 | 
				
			||||||
 | 
					3. 选择文件夹观察是否正确显示两个云盘的内容
 | 
				
			||||||
 | 
					4. 验证分类节点是否按云盘名称区分
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 已知限制
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. **文件格式解析**:目前主要支持百度网盘(bypy)的输出格式,其他云盘可能需要调整解析逻辑
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2. **深度遍历**:当前只显示一级文件列表,不支持展开子目录(可作为未来改进)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					3. **大文件列表**:如果远程目录包含数千个文件,TreeView可能会有性能问题(建议添加分页或虚拟滚动)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 未来改进方向
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [ ] 支持递归加载子目录
 | 
				
			||||||
 | 
					- [ ] 添加文件图标根据扩展名区分
 | 
				
			||||||
 | 
					- [ ] 支持文件右键菜单(下载、删除、分享等)
 | 
				
			||||||
 | 
					- [ ] 添加搜索和过滤功能
 | 
				
			||||||
 | 
					- [ ] 实现虚拟滚动优化大列表性能
 | 
				
			||||||
 | 
					- [ ] 缓存远程文件列表减少API调用
 | 
				
			||||||
 | 
					- [ ] 支持拖拽上传文件到远程目录
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 相关文件
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `cloudsync/ui/sync_tab.py:391-474` - `_refresh_remote_tree()` 方法实现
 | 
				
			||||||
 | 
					- `cloudsync/ui/sync_tab.py:265-286` - `_on_folder_select()` 触发机制
 | 
				
			||||||
 | 
					- `cloudsync/core/baidu_cloud.py:85-117` - 百度云list_files实现
 | 
				
			||||||
 | 
					- `cloudsync/core/base_cloud.py` - 云盘服务基类
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 版本历史
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- **2025-10-11**: 初始实现
 | 
				
			||||||
 | 
					  - 添加 `_refresh_remote_tree()` 方法
 | 
				
			||||||
 | 
					  - 支持多云盘并行查询
 | 
				
			||||||
 | 
					  - 实现文件格式解析和分类显示
 | 
				
			||||||
 | 
					  - 添加完整的错误处理和日志记录
 | 
				
			||||||
							
								
								
									
										362
									
								
								CloudSync/cloudsync/utils/folder_manager.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										362
									
								
								CloudSync/cloudsync/utils/folder_manager.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,362 @@
 | 
				
			|||||||
 | 
					"""
 | 
				
			||||||
 | 
					本地文件夹管理器 - 管理多个同步文件夹和历史记录
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					from typing import List, Dict, Optional
 | 
				
			||||||
 | 
					from datetime import datetime
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from .logger import get_logger
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FolderManager:
 | 
				
			||||||
 | 
					    """本地文件夹管理器"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, config_file: Optional[str] = None):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        初始化文件夹管理器
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            config_file: 配置文件路径,如果为None则使用默认路径
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.logger = get_logger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # 配置文件路径
 | 
				
			||||||
 | 
					        if config_file is None:
 | 
				
			||||||
 | 
					            config_dir = os.path.expanduser("~/.cloudsync")
 | 
				
			||||||
 | 
					            os.makedirs(config_dir, exist_ok=True)
 | 
				
			||||||
 | 
					            self.config_file = os.path.join(config_dir, "folders.json")
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.config_file = config_file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # 文件夹列表
 | 
				
			||||||
 | 
					        self.folders: List[Dict[str, str]] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # 加载配置
 | 
				
			||||||
 | 
					        self._load_config()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _load_config(self):
 | 
				
			||||||
 | 
					        """从配置文件加载文件夹列表"""
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            if os.path.exists(self.config_file):
 | 
				
			||||||
 | 
					                with open(self.config_file, 'r', encoding='utf-8') as f:
 | 
				
			||||||
 | 
					                    data = json.load(f)
 | 
				
			||||||
 | 
					                    self.folders = data.get('folders', [])
 | 
				
			||||||
 | 
					                    self.logger.info(f"Loaded {len(self.folders)} folders from config")
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                self.logger.info("No config file found, starting with empty folder list")
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            self.logger.error(f"Failed to load folder config: {e}")
 | 
				
			||||||
 | 
					            self.folders = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _save_config(self):
 | 
				
			||||||
 | 
					        """保存文件夹列表到配置文件"""
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            data = {
 | 
				
			||||||
 | 
					                'folders': self.folders,
 | 
				
			||||||
 | 
					                'last_updated': datetime.now().isoformat()
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            with open(self.config_file, 'w', encoding='utf-8') as f:
 | 
				
			||||||
 | 
					                json.dump(data, f, indent=2, ensure_ascii=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.logger.info(f"Saved {len(self.folders)} folders to config")
 | 
				
			||||||
 | 
					            return True
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            self.logger.error(f"Failed to save folder config: {e}")
 | 
				
			||||||
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def add_folder(self, path: str, remote_path: str = "/CloudSync", enabled: bool = True) -> bool:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        添加文件夹
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            path: 本地文件夹路径
 | 
				
			||||||
 | 
					            remote_path: 对应的远程路径
 | 
				
			||||||
 | 
					            enabled: 是否启用同步
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            是否添加成功
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        # 标准化路径
 | 
				
			||||||
 | 
					        path = os.path.abspath(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # 检查路径是否存在
 | 
				
			||||||
 | 
					        if not os.path.exists(path):
 | 
				
			||||||
 | 
					            self.logger.warning(f"Path does not exist: {path}")
 | 
				
			||||||
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # 检查是否已存在
 | 
				
			||||||
 | 
					        if self.get_folder(path) is not None:
 | 
				
			||||||
 | 
					            self.logger.info(f"Folder already exists: {path}")
 | 
				
			||||||
 | 
					            # 更新最后访问时间
 | 
				
			||||||
 | 
					            self.update_folder_access(path)
 | 
				
			||||||
 | 
					            return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # 添加新文件夹
 | 
				
			||||||
 | 
					        folder_info = {
 | 
				
			||||||
 | 
					            'path': path,
 | 
				
			||||||
 | 
					            'remote_path': remote_path,
 | 
				
			||||||
 | 
					            'enabled': enabled,
 | 
				
			||||||
 | 
					            'added_at': datetime.now().isoformat(),
 | 
				
			||||||
 | 
					            'last_accessed': datetime.now().isoformat(),
 | 
				
			||||||
 | 
					            'access_count': 1
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.folders.append(folder_info)
 | 
				
			||||||
 | 
					        self._save_config()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.logger.info(f"Added folder: {path} -> {remote_path}")
 | 
				
			||||||
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def remove_folder(self, path: str) -> bool:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        移除文件夹
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            path: 本地文件夹路径
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            是否移除成功
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        path = os.path.abspath(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # 查找并移除
 | 
				
			||||||
 | 
					        for i, folder in enumerate(self.folders):
 | 
				
			||||||
 | 
					            if folder['path'] == path:
 | 
				
			||||||
 | 
					                self.folders.pop(i)
 | 
				
			||||||
 | 
					                self._save_config()
 | 
				
			||||||
 | 
					                self.logger.info(f"Removed folder: {path}")
 | 
				
			||||||
 | 
					                return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.logger.warning(f"Folder not found: {path}")
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_folder(self, path: str) -> Optional[Dict[str, str]]:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        获取文件夹信息
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            path: 本地文件夹路径
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            文件夹信息字典,如果不存在则返回None
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        path = os.path.abspath(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for folder in self.folders:
 | 
				
			||||||
 | 
					            if folder['path'] == path:
 | 
				
			||||||
 | 
					                return folder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_folder_access(self, path: str) -> bool:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        更新文件夹访问时间和次数
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            path: 本地文件夹路径
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            是否更新成功
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        path = os.path.abspath(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for folder in self.folders:
 | 
				
			||||||
 | 
					            if folder['path'] == path:
 | 
				
			||||||
 | 
					                folder['last_accessed'] = datetime.now().isoformat()
 | 
				
			||||||
 | 
					                folder['access_count'] = folder.get('access_count', 0) + 1
 | 
				
			||||||
 | 
					                self._save_config()
 | 
				
			||||||
 | 
					                return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_folder_enabled(self, path: str, enabled: bool) -> bool:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        更新文件夹启用状态
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            path: 本地文件夹路径
 | 
				
			||||||
 | 
					            enabled: 是否启用
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            是否更新成功
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        path = os.path.abspath(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for folder in self.folders:
 | 
				
			||||||
 | 
					            if folder['path'] == path:
 | 
				
			||||||
 | 
					                folder['enabled'] = enabled
 | 
				
			||||||
 | 
					                self._save_config()
 | 
				
			||||||
 | 
					                return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_folder_remote_path(self, path: str, remote_path: str) -> bool:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        更新文件夹远程路径
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            path: 本地文件夹路径
 | 
				
			||||||
 | 
					            remote_path: 新的远程路径
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            是否更新成功
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        path = os.path.abspath(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for folder in self.folders:
 | 
				
			||||||
 | 
					            if folder['path'] == path:
 | 
				
			||||||
 | 
					                folder['remote_path'] = remote_path
 | 
				
			||||||
 | 
					                self._save_config()
 | 
				
			||||||
 | 
					                return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_all_folders(self, enabled_only: bool = False) -> List[Dict[str, str]]:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        获取所有文件夹
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            enabled_only: 是否只返回启用的文件夹
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            文件夹信息列表
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if enabled_only:
 | 
				
			||||||
 | 
					            return [f for f in self.folders if f.get('enabled', True)]
 | 
				
			||||||
 | 
					        return self.folders.copy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_recent_folders(self, limit: int = 10) -> List[Dict[str, str]]:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        获取最近使用的文件夹
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            limit: 返回数量限制
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            按最近访问时间排序的文件夹列表
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        # 按最后访问时间排序
 | 
				
			||||||
 | 
					        sorted_folders = sorted(
 | 
				
			||||||
 | 
					            self.folders,
 | 
				
			||||||
 | 
					            key=lambda f: f.get('last_accessed', ''),
 | 
				
			||||||
 | 
					            reverse=True
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return sorted_folders[:limit]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_most_used_folders(self, limit: int = 10) -> List[Dict[str, str]]:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        获取最常用的文件夹
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            limit: 返回数量限制
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            按访问次数排序的文件夹列表
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        # 按访问次数排序
 | 
				
			||||||
 | 
					        sorted_folders = sorted(
 | 
				
			||||||
 | 
					            self.folders,
 | 
				
			||||||
 | 
					            key=lambda f: f.get('access_count', 0),
 | 
				
			||||||
 | 
					            reverse=True
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return sorted_folders[:limit]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def clean_invalid_folders(self) -> int:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        清理不存在的文件夹
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            清理的文件夹数量
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        initial_count = len(self.folders)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # 过滤出仍然存在的文件夹
 | 
				
			||||||
 | 
					        self.folders = [
 | 
				
			||||||
 | 
					            f for f in self.folders
 | 
				
			||||||
 | 
					            if os.path.exists(f['path'])
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        removed_count = initial_count - len(self.folders)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if removed_count > 0:
 | 
				
			||||||
 | 
					            self._save_config()
 | 
				
			||||||
 | 
					            self.logger.info(f"Cleaned {removed_count} invalid folders")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return removed_count
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def export_config(self, export_path: str) -> bool:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        导出配置到指定路径
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            export_path: 导出文件路径
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            是否导出成功
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            data = {
 | 
				
			||||||
 | 
					                'folders': self.folders,
 | 
				
			||||||
 | 
					                'exported_at': datetime.now().isoformat(),
 | 
				
			||||||
 | 
					                'version': '1.0'
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            with open(export_path, 'w', encoding='utf-8') as f:
 | 
				
			||||||
 | 
					                json.dump(data, f, indent=2, ensure_ascii=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.logger.info(f"Exported config to: {export_path}")
 | 
				
			||||||
 | 
					            return True
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            self.logger.error(f"Failed to export config: {e}")
 | 
				
			||||||
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def import_config(self, import_path: str, merge: bool = True) -> bool:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        从指定路径导入配置
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            import_path: 导入文件路径
 | 
				
			||||||
 | 
					            merge: 是否合并到现有配置(False则替换)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            是否导入成功
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            with open(import_path, 'r', encoding='utf-8') as f:
 | 
				
			||||||
 | 
					                data = json.load(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            imported_folders = data.get('folders', [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if merge:
 | 
				
			||||||
 | 
					                # 合并:添加不存在的文件夹
 | 
				
			||||||
 | 
					                existing_paths = {f['path'] for f in self.folders}
 | 
				
			||||||
 | 
					                for folder in imported_folders:
 | 
				
			||||||
 | 
					                    if folder['path'] not in existing_paths:
 | 
				
			||||||
 | 
					                        self.folders.append(folder)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                # 替换
 | 
				
			||||||
 | 
					                self.folders = imported_folders
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self._save_config()
 | 
				
			||||||
 | 
					            self.logger.info(f"Imported {len(imported_folders)} folders from: {import_path}")
 | 
				
			||||||
 | 
					            return True
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            self.logger.error(f"Failed to import config: {e}")
 | 
				
			||||||
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 全局文件夹管理器实例
 | 
				
			||||||
 | 
					_folder_manager = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_folder_manager() -> FolderManager:
 | 
				
			||||||
 | 
					    """获取全局文件夹管理器实例"""
 | 
				
			||||||
 | 
					    global _folder_manager
 | 
				
			||||||
 | 
					    if _folder_manager is None:
 | 
				
			||||||
 | 
					        _folder_manager = FolderManager()
 | 
				
			||||||
 | 
					    return _folder_manager
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user