Files
ewoooc/web/templates/components/_loading.html
ogt 0099543c05
Some checks failed
CD Pipeline / deploy (push) Failing after 5m18s
fix(security): 全域健檢 — 40 項安全/Bug/品質修復
🔴 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>
2026-04-22 01:12:23 +08:00

338 lines
8.7 KiB
HTML
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{#
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>