mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
Add refresh loras
This commit is contained in:
13
nodes.py
13
nodes.py
@@ -161,6 +161,7 @@ class LorasEndpoint:
|
||||
"folder": lora["folder"],
|
||||
"sha256": lora["sha256"],
|
||||
"file_path": lora["file_path"],
|
||||
"modified": lora["modified"],
|
||||
"civitai": lora.get("civitai", {}) or {} # 确保当 civitai 为 None 时返回空字典
|
||||
}
|
||||
except Exception as e:
|
||||
@@ -174,6 +175,7 @@ class LorasEndpoint:
|
||||
"folder": lora.get("folder", ""),
|
||||
"sha256": lora.get("sha256", ""),
|
||||
"file_path": lora.get("file_path", ""),
|
||||
"modified": lora.get("modified", ""),
|
||||
"civitai": {
|
||||
"id": "",
|
||||
"modelId": "",
|
||||
@@ -289,14 +291,17 @@ class LorasEndpoint:
|
||||
# 更新模型名称(优先使用CivitAI名称)
|
||||
if 'model' in civitai_metadata:
|
||||
local_metadata['model_name'] = civitai_metadata['model'].get('name', local_metadata.get('model_name'))
|
||||
# update base model
|
||||
local_metadata['base_model'] = civitai_metadata.get('baseModel')
|
||||
|
||||
# 4. 下载预览图
|
||||
first_image = next((img for img in civitai_metadata.get('images', []) if img.get('type') == 'image'), None)
|
||||
if first_image:
|
||||
preview_extension = os.path.splitext(first_image['url'])[-1] # Get the image file extension
|
||||
first_preview = next((img for img in civitai_metadata.get('images', [])), None)
|
||||
if first_preview:
|
||||
|
||||
preview_extension = '.mp4' if first_preview['type'] == 'video' else os.path.splitext(first_preview['url'])[-1] # Get the file extension
|
||||
preview_filename = os.path.splitext(os.path.basename(data['file_path']))[0] + preview_extension
|
||||
preview_path = os.path.join(os.path.dirname(data['file_path']), preview_filename)
|
||||
await client.download_preview_image(first_image['url'], preview_path)
|
||||
await client.download_preview_image(first_preview['url'], preview_path)
|
||||
# 存储相对路径,使用正斜杠格式
|
||||
local_metadata['preview_url'] = os.path.relpath(preview_path, self.loras_root).replace(os.sep, '/')
|
||||
|
||||
|
||||
@@ -2,15 +2,13 @@
|
||||
function sortCards(sortBy) {
|
||||
const grid = document.getElementById('loraGrid');
|
||||
const cards = Array.from(grid.children);
|
||||
|
||||
|
||||
cards.sort((a, b) => {
|
||||
switch(sortBy) {
|
||||
case 'name':
|
||||
return a.dataset.name.localeCompare(b.dataset.name);
|
||||
case 'date':
|
||||
return new Date(b.dataset.date) - new Date(a.dataset.date);
|
||||
case 'size':
|
||||
return parseFloat(b.dataset.size) - parseFloat(a.dataset.size);
|
||||
return b.dataset.modified - a.dataset.modified;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -19,13 +17,59 @@ function sortCards(sortBy) {
|
||||
|
||||
// 刷新功能
|
||||
async function refreshLoras() {
|
||||
const loadingOverlay = document.getElementById('loading-overlay');
|
||||
const loraGrid = document.getElementById('loraGrid');
|
||||
const currentSort = document.getElementById('sortSelect').value;
|
||||
const activeFolder = document.querySelector('.tag.active')?.dataset.folder;
|
||||
|
||||
try {
|
||||
// Show loading overlay
|
||||
loadingOverlay.style.display = 'flex';
|
||||
|
||||
// Fetch new data
|
||||
const response = await fetch('/loras?refresh=true');
|
||||
if (response.ok) {
|
||||
location.reload();
|
||||
if (!response.ok) throw new Error('Refresh failed');
|
||||
|
||||
// Parse the HTML response
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(await response.text(), 'text/html');
|
||||
|
||||
// Get the new lora cards
|
||||
const newLoraGrid = doc.getElementById('loraGrid');
|
||||
|
||||
// Update the grid content
|
||||
loraGrid.innerHTML = newLoraGrid.innerHTML;
|
||||
|
||||
// Re-attach click listeners to new cards
|
||||
document.querySelectorAll('.lora-card').forEach(card => {
|
||||
card.addEventListener('click', () => {
|
||||
const meta = JSON.parse(card.dataset.meta || '{}');
|
||||
if (Object.keys(meta).length > 0) {
|
||||
showModal(meta);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Re-apply current sorting
|
||||
sortCards(currentSort);
|
||||
|
||||
// Re-apply current folder filter if any
|
||||
if (activeFolder) {
|
||||
document.querySelectorAll('.lora-card').forEach(card => {
|
||||
if (card.getAttribute('data-folder') === activeFolder) {
|
||||
card.style.display = '';
|
||||
} else {
|
||||
card.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Refresh failed:', error);
|
||||
alert('Failed to refresh loras');
|
||||
} finally {
|
||||
// Hide loading overlay
|
||||
loadingOverlay.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,10 +138,16 @@ async function deleteModel(fileName) {
|
||||
}
|
||||
|
||||
// 初始化排序
|
||||
document.getElementById('sortSelect').addEventListener('change', (e) => {
|
||||
document.getElementById('sortSelect')?.addEventListener('change', (e) => {
|
||||
sortCards(e.target.value);
|
||||
});
|
||||
|
||||
// 立即执行初始排序
|
||||
const sortSelect = document.getElementById('sortSelect');
|
||||
if (sortSelect) {
|
||||
sortCards(sortSelect.value);
|
||||
}
|
||||
|
||||
// 添加搜索功能
|
||||
document.getElementById('searchInput')?.addEventListener('input', (e) => {
|
||||
const term = e.target.value.toLowerCase();
|
||||
@@ -123,9 +173,9 @@ function showModal(lora) {
|
||||
const modal = document.getElementById('loraModal');
|
||||
modal.innerHTML = `
|
||||
<div class="modal-content">
|
||||
<h2>${lora.name}</h2>
|
||||
<h2>${lora.model.name}</h2>
|
||||
<div class="carousel">
|
||||
${lora.images.map(img => `<img src="${img}" alt="Preview">`).join('')}
|
||||
${lora.images.map(img => `<img src="${img.url}" alt="Preview">`).join('')}
|
||||
</div>
|
||||
<div class="description">${lora.description}</div>
|
||||
<button class="close" onclick="closeModal()">×</button>
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
<select id="sortSelect">
|
||||
<option value="name">Name</option>
|
||||
<option value="date">Date</option>
|
||||
<option value="size">Size</option>
|
||||
</select>
|
||||
<button onclick="refreshLoras()"><i class="fas fa-sync"></i> Refresh</button>
|
||||
<button onclick="fetchCivitai()" class="secondary"><i class="fas fa-download"></i> Fetch</button>
|
||||
@@ -54,9 +53,17 @@
|
||||
data-name="{{ lora.model_name }}"
|
||||
data-file_name="{{ lora.file_name }}"
|
||||
data-folder="{{ lora.folder }}"
|
||||
data-modified="{{ lora.modified }}"
|
||||
data-meta="{{ lora.civitai | default({}) | tojson | forceescape }}">
|
||||
<div class="card-preview">
|
||||
<img src="{{ ('/loras_static/previews/' + lora.preview_url) if lora.preview_url else '/loras_static/images/no-preview.png' }}" alt="{{ lora.name }}">
|
||||
{% if lora.preview_url.endswith('.mp4') or lora.preview_url.endswith('.webm') %}
|
||||
<video controls>
|
||||
<source src="{{ '/loras_static/previews/' + lora.preview_url }}" type="video/mp4">
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
{% else %}
|
||||
<img src="{{ ('/loras_static/previews/' + lora.preview_url) if lora.preview_url else '/loras_static/images/no-preview.png' }}" alt="{{ lora.name }}">
|
||||
{% endif %}
|
||||
<div class="card-header">
|
||||
<span class="base-model-label" title="{{ lora.base_model }}">
|
||||
{{ lora.base_model }}
|
||||
@@ -89,6 +96,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/loras_static/js/script.js"></script>
|
||||
<script src="/loras_static/js/script.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -6,7 +6,7 @@ BASE_MODEL_MAPPING = {
|
||||
"sd-v2-1": "SD2.1",
|
||||
"sdxl": "SDXL",
|
||||
"sd-v2": "SD2.0",
|
||||
"flux1": "Flux1.D",
|
||||
"flux1": "Flux.1 D",
|
||||
}
|
||||
|
||||
def determine_base_model(version_string: Optional[str]) -> str:
|
||||
|
||||
Reference in New Issue
Block a user