mirror of
https://github.com/linshenkx/prompt-optimizer.git
synced 2026-05-06 21:50:27 +08:00
refactor(image): rebuild reference prompt pipeline
- Introduce the new reference prompt composition and migration template pipeline - Replace the legacy image prompt extraction path and align template loading contracts - Update text2image workspace integration and add reference pipeline coverage
This commit is contained in:
@@ -0,0 +1,519 @@
|
||||
# Reference Image Dialog Redesign Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Rework the text-to-image reference-image dialog into a simpler, clearer flow with thumbnail-first context, user-facing mode names, no undo complexity, and a hard 5-variable cap.
|
||||
|
||||
**Architecture:** Keep the existing three-stage reference pipeline intact (`ReferenceSpec -> PromptDraft -> VariableizedPrompt`) and only reshape the dialog state, layout, copy, and variable extraction policy around it. Treat the modal as a confirmation-and-light-edit surface rather than a strongly synchronized editor, so prompt text and variables can diverge temporarily without triggering re-extraction logic.
|
||||
|
||||
**Tech Stack:** Vue 3, Naive UI, TypeScript, Vitest, existing core template system
|
||||
|
||||
---
|
||||
|
||||
## File Map
|
||||
|
||||
### Core files to modify
|
||||
|
||||
- `packages/ui/src/components/image-mode/ImageText2ImageWorkspace.vue`
|
||||
- Reference-image modal structure, layout, user-facing wording hooks, thumbnail presentation, and removal of undo banner UI.
|
||||
- `packages/ui/src/composables/image/useReferencePromptDialog.ts`
|
||||
- Dialog state model, removal of apply snapshot/undo, addition of current-prompt preview state if needed.
|
||||
- `packages/ui/src/services/ImageStyleExtractor.ts`
|
||||
- Service-layer variable cap and any helper for trimming extracted variables to 5 high-priority entries.
|
||||
- `packages/ui/src/i18n/locales/zh-CN.ts`
|
||||
- Main Chinese copy changes for the dialog.
|
||||
- `packages/ui/src/i18n/locales/zh-TW.ts`
|
||||
- Traditional Chinese parity for the same copy.
|
||||
- `packages/ui/src/i18n/locales/en-US.ts`
|
||||
- English parity for the same copy.
|
||||
- `packages/core/src/services/template/default-templates/variable-extraction/extraction.ts`
|
||||
- Tighten extraction policy and cap guidance to 5 variables in Chinese.
|
||||
- `packages/core/src/services/template/default-templates/variable-extraction/extraction_en.ts`
|
||||
- Tighten extraction policy and cap guidance to 5 variables in English.
|
||||
|
||||
### Test files to modify
|
||||
|
||||
- `packages/ui/tests/unit/composables/useReferencePromptDialog.spec.ts`
|
||||
- Update expectations away from undo and toward simplified apply behavior.
|
||||
- `packages/ui/tests/unit/services/ImageStyleExtractor.reference-migration.spec.ts`
|
||||
- Add assertions for the 5-variable hard cap and final-prompt-only retention.
|
||||
- `packages/ui/tests/unit/image/reference-image-theme-guards.spec.ts`
|
||||
- Update source guard assertions to match thumbnail layout, no undo banner, and controlled modal sizing.
|
||||
|
||||
### Optional new tests
|
||||
|
||||
- `packages/ui/tests/unit/image/reference-image-dialog-layout.spec.ts`
|
||||
- Add only if the existing theme guard becomes too brittle to express the new structure cleanly.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Simplify Dialog State and Remove Undo
|
||||
|
||||
**Files:**
|
||||
- Modify: `packages/ui/src/composables/image/useReferencePromptDialog.ts`
|
||||
- Test: `packages/ui/tests/unit/composables/useReferencePromptDialog.spec.ts`
|
||||
|
||||
- [ ] **Step 1: Write the failing composable test for “apply without undo”**
|
||||
|
||||
```ts
|
||||
it('applies prompt and variables without exposing undo state', () => {
|
||||
const dialog = useReferencePromptDialog(/* ... */)
|
||||
dialog.openDialog()
|
||||
dialog.setGeneratedPreview(createPreview())
|
||||
|
||||
dialog.applyToCurrentPrompt()
|
||||
|
||||
expect(dialog).not.toHaveProperty('canUndoLastApply')
|
||||
expect(dialog).not.toHaveProperty('undoLastApply')
|
||||
})
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add a failing test for current-prompt preview behavior**
|
||||
|
||||
```ts
|
||||
it('stores detected current prompt for preview while keeping full prompt available for migration decisions', () => {
|
||||
const dialog = useReferencePromptDialog(/* original prompt is long text */)
|
||||
dialog.openDialog()
|
||||
|
||||
expect(dialog.detectedOriginalPrompt.value).toContain('当前提示词')
|
||||
})
|
||||
```
|
||||
|
||||
Note:
|
||||
- If the implementation chooses a computed preview string instead of a second ref, assert the chosen public API instead of inventing a new property.
|
||||
|
||||
- [ ] **Step 3: Run the composable test file**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
pnpm -F @prompt-optimizer/ui test -- tests/unit/composables/useReferencePromptDialog.spec.ts
|
||||
```
|
||||
|
||||
Expected:
|
||||
- FAIL because undo APIs still exist and the new preview expectation is not implemented yet.
|
||||
|
||||
- [ ] **Step 4: Remove undo state from the composable**
|
||||
|
||||
Implementation direction:
|
||||
|
||||
```ts
|
||||
// Remove:
|
||||
// - lastApplySnapshot
|
||||
// - canUndoLastApply
|
||||
// - undoLastApply()
|
||||
|
||||
const applyToCurrentPrompt = () => {
|
||||
if (!canApply.value) return false
|
||||
|
||||
options.applyPrompt(workingPrompt.value)
|
||||
options.applyVariables(cloneVariables(workingVariables.value))
|
||||
options.resetPromptArtifacts?.()
|
||||
closeDialog()
|
||||
return true
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Add or expose a small current-prompt preview value**
|
||||
|
||||
Implementation direction:
|
||||
|
||||
```ts
|
||||
const detectedOriginalPromptPreview = computed(() =>
|
||||
detectedOriginalPrompt.value.trim(),
|
||||
)
|
||||
```
|
||||
|
||||
Rules:
|
||||
- Keep the full original prompt for mode-switch logic.
|
||||
- Let the workspace decide how many lines to show visually.
|
||||
|
||||
- [ ] **Step 6: Re-run the composable tests**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
pnpm -F @prompt-optimizer/ui test -- tests/unit/composables/useReferencePromptDialog.spec.ts
|
||||
```
|
||||
|
||||
Expected:
|
||||
- PASS
|
||||
|
||||
- [ ] **Step 7: Commit**
|
||||
|
||||
```powershell
|
||||
git add packages/ui/src/composables/image/useReferencePromptDialog.ts packages/ui/tests/unit/composables/useReferencePromptDialog.spec.ts
|
||||
git commit -m "refactor(ui): simplify reference dialog state"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Rebuild the Modal Information Architecture and Layout
|
||||
|
||||
**Files:**
|
||||
- Modify: `packages/ui/src/components/image-mode/ImageText2ImageWorkspace.vue`
|
||||
- Test: `packages/ui/tests/unit/image/reference-image-theme-guards.spec.ts`
|
||||
|
||||
- [ ] **Step 1: Write the failing UI source guard updates**
|
||||
|
||||
Add expectations for:
|
||||
- thumbnail-oriented reference image block
|
||||
- separate detected-current-prompt section
|
||||
- `风格迁移 / 复刻图片` copy hooks
|
||||
- no undo banner markup
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
expect(source).toMatch(/reference-dialog-context-grid/)
|
||||
expect(source).toMatch(/reference-dialog-thumbnail/)
|
||||
expect(source).toMatch(/detectedCurrentPromptTitle/)
|
||||
expect(source).not.toMatch(/reference-image-undo-button/)
|
||||
expect(source).not.toMatch(/undoBanner/)
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run the UI source guard test**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
pnpm -F @prompt-optimizer/ui test -- tests/unit/image/reference-image-theme-guards.spec.ts
|
||||
```
|
||||
|
||||
Expected:
|
||||
- FAIL because the current modal still uses the old arrangement and undo markup.
|
||||
|
||||
- [ ] **Step 3: Replace the large reference preview with a compact thumbnail layout**
|
||||
|
||||
Implementation direction inside `ImageText2ImageWorkspace.vue`:
|
||||
|
||||
```vue
|
||||
<div class="reference-dialog-source-row">
|
||||
<button class="reference-dialog-thumbnail">
|
||||
<NImage ... />
|
||||
</button>
|
||||
<div class="reference-dialog-source-meta">
|
||||
<NText strong>{{ referenceDialog.sourceImageName || t(...) }}</NText>
|
||||
<NText depth="3">{{ t('imageWorkspace.referenceImage.sourceImageHint') }}</NText>
|
||||
<NButton size="small" secondary>{{ ... }}</NButton>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
Rules:
|
||||
- Thumbnail should not dominate vertical space.
|
||||
- Keep Naive UI theming and avoid hardcoded light-only backgrounds.
|
||||
|
||||
- [ ] **Step 4: Split “detected current prompt” into its own section**
|
||||
|
||||
Implementation direction:
|
||||
|
||||
```vue
|
||||
<NCard v-if="referenceDialog.showModeSwitch" ...>
|
||||
<NText strong>{{ t('imageWorkspace.referenceImage.detectedCurrentPromptTitle') }}</NText>
|
||||
<NText depth="3" class="reference-dialog-current-prompt-preview">
|
||||
{{ referenceDialog.detectedOriginalPromptPreview }}
|
||||
</NText>
|
||||
</NCard>
|
||||
```
|
||||
|
||||
Rules:
|
||||
- Show only preview text visually via CSS line clamp.
|
||||
- Do not place it under the usage-mode heading.
|
||||
|
||||
- [ ] **Step 5: Convert the mode selector into user-facing option cards**
|
||||
|
||||
Implementation direction:
|
||||
|
||||
```vue
|
||||
<NRadioGroup ...>
|
||||
<div class="reference-dialog-mode-grid">
|
||||
<label class="reference-dialog-mode-card">
|
||||
<NRadio value="migrate" />
|
||||
<NText strong>{{ t('imageWorkspace.referenceImage.styleTransfer') }}</NText>
|
||||
<NText depth="3">{{ t('imageWorkspace.referenceImage.styleTransferDescription') }}</NText>
|
||||
</label>
|
||||
</div>
|
||||
</NRadioGroup>
|
||||
```
|
||||
|
||||
Rules:
|
||||
- Preserve the underlying radio semantics.
|
||||
- Increase selection clarity with border/background states derived from theme tokens.
|
||||
|
||||
- [ ] **Step 6: Move the result area to a mixed layout**
|
||||
|
||||
Implementation direction:
|
||||
|
||||
```vue
|
||||
<div class="reference-dialog-results-grid">
|
||||
<NCard class="reference-dialog-section reference-dialog-section--prompt">...</NCard>
|
||||
<NCard class="reference-dialog-section reference-dialog-section--variables">...</NCard>
|
||||
</div>
|
||||
```
|
||||
|
||||
Rules:
|
||||
- Desktop: `2fr / 1fr`
|
||||
- Narrow widths: stack vertically
|
||||
- Prompt textarea gets a stable minimum height
|
||||
- Variable list gets a stable min/max height with scrolling
|
||||
|
||||
- [ ] **Step 7: Remove the undo banner from the workspace**
|
||||
|
||||
Delete:
|
||||
- success alert block above the template/model controls
|
||||
- `handleReferenceDialogUndo` wiring
|
||||
- any `referenceDialog.canUndoLastApply` template branches
|
||||
|
||||
- [ ] **Step 8: Re-run the UI source guard test**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
pnpm -F @prompt-optimizer/ui test -- tests/unit/image/reference-image-theme-guards.spec.ts
|
||||
```
|
||||
|
||||
Expected:
|
||||
- PASS
|
||||
|
||||
- [ ] **Step 9: Commit**
|
||||
|
||||
```powershell
|
||||
git add packages/ui/src/components/image-mode/ImageText2ImageWorkspace.vue packages/ui/tests/unit/image/reference-image-theme-guards.spec.ts
|
||||
git commit -m "feat(ui): redesign reference image dialog layout"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Update Dialog Copy Across Locales
|
||||
|
||||
**Files:**
|
||||
- Modify: `packages/ui/src/i18n/locales/zh-CN.ts`
|
||||
- Modify: `packages/ui/src/i18n/locales/zh-TW.ts`
|
||||
- Modify: `packages/ui/src/i18n/locales/en-US.ts`
|
||||
|
||||
- [ ] **Step 1: Add a failing check in the UI source guard or locale-aware test**
|
||||
|
||||
If no locale test exists, extend the existing source guard to assert the new translation keys are referenced and old ones are gone.
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
expect(source).toMatch(/styleTransfer/)
|
||||
expect(source).toMatch(/replicateImage/)
|
||||
expect(source).not.toMatch(/migrateToCurrentPrompt/)
|
||||
expect(source).not.toMatch(/replicateOnly/)
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run the relevant test file**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
pnpm -F @prompt-optimizer/ui test -- tests/unit/image/reference-image-theme-guards.spec.ts
|
||||
```
|
||||
|
||||
Expected:
|
||||
- FAIL until the component and locale keys agree.
|
||||
|
||||
- [ ] **Step 3: Update the locale entries**
|
||||
|
||||
Chinese target copy:
|
||||
|
||||
```ts
|
||||
styleTransfer: "风格迁移",
|
||||
styleTransferDescription: "在原提示词的基础上学习图片风格进行改造",
|
||||
replicateImage: "复刻图片",
|
||||
replicateImageDescription: "丢弃原始提示词内容,反推图片对应提示词",
|
||||
detectedCurrentPromptTitle: "检测到当前提示词",
|
||||
```
|
||||
|
||||
Also remove:
|
||||
- `undoBanner`
|
||||
- `undo`
|
||||
- `undoSuccess`
|
||||
|
||||
- [ ] **Step 4: Keep cross-locale parity**
|
||||
|
||||
Do not leave `zh-TW` and `en-US` behind even if the main product language is Chinese.
|
||||
|
||||
- [ ] **Step 5: Re-run the UI test**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
pnpm -F @prompt-optimizer/ui test -- tests/unit/image/reference-image-theme-guards.spec.ts
|
||||
```
|
||||
|
||||
Expected:
|
||||
- PASS
|
||||
|
||||
- [ ] **Step 6: Commit**
|
||||
|
||||
```powershell
|
||||
git add packages/ui/src/i18n/locales/zh-CN.ts packages/ui/src/i18n/locales/zh-TW.ts packages/ui/src/i18n/locales/en-US.ts packages/ui/src/components/image-mode/ImageText2ImageWorkspace.vue packages/ui/tests/unit/image/reference-image-theme-guards.spec.ts
|
||||
git commit -m "refactor(ui): update reference dialog copy"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Tighten Variable Extraction to 5 High-Value Variables
|
||||
|
||||
**Files:**
|
||||
- Modify: `packages/core/src/services/template/default-templates/variable-extraction/extraction.ts`
|
||||
- Modify: `packages/core/src/services/template/default-templates/variable-extraction/extraction_en.ts`
|
||||
- Modify: `packages/ui/src/services/ImageStyleExtractor.ts`
|
||||
- Test: `packages/ui/tests/unit/services/ImageStyleExtractor.reference-migration.spec.ts`
|
||||
|
||||
- [ ] **Step 1: Add a failing service test for the 5-variable cap**
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
it('caps extracted variables at 5 entries', async () => {
|
||||
const result = await extractPromptVariables({
|
||||
prompt: SOME_PROMPT,
|
||||
modelKey: 'text-model',
|
||||
variableExtractionService: {
|
||||
extract: vi.fn().mockResolvedValue({
|
||||
variables: Array.from({ length: 7 }, (_, index) => ({
|
||||
name: `变量${index + 1}`,
|
||||
value: `值${index + 1}`,
|
||||
position: { originalText: `词${index + 1}`, occurrence: 1 },
|
||||
reason: 'test',
|
||||
})),
|
||||
}),
|
||||
} as any,
|
||||
})
|
||||
|
||||
expect(Object.keys(result.variableDefaults)).toHaveLength(5)
|
||||
})
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run the reference-migration service tests**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
pnpm -F @prompt-optimizer/ui test -- tests/unit/services/ImageStyleExtractor.reference-migration.spec.ts
|
||||
```
|
||||
|
||||
Expected:
|
||||
- FAIL because no hard cap exists yet.
|
||||
|
||||
- [ ] **Step 3: Tighten the variable-extraction prompt templates**
|
||||
|
||||
Chinese and English template changes should:
|
||||
- reduce max variable count from 20 to 5
|
||||
- instruct the model to prioritize subject, count, color, key action, and key scene/style anchor
|
||||
- avoid low-value decorative fragments
|
||||
|
||||
Example rule block:
|
||||
|
||||
```ts
|
||||
- 最多返回5个变量,按重要性排序
|
||||
- 优先保留主体、数量、颜色、关键动作、关键场景或核心风格锚点
|
||||
- 避免提取低价值修饰词、重复限定词和局部装饰
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Add a hard-cap safeguard in `ImageStyleExtractor.ts`**
|
||||
|
||||
Implementation direction:
|
||||
|
||||
```ts
|
||||
const MAX_REFERENCE_DIALOG_VARIABLES = 5
|
||||
|
||||
const limitedVariables = result.variables.slice(0, MAX_REFERENCE_DIALOG_VARIABLES)
|
||||
const variableizedPrompt = replaceExtractedVariablesInPrompt(prompt, limitedVariables)
|
||||
const keptVariableNames = scanVariablesFromValue(variableizedPrompt)
|
||||
|
||||
return {
|
||||
prompt: variableizedPrompt,
|
||||
variableDefaults: buildFilteredDefaultsFromExtractedVariables(keptVariableNames, limitedVariables),
|
||||
rawText,
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Re-run the service tests**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
pnpm -F @prompt-optimizer/ui test -- tests/unit/services/ImageStyleExtractor.reference-migration.spec.ts
|
||||
```
|
||||
|
||||
Expected:
|
||||
- PASS
|
||||
|
||||
- [ ] **Step 6: Commit**
|
||||
|
||||
```powershell
|
||||
git add packages/core/src/services/template/default-templates/variable-extraction/extraction.ts packages/core/src/services/template/default-templates/variable-extraction/extraction_en.ts packages/ui/src/services/ImageStyleExtractor.ts packages/ui/tests/unit/services/ImageStyleExtractor.reference-migration.spec.ts
|
||||
git commit -m "refactor(image): cap reference dialog variables"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 5: Final Verification and Manual Smoke Check
|
||||
|
||||
**Files:**
|
||||
- Verify all files from Tasks 1-4
|
||||
- Optional notes update in: `docs/superpowers/specs/2026-03-31-reference-image-dialog-redesign-design.md`
|
||||
|
||||
- [ ] **Step 1: Run the targeted UI and service tests together**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
pnpm -F @prompt-optimizer/ui test -- tests/unit/composables/useReferencePromptDialog.spec.ts tests/unit/image/reference-image-theme-guards.spec.ts tests/unit/services/ImageStyleExtractor.reference-migration.spec.ts
|
||||
```
|
||||
|
||||
Expected:
|
||||
- PASS
|
||||
|
||||
- [ ] **Step 2: Run UI typecheck**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
pnpm -F @prompt-optimizer/ui typecheck
|
||||
```
|
||||
|
||||
Expected:
|
||||
- PASS
|
||||
|
||||
- [ ] **Step 3: Run a local manual smoke test**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
pnpm dev:fresh
|
||||
```
|
||||
|
||||
Manual checklist:
|
||||
- Open `http://127.0.0.1:18181/#/image/text2image`
|
||||
- Click `参考图`
|
||||
- Confirm there is no undo banner in the workspace after apply
|
||||
- Confirm the reference image is shown as a thumbnail, not a large preview
|
||||
- Confirm `检测到当前提示词` is separate from the mode area
|
||||
- Confirm `风格迁移 / 复刻图片` are clearly distinguishable
|
||||
- Confirm the prompt editor and variables panel both have stable visible height
|
||||
|
||||
If model/auth config blocks full end-to-end generation, still verify the static layout and state behavior around modal opening, mode switching, and absence of undo affordances.
|
||||
|
||||
- [ ] **Step 4: Commit the verified final state**
|
||||
|
||||
```powershell
|
||||
git add packages/ui/src/components/image-mode/ImageText2ImageWorkspace.vue packages/ui/src/composables/image/useReferencePromptDialog.ts packages/ui/src/services/ImageStyleExtractor.ts packages/ui/src/i18n/locales/zh-CN.ts packages/ui/src/i18n/locales/zh-TW.ts packages/ui/src/i18n/locales/en-US.ts packages/core/src/services/template/default-templates/variable-extraction/extraction.ts packages/core/src/services/template/default-templates/variable-extraction/extraction_en.ts packages/ui/tests/unit/composables/useReferencePromptDialog.spec.ts packages/ui/tests/unit/image/reference-image-theme-guards.spec.ts packages/ui/tests/unit/services/ImageStyleExtractor.reference-migration.spec.ts
|
||||
git commit -m "feat(ui): simplify reference image migration dialog"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes for the Implementer
|
||||
|
||||
- Do not reintroduce “sync variables” or “undo once” under new names.
|
||||
- Keep the modal built on Naive UI primitives and theme tokens.
|
||||
- Prefer CSS line-clamp or constrained container height for current-prompt preview rather than trimming the underlying source text aggressively.
|
||||
- Keep the three-stage service architecture intact; this plan is a UI and policy refinement, not a pipeline rewrite.
|
||||
- If the workspace file becomes too hard to reason about, it is acceptable to extract a small presentational subcomponent for the mode cards or result grid, but only if it reduces complexity instead of spreading it.
|
||||
@@ -0,0 +1,434 @@
|
||||
# 文生图参考图弹窗重构设计
|
||||
|
||||
## 背景
|
||||
|
||||
当前文生图中的“参考图”弹窗已经接入三段式内部链路:
|
||||
|
||||
1. `ReferenceSpec` 提取
|
||||
2. `PromptDraft` 生成或迁移
|
||||
3. `VariableizedPrompt` 抽取
|
||||
|
||||
但当前交互仍存在几个明显问题:
|
||||
|
||||
- 弹窗承担了过多“临时补救”职责,例如应用后撤销,导致状态复杂度偏高。
|
||||
- “检测到当前提示词”被放在“怎么使用这张参考图”内部,信息层级不清晰。
|
||||
- 模式命名偏实现视角,用户第一眼难以理解差异。
|
||||
- 参考图预览区域占用空间过大,挤压了真正重要的结果编辑区。
|
||||
- 变量区缺少明确产品边界,当前结果更像调试信息而不是可确认的产物。
|
||||
- 当前变量提取策略过于宽松,不适合参考图迁移场景,容易抽出过多变量。
|
||||
|
||||
本次重构目标不是新增更强的自动能力,而是把参考图弹窗整理成一个更清晰、更可理解、更可确认的前置改造流程。
|
||||
|
||||
## 目标
|
||||
|
||||
### 产品目标
|
||||
|
||||
- 让用户能快速理解“这张参考图会怎么影响当前提示词”。
|
||||
- 保持现有 `文生图 / 图生图` 一级入口和模板下拉不变。
|
||||
- 让“参考图”成为清晰的前置改造工具,而不是半自动编辑器。
|
||||
- 保留 prompt 与变量的人工微调能力,但删除不必要的状态补丁和联动复杂度。
|
||||
|
||||
### 交互目标
|
||||
|
||||
- 让弹窗第一眼就能看懂当前上下文、可选模式和最终结果。
|
||||
- 把视觉重心从“参考图展示”转移到“生成后的提示词”和“变量预览”。
|
||||
- 让模式命名直接对应用户心智,而不是内部实现术语。
|
||||
|
||||
### 技术目标
|
||||
|
||||
- 删除撤销链路及其相关状态。
|
||||
- 保持三段式架构不变,只收敛 UI 结构、文案与变量策略。
|
||||
- 把变量数量稳定控制在 5 个以内,并保证优先级一致。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不修改图生图工作区。
|
||||
- 不新增收藏、URL、Garden 导入等参考来源。
|
||||
- 不引入 prompt 与变量的实时双向同步。
|
||||
- 不把参考图弹窗演化为 JSON 树编辑器或多步向导。
|
||||
- 不改变现有优化按钮、模板选择、主工作区链路。
|
||||
|
||||
## 设计原则
|
||||
|
||||
### 1. 参考图是来源,不是主角
|
||||
|
||||
参考图用于确认风格来源是否正确,不应该占据大块主编辑空间。默认展示应为缩略图,而不是大图卡片。
|
||||
|
||||
### 2. 先交代上下文,再让用户做选择
|
||||
|
||||
“检测到当前提示词”属于系统当前上下文,应先独立告知用户,再让用户选择如何使用参考图。
|
||||
|
||||
### 3. 模式命名必须是用户语言
|
||||
|
||||
模式名称应直接表达结果差异,而不是实现逻辑。用户要看懂“风格迁移”和“复刻图片”,而不是推断“保留当前内容”和“按参考图生成”的含义。
|
||||
|
||||
### 4. 结果区是弹窗的视觉中心
|
||||
|
||||
弹窗应把主要空间分配给最终会被应用的两类结果:
|
||||
|
||||
- 生成后的提示词
|
||||
- 提取到的变量
|
||||
|
||||
### 5. 简化优先于强一致
|
||||
|
||||
本期保留“初次生成时自动抽变量,之后允许手动改 prompt 和变量值”的弱一致策略,不引入自动重算或手动同步动作。
|
||||
|
||||
## 方案比较
|
||||
|
||||
### 方案 A:纯纵向堆叠
|
||||
|
||||
按顺序纵向排列所有内容块:
|
||||
|
||||
- 参考图
|
||||
- 检测到当前提示词
|
||||
- 使用方式
|
||||
- 生成后的提示词
|
||||
- 变量预览
|
||||
|
||||
优点:
|
||||
|
||||
- 实现简单
|
||||
- 信息顺序线性
|
||||
|
||||
缺点:
|
||||
|
||||
- 弹窗过长
|
||||
- 重点区域不够突出
|
||||
- prompt 与变量缺少工作台感
|
||||
|
||||
### 方案 B:完全左右双栏
|
||||
|
||||
整个弹窗采用左右布局,把上下文和结果一起放入双栏。
|
||||
|
||||
优点:
|
||||
|
||||
- 可在桌面端压缩高度
|
||||
- 对比感更强
|
||||
|
||||
缺点:
|
||||
|
||||
- 信息关系变复杂
|
||||
- 辅助信息和核心结果抢空间
|
||||
- 响应式和主题适配更容易出问题
|
||||
|
||||
### 方案 C:上轻下重的混合布局
|
||||
|
||||
顶部为轻量上下文区,中部为模式选择,底部为结果工作区双栏。
|
||||
|
||||
结构为:
|
||||
|
||||
- 顶部:`参考图` 缩略图卡 + `检测到当前提示词` 摘要卡
|
||||
- 中部:`风格迁移 / 复刻图片` 两张模式卡
|
||||
- 底部:左侧 `生成后的提示词`,右侧 `提取到的变量`
|
||||
|
||||
优点:
|
||||
|
||||
- 信息优先级清晰
|
||||
- 结果区获得足够空间
|
||||
- 比纯双栏更稳,比纯纵向更紧凑
|
||||
|
||||
缺点:
|
||||
|
||||
- 需要对弹窗结构和样式做一次性整理
|
||||
|
||||
### 推荐方案
|
||||
|
||||
采用方案 C。它最符合当前产品定位,也最容易沿用 Naive UI 和现有弹窗结构做稳定落地。
|
||||
|
||||
## 信息架构
|
||||
|
||||
### 1. 参考图
|
||||
|
||||
作为第一块区域展示,采用缩略图样式:
|
||||
|
||||
- 左侧固定尺寸缩略图,建议 `96x96` 或 `112x112`
|
||||
- 右侧展示文件名、说明文字和“上传/更换图片”按钮
|
||||
- 默认不展示大图,不占用额外垂直空间
|
||||
- 点击缩略图时可沿用现有图片预览能力,但不作为默认状态
|
||||
|
||||
说明文案继续保留:
|
||||
|
||||
- `仅支持本地 PNG/JPEG,最大 10MB`
|
||||
|
||||
### 2. 检测到当前提示词
|
||||
|
||||
仅在当前原始提示词非空时显示,作为独立信息卡片放在参考图区域之后。
|
||||
|
||||
展示规则:
|
||||
|
||||
- 标题:`检测到当前提示词`
|
||||
- 只展示前 2 到 3 行摘要
|
||||
- 超出内容省略,不展示完整正文
|
||||
- 目的仅为帮助用户判断是否保留当前内容,避免把遗留文本误当成当前意图
|
||||
|
||||
该区域不承担编辑功能。
|
||||
|
||||
### 3. 怎么使用这张参考图
|
||||
|
||||
作为单独区域展示,不再混入当前提示词信息。
|
||||
|
||||
模式命名改为:
|
||||
|
||||
- `风格迁移`
|
||||
- `复刻图片`
|
||||
|
||||
模式说明改为:
|
||||
|
||||
- `风格迁移`:在原提示词的基础上学习图片风格进行改造
|
||||
- `复刻图片`:丢弃原始提示词内容,反推图片对应提示词
|
||||
|
||||
展示方式:
|
||||
|
||||
- 使用可点击卡片承载单选逻辑,而不是仅显示普通文字型 radio
|
||||
- 卡片需有明显选中态,便于第一眼区分
|
||||
|
||||
规则:
|
||||
|
||||
- 当前提示词为空时,不显示模式切换,默认只走 `复刻图片`
|
||||
- 当前提示词非空时,默认推荐 `风格迁移`
|
||||
|
||||
## 弹窗布局
|
||||
|
||||
### 桌面端
|
||||
|
||||
采用混合布局:
|
||||
|
||||
- 顶部上下文区:纵向排列两个轻量卡片
|
||||
- `参考图`
|
||||
- `检测到当前提示词`
|
||||
- 中部模式区:两张模式卡横向排布
|
||||
- 底部结果区:左右布局
|
||||
- 左:`生成后的提示词`,宽度约 `2fr`
|
||||
- 右:`提取到的变量`,宽度约 `1fr`
|
||||
|
||||
### 窄屏
|
||||
|
||||
底部结果区自动回退为纵向堆叠:
|
||||
|
||||
- 先显示 `生成后的提示词`
|
||||
- 再显示 `提取到的变量`
|
||||
|
||||
### 弹窗尺寸
|
||||
|
||||
- 继续基于 Naive UI `NModal + NCard`
|
||||
- 控制整体宽度,不允许回退为异常全屏
|
||||
- 建议桌面宽度保持在 `min(880px, calc(100vw - 32px))` 左右的级别
|
||||
- 保持主题跟随,避免硬编码浅色背景或阴影逻辑
|
||||
|
||||
## 结果编辑区设计
|
||||
|
||||
### 生成后的提示词
|
||||
|
||||
这是弹窗的主内容区,应具备稳定高度。
|
||||
|
||||
规则:
|
||||
|
||||
- 使用单个可编辑 textarea
|
||||
- 不再展示“请先上传参考图生成预览”之类的说明文案
|
||||
- 未生成前允许为空,但界面仍保留固定编辑区域
|
||||
- 建议最小高度约 `260px ~ 320px`
|
||||
- 加载中只显示轻量状态提示,不挤压编辑区高度
|
||||
|
||||
### 提取到的变量
|
||||
|
||||
作为结果工作区的一部分展示,而不是附属信息。
|
||||
|
||||
规则:
|
||||
|
||||
- 变量名只读
|
||||
- 变量值可编辑
|
||||
- 区域需具备明确最小高度和滚动能力
|
||||
- 变量行之间保持稳定间距,避免像表单碎片一样堆在底部
|
||||
|
||||
## 变量策略
|
||||
|
||||
### 产品规则
|
||||
|
||||
- 变量只在首次生成预览时自动提取一次
|
||||
- 用户编辑 prompt 后,不自动重算变量
|
||||
- 不再提供“同步变量”或“重新提取变量”按钮
|
||||
- 点击应用时:
|
||||
- 直接采用当前 prompt 文本
|
||||
- 直接采用当前变量区值
|
||||
- 不再做额外重算
|
||||
|
||||
这意味着 prompt 与变量允许短暂不完全一致,这是有意的简化,不视为缺陷。
|
||||
|
||||
### 数量上限
|
||||
|
||||
变量总数必须控制在 5 个以内。
|
||||
|
||||
采用三层约束:
|
||||
|
||||
1. 参考图生成与迁移模板中,要求输出更适合少量高价值变量抽取的结构
|
||||
2. 变量提取模板中明确要求最多返回 5 个变量,并按重要性排序
|
||||
3. UI 服务层增加硬上限兜底,只保留前 5 个变量
|
||||
|
||||
### 优先级
|
||||
|
||||
优先保留以下变量类型:
|
||||
|
||||
- 主体
|
||||
- 数量
|
||||
- 颜色
|
||||
- 关键动作
|
||||
- 关键场景或核心风格锚点
|
||||
|
||||
低优先级项应避免被抽成变量:
|
||||
|
||||
- 细碎修饰词
|
||||
- 重复限定词
|
||||
- 对最终复用价值不高的局部装饰
|
||||
|
||||
## 状态与数据流
|
||||
|
||||
### 打开弹窗
|
||||
|
||||
1. 读取当前原始提示词
|
||||
2. 若非空,生成摘要用于“检测到当前提示词”
|
||||
3. 初始化模式:
|
||||
- 有当前提示词时默认 `风格迁移`
|
||||
- 无当前提示词时默认 `复刻图片`
|
||||
4. 清空本次参考图预览结果
|
||||
|
||||
### 上传参考图后生成预览
|
||||
|
||||
#### 复刻图片
|
||||
|
||||
1. `extractReferenceSpecFromImage`
|
||||
2. `composePromptFromReferenceSpec`
|
||||
3. `extractPromptVariables`
|
||||
4. 将结果填入弹窗中的 prompt 和变量区
|
||||
|
||||
#### 风格迁移
|
||||
|
||||
1. `extractReferenceSpecFromImage`
|
||||
2. `migratePromptWithReferenceSpec`
|
||||
3. `extractPromptVariables`
|
||||
4. 将结果填入弹窗中的 prompt 和变量区
|
||||
|
||||
### 应用到当前提示词
|
||||
|
||||
1. 使用当前编辑框中的 prompt 作为最终文本
|
||||
2. 使用当前变量区中的值覆盖当前临时变量
|
||||
3. 关闭弹窗
|
||||
4. 不再保留撤销快照
|
||||
|
||||
## 需要删除的复杂度
|
||||
|
||||
### 删除撤销链路
|
||||
|
||||
移除以下能力:
|
||||
|
||||
- 弹窗应用后的撤销提示条
|
||||
- `lastApplySnapshot`
|
||||
- `canUndoLastApply`
|
||||
- `undoLastApply()`
|
||||
- 相关 UI 按钮与成功提示
|
||||
|
||||
原因:
|
||||
|
||||
- 弹窗本身已承担最终确认职责
|
||||
- 应用后撤销会引入额外状态与心智负担
|
||||
- 不符合本功能“确认后替换”的简单模型
|
||||
|
||||
### 删除变量同步链路
|
||||
|
||||
移除或保持不存在以下能力:
|
||||
|
||||
- 手动同步变量
|
||||
- 自动重算变量
|
||||
- prompt 变更后的失焦刷新
|
||||
- 变量与 prompt 的双向联动逻辑
|
||||
|
||||
原因:
|
||||
|
||||
- 这会把弹窗变成编辑器,不再是前置参考改造工具
|
||||
- 当前 MVP 的价值在于快速得到一份可用起点,而不是维护强一致的数据模型
|
||||
|
||||
## 文案调整
|
||||
|
||||
### 主要文案
|
||||
|
||||
- `识图提取` 保持为 `参考图`
|
||||
- `检测到当前提示词:{prompt}` 改为分离式标题和摘要内容,不再拼成一整句
|
||||
- `保留当前内容` 改为 `风格迁移`
|
||||
- `按参考图生成` 改为 `复刻图片`
|
||||
|
||||
### 模式说明
|
||||
|
||||
- `风格迁移`:在原提示词的基础上学习图片风格进行改造
|
||||
- `复刻图片`:丢弃原始提示词内容,反推图片对应提示词
|
||||
|
||||
## 影响范围
|
||||
|
||||
### UI
|
||||
|
||||
- `packages/ui/src/components/image-mode/ImageText2ImageWorkspace.vue`
|
||||
- `packages/ui/src/composables/image/useReferencePromptDialog.ts`
|
||||
- `packages/ui/src/i18n/locales/zh-CN.ts`
|
||||
- `packages/ui/src/i18n/locales/zh-TW.ts`
|
||||
- `packages/ui/src/i18n/locales/en-US.ts`
|
||||
|
||||
### 服务与模板
|
||||
|
||||
- `packages/ui/src/services/ImageStyleExtractor.ts`
|
||||
- `packages/core/src/services/template/default-templates/image-prompt-composition/`
|
||||
- `packages/core/src/services/template/default-templates/image-prompt-migration/`
|
||||
- `packages/core/src/services/template/default-templates/variable-extraction/`
|
||||
|
||||
## 错误处理
|
||||
|
||||
- 上传失败时,维持当前 prompt 和变量不变
|
||||
- 参考图解析失败时,仅提示本次生成失败,不关闭弹窗
|
||||
- 变量提取失败时,允许 prompt 继续展示,但变量区为空
|
||||
- 当前提示词为空时,不展示模式选择,也不报错
|
||||
|
||||
## 测试要点
|
||||
|
||||
### 交互测试
|
||||
|
||||
- 弹窗不再显示应用后撤销提示
|
||||
- 当前提示词非空时,先显示摘要,再显示模式选择
|
||||
- 模式名称和说明文案已切换为 `风格迁移 / 复刻图片`
|
||||
- 参考图区域使用缩略图,不再占用大图高度
|
||||
- prompt 区和变量区有稳定高度
|
||||
|
||||
### 逻辑测试
|
||||
|
||||
- `风格迁移` 默认选中,仅在当前提示词非空时出现
|
||||
- `复刻图片` 在当前提示词为空时自动生效
|
||||
- 应用时不再保存撤销快照
|
||||
- 编辑 prompt 不触发变量自动刷新
|
||||
- 变量数量始终不超过 5 个
|
||||
|
||||
### 回归测试
|
||||
|
||||
- 未使用参考图时,文生图现有流程不变
|
||||
- 图生图工作区不受影响
|
||||
- 三段式内部服务链路保持不变
|
||||
|
||||
## 验收标准
|
||||
|
||||
- 用户能在首次打开弹窗时看懂“当前看到了什么”和“可以怎么用这张图”
|
||||
- 参考图不再抢占主编辑区空间
|
||||
- `风格迁移 / 复刻图片` 的语义差异无需额外解释即可理解
|
||||
- 弹窗应用链路不再包含撤销和同步变量等补救型复杂度
|
||||
- 变量数量被稳定控制在 5 个以内
|
||||
|
||||
## 实施建议
|
||||
|
||||
建议按以下顺序实施:
|
||||
|
||||
1. 先删状态复杂度
|
||||
- 移除撤销状态与相关文案
|
||||
2. 再改 UI 信息架构
|
||||
- 缩略图参考图
|
||||
- 当前提示词摘要卡
|
||||
- 模式卡
|
||||
- 底部混合布局
|
||||
3. 最后收变量策略
|
||||
- 提取模板收紧
|
||||
- 服务层硬上限兜底
|
||||
|
||||
这样可以先把交互心智收干净,再保证变量结果稳定。
|
||||
Reference in New Issue
Block a user