Some checks failed
CD Pipeline / deploy (push) Failing after 5m18s
🔴 Critical - auto_heal_service: 補 import re + sqlalchemy.text + 修正 orchestrator 變數名 + autoheal_playbook→playbooks 表名 + _alert_and_store cooldown 修復 - aider_heal_executor: shell injection 改 shell=False + list 參數 - docker-compose: DISABLE_LOGIN 改 env var + 移除密碼 fallback + POSTGRES_HOST 修正 - app.py: /api/backup /api/run_task 等 6 個管理 API 加 @login_required - config.py + pg_sync + e2e_test: 移除 wooo_pg_2026 hardcoded 密碼 fallback - pg_backup.sh: 移除 TELEGRAM_TOKEN= 中間變數,直接用 $TELEGRAM_BOT_TOKEN - migration 014: trigger_pattern→match_pattern + 補 error_type NOT NULL 欄位 🟡 High - telegram_bot_service: str(e) 改通用訊息 + session try/finally + 移除 pa:/pr: 舊 callback - run_scheduler: ElephantAlpha thread 死亡監控 + 自動重啟 + Telegram 告警 + agent_context 03:30 TTL 定時清理任務 - openclaw_learning_service: build_rag_context 兩路徑加 .limit(200) - hooks: commit-quality + momo-prod-guard 空 catch 改 stderr+exit(1) - scripts/code_review: auto_yes 預設改 false - db_backup_service: PGPASSWORD 透過 env dict 傳遞 📦 Migrations - 013_autoheal: 修正建表順序 playbooks→incidents(外鍵前向引用) - 018_add_missing_indexes: heal_logs/incidents 外鍵索引 + cleanup_expired_agent_context() 🟢 Infrastructure - requirements.txt: 加版本下界 Flask>=2.3 SQLAlchemy>=1.4 等 - cd.yaml: 新增 run_scheduler.py + run_telegram_bot.py 監聽路徑 - .gitignore: insert_playbook_local.py 加入忽略 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
338 lines
8.7 KiB
HTML
Executable File
338 lines
8.7 KiB
HTML
Executable File
{#
|
||
WOOO 品牌載入動畫組件
|
||
|
||
使用方式:
|
||
1. 在頁面中 include 此組件:
|
||
{% include 'components/_loading.html' %}
|
||
|
||
2. 在 JavaScript 中控制顯示/隱藏:
|
||
showLoading('正在載入數據...') // 顯示
|
||
hideLoading() // 隱藏
|
||
|
||
3. 也可直接操作 DOM:
|
||
document.getElementById('loadingOverlay').style.display = 'flex'; // 顯示
|
||
document.getElementById('loadingOverlay').style.display = 'none'; // 隱藏
|
||
#}
|
||
|
||
<!-- WOOO Loading Overlay -->
|
||
<div id="loadingOverlay" class="wooo-loading-overlay">
|
||
<div class="loading-logo-container">
|
||
<!-- 脈衝光暈 -->
|
||
<div class="logo-pulse"></div>
|
||
<!-- 外層旋轉光環 -->
|
||
<div class="logo-ring"></div>
|
||
<!-- 內層反向旋轉光環 -->
|
||
<div class="logo-ring-inner"></div>
|
||
<!-- 環繞粒子 -->
|
||
<div class="orbit-particles">
|
||
<div class="orbit-particle"></div>
|
||
<div class="orbit-particle"></div>
|
||
<div class="orbit-particle"></div>
|
||
<div class="orbit-particle"></div>
|
||
</div>
|
||
<!-- 閃爍星星 -->
|
||
<div class="sparkles">
|
||
<div class="sparkle"></div>
|
||
<div class="sparkle"></div>
|
||
<div class="sparkle"></div>
|
||
<div class="sparkle"></div>
|
||
<div class="sparkle"></div>
|
||
<div class="sparkle"></div>
|
||
</div>
|
||
<!-- LOGO -->
|
||
<div class="loading-logo">WOOO</div>
|
||
</div>
|
||
<div class="loading-text" id="loadingText">
|
||
<i class="fas fa-spinner fa-spin me-2"></i>正在載入數據...
|
||
</div>
|
||
<div class="loading-progress">
|
||
<div class="loading-progress-bar"></div>
|
||
</div>
|
||
<div class="loading-hint" id="loadingHint">
|
||
大量資料可能需要較長時間,請稍候
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
/* ============================================
|
||
WOOO 品牌載入動畫樣式
|
||
============================================ */
|
||
|
||
.wooo-loading-overlay {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(240, 245, 255, 0.95) 100%);
|
||
z-index: 9999;
|
||
display: none;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
gap: 25px;
|
||
backdrop-filter: blur(8px);
|
||
}
|
||
|
||
/* LOGO 動畫容器 */
|
||
.wooo-loading-overlay .loading-logo-container {
|
||
position: relative;
|
||
width: 160px;
|
||
height: 160px;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
|
||
.wooo-loading-overlay .loading-logo {
|
||
z-index: 3;
|
||
animation: wooo-cloud-float 3s ease-in-out infinite;
|
||
font-size: 2.5rem;
|
||
font-weight: 800;
|
||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||
background: linear-gradient(135deg, #4F46E5 0%, #7C3AED 100%);
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
background-clip: text;
|
||
letter-spacing: 4px;
|
||
filter: drop-shadow(0 4px 15px rgba(79, 70, 229, 0.4));
|
||
}
|
||
|
||
/* 雲端飄動動畫 */
|
||
@keyframes wooo-cloud-float {
|
||
0%, 100% {
|
||
transform: translateY(0) translateX(0) scale(1);
|
||
}
|
||
25% {
|
||
transform: translateY(-15px) translateX(5px) scale(1.02);
|
||
}
|
||
50% {
|
||
transform: translateY(-8px) translateX(-3px) scale(1);
|
||
}
|
||
75% {
|
||
transform: translateY(-20px) translateX(3px) scale(1.01);
|
||
}
|
||
}
|
||
|
||
/* 外層旋轉光環 */
|
||
.wooo-loading-overlay .logo-ring {
|
||
position: absolute;
|
||
width: 150px;
|
||
height: 150px;
|
||
border: 4px solid transparent;
|
||
border-top-color: #4F46E5;
|
||
border-right-color: #7C3AED;
|
||
border-radius: 50%;
|
||
animation: wooo-ring-spin 2s linear infinite;
|
||
}
|
||
|
||
/* 內層反向旋轉光環 */
|
||
.wooo-loading-overlay .logo-ring-inner {
|
||
position: absolute;
|
||
width: 120px;
|
||
height: 120px;
|
||
border: 3px solid transparent;
|
||
border-bottom-color: #EC4899;
|
||
border-left-color: #F59E0B;
|
||
border-radius: 50%;
|
||
animation: wooo-ring-spin-reverse 1.5s linear infinite;
|
||
}
|
||
|
||
/* 脈衝光暈 */
|
||
.wooo-loading-overlay .logo-pulse {
|
||
position: absolute;
|
||
width: 100px;
|
||
height: 100px;
|
||
background: radial-gradient(circle, rgba(79, 70, 229, 0.3) 0%, transparent 70%);
|
||
border-radius: 50%;
|
||
animation: wooo-pulse-expand 2s ease-out infinite;
|
||
}
|
||
|
||
@keyframes wooo-ring-spin {
|
||
0% { transform: rotate(0deg); }
|
||
100% { transform: rotate(360deg); }
|
||
}
|
||
|
||
@keyframes wooo-ring-spin-reverse {
|
||
0% { transform: rotate(0deg); }
|
||
100% { transform: rotate(-360deg); }
|
||
}
|
||
|
||
@keyframes wooo-pulse-expand {
|
||
0% {
|
||
transform: scale(0.8);
|
||
opacity: 1;
|
||
}
|
||
100% {
|
||
transform: scale(1.8);
|
||
opacity: 0;
|
||
}
|
||
}
|
||
|
||
/* 環繞粒子 */
|
||
.wooo-loading-overlay .orbit-particles {
|
||
position: absolute;
|
||
width: 160px;
|
||
height: 160px;
|
||
animation: wooo-orbit-rotate 4s linear infinite;
|
||
}
|
||
|
||
.wooo-loading-overlay .orbit-particle {
|
||
position: absolute;
|
||
width: 8px;
|
||
height: 8px;
|
||
background: linear-gradient(135deg, #4F46E5, #7C3AED);
|
||
border-radius: 50%;
|
||
box-shadow: 0 0 10px rgba(79, 70, 229, 0.8);
|
||
}
|
||
|
||
.wooo-loading-overlay .orbit-particle:nth-child(1) {
|
||
top: 0;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
}
|
||
|
||
.wooo-loading-overlay .orbit-particle:nth-child(2) {
|
||
top: 50%;
|
||
right: 0;
|
||
transform: translateY(-50%);
|
||
}
|
||
|
||
.wooo-loading-overlay .orbit-particle:nth-child(3) {
|
||
bottom: 0;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
}
|
||
|
||
.wooo-loading-overlay .orbit-particle:nth-child(4) {
|
||
top: 50%;
|
||
left: 0;
|
||
transform: translateY(-50%);
|
||
}
|
||
|
||
@keyframes wooo-orbit-rotate {
|
||
0% { transform: rotate(0deg); }
|
||
100% { transform: rotate(360deg); }
|
||
}
|
||
|
||
/* 閃爍星星 */
|
||
.wooo-loading-overlay .sparkles {
|
||
position: absolute;
|
||
width: 180px;
|
||
height: 180px;
|
||
}
|
||
|
||
.wooo-loading-overlay .sparkle {
|
||
position: absolute;
|
||
width: 4px;
|
||
height: 4px;
|
||
background: #FCD34D;
|
||
border-radius: 50%;
|
||
animation: wooo-sparkle-twinkle 1.5s ease-in-out infinite;
|
||
}
|
||
|
||
.wooo-loading-overlay .sparkle:nth-child(1) { top: 10%; left: 20%; animation-delay: 0s; }
|
||
.wooo-loading-overlay .sparkle:nth-child(2) { top: 5%; right: 25%; animation-delay: 0.3s; }
|
||
.wooo-loading-overlay .sparkle:nth-child(3) { bottom: 15%; right: 15%; animation-delay: 0.6s; }
|
||
.wooo-loading-overlay .sparkle:nth-child(4) { bottom: 10%; left: 25%; animation-delay: 0.9s; }
|
||
.wooo-loading-overlay .sparkle:nth-child(5) { top: 30%; left: 5%; animation-delay: 1.2s; }
|
||
.wooo-loading-overlay .sparkle:nth-child(6) { top: 25%; right: 5%; animation-delay: 0.4s; }
|
||
|
||
@keyframes wooo-sparkle-twinkle {
|
||
0%, 100% {
|
||
transform: scale(0);
|
||
opacity: 0;
|
||
}
|
||
50% {
|
||
transform: scale(1);
|
||
opacity: 1;
|
||
}
|
||
}
|
||
|
||
/* 載入文字 */
|
||
.wooo-loading-overlay .loading-text {
|
||
font-size: 1.2rem;
|
||
color: #4F46E5;
|
||
font-weight: 600;
|
||
text-align: center;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
|
||
.wooo-loading-overlay .loading-hint {
|
||
font-size: 0.85rem;
|
||
color: #6b7280;
|
||
text-align: center;
|
||
max-width: 300px;
|
||
}
|
||
|
||
/* 進度條 */
|
||
.wooo-loading-overlay .loading-progress {
|
||
width: 200px;
|
||
height: 4px;
|
||
background: rgba(79, 70, 229, 0.2);
|
||
border-radius: 2px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.wooo-loading-overlay .loading-progress-bar {
|
||
height: 100%;
|
||
background: linear-gradient(90deg, #4F46E5, #7C3AED, #4F46E5);
|
||
background-size: 200% 100%;
|
||
animation: wooo-progress-flow 1.5s linear infinite;
|
||
width: 100%;
|
||
}
|
||
|
||
@keyframes wooo-progress-flow {
|
||
0% { background-position: 100% 0; }
|
||
100% { background-position: -100% 0; }
|
||
}
|
||
</style>
|
||
|
||
<script>
|
||
/**
|
||
* WOOO 載入動畫控制函數
|
||
*/
|
||
|
||
// 顯示載入動畫
|
||
function showLoading(text, hint) {
|
||
const overlay = document.getElementById('loadingOverlay');
|
||
const loadingText = document.getElementById('loadingText');
|
||
const loadingHint = document.getElementById('loadingHint');
|
||
|
||
if (text && loadingText) {
|
||
loadingText.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>' + text;
|
||
}
|
||
if (hint && loadingHint) {
|
||
loadingHint.textContent = hint;
|
||
}
|
||
|
||
if (overlay) {
|
||
overlay.style.display = 'flex';
|
||
}
|
||
}
|
||
|
||
// 隱藏載入動畫
|
||
function hideLoading() {
|
||
const overlay = document.getElementById('loadingOverlay');
|
||
if (overlay) {
|
||
overlay.style.display = 'none';
|
||
}
|
||
}
|
||
|
||
// 更新載入文字
|
||
function updateLoadingText(text) {
|
||
const loadingText = document.getElementById('loadingText');
|
||
if (loadingText && text) {
|
||
loadingText.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>' + text;
|
||
}
|
||
}
|
||
|
||
// 更新載入提示
|
||
function updateLoadingHint(hint) {
|
||
const loadingHint = document.getElementById('loadingHint');
|
||
if (loadingHint && hint) {
|
||
loadingHint.textContent = hint;
|
||
}
|
||
}
|
||
</script>
|