User switching the 分辨率 or AI 模型 dropdown shows an info-only QMessageBox
(no block, no revert) about the impact: resolution -> per-resolution timeout +
next-run-only; model -> api_type + billing/effect may differ + next-run-only.
Trigger via QComboBox.activated (user-only) so programmatic sets don't pop.
Add §10.2 design + §19.7 task (not yet implemented).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 生成设置 -> 3 cols x 2 rows; AI 模型 dropdown moved under it on the right.
- 数据源/输出 become inline label+path rows; bigger 通用话术 + 最终提示词预览
(preview now shows the appended output requirements). Right column widened
to ~400 (left ~360). Update §10 and re-render ui-ai-outfit.png.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Final prompt = user 话术 + an auto-appended 「批量生成输出要求」block ported
from the old tool (参考解析度 dynamic = resolution setting; 固定 1:1 / 结合标题与
参考图 / 不可跑版 fixed). Simplified wording, always appended, preview must
include it. Add §7.1 design + §19.6 task (not yet implemented).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Template covering all four api_type variants (chat/gemini/images/images_edits).
Copy to ~/.cmbot/config/ai_models.json and fill real values; the real file
(with keys) stays out of git.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Left column content is clipped on the right (looks covered by the center).
Measured offscreen: the left QScrollArea has h-scroll AlwaysOff while its
inner content demands 829px min width vs a ~428px viewport. The driver is the
样本行 QComboBox (minimumSizeHint ~743px from its long '第N行·货号·标题' item),
which inflates the preview group. Documented root cause + fix direction
(constrain combo size policy; left scroll AsNeeded).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Replace the prompt-preview dialog with an inline, live preview pinned at
the bottom of the left column (sample-row dropdown, title substituted).
- Move 生成设置 from the left into the right run column (2-col), so left
becomes a focused 数据源 + 话术 + 预览 authoring column.
- Update §7 (inline preview) and §10 (left/right column contents) + re-render
the mockup.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Prompt offers only {title}; product_id is used for Excel column B and the
output filename (货号.jpg), not for AI generation. Update §7/§10 and the
mockup (remove the 插入货号 chip + {product_id} from the sample prompt).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- New docs/ui-ai-outfit.html + ui-ai-outfit.png: 「2 AI 穿搭」page
mockup, same chrome/palette/components as docs/ui-v1 (blue-only).
- Center = recent-results thumbnail strip (finished outputs only) +
detail table; dropped the live single-image preview to avoid the
concurrent "which row" ambiguity.
- §7: 保存话术 persists template via config_service; 预览最终提示词 is a
button opening a read-only QDialog rendered from a sample row.
- §8: concurrency is Python threads (ThreadPoolExecutor); Qt only
signals back to the main thread to refresh UI; default 1 for API limit.
- §10: three-column layout, results-strip rationale, settings 3-col.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Design for the "2 AI 穿搭" tab: Excel as the (fixed) data source → convert rows
to OutfitTask → garment image + prompt → AI image API → person-wearing-clothes
JPG → write result path back to Excel. Ports the old project's API client /
batch / retry into cmbot's app/core/services layering, reusing config/log/
~/.cmbot/output. Also fixes the 旧ai穿搭项目.md §6 recommendation (keep Excel).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Default output moves from ~/.cmbot/output (buried in the user profile) to a
合并后的图片\ folder next to Launcher.exe — easy to find and not replaced on
update (NOT under app\, which is swapped each update). Falls back to
~/.cmbot/output if the install root is read-only; user can still pick any dir.
docs/10 §4/§5, docs/02 config, docs/07 §7.5; tasks 17.22.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the red-dot-on-the-gear treatment with a low-key blue "发现新版本
vX.Y.Z" label to the left of the ⚙ 配置 button (red reads as error; the text
is clearer and shows the version). docs/07 §4.3, docs/10 §12 and related
wording updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Launcher only applies a staged update + launches (no download at startup);
downloading happens in the app's settings dialog. docs/10 §3/§6/§8/§12/§16/§18
rewritten for the two-phase flow (installer.download_and_stage / apply_staged);
docs/07 §4.3/§4.4 cover the gear dot + "检查并更新" button; tasks 17.21.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Superseded by src/launcher.py (Launcher.exe) + the portable layout from
build.ps1. The PS prototype validated the flow; removed to avoid confusion
with the old %LOCALAPPDATA% installer. docs/10 §16 and tasks 17.19 updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A low-key "⚙ 配置" button at the right end of the flow-tab row (separated by
stretch, not a numbered step) opens a settings dialog to edit update_source /
update_user / update_pass, with a test-connection check. Dialog is pure UI;
main_window owns save_config. docs/07 §3/§4.1/§4.3/§4.4; tasks 17.20.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Launcher is a compiled Python/PyInstaller Launcher.exe (retires update.ps1
and install_local.ps1)
- portable: extract to any writable dir; InstallRoot = Launcher.exe's folder,
no longer tied to %LOCALAPPDATA%
- user data moves to ~/.cmbot (%USERPROFILE%\.cmbot): always writable, per-user,
survives program updates; get_data_dir() three-tier (env -> ~/.cmbot -> dev root)
- writability check now applies to the program dir only; first-run seeds default
templates from app\config into ~/.cmbot
- docs/10 §3/§4/§5/§8/§9/§11/§16 updated; tasks 17.19 added (docs done, code TODO)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
#1 BOM: PowerShell Set-Content -Encoding UTF8 writes a BOM that made the in-app
json.loads silently fail (banner never showed even with an update available).
- update_service: decode manifest with utf-8-sig (HTTP + local)
- build.ps1: write manifest.json without BOM (UTF8Encoding $false)
- tests: +2 covering BOM manifests (HTTP + local)
#2 docs: docs/10 §16 status synced to the implemented app/app.old/version.txt +
SHA-256 model (stages 2/3 done + e2e verified); tasks 17.18 updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
scripts/update.ps1: check manifest, stage+verify the new version, swap it in
alongside the running one (versions\<ver> + current.txt pointer), then launch
with CMBOT_DATA_DIR. Degrades to the local version on any failure; never
overwrites the running version. Rollback = edit current.txt.
Verified against a fake versioned layout: update, idempotent re-run, unreachable
source, no source, corrupt download (marker missing), malformed manifest.
Not yet wired into a real install layout (build.ps1 still ships flat onedir).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Read manifest.json from the configured update_source and show a dismissable
banner when a newer version is available. Notify-only — no install yet.
- services/update_service.py: version compare + check_for_update (pure, tested)
- config: add update_source key (empty = no check)
- main_window: top banner, background-thread check; open folder via os.startfile
(QDesktopServices.openUrl mishandles file:// folder URLs — ShellExecute err 2)
- tests: +15 covering version compare and check_for_update branches
- docs 02/05/10 + tasks 17.16
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- add get_data_dir() with CMBOT_DATA_DIR override, fallback to program dir
- point config/logs/output at the data root; resources stay on program root
- harden config/template writes with parents=True for a deep data root
- add docs/10-lan-update.md (LAN auto-update design); default install root
%LOCALAPPDATA%\CMBot for elevation-free self-update
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Output filename now includes the print: <garment>_<print>.<ext>, e.g.
1_TY030.png (folder grouping unchanged) (§17.12).
- Hide the single-export button (export via the queue) and remove the
orphaned static export hint label (§17.13).
- Fix: selecting a non-fine-tuned queue item now lays the print out per the
selected template (apply_current) instead of load_print's centred default;
still guarded by _loading_queue_item so it isn't marked 已微调 (§17.14).
Docs: PRD 6.6/6.8/9, UI design 7.6/7.7/10/12.4, tasks.md 17.12–17.14.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Auto-preview the first image after a folder loads (both panels), so the
canvas isn't empty (§17.8).
- Group exports as <output_dir>/<timestamp>/<print_stem>/<garment_stem>.<ext>;
one timestamp per export run, shared across the batch (§17.9).
- Remember the last garment/print folders and reopen the picker there;
persisted via config, wired through main_window (§17.10).
- Shrink the 3 box templates further and lower them (chest placement).
- Fix: batch export ignored the chosen format/quality/output dir because the
queue never received ExportOptions. Export panel now emits
export_options_changed → queue.set_export_options (+ initial sync) (§17.11).
Docs: PRD 6.1/6.8/9, architecture 4.12, UI design 5.1, tasks.md 17.8–17.11.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The in-content header strip showed the app name + version, duplicating the
OS window title (setWindowTitle). With the 设置 button already gone it had no
other purpose, so remove it (and its styles / unused _HEADER_HEIGHT). Name and
version stay visible via the OS title bar; the work area gains ~40px.
Docs: UI design 3 (layout) and 4.1 (title bar), tasks.md 17.7.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The 设置 button was a layout placeholder from the initial header build —
never wired to anything, so clicking it did nothing. Remove it (and its
style) rather than leave a dead control; current settings (output
dir/format/quality) are editable inline in the export panel.
Docs: UI design 4.1 records that no settings entry is provided for now.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Template delete: add a 删除 button (reuses template_service.delete_template)
with a confirm dialog; hidden for built-ins like 保存; reloads and re-selects
the first built-in after deletion, persisting the new selection.
- Whole reset: move the template-wide reset out of the template area to the
bottom of the transform panel and rename it to 位置尺寸旋转重置为当前模板, so it
sits with the params it resets, beside the three per-section resets.
- Compact layout: pair X/Y and 宽/高 onto single rows (short labels), and put
the export 格式/质量 selectors on one row. Sync logic unchanged.
Docs: PRD 6.6, UI design 7.1/7.2/7.3/7.4/7.5/10, tasks.md 17.4/17.5/17.6.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
§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>
Switching the preview garment cleared the scene (print lost), and
re-loading a print used the canvas's hard-coded centred default instead
of the selected template.
- template_panel: add apply_current() to re-emit the selected template
for the current garment/print sizes and sync _current_state.
- main_window: remember the current print path, restore it after a
garment switch, and call apply_current() after garment/print changes
so the selected template stays sticky. Fine-tuned items are unaffected.
- Also feed template_applied into export_panel.set_transform to keep the
single-export transform in sync.
Docs: record the sticky-template rule (PRD 6.6).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Material list:
- Switch asset list from one-per-row to a wrapping thumbnail grid
(IconMode cards: thumbnail + corner checkbox + elided name, subfolder
moved to tooltip).
Templates:
- Template.to_transform_state now contains-fits the print inside the
target box by the print's native aspect ratio (no stretch); falls back
to the box when print size is unknown.
- Feed print native size into template_panel for aspect-aware fitting.
- Shrink built-in template boxes to realistic print proportions.
UI hierarchy:
- Promote 打开文件夹 buttons to primary (filled accent).
- Add inline 归零 (reset angle) and a 重置位置/尺寸/角度 button to the
transform panel; wire it to re-apply the selected template.
- Hide 保存 for built-in templates instead of leaving it greyed.
Docs: record template box/contain behavior (PRD) and the grid layout,
button hierarchy, and reset/save-visibility rules (UI design).
Tests: add 3 aspect-fit cases for to_transform_state.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>