From 756638a28a40d175284b34d1bff082e02b16b45f Mon Sep 17 00:00:00 2001 From: brother7 <7brother7@gmail.com> Date: Wed, 2 Sep 2026 17:48:03 +0800 Subject: [PATCH] feat: simplify AI design for young creators --- .../20260902-design-youth-client-7c5e3a82.md | 107 ++ src/pages/ImageCanvas/CreativeChoiceGrid.tsx | 96 ++ .../ImageCanvas/DesignConversationPane.tsx | 101 +- .../ImageCanvas/DesignProductionPanel.tsx | 160 ++- src/pages/ImageCanvas/FineTuneDrawer.tsx | 949 ++++++++++++++++++ src/pages/ImageCanvas/YouthCreationCard.tsx | 478 +++++++++ src/pages/ImageCanvas/index.tsx | 213 ++-- .../ImageCanvas/youth-form-projection.ts | 398 ++++++++ src/pages/ImageCanvas/youth-issue-copy.ts | 119 +++ src/stores/image-workspace.ts | 36 +- tests/e2e/image-workspace-v2.spec.ts | 81 +- tests/unit/fine-tune-drawer.test.tsx | 277 +++++ tests/unit/image-canvas-page.test.tsx | 75 +- tests/unit/image-workspace-store.test.ts | 120 +++ tests/unit/youth-creation-card.test.tsx | 343 +++++++ tests/unit/youth-form-projection.test.ts | 290 ++++++ tests/unit/youth-issue-copy.test.ts | 49 + 17 files changed, 3595 insertions(+), 297 deletions(-) create mode 100644 .project-docs/30-worklog/tasks/20260902-design-youth-client-7c5e3a82.md create mode 100644 src/pages/ImageCanvas/CreativeChoiceGrid.tsx create mode 100644 src/pages/ImageCanvas/FineTuneDrawer.tsx create mode 100644 src/pages/ImageCanvas/YouthCreationCard.tsx create mode 100644 src/pages/ImageCanvas/youth-form-projection.ts create mode 100644 src/pages/ImageCanvas/youth-issue-copy.ts create mode 100644 tests/unit/fine-tune-drawer.test.tsx create mode 100644 tests/unit/youth-creation-card.test.tsx create mode 100644 tests/unit/youth-form-projection.test.ts create mode 100644 tests/unit/youth-issue-copy.test.ts diff --git a/.project-docs/30-worklog/tasks/20260902-design-youth-client-7c5e3a82.md b/.project-docs/30-worklog/tasks/20260902-design-youth-client-7c5e3a82.md new file mode 100644 index 00000000..6e7a1be3 --- /dev/null +++ b/.project-docs/30-worklog/tasks/20260902-design-youth-client-7c5e3a82.md @@ -0,0 +1,107 @@ +# Task: Implement youth-facing AI Design experience + +## Identity + +- Task ID: 20260902-design-youth-client-7c5e3a82 +- Mode: Feature +- Branch: codex/20260902-design-youth-client-7c5e3a82-design-youth-client +- Worktree: D:\Datas\OthersProjects\makelore-design-youth-client-7c5e3a82 +- Base commit: 841273b43354b2237a52a7081a9fceb647ef4e3f +- Owner: codex-root +- Status: Ready for integration + +## Scope + +- Replace the default comprehensive AI Design form with conversation plus a compact + “我的创作” Creation Card projected from the canonical Current Specification. +- Add a reviewed A/B/C field-presentation catalog, pure youth projection, contextual + “精细调整” controls, responsive desktop/mobile composition, and youth-facing + conversation/Quote/Task/result copy. +- Reuse the existing V2 typed reducer, Quote confirmation, Task/Asset reconciliation, + upload and local-draft behavior; do not add another state store or API contract. + +## Intent And Constraints + +- One understandable default serves creators aged 8-16; there are no age or expert + modes. Advanced control is contextual progressive disclosure. +- Conversation is the default mobile surface. Desktop gives conversation visual + priority and keeps the concise Creation Card visible. +- Direct choices use existing typed semantic commands and never synthesize chat + turns. Readiness is derived from concrete blockers/questions, not field counts. +- Preserve Main ownership of Works credentials and V2 transport, Chinese-only UI, + existing light visual language, 44 px targets, keyboard focus and reduced motion. +- No database/DTO change, second brief/store, compatibility layer, broad redesign, + package, deployment, publication, push or paid generation is in scope. + +## Concurrent Task Gate + +- Task ID: `20260902-design-youth-client-7c5e3a82` +- Mode: Feature +- Branch/worktree: `codex/20260902-design-youth-client-7c5e3a82-design-youth-client` / + `D:\Datas\OthersProjects\makelore-design-youth-client-7c5e3a82` +- Base commit: `841273b43354b2237a52a7081a9fceb647ef4e3f` +- Ownership result: Isolated and claimed by `codex-root`. +- Other active work: Model Tools owns a separate integration worktree and Plugin/Pi + files; it does not own the ImageCanvas Design surface. +- Gate result: Passed. + +## Project Context Loaded + +- Read the startup memory set, current state, architecture, business rules, success + criteria, ADR-007, commitments, peer task scope, and the accepted youth + experience/implementation specifications. +- The Current Specification remains the single semantic authority; Renderer drafts, + Task events and assistant deltas cannot become Creation Card truth. +- The UI reference library reinforced progressive disclosure and accessibility; its + parallax/dark-mode direction was rejected as inconsistent with MakeLore. +- Planning Gate result: Passed. + +## Outcome + +- Replaced the default professional field matrix with a conversation-first AI Design + surface and one compact “我的创作” card. The card is a pure projection of the + canonical Workspace Specification, Quote, Task and Asset state; the existing V2 + reducer and typed commands remain the only write path. +- Added an exhaustive A/B/C presentation catalog for every current Specification + field, one active creative choice with an additional “你帮我选” option, contextual + “精细调整”, and a responsive single-mounted card that becomes a mobile bottom + sheet at narrow widths. +- Reworded conversation, Quote, Task, recovery and result states for creators aged + 8–16. Compiler and Provider issue messages now cross a code-based youth-copy + boundary with safe unknown fallbacks, so raw English or technical messages are + not rendered in the youth UI. +- Kept video story editing on stable canonical Shot identities. The drawer supports + the server contract of up to 24 Shots and preserves timing, camera, framing, + motion, focus and transition data while a creator edits only a story beat. +- Bound transient Quote blockers to the canonical Specification revision: same- + revision refreshes preserve useful feedback, while a successful semantic change + clears stale blockers and enables a fresh Quote check. A terminal + `design_quote_blocked` response or event also settles its pending operation, so an + old Quote request cannot remain as a misleading “unknown” recovery action. +- No database migration, public DTO/API change, compatibility layer, second semantic + store, Provider activation or paid generation was added. + +## Verification + +- `pnpm exec vitest run tests/unit/youth-form-projection.test.ts tests/unit/youth-creation-card.test.tsx tests/unit/youth-issue-copy.test.ts tests/unit/fine-tune-drawer.test.tsx tests/unit/image-workspace-store.test.ts tests/unit/image-canvas-page.test.tsx` — 40 passed, including terminal Quote-blocked settlement, blocked-event recovery into a revised Quote, 24-Shot preservation, and explicit deletion of a cleared Shot. +- Broad client suite — 1802 passed and 2 skipped; two Electron binary-preparation + cases initially reported transient Windows `spawn EBUSY`, then their focused + rerun passed 3/3. The separate pressure suite passed 1/1. +- `pnpm exec tsc --noEmit` — passed. +- Scoped ESLint over every changed/new source and test file — passed. +- `pnpm run build:vite` — passed; only pre-existing chunk-size and mixed static/ + dynamic import warnings were reported. +- `pnpm exec playwright test tests/e2e/image-workspace-v2.spec.ts` — 2 passed, + covering 375 px, 768 px and desktop composition plus direct edit, chat, Quote, + confirmation and Task flow. + +## Follow-ups + +- Run moderated usability sessions with creators aged 8–16 after integration. +- Paid Provider activation and live paid-generation acceptance remain a separate + release gate. + +## Promotion Candidates + +- None. This task implements the already accepted youth Design experience and does + not introduce a new canonical architecture or product decision. diff --git a/src/pages/ImageCanvas/CreativeChoiceGrid.tsx b/src/pages/ImageCanvas/CreativeChoiceGrid.tsx new file mode 100644 index 00000000..23e0bebe --- /dev/null +++ b/src/pages/ImageCanvas/CreativeChoiceGrid.tsx @@ -0,0 +1,96 @@ +import { Check, Sparkles, X } from 'lucide-react'; +import { cn } from '@/lib/utils'; +import type { YouthActiveChoice } from './youth-form-projection'; + +export type CreativeChoiceGridProps = { + choice: YouthActiveChoice; + disabled?: boolean; + onSelect: (optionId: string) => void; + onReject?: () => void; +}; + +/** + * A small, keyboard-friendly surface for the one decision the creator needs + * to make next. The server-provided option label stays visible verbatim (so + * options such as “你帮我选” remain useful), while the first option gets a + * gentle recommendation marker. + */ +export function CreativeChoiceGrid({ + choice, + disabled = false, + onSelect, + onReject, +}: CreativeChoiceGridProps) { + if (choice.options.length === 0) return null; + + return ( +
+
+
+
+
+

