feat: add folder tree and unified folder tree endpoints, enhance download modal with folder path input and tree navigation

This commit is contained in:
Will Miao
2025-08-12 22:34:53 +08:00
parent 71ddfafa98
commit 286f4ff384
8 changed files with 944 additions and 37 deletions

View File

@@ -57,6 +57,8 @@ class BaseModelRoutes(ABC):
app.router.add_get(f'/api/{prefix}/scan', self.scan_models)
app.router.add_get(f'/api/{prefix}/roots', self.get_model_roots)
app.router.add_get(f'/api/{prefix}/folders', self.get_folders)
app.router.add_get(f'/api/{prefix}/folder-tree', self.get_folder_tree)
app.router.add_get(f'/api/{prefix}/unified-folder-tree', self.get_unified_folder_tree)
app.router.add_get(f'/api/{prefix}/find-duplicates', self.find_duplicate_models)
app.router.add_get(f'/api/{prefix}/find-filename-conflicts', self.find_filename_conflicts)
@@ -346,6 +348,43 @@ class BaseModelRoutes(ABC):
'error': str(e)
}, status=500)
async def get_folder_tree(self, request: web.Request) -> web.Response:
"""Get hierarchical folder tree structure for download modal"""
try:
model_root = request.query.get('model_root')
if not model_root:
return web.json_response({
'success': False,
'error': 'model_root parameter is required'
}, status=400)
folder_tree = await self.service.get_folder_tree(model_root)
return web.json_response({
'success': True,
'tree': folder_tree
})
except Exception as e:
logger.error(f"Error getting folder tree: {e}")
return web.json_response({
'success': False,
'error': str(e)
}, status=500)
async def get_unified_folder_tree(self, request: web.Request) -> web.Response:
"""Get unified folder tree across all model roots"""
try:
unified_tree = await self.service.get_unified_folder_tree()
return web.json_response({
'success': True,
'tree': unified_tree
})
except Exception as e:
logger.error(f"Error getting unified folder tree: {e}")
return web.json_response({
'success': False,
'error': str(e)
}, status=500)
async def find_duplicate_models(self, request: web.Request) -> web.Response:
"""Find models with duplicate SHA256 hashes"""
try:

View File

@@ -272,4 +272,62 @@ class BaseModelService(ABC):
def get_model_roots(self) -> List[str]:
"""Get model root directories"""
return self.scanner.get_model_roots()
return self.scanner.get_model_roots()
async def get_folder_tree(self, model_root: str) -> Dict:
"""Get hierarchical folder tree for a specific model root"""
cache = await self.scanner.get_cached_data()
# Build tree structure from folders
tree = {}
for folder in cache.folders:
# Check if this folder belongs to the specified model root
folder_belongs_to_root = False
for root in self.scanner.get_model_roots():
if root == model_root:
folder_belongs_to_root = True
break
if not folder_belongs_to_root:
continue
# Split folder path into components
parts = folder.split('/') if folder else []
current_level = tree
for part in parts:
if part not in current_level:
current_level[part] = {}
current_level = current_level[part]
return tree
async def get_unified_folder_tree(self) -> Dict:
"""Get unified folder tree across all model roots"""
cache = await self.scanner.get_cached_data()
# Build unified tree structure by analyzing all relative paths
unified_tree = {}
# Get all model roots for path normalization
model_roots = self.scanner.get_model_roots()
for folder in cache.folders:
if not folder: # Skip empty folders
continue
# Find which root this folder belongs to by checking the actual file paths
# This is a simplified approach - we'll use the folder as-is since it should already be relative
relative_path = folder
# Split folder path into components
parts = relative_path.split('/')
current_level = unified_tree
for part in parts:
if part not in current_level:
current_level[part] = {}
current_level = current_level[part]
return unified_tree