feat: persist template/batch-mode, per-aspect resets, de-dup template actions

§17.1 Preferences persistence:
- Wire the previously-unused config_service; remember and restore the
  last-selected template and last batch mode. main_window loads config,
  distributes initial values, then persists on change (save-on-change).
- template_panel: template_changed signal, select_template,
  current_template_state. queue_panel: set_batch_mode + batch_mode_changed.

§17.2 Independent resets:
- Replace the combined reset and 归零 with per-section 位置/尺寸/旋转 reset
  buttons (quiet ghost styling) that restore only their own aspect to the
  selected template. Size reset changes width/height only, leaving X/Y.

Button de-dup:
- Remove the export panel's 应用为模板 / 重置为模板 — literal duplicates of
  the template panel's 另存为 / 重置为模板. Template actions now live only
  in the template area; the export panel handles output only.

Docs: PRD (6.6/6.9/9/10), architecture (4.12), UI design (7.x/10),
development-rules (6, single-home actions + consistent naming), tasks.md (17).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-16 17:01:58 +08:00
co-authored by Claude Opus 4.8
parent 69a6dc892a
commit f767ec2660
11 changed files with 300 additions and 115 deletions
+2 -33
View File
@@ -2,7 +2,7 @@ import logging
from pathlib import Path
from typing import Optional
from PySide6.QtCore import Qt, Signal
from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
QComboBox,
QFileDialog,
@@ -24,10 +24,7 @@ logger = logging.getLogger(__name__)
class ExportPanel(QWidget):
"""Right-panel section: output settings and export / template actions."""
apply_as_template = Signal() # "应用为模板" clicked
reset_to_template = Signal() # "重置为模板" clicked
"""Right-panel section: output settings and single-image export."""
def __init__(self, parent=None):
super().__init__(parent)
@@ -58,7 +55,6 @@ class ExportPanel(QWidget):
body_col.addLayout(self._make_format_form())
body_col.addWidget(self._make_hint_label())
body_col.addWidget(self._make_export_btn())
body_col.addLayout(self._make_secondary_btns())
col.addWidget(body)
@@ -116,24 +112,6 @@ class ExportPanel(QWidget):
self._export_btn.clicked.connect(self._do_export)
return self._export_btn
def _make_secondary_btns(self) -> QHBoxLayout:
row = QHBoxLayout()
row.setSpacing(6)
apply_btn = QPushButton("应用为模板")
apply_btn.setObjectName("exportSecBtn")
apply_btn.setToolTip("将当前印花参数另存为新模板")
apply_btn.clicked.connect(lambda: self.apply_as_template.emit())
reset_btn = QPushButton("重置为模板")
reset_btn.setObjectName("exportSecBtn")
reset_btn.setToolTip("将印花参数还原为所选模板的默认值")
reset_btn.clicked.connect(lambda: self.reset_to_template.emit())
row.addWidget(apply_btn)
row.addWidget(reset_btn)
return row
# ── public API ───────────────────────────────────────────────────────────
def set_garment(self, path: Optional[str]):
@@ -284,13 +262,4 @@ class ExportPanel(QWidget):
background-color: #c8c8c8;
color: #888888;
}
#exportSecBtn {
font-size: 12px;
padding: 4px 8px;
border: 1px solid #d6d6d6;
border-radius: 3px;
background: #f0f0f0;
}
#exportSecBtn:hover { background: #e0e0e0; }
#exportSecBtn:pressed { background: #d0d0d0; }
""")