feat: 添加依赖自动检测与安装、选项记忆、KDocs登录优化

- 新增依赖检测模块:启动时自动检测wkhtmltoimage和Playwright Chromium
- 新增依赖安装对话框:缺失时提示用户一键下载安装
- 修复选项记忆功能:浏览类型、自动截图、自动上传选项现在会保存
- 优化KDocs登录检测:未登录时自动切换到金山文档页面并显示二维码
- 简化日志输出:移除debug信息,保留用户友好的状态提示
- 新增账号变化信号:账号管理页面的修改会自动同步到浏览任务页面

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-19 01:28:06 +08:00
parent 83fef6dff2
commit 9743186a9e
11 changed files with 713 additions and 506 deletions

View File

@@ -0,0 +1,228 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
依赖检测和安装模块
检测 wkhtmltoimage 和 Playwright Chromium 是否已安装
如果缺失则从直链下载安装
"""
import os
import shutil
import subprocess
import tempfile
import zipfile
from pathlib import Path
from typing import Optional, Callable, Dict, Tuple
# 直链下载地址
DOWNLOAD_URLS = {
"wkhtmltopdf": "http://by.haory.cn/3/1223/wkhtmltox.exe",
"chromium": "http://by.haory.cn/3/1223/chromium-win64.zip",
}
# Playwright chromium 版本目录名(与 playwright 1.57.0 对应)
CHROMIUM_VERSION_DIR = "chromium-1200"
def check_wkhtmltoimage() -> bool:
"""检测 wkhtmltoimage 是否已安装"""
# 先检查 PATH
if shutil.which("wkhtmltoimage"):
return True
# 检查默认安装路径
default_paths = [
r"C:\Program Files\wkhtmltopdf\bin\wkhtmltoimage.exe",
r"C:\Program Files (x86)\wkhtmltopdf\bin\wkhtmltoimage.exe",
]
for p in default_paths:
if os.path.exists(p):
return True
return False
def check_playwright_chromium() -> bool:
"""检测 Playwright Chromium 浏览器是否已安装"""
local_appdata = os.environ.get("LOCALAPPDATA", "")
if not local_appdata:
return False
chromium_path = Path(local_appdata) / "ms-playwright" / CHROMIUM_VERSION_DIR
# 检查目录是否存在且包含chrome.exe
if chromium_path.exists():
chrome_exe = chromium_path / "chrome-win" / "chrome.exe"
if chrome_exe.exists():
return True
return False
def get_missing_dependencies() -> Dict[str, bool]:
"""获取缺失的依赖列表"""
return {
"wkhtmltoimage": not check_wkhtmltoimage(),
"chromium": not check_playwright_chromium(),
}
def download_file(url: str, dest_path: str, progress_callback: Optional[Callable] = None) -> bool:
"""
下载文件
Args:
url: 下载地址
dest_path: 保存路径
progress_callback: 进度回调 (downloaded_bytes, total_bytes)
Returns:
是否成功
"""
import urllib.request
try:
def report_progress(block_num, block_size, total_size):
if progress_callback:
downloaded = block_num * block_size
progress_callback(downloaded, total_size)
urllib.request.urlretrieve(url, dest_path, reporthook=report_progress)
return True
except Exception as e:
print(f"下载失败: {e}")
return False
def install_wkhtmltopdf(installer_path: str, log_callback: Optional[Callable] = None) -> bool:
"""
安装 wkhtmltopdf
Args:
installer_path: 安装包路径
log_callback: 日志回调
Returns:
是否成功
"""
def log(msg):
if log_callback:
log_callback(msg)
try:
log("正在启动 wkhtmltopdf 安装程序...")
# 启动安装程序(需要用户手动完成安装向导)
subprocess.Popen([installer_path], shell=True)
log("请在安装向导中完成安装(建议保持默认路径)")
return True
except Exception as e:
log(f"启动安装程序失败: {e}")
return False
def install_playwright_chromium(zip_path: str, log_callback: Optional[Callable] = None) -> bool:
"""
安装 Playwright Chromium 浏览器
Args:
zip_path: zip包路径
log_callback: 日志回调
Returns:
是否成功
"""
def log(msg):
if log_callback:
log_callback(msg)
try:
local_appdata = os.environ.get("LOCALAPPDATA", "")
if not local_appdata:
log("无法获取 LOCALAPPDATA 路径")
return False
# 目标目录
playwright_dir = Path(local_appdata) / "ms-playwright"
chromium_dir = playwright_dir / CHROMIUM_VERSION_DIR
# 创建目录
playwright_dir.mkdir(parents=True, exist_ok=True)
log("正在解压 Chromium 浏览器...")
# 解压
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
zip_ref.extractall(chromium_dir)
# 创建标记文件Playwright需要这些文件来确认安装完成
(chromium_dir / "INSTALLATION_COMPLETE").touch()
(chromium_dir / "DEPENDENCIES_VALIDATED").touch()
log("Chromium 浏览器安装成功")
return True
except Exception as e:
log(f"安装 Chromium 失败: {e}")
return False
def download_and_install_dependency(
dep_name: str,
progress_callback: Optional[Callable] = None,
log_callback: Optional[Callable] = None
) -> Tuple[bool, str]:
"""
下载并安装指定依赖
Args:
dep_name: 依赖名称 ("wkhtmltoimage""chromium")
progress_callback: 下载进度回调
log_callback: 日志回调
Returns:
(是否成功, 错误信息)
"""
def log(msg):
if log_callback:
log_callback(msg)
# 获取下载地址
if dep_name == "wkhtmltoimage":
url = DOWNLOAD_URLS["wkhtmltopdf"]
filename = "wkhtmltox_installer.exe"
elif dep_name == "chromium":
url = DOWNLOAD_URLS["chromium"]
filename = "chromium-win64.zip"
else:
return False, f"未知依赖: {dep_name}"
# 下载到临时目录
temp_dir = tempfile.gettempdir()
download_path = os.path.join(temp_dir, filename)
log(f"正在下载 {dep_name}...")
if not download_file(url, download_path, progress_callback):
return False, "下载失败"
log("下载完成,正在安装...")
# 安装
if dep_name == "wkhtmltoimage":
success = install_wkhtmltopdf(download_path, log_callback)
if success:
return True, "安装程序已启动,请完成安装向导"
else:
return False, "启动安装程序失败"
elif dep_name == "chromium":
success = install_playwright_chromium(download_path, log_callback)
# 清理下载的zip文件
try:
os.remove(download_path)
except:
pass
if success:
return True, ""
else:
return False, "安装失败"
return False, "未知错误"