強化 PPT 產線與線上預覽
Some checks failed
CD Pipeline / deploy (push) Has been cancelled

This commit is contained in:
OoO
2026-05-18 15:44:11 +08:00
parent 921e9eeb15
commit d2d8dbab65
16 changed files with 980 additions and 27 deletions

View File

@@ -49,6 +49,22 @@
</div>
</div>
</section>
{% if not vision_status.ready %}
<section class="ppt-diagnostic-strip">
<div>
<div class="ppt-label">視覺 QA 尚未就緒</div>
<strong>目前不是模型能力問題,而是執行環境尚未完整開啟。</strong>
</div>
<div class="ppt-diagnostic-items">
<span>PPT_VISION_ENABLED={{ vision_status.env_value }}</span>
<span>模型 {{ vision_status.model }}</span>
<span>{{ 'LibreOffice OK' if vision_status.converter_ready else '缺 LibreOffice' }}</span>
</div>
{% if vision_status.blockers %}
<small class="text-muted">{{ vision_status.blockers|join('') }}</small>
{% endif %}
</section>
{% endif %}
{% if error %}<div class="alert alert-warning mt-3"><strong><i class="fas fa-triangle-exclamation me-1"></i></strong>{{ error }}</div>{% endif %}
<section class="ppt-toolbar">
@@ -79,35 +95,98 @@
data-report-types="{{ auto_generation_missing_report_types | join(',') }}">
<div class="ppt-panel-head">
<div>
<div class="ppt-label">自動產生定義</div>
<h2 class="ppt-panel-title">簡報產線覆蓋狀態</h2>
<div class="ppt-label">Production Command Center</div>
<h2 class="ppt-panel-title">簡報產線控制台</h2>
</div>
<button class="btn btn-sm btn-outline-primary" type="button" data-ppt-generate-missing {% if not auto_generation.enabled or auto_generation.missing_count == 0 %}disabled{% endif %}>
<i class="fas fa-wand-magic-sparkles me-1" aria-hidden="true"></i>補齊缺漏簡報
</button>
</div>
<div class="ppt-panel-body">
<div class="ppt-auto-grid">
{% for item in auto_generation_items %}
<div class="ppt-mini">
<span class="ppt-label">{{ item.label }}</span>
<strong class="{% if item.ready %}status-good{% elif item.has_other_versions %}status-blue{% else %}status-warn{% endif %}">
{% if item.ready %}目標已產生{% elif item.has_other_versions %}有其他版本{% else %}待補齊{% endif %}
</strong>
<small class="text-muted">
{{ item.target_label or '最新資料' }} · {{ item.count }} 筆{% if item.sources %} · {{ item.sources|join(' + ') }}{% endif %}
{% if item.latest_generated_at %}<br>最近 {{ item.latest_generated_at }}{% endif %}
</small>
<div class="ppt-pipeline-layout">
<div class="ppt-cadence-rail" aria-label="PPT 定期產出節奏">
{% for cadence in auto_generation.cadences %}
<article class="ppt-cadence-tile is-{{ cadence.status }}">
<div class="ppt-cadence-top">
<span class="ppt-label">{{ cadence.label }}</span>
<strong>{{ cadence.schedule_text }}</strong>
</div>
<div class="ppt-cadence-meter" aria-hidden="true">
<span style="width: {{ cadence.progress_pct }}%"></span>
</div>
<div class="ppt-cadence-meta">
<span>{{ cadence.gate }}</span>
{% if cadence.missing_count > 0 %}<span>缺 {{ cadence.missing_count }} 類</span>{% else %}<span>完整</span>{% endif %}
</div>
</article>
{% endfor %}
</div>
<div class="ppt-coverage-board">
<div class="ppt-coverage-score">
<div>
<span class="ppt-label">定義簡報</span>
<strong>{{ auto_generation.ready_count }}/{{ auto_generation.total }}</strong>
<small class="text-muted">目前缺漏 {{ auto_generation.missing_count }} 類</small>
</div>
<div>
<span class="ppt-label">DB 紀錄</span>
<strong>{{ generation_runs|length }}</strong>
<small class="text-muted">本月最近寫入</small>
</div>
<div>
<span class="ppt-label">線上預覽</span>
<strong>PDF</strong>
<small class="text-muted">PPTX 轉檔快取</small>
</div>
</div>
<div class="ppt-coverage-list" aria-label="定義簡報覆蓋明細">
{% for item in auto_generation_items %}
<div class="ppt-coverage-row">
<div>
<strong>{{ item.label }}</strong>
<small>{{ item.target_label or '最新資料' }}{% if item.latest_generated_at %} · {{ item.latest_generated_at }}{% endif %}</small>
</div>
<span class="ppt-run-status {% if item.ready %}is-ready{% elif item.has_other_versions %}is-partial{% else %}is-missing_file{% endif %}">
{% if item.ready %}已產生{% elif item.has_other_versions %}其他版本{% else %}待補齊{% endif %}
</span>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
<div class="ppt-auto-status small text-muted mt-3" data-ppt-auto-status>
{% if auto_generation.enabled %}
每日 20:30 會自動補齊定義簡報;目前缺漏 {{ auto_generation.missing_count }} 類。
{{ auto_generation.cadence_summary }} 會定期產出並寫入 DB;目前缺漏 {{ auto_generation.missing_count }} 類。
{% else %}
PPT_AUTO_GENERATION_ENABLED=false已停用自動補齊。
{% endif %}
</div>
<div class="ppt-run-log mt-3">
<div class="ppt-run-log-head">
<div>
<div class="ppt-label">DB 產出紀錄</div>
<h3>最近寫入 ppt_generation_runs</h3>
</div>
<small class="text-muted">產出檔案、參數、狀態會同步保留在資料庫</small>
</div>
{% if generation_runs %}
<div class="ppt-run-list">
{% for run in generation_runs %}
<div class="ppt-run-row">
<span class="ppt-run-kind">{{ run.schedule_label }}</span>
<strong>{{ run.report_label }}</strong>
<span class="ppt-run-target">{{ run.target_label or '最新資料' }}</span>
<span class="ppt-run-status is-{{ run.status }}">{{ run.status_label }}</span>
<small class="text-muted">{{ run.started_at }}{% if run.finished_at %} → {{ run.finished_at }}{% endif %}</small>
</div>
{% endfor %}
</div>
{% else %}
<div class="ppt-empty ppt-run-empty">
目前查無本月 DB 產出紀錄;下一次自動排程或手動補齊後,會寫入 ppt_generation_runs 並顯示在這裡。
</div>
{% endif %}
</div>
</div>
</section>
<section class="ppt-grid">
@@ -223,7 +302,7 @@
{% if f.file_exists %}
{% if f.is_valid_ppt %}
<a class="btn btn-outline-primary btn-sm" href="{{ url_for('admin_observability.ppt_audit_file', filename=f.name) }}" target="_blank" rel="noopener">
<i class="fas fa-file-powerpoint me-1"></i>開啟
<i class="fas fa-eye me-1"></i>線上預覽
</a>
{% else %}
<span class="small status-bad">檔案不可預覽</span>

