certflow.views.common package¶
Submodules¶
Module contents¶
视图通用层包
集中放置跨视图复用的 UI 基础设施(非具体业务窗体)。 与 ``views/bases``(视图基类契约)的区别:本包提供的是应用级、 被多个 View 共享的「呈现规则」管理器,如主题样式与界面文案国际化。
归属判定:本包内模块均强依赖 PySide6,属 UI 层设施, 不可下沉至 handlers / services 等下层(下层需保持无 Qt 可导入)。
- Exports:
I18nManager: 国际化管理器,提供中/英文界面文案切换 ThemeManager: 主题管理器,提供浅色/深色 QSS 全局切换 safe_qdate: 校验式 QDate 构造,非法参数返回 None parse_qdate: 校验式 QDate 解析,解析失败返回 None
- class certflow.views.common.I18nManager(parent=None)[源代码]¶
基类:
QObject国际化管理器 — 中/英文切换
维护核心 UI 文本的翻译字典,语言切换时发出信号通知各 View 刷新。
- 参数:
parent (QObject | None)
- language_changed¶
语言变更信号,携带新语言代码 (zh_CN / en_US)
- TRANSLATIONS: dict[str, dict[str, str]] = {'-- 没有历史文件,请浏览 --': '-- No history, please browse --', '-- 选择历史文件 --': '-- Select History File --', 'CertFlow - 阀门证书管理系统': 'CertFlow - Valve Certificate Management System', 'English': 'English', 'X 偏移 (向右为正):': 'X Offset (right positive):', 'Y 偏移 (向下为正):': 'Y Offset (down positive):', 'dark (深色)': 'dark (Dark)', 'en_US (English)': 'en_US (English)', 'light (浅色)': 'light (Light)', 'zh_CN (简体中文)': 'zh_CN (Simplified Chinese)', '⚙️ 偏好设置': '⚙️ Preferences', '⚙️ 系统设置': '⚙️ Settings', '✅ 系统就绪': '✅ System Ready', '✓ 是': '✓ Yes', '✗ 否': '✗ No', '个值': ' values', '个子节点': ' sub-nodes', '个字段': ' fields', '个对象': ' objects', '个扫描件': 'scan file(s)', '个文件': 'file(s)', '主题:': 'Theme:', '产品名称': 'Product Name', '产品型号': 'Product Model', '介质': 'Medium', '份...': 'copy/copies...', '份数': 'Copies', '保存失败': 'Save Failed', '保存成功': 'Save Successful', '保存设置': 'Save Settings', '值': 'Value', '值 / 说明': 'Value / Description', '全选': 'Select All', '关闭': 'Close', '分钟': ' min', '切换界面显示语言,保存后立即生效': 'Switch the interface display language, takes effect immediately after saving', '切换界面颜色主题,保存后立即生效。也可点击导航栏右侧的 🌙/☀️ 按钮快速切换': 'Switch the interface color theme, takes effect immediately after saving. You can also click the 🌙/☀️ button on the right side of the navigation bar to quickly toggle', '列映射': 'Column Mapping', '列表': 'List', '刷新': 'Refresh', '剩余': 'remaining', '单张打印': 'Single Print', '压力': 'Pressure', '取消': 'Cancel', '取消全选': 'Deselect All', '变更': 'Changes', '否': 'No', '启用后,系统会定时自动保存打印视图中正在编辑的合格证数据到数据库,防止意外退出丢失记录': 'When enabled, the system periodically auto-saves the certificate data being edited in the print view to the database, preventing data loss on unexpected exit', '启用自动保存': 'Enable Auto Save', '字段': 'Field', '导入': 'Import', '导入中...': 'Importing...', '导入完成': 'Import Completed', '导入对话框中「最近文件」列表的最大保留条数,超出后自动裁剪': "Maximum number of entries kept in the 'Recent Files' list in the import dialog, older entries are trimmed automatically", '导入数据前弹出确认对话框,防止误操作覆盖已有销售计划记录': 'Show a confirmation dialog before importing data to prevent accidentally overwriting existing sales plan records', '导入配置': 'Import Configuration', '导出': 'Export', '就绪': 'Ready', '工作表': 'Worksheet', '已加载': 'Loaded', '已发送第一张打印': 'First print sent', '已完成': 'Completed', '已生成': 'Generated', '常规': 'Regular', '张': 'cards', '张合格证打印,是否生成扫描件?': 'certificate(s) printed. Generate scans?', '张,是否继续?': 'cards, continue?', '总记录': 'Total Records', '恢复默认': 'Restore Defaults', '手动输入': 'Manual Input', '打印历史': 'Print History', '打印合格证': 'Print Certificates', '打印坐标:': 'Print Coordinates:', '打印失败': 'Print Failed', '打印字体:': 'Print Font:', '打印完成': 'Print Completed', '打印机': 'Printer', '打印选中': 'Print Selected', '扫描件生成': 'Scan Generation', '扫描件生成完成!\n共': 'Scan generation completed!\nTotal', '批量参数:': 'Batch Parameters:', '批量打印': 'Batch Print', '批量打印完成,共': 'Batch print completed, total', '批量打印已取消': 'Batch print cancelled', '报告生成': 'Report Generation', '报告类型': 'Report Type', '提示': 'Notice', '搜索': 'Search', '操作符': 'Operator', '数据起始行': 'Data Start Row', '新增': 'New', '无可打印的编号': 'No serial numbers to print', '是': 'Yes', '最大保留数量:': 'Max Recent Files:', '最近文件': 'Recent Files', '材质报告': 'Material Report', '条记录': 'record(s)', '查询': 'Query', '检验标准': 'Inspection Standard', '模板': 'Template', '正在打印': 'Printing', '浏览...': 'Browse...', '添加条件': 'Add Condition', '清除历史': 'Clear History', '清除条件': 'Clear Conditions', '温度': 'Temperature', '生成': 'Generate', '生成 PDF': 'Generate PDF', '生成完成': 'Generation Completed', '生成扫描件': 'Generate Scans', '生成报告': 'Generate Reports', '界面': 'Interface', '确定': 'OK', '确定要将所有设置恢复为默认值吗?\n此操作不会保存,需点击「保存设置」生效。': "Are you sure you want to restore all settings to defaults?\nThis will not save automatically, click 'Save Settings' to apply.", '确认': 'Confirm', '确认恢复': 'Confirm Restore', '确认批量打印': 'Confirm Batch Print', '空列表': 'empty list', '空字符串': 'empty string', '简体中文': 'Simplified Chinese', '粗体': 'Bold', '系统级打印配置 (来自 config.yaml,只读)': 'System Print Config (from config.yaml, read-only)', '系统设置': 'Settings', '纸张尺寸:': 'Paper Size:', '结束编号': 'End Serial', '编号模式': 'Serial Number Mode', '自动保存的时间间隔,仅在「启用自动保存」开启时生效': "Auto-save time interval, only effective when 'Enable Auto Save' is on", '自动保存间隔:': 'Auto Save Interval:', '自动生成': 'Auto Generate', '节点': 'Node', '表头行': 'Header Row', '覆盖前确认': 'Confirm Before Overwrite', '规格': 'Specification', '警告': 'Warning', '设置已保存到 userconfig.yaml': 'Settings saved to userconfig.yaml', '试压报告': 'Pressure Test Report', '语言': 'Language', '语言:': 'Language:', '起始编号': 'Start Serial', '跳过': 'Skipped', '跳过行': 'Skip Rows', '输出目录': 'Output Directory', '进度': 'Progress', '选择文件': 'Select File', '选择目录': 'Select Directory', '通用': 'General', '重复跳过': 'Duplicates Skipped', '重置': 'Reset', '错误': 'Error', '项': ' items', '预览': 'Preview', '高级筛选': 'Advanced Filter', '默认份数:': 'Default Copies:', '默认打印机:': 'Default Printer:', '🏭 CertFlow': '🏭 CertFlow', '📄 报告生成': '📄 Generate Reports', '📋 以下为 config.yaml 全部配置节点的只读展示,修改请直接编辑 config.yaml 文件后重启。': '📋 Read-only view of all config.yaml nodes. Edit the config.yaml file directly and restart to apply changes.', '📋 计划导入': '📋 Import Plans', '📋 配置总览': '📋 Config Overview', '📜 打印历史': '📜 Print History', '📸 扫描件生成': '📸 Generate Scans', '🔍 查询与补充': '🔍 Query & Supplement', '🔧 打印机物理偏移 (mm) — 用户可调,保存到 userconfig.yaml': '🔧 Printer Physical Offset (mm) — adjustable, saved to userconfig.yaml', '🖨 打印合格证': '🖨 Print Certificates', '🖨️ 打印设置': '🖨️ Print Settings'}¶
- staticMetaObject = PySide6.QtCore.QMetaObject("I18nManager" inherits "QObject": Methods: #4 type=Signal, signature=language_changed(QString), parameters=QString )¶
- class certflow.views.common.ThemeManager(app, parent=None)[源代码]¶
基类:
QObject主题管理器 — 浅色/深色主题切换
维护两套完整的 QSS (Qt Style Sheets),通过替换 application-level stylesheet 实现全局主题切换。
- 参数:
app (QApplication)
parent (QObject | None)
- LIGHT_THEME = '\n /* ===== 全局 ===== */\n QMainWindow, QDialog, QWidget {\n background-color: #f5f6fa;\n color: #2c3e50;\n font-family: "Microsoft YaHei", "SimHei", sans-serif;\n }\n\n /* ===== 导航栏 ===== */\n QWidget#navBar {\n background-color: #2c3e50;\n }\n QWidget#navBar QPushButton#navLogo {\n background-color: transparent;\n color: #ecf0f1;\n border: none;\n padding: 8px 16px;\n font-weight: bold;\n font-size: 16px;\n }\n QWidget#navBar QPushButton {\n background-color: transparent;\n color: #ecf0f1;\n border: none;\n padding: 8px 16px;\n font-size: 14px;\n }\n QWidget#navBar QPushButton:hover {\n background-color: #34495e;\n }\n QWidget#navBar QPushButton:checked {\n background-color: #1abc9c;\n color: white;\n }\n QWidget#navBar QPushButton#themeToggleBtn {\n background-color: transparent;\n color: #ecf0f1;\n border: 1px solid #4a6278;\n border-radius: 4px;\n padding: 4px 12px;\n font-size: 16px;\n }\n QWidget#navBar QPushButton#themeToggleBtn:hover {\n background-color: #34495e;\n }\n\n /* ===== 主按钮 ===== */\n QPushButton {\n background-color: #2c7be5;\n color: white;\n border: none;\n padding: 6px 16px;\n border-radius: 4px;\n font-size: 13px;\n }\n QPushButton:hover {\n background-color: #1a68d1;\n }\n QPushButton:pressed {\n background-color: #1557b0;\n }\n QPushButton:disabled {\n background-color: #adb5bd;\n color: #6c757d;\n }\n\n /* ===== 次要按钮 ===== */\n QPushButton[secondary="true"] {\n background-color: #6c757d;\n color: white;\n }\n QPushButton[secondary="true"]:hover {\n background-color: #5a6268;\n }\n\n /* ===== 成功按钮 ===== */\n QPushButton[success="true"] {\n background-color: #28a745;\n color: white;\n }\n QPushButton[success="true"]:hover {\n background-color: #218838;\n }\n\n /* ===== 输入框 ===== */\n QLineEdit, QSpinBox, QDoubleSpinBox, QComboBox, QDateEdit {\n background-color: white;\n color: #2c3e50;\n border: 1px solid #ced4da;\n border-radius: 4px;\n padding: 4px 8px;\n font-size: 13px;\n }\n QLineEdit:focus, QSpinBox:focus, QDoubleSpinBox:focus, QComboBox:focus {\n border-color: #2c7be5;\n }\n QComboBox::drop-down {\n border: none;\n padding-right: 8px;\n }\n QComboBox QAbstractItemView {\n background-color: white;\n color: #2c3e50;\n selection-background-color: #2c7be5;\n selection-color: white;\n }\n\n /* ===== 表格 ===== */\n QTableWidget, QTableView {\n background-color: white;\n alternate-background-color: #f8f9fa;\n color: #2c3e50;\n gridline-color: #dee2e6;\n border: 1px solid #dee2e6;\n font-size: 13px;\n selection-background-color: #cce5ff;\n selection-color: #2c3e50;\n }\n QHeaderView::section {\n background-color: #e9ecef;\n color: #495057;\n padding: 6px;\n border: 1px solid #dee2e6;\n font-weight: bold;\n }\n\n /* ===== 分组框 ===== */\n QGroupBox {\n border: 1px solid #dee2e6;\n border-radius: 6px;\n margin-top: 8px;\n padding-top: 16px;\n font-weight: bold;\n color: #495057;\n }\n QGroupBox::title {\n subcontrol-origin: margin;\n left: 12px;\n padding: 0 6px;\n }\n\n /* ===== 标签页 ===== */\n QTabWidget::pane {\n border: 1px solid #dee2e6;\n background-color: white;\n }\n QTabBar::tab {\n background-color: #e9ecef;\n color: #495057;\n padding: 8px 20px;\n border: 1px solid #dee2e6;\n border-bottom: none;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n }\n QTabBar::tab:selected {\n background-color: white;\n color: #2c7be5;\n font-weight: bold;\n }\n QTabBar::tab:hover:!selected {\n background-color: #dee2e6;\n }\n\n /* ===== 滚动条 ===== */\n QScrollBar:vertical {\n background: #f5f6fa;\n width: 10px;\n border-radius: 5px;\n }\n QScrollBar::handle:vertical {\n background: #ced4da;\n border-radius: 5px;\n min-height: 20px;\n }\n QScrollBar::handle:vertical:hover {\n background: #adb5bd;\n }\n QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {\n height: 0;\n }\n\n /* ===== 复选框/单选框 ===== */\n QCheckBox, QRadioButton {\n color: #2c3e50;\n spacing: 6px;\n }\n QCheckBox::indicator {\n width: 16px;\n height: 16px;\n }\n\n /* ===== 标签 ===== */\n QLabel {\n color: #2c3e50;\n }\n\n /* ===== 进度条 ===== */\n QProgressBar {\n background-color: #e9ecef;\n border: none;\n border-radius: 4px;\n height: 8px;\n text-align: center;\n }\n QProgressBar::chunk {\n background-color: #2c7be5;\n border-radius: 4px;\n }\n\n /* ===== 树形控件 ===== */\n QTreeWidget {\n background-color: white;\n alternate-background-color: #f8f9fa;\n color: #2c3e50;\n border: 1px solid #dee2e6;\n }\n QTreeWidget::item:selected {\n background-color: #cce5ff;\n color: #2c3e50;\n }\n\n /* ===== 状态栏 ===== */\n QStatusBar {\n background-color: #e9ecef;\n color: #6c757d;\n }\n '¶
- DARK_THEME = '\n /* ===== 全局 ===== */\n QMainWindow, QDialog, QWidget {\n background-color: #1e1e2e;\n color: #cdd6f4;\n font-family: "Microsoft YaHei", "SimHei", sans-serif;\n }\n\n /* ===== 导航栏 ===== */\n QWidget#navBar {\n background-color: #11111b;\n }\n QWidget#navBar QPushButton#navLogo {\n background-color: transparent;\n color: #bac2de;\n border: none;\n padding: 8px 16px;\n font-weight: bold;\n font-size: 16px;\n }\n QWidget#navBar QPushButton {\n background-color: transparent;\n color: #bac2de;\n border: none;\n padding: 8px 16px;\n font-size: 14px;\n }\n QWidget#navBar QPushButton:hover {\n background-color: #313244;\n }\n QWidget#navBar QPushButton:checked {\n background-color: #89b4fa;\n color: #1e1e2e;\n }\n QWidget#navBar QPushButton#themeToggleBtn {\n background-color: transparent;\n color: #bac2de;\n border: 1px solid #45475a;\n border-radius: 4px;\n padding: 4px 12px;\n font-size: 16px;\n }\n QWidget#navBar QPushButton#themeToggleBtn:hover {\n background-color: #313244;\n }\n\n /* ===== 主按钮 ===== */\n QPushButton {\n background-color: #89b4fa;\n color: #1e1e2e;\n border: none;\n padding: 6px 16px;\n border-radius: 4px;\n font-size: 13px;\n }\n QPushButton:hover {\n background-color: #74a8f7;\n }\n QPushButton:pressed {\n background-color: #5e9cf5;\n }\n QPushButton:disabled {\n background-color: #45475a;\n color: #6c7086;\n }\n\n /* ===== 次要按钮 ===== */\n QPushButton[secondary="true"] {\n background-color: #585b70;\n color: #cdd6f4;\n }\n QPushButton[secondary="true"]:hover {\n background-color: #6c7086;\n }\n\n /* ===== 成功按钮 ===== */\n QPushButton[success="true"] {\n background-color: #a6e3a1;\n color: #1e1e2e;\n }\n QPushButton[success="true"]:hover {\n background-color: #94e2d5;\n }\n\n /* ===== 输入框 ===== */\n QLineEdit, QSpinBox, QDoubleSpinBox, QComboBox, QDateEdit {\n background-color: #313244;\n color: #cdd6f4;\n border: 1px solid #45475a;\n border-radius: 4px;\n padding: 4px 8px;\n font-size: 13px;\n }\n QLineEdit:focus, QSpinBox:focus, QDoubleSpinBox:focus, QComboBox:focus {\n border-color: #89b4fa;\n }\n QComboBox::drop-down {\n border: none;\n padding-right: 8px;\n }\n QComboBox QAbstractItemView {\n background-color: #313244;\n color: #cdd6f4;\n selection-background-color: #89b4fa;\n selection-color: #1e1e2e;\n }\n\n /* ===== 表格 ===== */\n QTableWidget, QTableView {\n background-color: #1e1e2e;\n alternate-background-color: #313244;\n color: #cdd6f4;\n gridline-color: #45475a;\n border: 1px solid #45475a;\n font-size: 13px;\n selection-background-color: #45475a;\n selection-color: #cdd6f4;\n }\n QHeaderView::section {\n background-color: #313244;\n color: #bac2de;\n padding: 6px;\n border: 1px solid #45475a;\n font-weight: bold;\n }\n\n /* ===== 分组框 ===== */\n QGroupBox {\n border: 1px solid #45475a;\n border-radius: 6px;\n margin-top: 8px;\n padding-top: 16px;\n font-weight: bold;\n color: #bac2de;\n }\n QGroupBox::title {\n subcontrol-origin: margin;\n left: 12px;\n padding: 0 6px;\n }\n\n /* ===== 标签页 ===== */\n QTabWidget::pane {\n border: 1px solid #45475a;\n background-color: #1e1e2e;\n }\n QTabBar::tab {\n background-color: #313244;\n color: #6c7086;\n padding: 8px 20px;\n border: 1px solid #45475a;\n border-bottom: none;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n }\n QTabBar::tab:selected {\n background-color: #1e1e2e;\n color: #89b4fa;\n font-weight: bold;\n }\n QTabBar::tab:hover:!selected {\n background-color: #45475a;\n }\n\n /* ===== 滚动条 ===== */\n QScrollBar:vertical {\n background: #1e1e2e;\n width: 10px;\n border-radius: 5px;\n }\n QScrollBar::handle:vertical {\n background: #45475a;\n border-radius: 5px;\n min-height: 20px;\n }\n QScrollBar::handle:vertical:hover {\n background: #585b70;\n }\n QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {\n height: 0;\n }\n\n /* ===== 复选框/单选框 ===== */\n QCheckBox, QRadioButton {\n color: #cdd6f4;\n spacing: 6px;\n }\n QCheckBox::indicator {\n width: 16px;\n height: 16px;\n }\n\n /* ===== 标签 ===== */\n QLabel {\n color: #cdd6f4;\n }\n\n /* ===== 进度条 ===== */\n QProgressBar {\n background-color: #313244;\n border: none;\n border-radius: 4px;\n height: 8px;\n text-align: center;\n }\n QProgressBar::chunk {\n background-color: #89b4fa;\n border-radius: 4px;\n }\n\n /* ===== 树形控件 ===== */\n QTreeWidget {\n background-color: #1e1e2e;\n alternate-background-color: #313244;\n color: #cdd6f4;\n border: 1px solid #45475a;\n }\n QTreeWidget::item:selected {\n background-color: #45475a;\n color: #cdd6f4;\n }\n\n /* ===== 状态栏 ===== */\n QStatusBar {\n background-color: #313244;\n color: #6c7086;\n }\n '¶
- apply_theme(theme)[源代码]¶
应用指定主题
- 参数:
theme (str) -- 主题名称,可选 "light" 或 "dark"
- 返回:
切换成功时更新 _current_theme 并替换全局样式表
- 返回类型:
None
- staticMetaObject = PySide6.QtCore.QMetaObject("ThemeManager" inherits "QObject": )¶
- certflow.views.common.parse_qdate(text, fmt='yyyy-MM-dd')[源代码]¶
用指定格式解析日期字符串为 QDate,失败时返回 None
QDate.fromString() 解析失败时会返回无效 QDate(setDate 后显示 1752-09-14),这里显式校验 isValid() 后再返回。