346 lines
17 KiB
HTML
346 lines
17 KiB
HTML
{#
|
||
EwoooC Frontend V2 shell.
|
||
|
||
使用方式:
|
||
{% include 'components/_ewoooc_shell.html' %}
|
||
|
||
呼叫頁需提供 active_page;未提供時會以空字串處理。
|
||
#}
|
||
|
||
{% set _active_page = active_page|default('') %}
|
||
{% set _analysis_pages = ['sales', 'daily_sales', 'monthly', 'growth'] %}
|
||
{% set _obs_pages = [
|
||
'obs_overview', 'obs_agent_orchestration', 'obs_business_intel',
|
||
'obs_host_health', 'obs_ai_calls', 'obs_budget',
|
||
'obs_promotion_review', 'obs_rag_queries', 'obs_quality_trend',
|
||
'obs_ppt_audit'
|
||
] %}
|
||
|
||
<style>
|
||
.momo-sidebar {
|
||
background: #f2eadf !important;
|
||
border-right: 1px solid rgba(42, 37, 32, 0.14);
|
||
box-shadow: inset -1px 0 0 rgba(255, 248, 238, 0.72), 16px 0 32px rgba(61, 38, 27, 0.08);
|
||
}
|
||
.momo-sidebar-logo {
|
||
color: var(--momo-text-primary, #2a2520);
|
||
border-bottom: 1px solid rgba(42, 37, 32, 0.12);
|
||
}
|
||
.momo-sidebar-logo small,
|
||
.momo-sidebar-logo .momo-muted {
|
||
color: var(--momo-text-secondary, #6f665b) !important;
|
||
}
|
||
.momo-brand-name {
|
||
color: var(--momo-text-primary, #2a2520) !important;
|
||
font-family: "JetBrains Mono", "Inter", var(--momo-font-family-base, system-ui), sans-serif !important;
|
||
font-size: 18px;
|
||
font-weight: 850;
|
||
line-height: 1;
|
||
letter-spacing: 0 !important;
|
||
text-rendering: geometricPrecision;
|
||
}
|
||
.momo-logo-image {
|
||
display: block;
|
||
width: min(168px, 100%);
|
||
height: 54px;
|
||
object-fit: contain;
|
||
object-position: left center;
|
||
border-radius: 8px;
|
||
}
|
||
.momo-logo-mark {
|
||
background: var(--momo-warm-terracotta, #e4573d);
|
||
color: var(--momo-bg-elevated, #fdfaf3);
|
||
box-shadow: none;
|
||
}
|
||
.momo-nav-group {
|
||
border-top-color: rgba(42, 37, 32, 0.14) !important;
|
||
}
|
||
.momo-nav-group-title {
|
||
color: var(--momo-text-tertiary, #9b9184) !important;
|
||
font-weight: 850;
|
||
}
|
||
.momo-nav-link {
|
||
color: var(--momo-text-primary, #2a2520) !important;
|
||
}
|
||
.momo-nav-link:hover {
|
||
background: var(--momo-page-accent-soft, rgba(201, 100, 66, 0.09)) !important;
|
||
color: var(--momo-page-accent-dark, var(--momo-accent-700, #8f4530)) !important;
|
||
}
|
||
.momo-nav-link.is-active {
|
||
background: var(--momo-page-accent, #e4573d) !important;
|
||
color: var(--momo-page-inverse, #fff8ee) !important;
|
||
box-shadow: 0 10px 22px rgba(228, 87, 61, 0.18);
|
||
}
|
||
.momo-nav-link .momo-nav-code {
|
||
color: var(--momo-text-tertiary, #9b9184) !important;
|
||
}
|
||
.momo-nav-link.is-active .momo-nav-code {
|
||
color: rgba(255, 248, 238, 0.76) !important;
|
||
}
|
||
.momo-nav-tree {
|
||
margin: 0;
|
||
}
|
||
.momo-nav-tree > summary {
|
||
list-style: none;
|
||
cursor: pointer;
|
||
}
|
||
.momo-nav-tree > summary::-webkit-details-marker {
|
||
display: none;
|
||
}
|
||
.momo-nav-tree-summary {
|
||
position: relative;
|
||
}
|
||
.momo-nav-tree-summary::after {
|
||
content: "⌄";
|
||
margin-left: auto;
|
||
color: var(--momo-text-tertiary, #9b9184);
|
||
font-size: 0.8rem;
|
||
transform: rotate(-90deg);
|
||
transition: transform 160ms ease;
|
||
}
|
||
.momo-nav-tree-summary.is-active::after {
|
||
color: rgba(255, 248, 238, 0.78);
|
||
}
|
||
.momo-nav-tree[open] .momo-nav-tree-summary::after {
|
||
transform: rotate(0deg);
|
||
}
|
||
.momo-nav-subtree {
|
||
margin: 0.42rem 0 0.72rem 1.05rem;
|
||
padding: 0.42rem 0 0.42rem 0.78rem;
|
||
border-left: 1px solid color-mix(in srgb, var(--momo-page-accent, #e4573d) 34%, transparent);
|
||
background: rgba(255, 248, 238, 0.48);
|
||
background-size: 10px 10px, auto;
|
||
border-radius: 0 0.95rem 0.95rem 0;
|
||
}
|
||
.momo-nav-subtitle {
|
||
margin: 0.68rem 0 0.3rem 0.42rem;
|
||
color: color-mix(in srgb, var(--momo-page-accent-dark, #8f4530) 58%, var(--momo-text-secondary, #6f665b));
|
||
font-size: 0.68rem;
|
||
letter-spacing: 0.12em;
|
||
text-transform: uppercase;
|
||
font-weight: 900;
|
||
}
|
||
.momo-nav-sublink {
|
||
display: grid;
|
||
grid-template-columns: 1rem minmax(0, 1fr) auto;
|
||
align-items: center;
|
||
gap: 0.45rem;
|
||
padding: 0.48rem 0.62rem;
|
||
border-radius: 0.7rem;
|
||
color: color-mix(in srgb, var(--momo-text-primary, #2a2520) 80%, var(--momo-text-secondary, #6f665b));
|
||
text-decoration: none;
|
||
font-size: 0.86rem;
|
||
font-weight: 780;
|
||
background: rgba(255, 252, 246, 0.34);
|
||
transition: background-color 160ms ease, color 160ms ease, transform 160ms ease, box-shadow 160ms ease;
|
||
}
|
||
.momo-nav-sublink i {
|
||
color: color-mix(in srgb, var(--momo-page-accent-dark, #8f4530) 66%, var(--momo-text-secondary, #6f665b));
|
||
}
|
||
.momo-nav-sublink:hover,
|
||
.momo-nav-sublink.is-active {
|
||
background: rgba(255, 248, 238, 0.92);
|
||
color: var(--momo-page-accent-dark, var(--momo-accent-700, #8f4530));
|
||
box-shadow: inset 0 0 0 1px rgba(201, 100, 66, 0.22), 0 8px 18px rgba(70, 46, 28, 0.08);
|
||
transform: translateX(2px);
|
||
}
|
||
.momo-nav-sublink .momo-nav-num {
|
||
color: color-mix(in srgb, var(--momo-text-secondary, #6f665b) 82%, var(--momo-page-accent-dark, #8f4530));
|
||
font-weight: 850;
|
||
}
|
||
.momo-nav-sublink.is-active .momo-nav-num {
|
||
color: var(--momo-page-accent-dark, rgba(127, 90, 73, 0.82));
|
||
}
|
||
.momo-nav-sublink .momo-nav-code {
|
||
opacity: 0.68;
|
||
font-size: 0.68rem;
|
||
}
|
||
.momo-obs-link {
|
||
position: relative;
|
||
text-decoration: none;
|
||
}
|
||
.momo-obs-link.is-alert {
|
||
color: #c96442;
|
||
box-shadow: 0 0 0 3px rgba(201, 100, 66, 0.12);
|
||
}
|
||
.momo-obs-badge {
|
||
position: absolute;
|
||
top: -0.22rem;
|
||
right: -0.22rem;
|
||
min-width: 1.05rem;
|
||
height: 1.05rem;
|
||
padding: 0 0.28rem;
|
||
border-radius: 999px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border: 1px solid rgba(255, 248, 238, 0.86);
|
||
background: var(--momo-page-accent, #e4573d);
|
||
color: var(--momo-page-inverse, #fff8ee);
|
||
box-shadow: 0 8px 18px rgba(132, 58, 34, 0.26);
|
||
font-size: 0.62rem;
|
||
line-height: 1;
|
||
font-weight: 900;
|
||
}
|
||
.momo-obs-badge[hidden] {
|
||
display: none;
|
||
}
|
||
</style>
|
||
{% set _scheduler = scheduler_stats|default({}) %}
|
||
{% set _momo_runs = _scheduler.get('momo_task', []) if _scheduler is mapping else [] %}
|
||
{% set _latest_run = _momo_runs[0] if _momo_runs else {} %}
|
||
{% set _has_scheduler_data = _latest_run is mapping and _latest_run %}
|
||
{% set _last_run = _latest_run.get('last_run', '--') if _has_scheduler_data else '--' %}
|
||
{% set _scanned = _latest_run.get('scanned_count', _latest_run.get('total_products', '--')) if _latest_run is mapping else '--' %}
|
||
{% set _added = _latest_run.get('new_records', _latest_run.get('added', '--')) if _latest_run is mapping else '--' %}
|
||
{% set _run_status = _latest_run.get('status', '') if _has_scheduler_data else '' %}
|
||
{% set _status_label = '尚無紀錄' if not _has_scheduler_data else ('最近成功' if _run_status in ['Success', 'success', 'SUCCESS'] else (_run_status or '已有紀錄')) %}
|
||
{% set _next_run = next_run|default(None) %}
|
||
{% set _session_username = session.get('username') if session is defined else None %}
|
||
{% set _session_role = session.get('role') if session is defined else None %}
|
||
{% set _is_logged_in = session.get('logged_in') if session is defined else false %}
|
||
|
||
<aside class="momo-sidebar" aria-label="主選單">
|
||
<a class="momo-sidebar-logo" href="/">
|
||
<img class="momo-logo-image" src="{{ url_for('static', filename='images/ewoooc_logo_nav.png') }}" alt="EwoooC">
|
||
</a>
|
||
|
||
<nav class="momo-nav momo-scroll">
|
||
<div class="momo-nav-group">
|
||
<div class="momo-nav-group-title momo-label">監控</div>
|
||
<a class="momo-nav-link {% if _active_page == 'dashboard' %}is-active{% endif %}" href="/">
|
||
<span class="momo-nav-icon"><i class="fas fa-border-all"></i></span>
|
||
<span class="momo-nav-label">商品看板</span>
|
||
<span class="momo-nav-code momo-mono">01</span>
|
||
</a>
|
||
<a class="momo-nav-link {% if _active_page in ['edm', 'campaigns'] %}is-active{% endif %}" href="/edm">
|
||
<span class="momo-nav-icon"><i class="fas fa-bullhorn"></i></span>
|
||
<span class="momo-nav-label">活動看板</span>
|
||
<span class="momo-nav-code momo-mono">02</span>
|
||
</a>
|
||
<details class="momo-nav-tree" {% if _active_page in _analysis_pages %}open{% endif %}>
|
||
<summary class="momo-nav-link momo-nav-tree-summary {% if _active_page in _analysis_pages %}is-active{% endif %}">
|
||
<span class="momo-nav-icon"><i class="fas fa-chart-line"></i></span>
|
||
<span class="momo-nav-label">分析報表</span>
|
||
<span class="momo-nav-code momo-mono">03</span>
|
||
</summary>
|
||
<div class="momo-nav-subtree">
|
||
<a class="momo-nav-sublink {% if _active_page == 'sales' %}is-active{% endif %}" href="/sales_analysis">
|
||
<i class="fas fa-chart-bar"></i><span>業績分析</span><span class="momo-nav-code momo-mono">01</span>
|
||
</a>
|
||
<a class="momo-nav-sublink {% if _active_page == 'daily_sales' %}is-active{% endif %}" href="/daily_sales">
|
||
<i class="fas fa-calendar-day"></i><span>當日業績</span><span class="momo-nav-code momo-mono">02</span>
|
||
</a>
|
||
<a class="momo-nav-sublink {% if _active_page == 'growth' %}is-active{% endif %}" href="/growth_analysis">
|
||
<i class="fas fa-arrow-trend-up"></i><span>成長分析</span><span class="momo-nav-code momo-mono">03</span>
|
||
</a>
|
||
<a class="momo-nav-sublink {% if _active_page == 'monthly' %}is-active{% endif %}" href="/monthly_summary_analysis">
|
||
<i class="fas fa-table"></i><span>月份總表</span><span class="momo-nav-code momo-mono">04</span>
|
||
</a>
|
||
{% if metabase_url %}
|
||
<a class="momo-nav-sublink" href="{{ metabase_url }}" target="_blank" rel="noopener">
|
||
<i class="fas fa-chart-pie"></i><span>自訂圖表</span><span class="momo-nav-code momo-mono">外部</span>
|
||
</a>
|
||
{% endif %}
|
||
{% if grist_url %}
|
||
<a class="momo-nav-sublink" href="{{ grist_url }}" target="_blank" rel="noopener">
|
||
<i class="fas fa-table-cells"></i><span>資料協作</span><span class="momo-nav-code momo-mono">外部</span>
|
||
</a>
|
||
{% endif %}
|
||
</div>
|
||
</details>
|
||
</div>
|
||
|
||
<div class="momo-nav-group">
|
||
<div class="momo-nav-group-title momo-label">營運</div>
|
||
<a class="momo-nav-link {% if _active_page == 'vendor_stockout' %}is-active{% endif %}" href="/vendor-stockout">
|
||
<span class="momo-nav-icon"><i class="fas fa-box-open"></i></span>
|
||
<span class="momo-nav-label">廠商缺貨</span>
|
||
<span class="momo-nav-code momo-mono">04</span>
|
||
</a>
|
||
<a class="momo-nav-link {% if _active_page in ['ai_recommend', 'ai_history', 'ai_intelligence'] %}is-active{% endif %}" href="/ai_recommend">
|
||
<span class="momo-nav-icon"><i class="fas fa-wand-magic-sparkles"></i></span>
|
||
<span class="momo-nav-label">AI 助手</span>
|
||
<span class="momo-nav-code momo-mono">05</span>
|
||
</a>
|
||
<a class="momo-nav-link {% if _active_page == 'auto_import' %}is-active{% endif %}" href="/auto_import">
|
||
<span class="momo-nav-icon"><i class="fas fa-download"></i></span>
|
||
<span class="momo-nav-label">雲端匯入</span>
|
||
<span class="momo-nav-code momo-mono">06</span>
|
||
</a>
|
||
</div>
|
||
|
||
<div class="momo-nav-group">
|
||
<div class="momo-nav-group-title momo-label">AI 中樞</div>
|
||
<details class="momo-nav-tree" {% if _active_page in _obs_pages %}open{% endif %}>
|
||
<summary class="momo-nav-link momo-nav-tree-summary {% if _active_page in _obs_pages %}is-active{% endif %}">
|
||
<span class="momo-nav-icon"><i class="fas fa-satellite-dish"></i></span>
|
||
<span class="momo-nav-label">AI 觀測台</span>
|
||
<span class="momo-nav-code momo-mono">07</span>
|
||
</summary>
|
||
<div class="momo-nav-subtree">
|
||
<div class="momo-nav-subtitle momo-label">戰情室</div>
|
||
<a class="momo-nav-sublink {% if _active_page == 'obs_overview' %}is-active{% endif %}" href="/observability/overview">
|
||
<i class="fas fa-gauge-high"></i><span>觀測台總覽</span><span class="momo-nav-code momo-mono">01</span>
|
||
</a>
|
||
<a class="momo-nav-sublink {% if _active_page == 'obs_agent_orchestration' %}is-active{% endif %}" href="/observability/agent_orchestration">
|
||
<i class="fas fa-network-wired"></i><span>Agent 編排矩陣</span><span class="momo-nav-code momo-mono">02</span>
|
||
</a>
|
||
<a class="momo-nav-sublink {% if _active_page == 'obs_business_intel' %}is-active{% endif %}" href="/observability/business_intel">
|
||
<i class="fas fa-briefcase"></i><span>商業面 × AI</span><span class="momo-nav-code momo-mono">03</span>
|
||
</a>
|
||
|
||
<div class="momo-nav-subtitle momo-label">系統與成本</div>
|
||
<a class="momo-nav-sublink {% if _active_page == 'obs_host_health' %}is-active{% endif %}" href="/observability/host_health">
|
||
<i class="fas fa-heartbeat"></i><span>主機健康</span><span class="momo-nav-code momo-mono">04</span>
|
||
</a>
|
||
<a class="momo-nav-sublink {% if _active_page == 'obs_ai_calls' %}is-active{% endif %}" href="/observability/ai_calls">
|
||
<i class="fas fa-chart-bar"></i><span>AI 呼叫</span><span class="momo-nav-code momo-mono">05</span>
|
||
</a>
|
||
<a class="momo-nav-sublink {% if _active_page == 'obs_budget' %}is-active{% endif %}" href="/observability/budget">
|
||
<i class="fas fa-wallet"></i><span>預算控管</span><span class="momo-nav-code momo-mono">06</span>
|
||
</a>
|
||
|
||
<div class="momo-nav-subtitle momo-label">RAG 與品質</div>
|
||
<a class="momo-nav-sublink {% if _active_page == 'obs_promotion_review' %}is-active{% endif %}" href="/observability/promotion_review">
|
||
<i class="fas fa-brain"></i><span>RAG 晉升審核</span><span class="momo-nav-code momo-mono">07</span>
|
||
</a>
|
||
<a class="momo-nav-sublink {% if _active_page == 'obs_rag_queries' %}is-active{% endif %}" href="/observability/rag_queries">
|
||
<i class="fas fa-magnifying-glass-chart"></i><span>RAG 召回詳情</span><span class="momo-nav-code momo-mono">08</span>
|
||
</a>
|
||
<a class="momo-nav-sublink {% if _active_page == 'obs_quality_trend' %}is-active{% endif %}" href="/observability/quality_trend">
|
||
<i class="fas fa-comments"></i><span>反饋趨勢</span><span class="momo-nav-code momo-mono">09</span>
|
||
</a>
|
||
<a class="momo-nav-sublink {% if _active_page == 'obs_ppt_audit' %}is-active{% endif %}" href="/observability/ppt_audit_history">
|
||
<i class="fas fa-search"></i><span>PPT 視覺審核</span><span class="momo-nav-code momo-mono">10</span>
|
||
</a>
|
||
</div>
|
||
</details>
|
||
</div>
|
||
|
||
<div class="momo-nav-group">
|
||
<div class="momo-nav-group-title momo-label">系統</div>
|
||
<a class="momo-nav-link {% if _active_page in ['settings', 'system_settings', 'logs', 'crawler', 'user_management', 'ai_automation_smoke'] %}is-active{% endif %}" href="/settings">
|
||
<span class="momo-nav-icon"><i class="fas fa-gear"></i></span>
|
||
<span class="momo-nav-label">系統管理</span>
|
||
<span class="momo-nav-code momo-mono">14</span>
|
||
</a>
|
||
</div>
|
||
</nav>
|
||
|
||
<div class="momo-status-card">
|
||
<div class="momo-status-title momo-label">爬蟲狀態</div>
|
||
<div class="momo-status-active momo-mono">
|
||
<span class="momo-live-dot"></span>
|
||
<span>{{ _status_label }}</span>
|
||
</div>
|
||
<div class="momo-status-meta momo-mono">
|
||
上次執行 {{ _last_run }}<br>
|
||
掃描筆數 {{ _scanned }}<br>
|
||
新增筆數 {% if _added == '--' %}--{% else %}+{{ _added }}{% endif %}
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<div class="momo-shell-backdrop" data-momo-sidebar-close></div>
|