This commit is contained in:
sjk
2026-01-06 19:36:42 +08:00
parent 15b579d64a
commit 19942144fb
261 changed files with 24034 additions and 5477 deletions

146
backend/error_screenshot.py Normal file
View File

@@ -0,0 +1,146 @@
"""
错误截图保存工具
当发生错误时自动截图并保存,便于问题排查
"""
import os
import sys
from datetime import datetime
from pathlib import Path
from typing import Optional
from playwright.async_api import Page
# 截图保存目录
SCREENSHOT_DIR = Path("error_screenshots")
SCREENSHOT_DIR.mkdir(exist_ok=True)
async def save_error_screenshot(
page: Optional[Page],
error_type: str,
error_message: str = "",
prefix: str = ""
) -> Optional[str]:
"""
保存错误截图
Args:
page: Playwright 页面对象
error_type: 错误类型login_failed, send_code_failed, publish_failed等
error_message: 错误信息(可选,会添加到日志)
prefix: 文件名前缀(可选)
Returns:
截图文件路径失败返回None
"""
if not page:
print("[错误截图] 页面对象为空,无法截图", file=sys.stderr)
return None
try:
# 生成文件名年月日时分秒_错误类型.png
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
# 清理错误类型字符串(移除特殊字符)
safe_error_type = "".join(c for c in error_type if c.isalnum() or c in ('_', '-'))
# 组合文件名
if prefix:
filename = f"{prefix}_{timestamp}_{safe_error_type}.png"
else:
filename = f"{timestamp}_{safe_error_type}.png"
filepath = SCREENSHOT_DIR / filename
# 截图
await page.screenshot(path=str(filepath), full_page=True)
# 打印日志
print(f"[错误截图] 已保存: {filepath}", file=sys.stderr)
if error_message:
print(f"[错误截图] 错误信息: {error_message}", file=sys.stderr)
# 返回文件路径
return str(filepath)
except Exception as e:
print(f"[错误截图] 截图失败: {str(e)}", file=sys.stderr)
return None
def cleanup_old_screenshots(days: int = 7):
"""
清理旧的错误截图
Args:
days: 保留最近几天的截图默认7天
"""
try:
import time
current_time = time.time()
cutoff_time = current_time - (days * 24 * 60 * 60)
deleted_count = 0
for file in SCREENSHOT_DIR.glob("*.png"):
if file.stat().st_mtime < cutoff_time:
file.unlink()
deleted_count += 1
if deleted_count > 0:
print(f"[错误截图] 已清理 {deleted_count} 个超过 {days} 天的旧截图", file=sys.stderr)
except Exception as e:
print(f"[错误截图] 清理旧截图失败: {str(e)}", file=sys.stderr)
async def save_screenshot_with_html(
page: Optional[Page],
error_type: str,
error_message: str = "",
prefix: str = ""
) -> tuple[Optional[str], Optional[str]]:
"""
保存错误截图和HTML源码用于深度调试
Args:
page: Playwright 页面对象
error_type: 错误类型
error_message: 错误信息(可选)
prefix: 文件名前缀(可选)
Returns:
(截图路径, HTML路径),失败返回(None, None)
"""
if not page:
return None, None
try:
# 生成文件名
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
safe_error_type = "".join(c for c in error_type if c.isalnum() or c in ('_', '-'))
if prefix:
base_filename = f"{prefix}_{timestamp}_{safe_error_type}"
else:
base_filename = f"{timestamp}_{safe_error_type}"
# 保存截图
screenshot_path = SCREENSHOT_DIR / f"{base_filename}.png"
await page.screenshot(path=str(screenshot_path), full_page=True)
# 保存HTML
html_path = SCREENSHOT_DIR / f"{base_filename}.html"
html_content = await page.content()
with open(html_path, 'w', encoding='utf-8') as f:
f.write(html_content)
print(f"[错误截图] 已保存截图: {screenshot_path}", file=sys.stderr)
print(f"[错误截图] 已保存HTML: {html_path}", file=sys.stderr)
if error_message:
print(f"[错误截图] 错误信息: {error_message}", file=sys.stderr)
return str(screenshot_path), str(html_path)
except Exception as e:
print(f"[错误截图] 保存截图和HTML失败: {str(e)}", file=sys.stderr)
return None, None