Panel had no stylesheet -> all buttons rendered native gray. Add
setObjectName('aiOutfitPanel') + _apply_styles() with QSS scoped to
#aiOutfitPanel (so dialogs keep native buttons): primary blue for 开始生成
(aiStartBtn, mirrors 开始批量导出/打开文件夹), quiet red for 停止生成 and the 话术
删除 (aiStopBtn/aiPromptDeleteBtn, mirrors 删除), secondary gray for the rest.
docs/11 §10.5 + tasks §19.11. Offscreen grab verified; full suite (12) green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- _on_finished(total==0) now shows _show_no_pending_message: counts 完成/失败
via read_all_rows and tells the user how to redo (clear E column / retry
failed), instead of the silent '完成 0,失败 0'.
- _on_tasks_loaded no longer calls _fill_sample_combo(tasks), so generating on
an all-完成 sheet no longer empties the preview dropdown (read_all_rows owns it).
- Offscreen-verified both paths; full suite (12 files) green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
After a whole sheet is 完成, clicking 开始生成 silently shows '0 待处理 /
完成 0' and also re-empties the preview sample dropdown. Document two fixes:
(1) a clear 'no pending rows' message (N done skipped / M failed retryable /
clear E column to redo), (2) _on_tasks_loaded must not reset the preview combo
(read_all_rows owns it). Add §10.4 + §19.10.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add excel_service.read_all_rows (every valid data row, status-independent) and
use it in _reload_sample_rows for the preview dropdown, so previewing still
works after the whole sheet is 完成. Generation still uses load_outfit_tasks.
+1 excel test (read_all_rows includes 完成/失败, skips incomplete); offscreen
all-完成 sheet now yields sample rows; full suite (12) green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bug: after a whole Excel finishes, re-selecting it shows an empty preview
sample-row dropdown because _reload_sample_rows uses load_outfit_tasks (which
skips 完成 rows). Preview should list all valid data rows regardless of status.
Document the cause + fix (new excel_service.read_all_rows for preview; generate
still uses load_outfit_tasks). Update §7 + add §10.3 / §19.9.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Upgrade the single prompt to multiple named templates (switch/new/save-as/
rename/delete/save, remember last). Decisions: all-custom (seed one 默认),
dirty-check confirm on switch, include rename. Storage: outfit_prompts.json +
outfit_prompt_name in app_config, migrate the old outfit_prompt.txt. Add §7.2
design + §19.8 task (not yet implemented).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add last_tab to DEFAULT_CONFIG; main_window restores it in _restore_preferences
(only enabled/implemented tabs 0/1; setCurrentIndex before connecting the persist
slot to avoid an echo write) and persists via _on_tab_persist on currentChanged.
Mirrors the existing last_template/last_batch_mode pattern. Document the key in
docs/02 §9. Offscreen-verified (restore 0/1, disabled 2 -> 0, persist); suite green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Connect QComboBox.activated (user-only) on the 分辨率 and AI 模型 dropdowns to
an info-only QMessageBox: resolution shows the per-resolution timeout +
next-run-only; model shows its api_type + billing/effect caveat + next-run-only.
Track last value so re-selecting the same item doesn't pop; programmatic sets
(apply_config/_fill_sample_combo) never pop. Offscreen-verified; suite (12) green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
- 数据源/输出 become inline label+path+browse rows (_inline_path_row);
removed the left group boxes to free vertical space.
- 通用话术 + 最终提示词预览 enlarged and stretch with window height.
- 生成设置 grid -> 3 columns (2 rows); AI 模型 dropdown moved under it in the
right column. Splitter sizes left360/center/right400; right minWidth 360.
- Verified offscreen against the mockup (real Qt grab); full suite (12) green.
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>
- core/ai_outfit: OUTPUT_REQUIREMENTS constant + build_output_requirements();
render_prompt(template, task, resolution=None) appends the block when a
resolution is given; generate_outfit_image passes the current resolution.
- ai_outfit_panel: inline preview now uses render_prompt/build_output_requirements
with the selected resolution and refreshes when the resolution combo changes,
so the preview equals what is actually sent.
- tests: +3 cases (tail with resolution, none without, helper empty/filled);
updated the success test for the appended tail. Full suite (12 files) green.
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>
Constrain the 样本行 and AI 模型 combos (AdjustToMinimumContentsLengthWithIcon
+ minimumContentsLength + Ignored size policy) so long items elide instead of
inflating the column's min width. Left scroll h-policy AlwaysOff -> AsNeeded as
a safety net; trim splitter initial sizes to fit the default window.
Measured: left inner minimumSizeHint 829px -> 200px (viewport ~398), no clip.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>