Simplify LoRA page rendering and implement singleton pattern for LoRA scanner

This commit is contained in:
Will Miao
2025-02-03 22:16:03 +08:00
parent 12cdadb583
commit a3af41e737
3 changed files with 30 additions and 49 deletions

View File

@@ -48,28 +48,12 @@ class LoraRoutes:
async def handle_loras_page(self, request: web.Request) -> web.Response:
"""Handle GET /loras request"""
try:
# Get cached data
# Get cached data for folders only
cache = await self.scanner.get_cached_data()
# Get initial data (first page 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
# Render template with folders only
template = self.template_env.get_template('loras.html')
rendered = template.render(
loras=formatted_loras,
folders=cache.folders,
total_items=initial_data['total']
)
rendered = template.render(folders=cache.folders)
return web.Response(
text=rendered,

View File

@@ -13,11 +13,30 @@ logger = logging.getLogger(__name__)
class LoraScanner:
"""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):
self._cache: Optional[LoraCache] = None
self._initialization_lock = asyncio.Lock()
self._initialization_task: Optional[asyncio.Task] = None
# 确保初始化只执行一次
if not hasattr(self, '_initialized'):
self._cache: Optional[LoraCache] = None
self._initialization_lock = asyncio.Lock()
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:
"""Get cached LoRA data, refresh if needed"""

View File

@@ -8,28 +8,7 @@ function debounce(func, wait) {
}
// Sorting functionality
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);
}
// function sortCards(sortBy) { ... }
// Loading management
class LoadingManager {
@@ -264,14 +243,12 @@ function initializeEventListeners() {
sortSelect.value = state.sortBy;
sortSelect.addEventListener('change', async (e) => {
state.sortBy = e.target.value;
await resetAndReload();
await resetAndReload(); // 直接重新从后端加载已排序的数据
});
}
// Folder filter handler
document.querySelectorAll('.folder-tags .tag').forEach(tag => {
// 移除原有的 onclick 属性处理方式,改用事件监听器
tag.removeAttribute('onclick');
tag.addEventListener('click', toggleFolder);
});
}
@@ -562,7 +539,8 @@ document.addEventListener('DOMContentLoaded', () => {
});
document.getElementById('sortSelect')?.addEventListener('change', e => {
sortCards(e.target.value);
// 移除这个函数
// sortCards(e.target.value);
});
lazyLoadImages();