project_qml_migration.md 4.31 KB
name: UI 迁移到 PySide6 + QML(QtQuick)
description: 2026-05-09 用户决定从 QWidget+QSS 转 QtQuick/QML,分支 feat/ui-qml-poc
type: project
originSessionId: 21abab40-0d6c-449a-ae72-9ca03205f077

Why:QWidget+QSS 视觉天花板低(layout 压缩 / sizeHint 不更新 / 字号溢出系列坑)。 QML layout 引擎稳定,圆角 / 阴影 / 动效原生支持,跨 Mac+Windows 视觉一致。 Python 业务后端完全不动,只换 UI 层。

分支feat/ui-qml-poc,独立于 master。

目录结构

core/                  业务核心(task #20 从 image_generator.py 拆出)
  paths.py / database.py / history.py / generation.py / jewelry.py
  runtime.py            启动期工具(crash diag / init_logging / cleanup / log_system_info)
bridges/               QML 桥层
  auth.py / imagegen.py / history.py / taskqueue.py / jewelry.py / _icons.py
qml_poc/main_qml.py    主入口(8-phase boot + setContextProperty 注入桥)
qml_poc/qml/           QML 文件
  Theme.qml (Singleton tokens)
  Main.qml / LoginScreen.qml / MainWindow.qml
  ImageGenTab.qml / StyleDesignerTab.qml / HistoryTab.qml
  components/ (PrimaryButton / SecondaryButton / ThemedTextField / ThemedComboBox / Card / CaptionLabel)
image_generator.py.txt  老 QWidget 代码(git mv 改 .txt 不参与执行,保留扒老逻辑用)
task_queue.py / audit_logger.py / preflight.py / config_util.py  保持 master 一致,未改架构

已完成(截至 2026-05-10):

  • :white_check_mark: #11 PoC UI 视觉 / #20 image_generator.py 拆 core/
  • :white_check_mark: #12 桥层(5 QObject contextProperty)/ #13 db 登录 + 记住凭据
  • :white_check_mark: #14 图片生成 tab 完整(核心 / 参考图 / 收藏 / 下载 / Ctrl+V / 14 比例 + 自动切模式 / 多任务 / 拖拽重排 DragHandler Finder 风格 / 跟手 ghost / 10MB 校验 / 编号 badge)
  • :white_check_mark: #16 历史 tab(ListView + 详情面板 + 右键菜单 / 清空 / 复制 prompt / 在文件管理器中显示选中 / :repeat: 重做按钮回填到生成 tab 不带生成图)
  • :white_check_mark: #17 任务队列 sidebar(taskQueue.model 增量 / 状态彩色 / 进度条 / 左键回填 loadTask / 右键 Menu 取消任务)
  • :white_check_mark: #15 款式设计 tab(8 字段 + 锁定 + 随机 + 字段右键恢复单类别默认 + 顶部全部恢复 + inline :heavy_plus_sign:/:wastebasket:️ 词条 + 实时 Prompt 预览)
  • :white_check_mark: 启动 8-phase boot:crash diag → RotatingFileHandler logs/app.log → 系统信息 → cleanup_clipboard_tempfiles → preflight → 窗口图标 → 桥层 → QML
  • :white_check_mark: 完整 logtrace:bridges/* + core/* 所有 except 用 logger.exception(...)
  • :white_check_mark: 剪贴板三层 fallback + macOS osascript 兜底(避免 Qt clipboard native crash)
  • :white_check_mark: 输入框右键菜单(剪切/复制/粘贴/全选,密码框禁复制剪切)
  • :white_check_mark: #21 修右键粘贴(TextField MouseArea 替代 TapHandler)+ 8px ScrollBar + 参考图双击 TapHandler.onDoubleTapped 系统查看器
  • :white_check_mark: #22 日志分级 fsync:TieredFsyncHandler(WARNING+ 同步 fsync / INFO buffered)
    • 1s 周期 daemon 线程兜底 + macOS DiagnosticReports 提示写入 crash_log.txt
  • :white_check_mark: #19 Windows 打包:ZB100ImageGenerator.spec 切 qml_poc/main_qml.py 入口, pathex=项目根,datas qml_poc/qml→MEIPASS/qml(不带 qml_poc/ 前缀! PyInstaller 把入口平铺到 _MEIPASS 根,Path(file_).parent/"qml" 找 _MEIPASS/qml) 本地 dist/ZB100ImageGenerator/ZB100ImageGenerator.exe 验证 8 phases 全过

剩余待办

  • #19 Mac build_mac_universal.sh 真机验证(含 .app + .dmg + Pillow .dylibs)
  • #19 image_generator.py.txt 真正删除(用户要求暂留作扒老逻辑参考;确认稳定后再删)
  • #18 系统暗色模式跟随(Theme.qml 加深色 token + Qt.styleHints.colorScheme 监听)
  • 款式设计批量词库管理对话框(旧版有,新版只有 inline :heavy_plus_sign:/:wastebasket:️)
  • 双击大图内嵌 viewer(当前 Qt.openUrlExternally 系统查看器替代,等价但 UX 不同)

How to apply

  • 业务代码改在 core/* + task_queue.py + audit_logger.py
  • UI 改在 qml_poc/qml/*;桥层 API 形状见 reference_bridges.md
  • 老逻辑参考 image_generator.py.txt(已重命名不参与执行)
  • 完整启动序列、logtrace 在 main_qml.py + core/runtime.py
  • 用户偏好:先做 #19 打包能交付给同事;#18 暗色等留以后单独迭代