- 新增依赖检测模块:启动时自动检测wkhtmltoimage和Playwright Chromium - 新增依赖安装对话框:缺失时提示用户一键下载安装 - 修复选项记忆功能:浏览类型、自动截图、自动上传选项现在会保存 - 优化KDocs登录检测:未登录时自动切换到金山文档页面并显示二维码 - 简化日志输出:移除debug信息,保留用户友好的状态提示 - 新增账号变化信号:账号管理页面的修改会自动同步到浏览任务页面 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
257 lines
8.6 KiB
Python
257 lines
8.6 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
主窗口
|
||
侧边栏导航 + 主内容区 + 日志输出区
|
||
"""
|
||
|
||
from PyQt6.QtWidgets import (
|
||
QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
||
QPushButton, QStackedWidget, QFrame, QLabel, QSplitter
|
||
)
|
||
from PyQt6.QtCore import Qt, QTimer
|
||
|
||
from .styles import get_stylesheet, LIGHT_THEME, DARK_THEME
|
||
from .log_widget import LogWidget
|
||
from .account_widget import AccountWidget
|
||
from .browse_widget import BrowseWidget
|
||
from .screenshot_widget import ScreenshotWidget
|
||
from .kdocs_widget import KDocsWidget
|
||
from .settings_widget import SettingsWidget
|
||
|
||
|
||
class MainWindow(QMainWindow):
|
||
"""主窗口"""
|
||
|
||
def __init__(self):
|
||
super().__init__()
|
||
self.setWindowTitle("知识管理平台助手 - 精简版")
|
||
self.setMinimumSize(1000, 700)
|
||
self.resize(1200, 800)
|
||
|
||
self._current_theme = "light"
|
||
self._setup_ui()
|
||
self._apply_theme("light")
|
||
|
||
def _setup_ui(self):
|
||
"""设置UI布局"""
|
||
central_widget = QWidget()
|
||
self.setCentralWidget(central_widget)
|
||
|
||
main_layout = QHBoxLayout(central_widget)
|
||
main_layout.setContentsMargins(0, 0, 0, 0)
|
||
main_layout.setSpacing(0)
|
||
|
||
# 侧边栏
|
||
sidebar = self._create_sidebar()
|
||
main_layout.addWidget(sidebar)
|
||
|
||
# 右侧区域(内容 + 日志)
|
||
right_widget = QWidget()
|
||
right_layout = QVBoxLayout(right_widget)
|
||
right_layout.setContentsMargins(0, 0, 0, 0)
|
||
right_layout.setSpacing(0)
|
||
|
||
# 使用分割器可以调整日志区域大小
|
||
splitter = QSplitter(Qt.Orientation.Vertical)
|
||
|
||
# 主内容区
|
||
self.content_stack = QStackedWidget()
|
||
self._create_pages()
|
||
splitter.addWidget(self.content_stack)
|
||
|
||
# 日志区域
|
||
self.log_widget = LogWidget()
|
||
splitter.addWidget(self.log_widget)
|
||
|
||
# 设置初始比例
|
||
splitter.setSizes([600, 150])
|
||
|
||
right_layout.addWidget(splitter)
|
||
main_layout.addWidget(right_widget, 1)
|
||
|
||
# 连接日志信号
|
||
self._connect_log_signals()
|
||
|
||
def _create_sidebar(self) -> QWidget:
|
||
"""创建侧边栏"""
|
||
sidebar = QFrame()
|
||
sidebar.setObjectName("sidebar")
|
||
sidebar.setFixedWidth(180)
|
||
|
||
layout = QVBoxLayout(sidebar)
|
||
layout.setContentsMargins(0, 0, 0, 0)
|
||
layout.setSpacing(0)
|
||
|
||
# 标题
|
||
title = QLabel("📋 知识管理助手")
|
||
title.setObjectName("sidebar_title")
|
||
title.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||
layout.addWidget(title)
|
||
|
||
# 分隔线
|
||
line = QFrame()
|
||
line.setFrameShape(QFrame.Shape.HLine)
|
||
line.setStyleSheet("background-color: rgba(255,255,255,0.1);")
|
||
layout.addWidget(line)
|
||
|
||
# 导航按钮
|
||
self._nav_buttons = []
|
||
|
||
nav_items = [
|
||
("📝 账号管理", 0),
|
||
("🔄 浏览任务", 1),
|
||
("📸 截图管理", 2),
|
||
("📤 金山文档", 3),
|
||
("⚙️ 系统设置", 4),
|
||
]
|
||
|
||
for text, index in nav_items:
|
||
btn = QPushButton(text)
|
||
btn.setCheckable(True)
|
||
btn.clicked.connect(lambda checked, idx=index: self._switch_page(idx))
|
||
layout.addWidget(btn)
|
||
self._nav_buttons.append(btn)
|
||
|
||
layout.addStretch()
|
||
|
||
# 版本信息
|
||
version_label = QLabel("v1.0.0")
|
||
version_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||
version_label.setStyleSheet("color: rgba(255,255,255,0.5); font-size: 11px; padding: 8px;")
|
||
layout.addWidget(version_label)
|
||
|
||
# 默认选中第一个
|
||
self._nav_buttons[0].setChecked(True)
|
||
|
||
return sidebar
|
||
|
||
def _create_pages(self):
|
||
"""创建各个页面"""
|
||
# 账号管理
|
||
self.account_widget = AccountWidget()
|
||
self.content_stack.addWidget(self.account_widget)
|
||
|
||
# 浏览任务
|
||
self.browse_widget = BrowseWidget()
|
||
self.content_stack.addWidget(self.browse_widget)
|
||
|
||
# 截图管理
|
||
self.screenshot_widget = ScreenshotWidget()
|
||
self.content_stack.addWidget(self.screenshot_widget)
|
||
|
||
# 金山文档
|
||
self.kdocs_widget = KDocsWidget()
|
||
self.content_stack.addWidget(self.kdocs_widget)
|
||
|
||
# 系统设置
|
||
self.settings_widget = SettingsWidget()
|
||
self.settings_widget.theme_changed.connect(self._apply_theme)
|
||
self.content_stack.addWidget(self.settings_widget)
|
||
|
||
def _connect_log_signals(self):
|
||
"""连接各模块的日志信号到日志面板"""
|
||
self.account_widget.log_signal.connect(self.log_widget.append_log)
|
||
self.browse_widget.log_signal.connect(self.log_widget.append_log)
|
||
self.screenshot_widget.log_signal.connect(self.log_widget.append_log)
|
||
self.kdocs_widget.log_signal.connect(self.log_widget.append_log)
|
||
self.settings_widget.log_signal.connect(self.log_widget.append_log)
|
||
|
||
# 账号变化时自动刷新浏览任务页面的账号列表
|
||
self.account_widget.accounts_changed.connect(self.browse_widget._refresh_accounts)
|
||
|
||
def _switch_page(self, index: int):
|
||
"""切换页面"""
|
||
# 更新导航按钮状态
|
||
for i, btn in enumerate(self._nav_buttons):
|
||
btn.setChecked(i == index)
|
||
|
||
# 切换页面
|
||
self.content_stack.setCurrentIndex(index)
|
||
|
||
def _apply_theme(self, theme_name: str):
|
||
"""应用主题"""
|
||
self._current_theme = theme_name
|
||
theme = LIGHT_THEME if theme_name == "light" else DARK_THEME
|
||
self.setStyleSheet(get_stylesheet(theme))
|
||
|
||
def log(self, message: str):
|
||
"""记录日志"""
|
||
self.log_widget.append_log(message)
|
||
|
||
def init_kdocs_login_check(self):
|
||
"""启动时自动检测金山文档登录状态(后台无头模式)"""
|
||
from config import get_config
|
||
config = get_config()
|
||
|
||
# 如果金山文档未启用或未配置链接,直接显示就绪
|
||
if not config.kdocs.enabled or not config.kdocs.doc_url.strip():
|
||
self.log("✅ 环境准备就绪")
|
||
return
|
||
|
||
self.log("🔄 正在检测金山文档登录状态...")
|
||
self._kdocs_init_worker = None
|
||
|
||
# 延迟100ms执行,让UI先显示出来
|
||
QTimer.singleShot(100, self._do_kdocs_login_check)
|
||
|
||
def _do_kdocs_login_check(self):
|
||
"""执行金山文档登录检测"""
|
||
from utils.worker import Worker
|
||
|
||
def check_kdocs_login(_signals=None, _should_stop=None):
|
||
from core.kdocs_uploader import get_kdocs_uploader
|
||
|
||
uploader = get_kdocs_uploader()
|
||
# 静默模式,不输出详细日志
|
||
uploader._log_callback = None
|
||
|
||
result = uploader.request_qr(force=False)
|
||
return result
|
||
|
||
def on_result(result):
|
||
if result and result.get("success"):
|
||
if result.get("logged_in"):
|
||
self.log("✅ 金山文档已登录")
|
||
self.log("✅ 环境准备就绪")
|
||
# 更新金山文档面板状态
|
||
self.kdocs_widget.status_label.setText("✅ 已登录")
|
||
from .constants import get_status_style
|
||
self.kdocs_widget.status_label.setStyleSheet(get_status_style(True))
|
||
else:
|
||
self.log("⚠️ 金山文档未登录,正在获取登录二维码...")
|
||
# 自动切换到金山文档页面并获取二维码
|
||
self._switch_page(3) # 索引3是金山文档页面
|
||
QTimer.singleShot(300, self.kdocs_widget._get_qr_code)
|
||
else:
|
||
error = result.get("error", "未知错误") if result else "检测失败"
|
||
self.log(f"⚠️ 金山文档检测失败: {error}")
|
||
self.log("✅ 环境准备就绪")
|
||
|
||
def on_error(error):
|
||
self.log(f"⚠️ 金山文档检测出错: {error}")
|
||
self.log("✅ 环境准备就绪")
|
||
|
||
self._kdocs_init_worker = Worker(check_kdocs_login)
|
||
self._kdocs_init_worker.signals.result.connect(on_result)
|
||
self._kdocs_init_worker.signals.error.connect(on_error)
|
||
self._kdocs_init_worker.start()
|
||
|
||
def closeEvent(self, event):
|
||
"""窗口关闭事件"""
|
||
# 保存配置
|
||
from config import get_config, save_config
|
||
config = get_config()
|
||
config.theme = self._current_theme
|
||
save_config(config)
|
||
|
||
# 清理金山文档上传器
|
||
try:
|
||
from core.kdocs_uploader import get_kdocs_uploader
|
||
uploader = get_kdocs_uploader()
|
||
uploader.close()
|
||
except Exception:
|
||
pass
|
||
|
||
event.accept()
|