mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-25 15:15:44 -03:00
Simplify LoRA page rendering and implement singleton pattern for LoRA scanner
This commit is contained in:
@@ -48,28 +48,12 @@ class LoraRoutes:
|
|||||||
async def handle_loras_page(self, request: web.Request) -> web.Response:
|
async def handle_loras_page(self, request: web.Request) -> web.Response:
|
||||||
"""Handle GET /loras request"""
|
"""Handle GET /loras request"""
|
||||||
try:
|
try:
|
||||||
# Get cached data
|
# Get cached data for folders only
|
||||||
cache = await self.scanner.get_cached_data()
|
cache = await self.scanner.get_cached_data()
|
||||||
|
|
||||||
# Get initial data (first page only)
|
# Render template with folders only
|
||||||
initial_data = await self.scanner.get_paginated_data(
|
|
||||||
page=1,
|
|
||||||
page_size=20,
|
|
||||||
sort_by='name'
|
|
||||||
)
|
|
||||||
|
|
||||||
formatted_loras = [
|
|
||||||
self.format_lora_data(l)
|
|
||||||
for l in initial_data['items']
|
|
||||||
]
|
|
||||||
|
|
||||||
# Render template
|
|
||||||
template = self.template_env.get_template('loras.html')
|
template = self.template_env.get_template('loras.html')
|
||||||
rendered = template.render(
|
rendered = template.render(folders=cache.folders)
|
||||||
loras=formatted_loras,
|
|
||||||
folders=cache.folders,
|
|
||||||
total_items=initial_data['total']
|
|
||||||
)
|
|
||||||
|
|
||||||
return web.Response(
|
return web.Response(
|
||||||
text=rendered,
|
text=rendered,
|
||||||
|
|||||||
@@ -14,10 +14,29 @@ logger = logging.getLogger(__name__)
|
|||||||
class LoraScanner:
|
class LoraScanner:
|
||||||
"""Service for scanning and managing LoRA files"""
|
"""Service for scanning and managing LoRA files"""
|
||||||
|
|
||||||
|
_instance = None
|
||||||
|
_lock = asyncio.Lock()
|
||||||
|
|
||||||
|
def __new__(cls):
|
||||||
|
if cls._instance is None:
|
||||||
|
cls._instance = super().__new__(cls)
|
||||||
|
return cls._instance
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
# 确保初始化只执行一次
|
||||||
|
if not hasattr(self, '_initialized'):
|
||||||
self._cache: Optional[LoraCache] = None
|
self._cache: Optional[LoraCache] = None
|
||||||
self._initialization_lock = asyncio.Lock()
|
self._initialization_lock = asyncio.Lock()
|
||||||
self._initialization_task: Optional[asyncio.Task] = None
|
self._initialization_task: Optional[asyncio.Task] = None
|
||||||
|
self._initialized = True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def get_instance(cls):
|
||||||
|
"""Get singleton instance with async support"""
|
||||||
|
async with cls._lock:
|
||||||
|
if cls._instance is None:
|
||||||
|
cls._instance = cls()
|
||||||
|
return cls._instance
|
||||||
|
|
||||||
async def get_cached_data(self, force_refresh: bool = False) -> LoraCache:
|
async def get_cached_data(self, force_refresh: bool = False) -> LoraCache:
|
||||||
"""Get cached LoRA data, refresh if needed"""
|
"""Get cached LoRA data, refresh if needed"""
|
||||||
|
|||||||
@@ -8,28 +8,7 @@ function debounce(func, wait) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sorting functionality
|
// Sorting functionality
|
||||||
function sortCards(sortBy) {
|
// function sortCards(sortBy) { ... }
|
||||||
const grid = document.getElementById('loraGrid');
|
|
||||||
if (!grid) return;
|
|
||||||
|
|
||||||
const fragment = document.createDocumentFragment();
|
|
||||||
const cards = Array.from(grid.children);
|
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
cards.sort((a, b) => sortBy === 'date'
|
|
||||||
? parseFloat(b.dataset.modified) - parseFloat(a.dataset.modified)
|
|
||||||
: a.dataset.name.localeCompare(b.dataset.name)
|
|
||||||
).forEach(card => fragment.appendChild(card));
|
|
||||||
|
|
||||||
grid.appendChild(fragment);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 立即执行初始排序
|
|
||||||
const sortSelect = document.getElementById('sortSelect');
|
|
||||||
if (sortSelect) {
|
|
||||||
sortCards(sortSelect.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loading management
|
// Loading management
|
||||||
class LoadingManager {
|
class LoadingManager {
|
||||||
@@ -264,14 +243,12 @@ function initializeEventListeners() {
|
|||||||
sortSelect.value = state.sortBy;
|
sortSelect.value = state.sortBy;
|
||||||
sortSelect.addEventListener('change', async (e) => {
|
sortSelect.addEventListener('change', async (e) => {
|
||||||
state.sortBy = e.target.value;
|
state.sortBy = e.target.value;
|
||||||
await resetAndReload();
|
await resetAndReload(); // 直接重新从后端加载已排序的数据
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Folder filter handler
|
// Folder filter handler
|
||||||
document.querySelectorAll('.folder-tags .tag').forEach(tag => {
|
document.querySelectorAll('.folder-tags .tag').forEach(tag => {
|
||||||
// 移除原有的 onclick 属性处理方式,改用事件监听器
|
|
||||||
tag.removeAttribute('onclick');
|
|
||||||
tag.addEventListener('click', toggleFolder);
|
tag.addEventListener('click', toggleFolder);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -562,7 +539,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('sortSelect')?.addEventListener('change', e => {
|
document.getElementById('sortSelect')?.addEventListener('change', e => {
|
||||||
sortCards(e.target.value);
|
// 移除这个函数
|
||||||
|
// sortCards(e.target.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
lazyLoadImages();
|
lazyLoadImages();
|
||||||
|
|||||||
Reference in New Issue
Block a user