WechatOnCloud/bridge/woc_bridge/routes/screenshot.py
Kris ed2ee086de refactor: 重构UI操作调度,引入优先级调度与监控
主要变更:
1. 新增UIActionScheduler实现优先级UI任务调度,支持CRITICAL/HIGH/NORMAL/LOW四级优先级
2. 替换原有SendQueue为UIActionScheduler,统一所有UI操作的调度逻辑
3. 为截图、登录、重启等API添加调度器封装,支持超时、限流与fast-fail机制
4. 新增Prometheus监控指标,统计UI任务执行、等待耗时、超时、限流与快速失败情况
5. 为QrCapture添加命令执行超时保护,避免X11操作卡死
6. 扩展StatusResponse与状态接口,暴露调度器指标
7. 新增完整的单元测试覆盖调度器功能
8. 为看门狗注入调度器,实现kill前队列清空与快速失败窗口
2026-07-18 03:43:28 +08:00

61 lines
2.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
import logging
from fastapi import APIRouter
from fastapi.responses import Response
from woc_bridge.config import _require_qr_capture, _require_send_queue
from woc_bridge.messaging.ui_action_scheduler import Priority
from woc_bridge.models import BridgeError
logger = logging.getLogger("woc-bridge")
router = APIRouter()
# ---------------------------------------------------------------------------
# 路由POST /api/screenshot
# ---------------------------------------------------------------------------
@router.post("/api/screenshot")
async def screenshot() -> Response:
"""截取完整屏幕并返回 PNG。
用于前端「截图」按钮 / 调试时观察微信实际界面状态(如确认 UI 操作是否
触发了正确的对话框)。截取整个 X 桌面DISPLAY 由 _state.config.display 指定)。
Returns:
ResponseContent-Type=image/pngbody 为 PNG 二进制
Raises:
BridgeError(WINDOW_NOT_FOUND): X 会话未就绪无法截图HTTP 503
其他异常由全局兜底处理器返回 BRIDGE_INTERNAL_ERROR
Notes:
- 截图由 qr_capture.capture_full_screenshot 完成,底层调
xdotool/getwindowgeometry + importImageMagick
- 与 /api/login/qr/start 区别本接口截全屏qr/start 截二维码区域
- 大屏幕截图可能 > 1MB调用方注意带宽
"""
logger.info("screenshot: 收到请求")
qr_capture = _require_qr_capture()
scheduler = _require_send_queue()
try:
if hasattr(scheduler, "execute"):
png_bytes = await scheduler.execute(
lambda: qr_capture.capture_full_screenshot(),
priority=Priority.LOW,
wait_timeout_ms=10000,
trace_id="screenshot",
)
else:
png_bytes = await qr_capture.capture_full_screenshot()
except BridgeError as e:
logger.warning("screenshot: 失败 %s: %s", e.code, e.message)
raise
except Exception as e:
logger.warning("screenshot: 失败 %s: %s", type(e).__name__, e)
raise
logger.info("screenshot: ✓ 截图成功 %d bytes", len(png_bytes))
return Response(content=png_bytes, media_type="image/png")