Files
zsglpt-pc/config.py
237899745 83fef6dff2 feat: 知识管理平台精简版 - PyQt6桌面应用
主要功能:
- 账号管理:添加/编辑/删除账号,测试登录
- 浏览任务:批量浏览应读/选读内容并标记已读
- 截图管理:wkhtmltoimage截图,查看历史
- 金山文档:扫码登录/微信快捷登录,自动上传截图

技术栈:
- PyQt6 GUI框架
- Playwright 浏览器自动化
- SQLite 本地数据存储
- wkhtmltoimage 网页截图

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 22:16:36 +08:00

229 lines
7.1 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.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
配置管理模块 - 精简版
使用JSON本地存储不搞数据库那些花里胡哨的东西
"""
import os
from dataclasses import dataclass, field
from typing import List, Optional
from pathlib import Path
# 项目根目录
BASE_DIR = Path(__file__).parent.absolute()
DATA_DIR = BASE_DIR / "data"
COOKIES_DIR = DATA_DIR / "cookies"
SCREENSHOTS_DIR = DATA_DIR / "screenshots"
# 确保目录存在
DATA_DIR.mkdir(exist_ok=True)
COOKIES_DIR.mkdir(exist_ok=True)
SCREENSHOTS_DIR.mkdir(exist_ok=True)
# 配置文件路径
CONFIG_FILE = DATA_DIR / "config.json"
ENCRYPTION_KEY_FILE = DATA_DIR / "encryption_key.bin"
ENCRYPTION_SALT_FILE = DATA_DIR / "encryption_salt.bin"
KDOCS_LOGIN_STATE_FILE = DATA_DIR / "kdocs_login_state.json"
@dataclass
class AccountConfig:
"""账号配置"""
username: str
password: str # 加密存储
remark: str = ""
enabled: bool = True
@dataclass
class KDocsConfig:
"""金山文档配置"""
enabled: bool = False
doc_url: str = "https://kdocs.cn/l/cpwEOo5ynKX4"
sheet_name: str = "Sheet1"
sheet_index: int = 0
unit_column: str = "A"
image_column: str = "D"
unit: str = "" # 县区名
name_column: str = "C" # 姓名列
row_start: int = 0 # 有效行起始0表示不限制
row_end: int = 0 # 有效行结束0表示不限制
@dataclass
class ScreenshotConfig:
"""截图配置"""
dir: str = str(SCREENSHOTS_DIR)
quality: int = 95
width: int = 1920
height: int = 1080
js_delay_ms: int = 3000
timeout_seconds: int = 60
wkhtmltoimage_path: str = "" # 自定义路径,空则自动查找
@dataclass
class ProxyConfig:
"""代理配置"""
enabled: bool = False
server: str = "" # http://host:port
@dataclass
class ZSGLConfig:
"""知识管理平台配置"""
base_url: str = "https://postoa.aidunsoft.com"
login_url: str = "https://postoa.aidunsoft.com/admin/login.aspx"
index_url_pattern: str = "index.aspx"
@dataclass
class AppConfig:
"""应用总配置"""
accounts: List[AccountConfig] = field(default_factory=list)
kdocs: KDocsConfig = field(default_factory=KDocsConfig)
screenshot: ScreenshotConfig = field(default_factory=ScreenshotConfig)
proxy: ProxyConfig = field(default_factory=ProxyConfig)
zsgl: ZSGLConfig = field(default_factory=ZSGLConfig)
theme: str = "light" # light/dark
def to_dict(self) -> dict:
"""转换为字典"""
return {
"accounts": [
{
"username": a.username,
"password": a.password,
"remark": a.remark,
"enabled": a.enabled
} for a in self.accounts
],
"kdocs": {
"enabled": self.kdocs.enabled,
"doc_url": self.kdocs.doc_url,
"sheet_name": self.kdocs.sheet_name,
"sheet_index": self.kdocs.sheet_index,
"unit_column": self.kdocs.unit_column,
"image_column": self.kdocs.image_column,
"unit": self.kdocs.unit,
"name_column": self.kdocs.name_column,
"row_start": self.kdocs.row_start,
"row_end": self.kdocs.row_end,
},
"screenshot": {
"dir": self.screenshot.dir,
"quality": self.screenshot.quality,
"width": self.screenshot.width,
"height": self.screenshot.height,
"js_delay_ms": self.screenshot.js_delay_ms,
"timeout_seconds": self.screenshot.timeout_seconds,
"wkhtmltoimage_path": self.screenshot.wkhtmltoimage_path,
},
"proxy": {
"enabled": self.proxy.enabled,
"server": self.proxy.server,
},
"zsgl": {
"base_url": self.zsgl.base_url,
"login_url": self.zsgl.login_url,
"index_url_pattern": self.zsgl.index_url_pattern,
},
"theme": self.theme,
}
@classmethod
def from_dict(cls, data: dict) -> "AppConfig":
"""从字典创建配置"""
config = cls()
# 加载账号
accounts_data = data.get("accounts", [])
config.accounts = [
AccountConfig(
username=a.get("username", ""),
password=a.get("password", ""),
remark=a.get("remark", ""),
enabled=a.get("enabled", True)
) for a in accounts_data
]
# 加载金山文档配置
kdocs_data = data.get("kdocs", {})
config.kdocs = KDocsConfig(
enabled=kdocs_data.get("enabled", False),
doc_url=kdocs_data.get("doc_url", "https://kdocs.cn/l/cpwEOo5ynKX4"),
sheet_name=kdocs_data.get("sheet_name", "Sheet1"),
sheet_index=kdocs_data.get("sheet_index", 0),
unit_column=kdocs_data.get("unit_column", "A"),
image_column=kdocs_data.get("image_column", "D"),
unit=kdocs_data.get("unit", ""),
name_column=kdocs_data.get("name_column", "C"),
row_start=kdocs_data.get("row_start", 0),
row_end=kdocs_data.get("row_end", 0),
)
# 加载截图配置
screenshot_data = data.get("screenshot", {})
config.screenshot = ScreenshotConfig(
dir=screenshot_data.get("dir", str(SCREENSHOTS_DIR)),
quality=screenshot_data.get("quality", 95),
width=screenshot_data.get("width", 1920),
height=screenshot_data.get("height", 1080),
js_delay_ms=screenshot_data.get("js_delay_ms", 3000),
timeout_seconds=screenshot_data.get("timeout_seconds", 60),
wkhtmltoimage_path=screenshot_data.get("wkhtmltoimage_path", ""),
)
# 加载代理配置
proxy_data = data.get("proxy", {})
config.proxy = ProxyConfig(
enabled=proxy_data.get("enabled", False),
server=proxy_data.get("server", ""),
)
# 加载知识管理平台配置
zsgl_data = data.get("zsgl", {})
config.zsgl = ZSGLConfig(
base_url=zsgl_data.get("base_url", "https://postoa.aidunsoft.com"),
login_url=zsgl_data.get("login_url", "https://postoa.aidunsoft.com/admin/login.aspx"),
index_url_pattern=zsgl_data.get("index_url_pattern", "index.aspx"),
)
# 主题
config.theme = data.get("theme", "light")
return config
# 全局配置实例
_config: Optional[AppConfig] = None
def get_config() -> AppConfig:
"""获取配置实例(懒加载)"""
global _config
if _config is None:
from utils.storage import load_config
_config = load_config()
return _config
def save_config(config: AppConfig = None):
"""保存配置"""
global _config
if config:
_config = config
if _config:
from utils.storage import save_config as _save
_save(_config)
def reload_config():
"""重新加载配置"""
global _config
from utils.storage import load_config
_config = load_config()
return _config