feat: 补齐 ppt_history 的 DB-backed 檔案回填並保留開啟/下載
All checks were successful
CD Pipeline / deploy (push) Successful in 59s
All checks were successful
CD Pipeline / deploy (push) Successful in 59s
This commit is contained in:
@@ -2235,6 +2235,7 @@ def ppt_audit_history():
|
||||
if not os.path.isdir(reports_dir):
|
||||
error = f'{reports_dir} 目錄不存在'
|
||||
else:
|
||||
files_by_name = {}
|
||||
for f in os.listdir(reports_dir):
|
||||
if not f.lower().endswith('.pptx'):
|
||||
continue
|
||||
@@ -2247,14 +2248,68 @@ def ppt_audit_history():
|
||||
try:
|
||||
mtime = os.path.getmtime(full)
|
||||
if month_start_ts <= mtime < month_end_ts:
|
||||
files.append({
|
||||
files_by_name[f] = {
|
||||
'source': 'filesystem',
|
||||
'name': f,
|
||||
'size_kb': round(os.path.getsize(full) / 1024, 1),
|
||||
'mtime': datetime.fromtimestamp(mtime).strftime('%Y-%m-%d %H:%M'),
|
||||
'mtime_ts': mtime,
|
||||
})
|
||||
'file_exists': True,
|
||||
'file_path': full,
|
||||
}
|
||||
except OSError:
|
||||
continue
|
||||
|
||||
# 補充:若 188 主機僅保留 DB 快取紀錄或掃描過程漏掉,仍可回補當月報表清單
|
||||
try:
|
||||
session = get_session()
|
||||
try:
|
||||
sql = """
|
||||
SELECT report_type, file_path, file_size, generated_at
|
||||
FROM ppt_reports
|
||||
WHERE generated_at >= :month_start
|
||||
AND generated_at < :month_end
|
||||
"""
|
||||
params = {'month_start': month_start, 'month_end': month_end}
|
||||
if report_type != 'all':
|
||||
sql += " AND report_type = :report_type"
|
||||
params['report_type'] = report_type
|
||||
rows = session.execute(sa_text(sql), params).fetchall()
|
||||
|
||||
for rpt_type, file_path, file_size, generated_at in rows:
|
||||
if not file_path:
|
||||
continue
|
||||
name = os.path.basename(file_path)
|
||||
if not name.lower().endswith('.pptx'):
|
||||
continue
|
||||
if report_prefix != 'all' and not name.startswith(report_prefix):
|
||||
continue
|
||||
if name in files_by_name:
|
||||
files_by_name[name]['source'] = 'both'
|
||||
continue
|
||||
if not generated_at:
|
||||
continue
|
||||
mtime = generated_at.timestamp()
|
||||
if not (month_start_ts <= mtime < month_end_ts):
|
||||
continue
|
||||
candidate_path = os.path.join(reports_dir, name)
|
||||
exists = os.path.isfile(candidate_path)
|
||||
files_by_name[name] = {
|
||||
'source': 'database',
|
||||
'name': name,
|
||||
'size_kb': round((file_size or 0) / 1024, 1),
|
||||
'mtime': generated_at.strftime('%Y-%m-%d %H:%M'),
|
||||
'mtime_ts': mtime,
|
||||
'file_exists': exists,
|
||||
'file_path': candidate_path if exists else file_path,
|
||||
'report_type': rpt_type,
|
||||
}
|
||||
finally:
|
||||
session.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
files = list(files_by_name.values())
|
||||
files.sort(key=lambda x: x['mtime_ts'], reverse=True)
|
||||
except Exception as e:
|
||||
error = f'{type(e).__name__}: {str(e)[:200]}'
|
||||
|
||||
@@ -274,7 +274,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm mb-0">
|
||||
<table class="table table-sm mb-0">
|
||||
<thead class="table-light">
|
||||
<tr><th>檔名</th><th class="text-end">KB</th><th>修改時間</th><th>狀態</th><th>操作</th></tr>
|
||||
</thead>
|
||||
@@ -282,17 +282,29 @@
|
||||
{% for f in files %}
|
||||
<tr>
|
||||
<td><code>{{ f.name }}</code></td>
|
||||
<td class="text-end">{{ f.size_kb }}</td>
|
||||
<td class="text-end">{{ f.size_kb if f.size_kb is not none else '—' }}</td>
|
||||
<td><small>{{ f.mtime }}</small></td>
|
||||
<td><small class="text-muted">22:00 排程掃描</small></td>
|
||||
<td>
|
||||
{% if f.source == 'database' %}
|
||||
<span class="text-muted">{% if f.file_exists %}資料庫快取 + 檔案可存取{% else %}資料庫快取(檔案未落盤){% endif %}</span>
|
||||
{% elif f.source == 'both' %}
|
||||
<span class="text-success">檔案 + 資料庫</span>
|
||||
{% else %}
|
||||
<span class="text-muted">22:00 掃描落盤</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<div class="ppt-file-actions">
|
||||
{% if f.file_exists %}
|
||||
<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>開啟
|
||||
</a>
|
||||
<a class="btn btn-outline-secondary btn-sm" href="{{ url_for('admin_observability.ppt_audit_file', filename=f.name, action='download') }}">
|
||||
<i class="fas fa-download me-1"></i>下載
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="small text-muted">本機暫無檔案,請先至來源回補</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user