View File

@@ -0,0 +1,48 @@
{% extends "ewoooc_base.html" %}
{% block title %}PPT 線上預覽{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/page-ppt-preview.css') }}">
{% endblock %}
{% block ewooo_content %}
<div class="container-fluid mt-3">
<section class="ppt-preview-hero">
<div>
<div class="ppt-preview-kicker"><i class="fas fa-file-powerpoint me-1"></i>PPT Online Preview</div>
<h1 class="ppt-preview-title">{{ filename }}</h1>
<p class="ppt-preview-subtitle">檔案大小 {{ file_size_kb }} KB · 修改時間 {{ file_mtime }} · 預覽以 PDF 快取呈現,原始 PPTX 仍可下載。</p>
</div>
<div class="ppt-preview-actions">
<a class="btn btn-outline-secondary btn-sm" href="{{ back_url }}"><i class="fas fa-angle-left me-1"></i>回產線</a>
<a class="btn btn-outline-primary btn-sm" href="{{ download_url }}"><i class="fas fa-download me-1"></i>下載 PPTX</a>
{% if preview.ok %}
<a class="btn btn-primary btn-sm" href="{{ pdf_url }}" target="_blank" rel="noopener"><i class="fas fa-up-right-from-square me-1"></i>開新視窗</a>
{% endif %}
</div>
</section>
{% if preview.ok %}
<section class="ppt-preview-frame">
<iframe src="{{ pdf_url }}" title="{{ filename }} 線上預覽"></iframe>
</section>
<p class="ppt-preview-note">
<span class="status-good">預覽已產生</span>
{% if preview.cache_hit %} · 使用既有快取{% else %} · 已建立新快取{% endif %}
{% if preview.converter %} · {{ preview.converter }}{% endif %}
</p>
{% else %}
<section class="ppt-preview-empty">
<div class="ppt-preview-kicker"><i class="fas fa-triangle-exclamation me-1"></i>Preview unavailable</div>
<h2>目前無法產生線上預覽</h2>
<p>{{ preview.error or '轉檔流程沒有回傳可用 PDF。' }}</p>
<div class="ppt-preview-diagnostics">
<span>需要容器內可執行 LibreOffice / soffice</span>
<span>部署後會用 PDF 快取避免每次重轉</span>
<span>原始 PPTX 可先下載檢查</span>
</div>
</section>
{% endif %}
</div>
{% endblock %}