This commit is contained in:
@@ -106,6 +106,75 @@ def get_ppt_vision_runtime_status() -> Dict[str, Any]:
|
||||
}
|
||||
|
||||
|
||||
def _public_audit_run_payload(run: Dict[str, Any] | None) -> Dict[str, Any] | None:
|
||||
if not run:
|
||||
return None
|
||||
summary = run.get('summary') or {}
|
||||
audited_files = []
|
||||
for item in summary.get('audited_files') or []:
|
||||
path = item.get('path') or ''
|
||||
audited_files.append({
|
||||
'filename': os.path.basename(path) if path else '',
|
||||
'slides_checked': int(item.get('slides_checked') or 0),
|
||||
'issues': int(item.get('issues') or 0),
|
||||
'error': item.get('error') or '',
|
||||
})
|
||||
errors = [str(error)[:160] for error in (summary.get('errors') or [])[:3]]
|
||||
payload = {
|
||||
'ok': bool(run.get('ok')),
|
||||
'status': run.get('status') or 'unknown',
|
||||
'queued_at': run.get('queued_at') or '',
|
||||
'started_at': run.get('started_at') or '',
|
||||
'finished_at': run.get('finished_at') or '',
|
||||
'filenames': [
|
||||
os.path.basename(str(name))
|
||||
for name in (run.get('filenames') or [])
|
||||
if str(name).lower().endswith('.pptx')
|
||||
],
|
||||
'max_files': run.get('max_files'),
|
||||
'error': run.get('error') or '',
|
||||
'summary': {
|
||||
'audited_count': len(audited_files),
|
||||
'total_issues': int(summary.get('total_issues') or 0),
|
||||
'error_count': len(summary.get('errors') or []),
|
||||
'errors': errors,
|
||||
'files': audited_files[:5],
|
||||
},
|
||||
}
|
||||
return payload
|
||||
|
||||
|
||||
def get_ppt_vision_audit_status() -> Dict[str, Any]:
|
||||
"""Return the current/last background visual QA run without touching DB."""
|
||||
running = _AUDIT_LOCK.locked()
|
||||
last_run = _public_audit_run_payload(_LAST_AUDIT_RUN)
|
||||
if running:
|
||||
status = 'running'
|
||||
status_label = '執行中'
|
||||
message = '視覺 QA 正在背景審核簡報。'
|
||||
elif last_run:
|
||||
status = last_run.get('status') or 'unknown'
|
||||
status_label = {
|
||||
'queued': '已排入',
|
||||
'running': '執行中',
|
||||
'completed': '已完成',
|
||||
'error': '錯誤',
|
||||
}.get(status, status)
|
||||
message = '最近一次視覺 QA 已完成。' if status == 'completed' else '最近一次視覺 QA 狀態可查。'
|
||||
else:
|
||||
status = 'idle'
|
||||
status_label = '待命'
|
||||
message = '尚未有背景視覺 QA 執行紀錄。'
|
||||
return {
|
||||
'ok': True,
|
||||
'running': running,
|
||||
'status': status,
|
||||
'status_label': status_label,
|
||||
'message': message,
|
||||
'last_run': last_run,
|
||||
}
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 結果容器
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
@@ -557,7 +626,7 @@ def start_ppt_vision_audit_background(
|
||||
'ok': True,
|
||||
'status': 'already_running',
|
||||
'message': 'PPT vision audit is already running.',
|
||||
'last_run': _LAST_AUDIT_RUN,
|
||||
'last_run': _public_audit_run_payload(_LAST_AUDIT_RUN),
|
||||
}
|
||||
|
||||
clean_filenames = [
|
||||
@@ -565,11 +634,27 @@ def start_ppt_vision_audit_background(
|
||||
for name in (filenames or [])
|
||||
if str(name).lower().endswith('.pptx')
|
||||
]
|
||||
queued_at = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
_LAST_AUDIT_RUN = {
|
||||
'ok': True,
|
||||
'status': 'queued',
|
||||
'queued_at': queued_at,
|
||||
'filenames': clean_filenames,
|
||||
'max_files': max_files,
|
||||
}
|
||||
|
||||
def _run():
|
||||
global _LAST_AUDIT_RUN
|
||||
with _AUDIT_LOCK:
|
||||
started_at = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
_LAST_AUDIT_RUN = {
|
||||
'ok': True,
|
||||
'status': 'running',
|
||||
'queued_at': queued_at,
|
||||
'started_at': started_at,
|
||||
'filenames': clean_filenames,
|
||||
'max_files': max_files,
|
||||
}
|
||||
try:
|
||||
summary = audit_recent_ppts(
|
||||
reports_dir=reports_dir,
|
||||
@@ -580,16 +665,22 @@ def start_ppt_vision_audit_background(
|
||||
_LAST_AUDIT_RUN = {
|
||||
'ok': True,
|
||||
'status': 'completed',
|
||||
'queued_at': queued_at,
|
||||
'started_at': started_at,
|
||||
'finished_at': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'filenames': clean_filenames,
|
||||
'max_files': max_files,
|
||||
'summary': summary,
|
||||
}
|
||||
except Exception as exc:
|
||||
_LAST_AUDIT_RUN = {
|
||||
'ok': False,
|
||||
'status': 'error',
|
||||
'queued_at': queued_at,
|
||||
'started_at': started_at,
|
||||
'finished_at': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'filenames': clean_filenames,
|
||||
'max_files': max_files,
|
||||
'error': f'{type(exc).__name__}: {str(exc)[:200]}',
|
||||
}
|
||||
logger.error("[PPTVision] background audit failed: %s", exc, exc_info=True)
|
||||
@@ -641,6 +732,7 @@ __all__ = [
|
||||
'ppt_vision_service',
|
||||
'is_ppt_vision_enabled',
|
||||
'get_ppt_vision_runtime_status',
|
||||
'get_ppt_vision_audit_status',
|
||||
'PPT_VISION_SYSTEM_PROMPT',
|
||||
'audit_recent_ppts',
|
||||
'start_ppt_vision_audit_background',
|
||||
|
||||
Reference in New Issue
Block a user