feat: Add initialization progress WebSocket and UI components

- Implement WebSocket route for initialization progress updates
- Create initialization component with progress bar and stages
- Add styles for initialization UI
- Update base template to include initialization component
- Enhance model scanner to broadcast progress during initialization
This commit is contained in:
Will Miao
2025-04-13 10:41:27 +08:00
parent 3982489e67
commit a043b487bd
10 changed files with 996 additions and 98 deletions

View File

@@ -37,49 +37,6 @@
<link rel="preconnect" href="https://civitai.com">
<link rel="preconnect" href="https://cdnjs.cloudflare.com">
<!-- Add styles for initialization notice -->
{% if is_initializing %}
<style>
.initialization-notice {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.85);
z-index: 9999;
margin-top: 0;
border-radius: 0;
display: flex;
justify-content: center;
align-items: center;
color: white;
}
.notice-content {
background-color: rgba(30, 30, 30, 0.9);
border-radius: 10px;
padding: 30px;
text-align: center;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
max-width: 500px;
width: 80%;
}
.loading-spinner {
border: 5px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top: 5px solid #fff;
width: 50px;
height: 50px;
margin: 0 auto 20px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
{% endif %}
<script>
// 计算滚动条宽度并设置CSS变量
document.addEventListener('DOMContentLoaded', () => {
@@ -95,15 +52,7 @@
</head>
<body data-page="{% block page_id %}base{% endblock %}">
{% if is_initializing %}
<div class="initialization-notice">
<div class="notice-content">
<div class="loading-spinner"></div>
<h2>{% block init_title %}Initializing{% endblock %}</h2>
<p>{% block init_message %}Scanning and building cache. This may take a few minutes...{% endblock %}</p>
</div>
</div>
{% else %}
<!-- Header is always visible, even during initialization -->
{% include 'components/header.html' %}
<div class="page-content">
@@ -113,37 +62,23 @@
{% block additional_components %}{% endblock %}
<div class="container">
{% block content %}{% endblock %}
{% if is_initializing %}
<!-- Show initialization component when initializing -->
{% include 'components/initialization.html' %}
{% else %}
<!-- Show regular content when not initializing -->
{% block content %}{% endblock %}
{% endif %}
</div>
{% block overlay %}{% endblock %}
</div>
{% endif %}
{% block main_script %}{% endblock %}
{% if is_initializing %}
<script>
// 检查初始化状态并设置自动刷新
async function checkInitStatus() {
try {
const response = await fetch('{% block init_check_url %}/api/loras?page=1&page_size=1{% endblock %}');
if (response.ok) {
// 如果成功获取数据,说明初始化完成,刷新页面
window.location.reload();
} else {
// 如果还未完成,继续轮询
setTimeout(checkInitStatus, 2000); // 每2秒检查一次
}
} catch (error) {
// 如果出错,继续轮询
setTimeout(checkInitStatus, 2000);
}
}
// 启动状态检查
setTimeout(checkInitStatus, 1000); // 给页面完全加载的时间
</script>
<!-- Load initialization JavaScript -->
<script type="module" src="/loras_static/js/components/initialization.js"></script>
{% else %}
{% block main_script %}{% endblock %}
{% endif %}
{% block additional_scripts %}{% endblock %}

View File

@@ -0,0 +1,104 @@
<!-- Initialization Component -->
<div class="initialization-container" id="initializationContainer">
<div class="initialization-content">
<div class="initialization-header">
<h2 id="initTitle">{% block init_title %}Initializing{% endblock %}</h2>
<p class="init-subtitle" id="initSubtitle">{% block init_message %}Preparing your workspace...{% endblock %}</p>
</div>
<div class="initialization-progress">
<div class="progress-bar-container">
<div class="progress-bar" id="initProgressBar"></div>
</div>
<div class="progress-details">
<span class="progress-percentage" id="progressPercentage">0%</span>
<span class="progress-status" id="progressStatus">Starting initialization...</span>
</div>
</div>
<div class="initialization-stages">
<div class="stage-item" id="stageScanFolders">
<div class="stage-icon">
<i class="fas fa-folder-open"></i>
</div>
<div class="stage-content">
<h4>Scanning Folders</h4>
<div class="stage-details" id="scanFoldersDetails">Discovering model directories...</div>
</div>
<div class="stage-status pending">
<i class="fas fa-clock"></i>
</div>
</div>
<div class="stage-item" id="stageCountModels">
<div class="stage-icon">
<i class="fas fa-calculator"></i>
</div>
<div class="stage-content">
<h4>Counting Models</h4>
<div class="stage-details" id="countModelsDetails">Analyzing files...</div>
</div>
<div class="stage-status pending">
<i class="fas fa-clock"></i>
</div>
</div>
<div class="stage-item" id="stageProcessModels">
<div class="stage-icon">
<i class="fas fa-cogs"></i>
</div>
<div class="stage-content">
<h4>Processing Models</h4>
<div class="stage-details" id="processModelsDetails">Reading model metadata...</div>
</div>
<div class="stage-status pending">
<i class="fas fa-clock"></i>
</div>
</div>
<div class="stage-item" id="stageFinalizing">
<div class="stage-icon">
<i class="fas fa-check-circle"></i>
</div>
<div class="stage-content">
<h4>Finalizing</h4>
<div class="stage-details" id="finalizingDetails">Building cache and optimizing...</div>
</div>
<div class="stage-status pending">
<i class="fas fa-clock"></i>
</div>
</div>
</div>
<div class="initialization-tips">
<div class="tips-header">
<i class="fas fa-lightbulb"></i>
<h3>Tips</h3>
</div>
<div class="tip-carousel" id="tipCarousel">
<div class="tip-item">
<p>You can drag and drop LoRA files into your folders to automatically import them.</p>
</div>
<div class="tip-item">
<p>Use Civitai URLs to quickly download and install new models.</p>
</div>
<div class="tip-item">
<p>Create recipes to save your favorite model combinations for future use.</p>
</div>
<div class="tip-item">
<p>Filter models by tags or base model type using the filter button in the header.</p>
</div>
<div class="tip-item">
<p>Press Ctrl+F (Cmd+F on Mac) to quickly search within your current view.</p>
</div>
</div>
<div class="tip-navigation">
<span class="tip-dot active" data-index="0"></span>
<span class="tip-dot" data-index="1"></span>
<span class="tip-dot" data-index="2"></span>
<span class="tip-dot" data-index="3"></span>
<span class="tip-dot" data-index="4"></span>
</div>
</div>
</div>
</div>