{choice.title}

+

{choice.body}

+
+
+ +
+ 选择一个创作方向 + {choice.options.map((option, index) => { + const descriptionId = `${choice.id}-${option.id}-description`; + return ( + + ); + })} +
+ + {onReject && ( + + )} +
+ ); +} diff --git a/src/pages/ImageCanvas/DesignConversationPane.tsx b/src/pages/ImageCanvas/DesignConversationPane.tsx index e33f593e..0d145354 100644 --- a/src/pages/ImageCanvas/DesignConversationPane.tsx +++ b/src/pages/ImageCanvas/DesignConversationPane.tsx @@ -1,16 +1,17 @@ import { useEffect, useMemo, useRef } from 'react'; -import { Check, Loader2, MessageSquareText, Send, Sparkles, X } from 'lucide-react'; +import { Loader2, MessageSquareText, Send, Sparkles } from 'lucide-react'; import { toast } from 'sonner'; import { Button } from '@/components/ui/button'; import { Textarea } from '@/components/ui/textarea'; import { cn } from '@/lib/utils'; import { useImageWorkspaceStore } from '@/stores/image-workspace'; import type { DesignWorkspace } from '../../../shared/image-workspace'; +import { CreativeChoiceGrid } from './CreativeChoiceGrid'; const STARTER_MESSAGES = [ - '帮我做一张新品发布主视觉,先问我最关键的问题', - '我有一个模糊想法,请帮我整理成专业的图片设计方案', - '我要做一段产品短视频,请先规划叙事和分镜', + '画一只会做饭的机器人', + '把我的涂鸦变成一段动画', + '做一张社团活动海报', ]; export function DesignConversationPane({ workspace }: { workspace: DesignWorkspace }) { @@ -28,6 +29,10 @@ export function DesignConversationPane({ workspace }: { workspace: DesignWorkspa const submittingChat = Object.values(pendingOperations).some( (operation) => operation.status === 'submitting' && operation.command.kind === 'apply_input', ); + const activeDecisionPrompt = workspace.form.decisionPrompts + .find((prompt) => prompt.options.length > 0) + ?? workspace.form.decisionPrompts[0] + ?? null; useEffect(() => { const scrollAnchor = scrollAnchorRef.current; @@ -38,8 +43,8 @@ export function DesignConversationPane({ workspace }: { workspace: DesignWorkspa const submit = () => { if (!chatDraft.trim() || submittingChat) return; - void sendChat().catch((error) => { - toast.error(error instanceof Error ? error.message : '消息发送失败'); + void sendChat().catch(() => { + toast.error('消息没有发出去,请再试一次'); }); }; @@ -51,10 +56,10 @@ export function DesignConversationPane({ workspace }: { workspace: DesignWorkspa
-

与设计 Agent 对话

+

一起做作品

- 你说的每句话都会先进入设计规格,再由服务端编译成专业生成方案。 + 先说一个想法就好,我会一次只问一个重要问题。

@@ -64,16 +69,16 @@ export function DesignConversationPane({ workspace }: { workspace: DesignWorkspa
-

从自然语言开始

+

你想创作什么?

- 不需要一次把需求说完整。Agent 会把信息写入右侧表单,并把关键取舍留给你确认。 + 可以说一个想法,也可以先放一张图片。不用一次想完整。

{STARTER_MESSAGES.map((message) => (
))} - {workspace.form.decisionPrompts.map((prompt) => ( -
-
-
- -
-
-

{prompt.title}

-

{prompt.body}

-
-
-
- {prompt.options.map((option) => ( - - ))} -
- -
- ))} + {activeDecisionPrompt && ( + { + void resolveDecisionPrompt(activeDecisionPrompt.id, 'select', optionId).catch(() => { + toast.error('这个选择没有保存,请再试一次'); + }); + }} + onReject={() => { + void resolveDecisionPrompt(activeDecisionPrompt.id, 'reject').catch(() => { + toast.error('这个选择没有保存,请再试一次'); + }); + }} + /> + )}
@@ -170,11 +140,12 @@ export function DesignConversationPane({ workspace }: { workspace: DesignWorkspa submittingChat && 'opacity-80', )}>