Files
NianAIGC/findings.md
2026-07-03 11:25:25 +08:00

36 KiB

Findings & Decisions

Requirements

  • User asked: "了解整个项目" — inspect and understand the whole project, then explain it clearly.
  • Expected output: concise but useful project map in Chinese, including purpose, stack, structure, runtime flow, commands, and notable risks.

Research Findings

  • Top-level project is not a Git repository; git status --short returned "fatal: not a git repository".
  • Root contains orchestration/docs files plus a removed extracted runtime application directory.
  • removed extracted runtime/node_modules is present, so dependencies appear already installed for the embedded runtime app.
  • The initial full file scan showed many bundled media assets under removed extracted runtime/public, especially starter/planning/Seedance examples.
  • README.md states this was extracted from the 智念助手 desktop app into an independent 智念创作助手 project.
  • The project is based on an existing extracted runtime Next.js standalone runtime; original source was deleted, so this is not a full source restoration.
  • Root package.json only orchestrates scripts: start/dev call removed runtime start script, health calls scripts/health-check.mjs, and info calls removed runtime info script.
  • Runtime package uses Next ^15.1.4, React ^19.0.0, Supabase client, Ali OSS, lucide-react, TypeScript, Vitest, and ESLint, but it is treated as generated runtime.
  • Runtime state should be written to root .runtime/, not under removed extracted runtime.
  • removed runtime start script loads .env and .env.local, optionally bundled .env.runtime only when ZHINIAN_LOAD_BUNDLED_ENV=1.
  • Startup creates .runtime/data, .runtime/uploads, and .runtime/generated-results, then launches removed extracted runtime/server.js with NODE_ENV=production.
  • Health check targets /api/desktop/health and expects JSON with appId: "removed-runtime" and ok: true.
  • .env.example shows the real generation path depends on Seedance / Volcengine Ark plus Aliyun OSS configuration.
  • Extraction notes confirm copied assets include Next standalone server runtime, .next output, runtime node_modules, public/reference media, content manifests, and planning cases; secrets, user uploads, generated results, and Electron host/process manager code were excluded.
  • npm run info succeeded and reports runtime app id removed-runtime, bundle timestamp 2026-05-14T04:01:58.653Z, entry server.js, and size 949,760,759 bytes.
  • App routes include: /, /studio, /studio/[mode], /planning, /projects, /projects/[id], and /billing.
  • API routes include: /api/assets, /api/assets/upload, /api/billing, /api/desktop/health, /api/generations, /api/generations/[id], /api/generations/[id]/retry, /api/projects, /api/projects/[id], /api/prompt/assemble, and /api/reference-templates.
  • File-serving routes expose runtime uploads and generated results via /uploads/[...path] and /generated-results/[...path].
  • Creation modes currently report one mode: video_studio / 宣传片创作台, editor type storyboard_cards.
  • Starter catalog has 14 cases across storefront_avatar_storyboard, music_sync_ad, and creative_remix; planning cases include five visible categories such as short-video promo and premium-brand.
  • Compiled API code reveals a local JSON store at app-state.json with users, assets, projects, generation_jobs, and credit_transactions.
  • The default local user is demo-merchant / demo@localmerchant.ai with 9999 demo credits.
  • /api/projects returns projects with their jobs; project creation is coupled to generation creation and deducts credits based on duration/resolution/ratio.
  • /api/assets/upload accepts multipart file, role, and optional promptLabel; it stores to Ali OSS when OSS env is complete, otherwise writes to local uploads and records an asset.
  • /api/prompt/assemble builds a Chinese Seedance-style video prompt from shop/project details, selected template, storyboard, and optional avatar/outfit selection.
  • Seedance client defaults: base URL https://ark.cn-beijing.volces.com/api/v3, model doubao-seedance-2-0-260128, ratio 9:16, duration 15, resolution 720p.
  • Real generation creation posts to /contents/generations/tasks; query uses /contents/generations/tasks/{id}.
  • Missing SEEDANCE_API_KEY causes a user-facing error and the project/job path refunds credits after marking the job failed.
  • Health response includes services.seedanceConfigured and services.objectStorageConfigured.
  • GET /api/generations/:id reads a local job, polls Seedance when provider_job_id exists, and backs up successful result videos to OSS or local generated-results.
  • POST /api/generations/:id/retry loads the original project settings and re-runs the generation creation flow.
  • GET /api/projects/:id returns one project with jobs; DELETE /api/projects/:id removes the project, jobs, and related credit transactions.
  • GET /api/assets returns local assets for the demo owner; GET /api/billing returns demo user and credit transactions.
  • GET /api/reference-templates?mode=... returns starter templates filtered by mode.
  • Content definition has one canonical creation mode: video_studio, product name 宣传片创作台, editor type storyboard_cards, reference-first workflow, and six asset slot labels.
  • Starter catalog contains 14 selectable templates and 85 local asset records from the Seedance guide plus local promo examples.
  • Template categories represented in content are storefront_avatar_storyboard, music_sync_ad, and creative_remix; docs say legacy mode arguments are accepted for compatibility.
  • Planning page content has five planning cases: 短视频宣传类, 剧情宣传类, 热门玩梗类, 卡通 IP 类, and 品质高级类.
  • Avatar presets currently include one default digital-human model and one default outfit pairing.
  • Runtime verification passed: npm run info succeeded, npm start launched Next on http://127.0.0.1:3000, and npm run health returned ok: true.
  • Health verification reports seedanceConfigured: false and objectStorageConfigured: false, matching the empty local env configuration.
  • Direct curl verification with --noproxy '*' returned 200 OK for /studio, {"projects":[]} for /api/projects, one template for /api/reference-templates?mode=video_studio, and the demo billing user.
  • Starting the runtime created .runtime/data/app-state.json with the demo user and initial credit transaction.

Technical Decisions

Decision Rationale

Issues Encountered

Issue Resolution
git status cannot run because the project root has no .git metadata Treat this as a plain project folder and avoid Git-based assumptions
zsh treats [id] in file paths as a glob pattern Quote bracketed Next.js dynamic route paths when reading them
Initial plain curl calls hit a local proxy and returned 502/empty output Use curl --noproxy '*' for localhost verification

Resources

  • Project root: /Users/inmanx/Documents/zhinian-creation-assistant
  • Runtime app: /Users/inmanx/Documents/zhinian-creation-assistant/removed extracted runtime
  • Root README: /Users/inmanx/Documents/zhinian-creation-assistant/README.md
  • Runtime README: /Users/inmanx/Documents/zhinian-creation-assistant/runtime/README.md
  • Startup script: /Users/inmanx/Documents/zhinian-creation-assistant/removed runtime start script
  • Health script: /Users/inmanx/Documents/zhinian-creation-assistant/scripts/health-check.mjs
  • Runtime info script: /Users/inmanx/Documents/zhinian-creation-assistant/removed runtime info script
  • Extraction notes: /Users/inmanx/Documents/zhinian-creation-assistant/docs/EXTRACTION_NOTES.md
  • App paths manifest: /Users/inmanx/Documents/zhinian-creation-assistant/removed extracted runtime/.next/server/app-paths-manifest.json
  • Compiled projects API: /Users/inmanx/Documents/zhinian-creation-assistant/removed extracted runtime/.next/server/app/api/projects/route.js
  • Compiled upload API: /Users/inmanx/Documents/zhinian-creation-assistant/removed extracted runtime/.next/server/app/api/assets/upload/route.js
  • Compiled prompt assembly API: /Users/inmanx/Documents/zhinian-creation-assistant/removed extracted runtime/.next/server/app/api/prompt/assemble/route.js
  • Compiled generation polling API: /Users/inmanx/Documents/zhinian-creation-assistant/removed extracted runtime/.next/server/app/api/generations/[id]/route.js
  • Compiled generation retry API: /Users/inmanx/Documents/zhinian-creation-assistant/removed extracted runtime/.next/server/app/api/generations/[id]/retry/route.js
  • Creation modes JSON: /Users/inmanx/Documents/zhinian-creation-assistant/removed extracted runtime/content/seedance-starter/creation-modes.json
  • Starter catalog JSON: /Users/inmanx/Documents/zhinian-creation-assistant/removed extracted runtime/content/seedance-starter/catalog.json
  • Planning cases JSON: /Users/inmanx/Documents/zhinian-creation-assistant/removed extracted runtime/content/removed planning case manifest.json
  • Runtime local state file: /Users/inmanx/Documents/zhinian-creation-assistant/.runtime/data/app-state.json

Visual/Browser Findings

  • 2026-05-29 UI polish verification:
    • /create, /create?mode=video, /assets, and /settings were checked during the product polish work.
    • 375, 768, 1024, and 1440 width checks showed no horizontal overflow after the compact header and mobile control changes.
    • The video duration dropdown on /create?mode=video exposes only 4 秒 through 15 秒.
    • The header logo loads from public/logo/zhinian-logo.png; after the final branding pass it has no border, background, or box shadow.

2026-05-29 UI/UX and Branding Findings

  • The current source app is now a Web app in the repository root, not the old removed extracted runtime standalone-only flow described in the earliest findings.
  • GSAP is used through lib/ui/motion.ts rather than directly sprinkled across components.
  • The UI direction is a professional creation workspace, not a marketing landing page.
  • Visible English eyebrows/descriptions were removed from module headers per user preference.
  • Topbar should remain compact and avoid horizontal scrolling below it.
  • Product name is now 智念AIGC平台.
  • Logo source folder: /Users/inmanx/Documents/icon/logo.
  • Current logo asset: public/logo/zhinian-logo.png.
  • Current logo was generated from /Users/inmanx/Documents/icon/logo/2d5b992caa14db16f594c4933e92e37e.png by removing the white background and cropping whitespace.
  • Avoid using the white transparent logo on the light topbar unless the topbar itself becomes dark; wrapping the logo in a dark frame changes the brand feel.

2026-05-29 Seedance Findings

  • Official Volcengine Ark "创建视频生成任务 API" docs say Seedance 2.0 duration supports integer seconds in [4, 15], or -1 for model-chosen duration.
  • Seedance 2.0 and Seedance 1.5 Pro support adaptive ratio behavior.
  • Supported ratios include 16:9, 4:3, 1:1, 3:4, 9:16, 21:9, and adaptive.
  • Supported resolutions include 480p, 720p, and 1080p, but Seedance 2.0 fast does not support 1080p.
  • frames is not supported for Seedance 2.0 / Seedance 1.5 Pro, so the current app should continue using integer duration.
  • generate_audio defaults true in the API and remains enabled in the app payload.

2026-05-29 Operational Findings

  • For localhost verification, continue using curl --noproxy '*' because local proxy settings can interfere with direct checks.
  • Before running npm run build, stop the dev server (screen -S zhinian-dev-ui -X quit and pkill -f 'next dev --hostname 127.0.0.1 --port 3000') to avoid stale Next dev chunk issues.
  • After build verification, restart the dev server in screen session zhinian-dev-ui on 127.0.0.1:3000.

2026-05-29 Deployment Findings

  • Server one-command deployment is now bash scripts/deploy.sh.
  • Docker Compose service name is zhinian-aigc.
  • Docker Compose defaults to exposing host port 3000; set APP_PORT in .env.local or shell to change it.
  • NEXT_PUBLIC_APP_URL should be set to the public domain or server URL in production so generated local file URLs are correct.
  • Persistent runtime data is bind-mounted through ./.runtime:/app/.runtime; this folder should be backed up on real servers.
  • .env.local is intentionally used as the compose env_file and remains ignored by Git.
  • Current local machine does not have the Docker CLI available, so Docker build was not run here; script syntax, app tests, production build, and local health were verified instead.

2026-05-29 Public API and Task Management Findings

  • User confirmed multi-task support should be task management logic, not an external message queue.
  • Public API v1 now uses ZHINIAN_API_KEYS, supporting Authorization: Bearer <key> and X-Zhinian-Api-Key.
  • Task creation and provider execution are now split: submit routes enqueue GenerationJob records; Worker ticks claim and process jobs.
  • generation_jobs now carries external client, idempotency, priority, attempts, lock, schedule, timing, and webhook fields.
  • Supabase/Postgres production mode expects the claim_generation_jobs function from supabase/schema.sql for atomic task claiming.
  • Local JSON mode serializes task claiming through the existing local write queue and is intended for single-instance development.
  • Worker execution can run as npm run worker, npm run worker:once, or the zhinian-worker Docker Compose service.
  • Internal Worker processing goes through /api/internal/worker/tick protected by ZHINIAN_INTERNAL_WORKER_TOKEN in production.
  • API v1 routes are /api/v1/capabilities, /api/v1/assets, /api/v1/jobs, /api/v1/jobs/:id, /api/v1/jobs/:id/cancel, and /api/v1/openapi.json.
  • Local verification created a public API job and processed it to succeeded through npm run worker:once in mock mode.
  • Public API asset access now includes /api/v1/assets/:id and /api/v1/assets/:id/download.
  • Uploaded and generated assets created through public API flows are tagged as api-client:<clientId> so integrations can query and download their own results later.
  • OpenAPI is generated dynamically from the current deployment origin at /api/v1/openapi.json.
  • Operations handoff docs live in docs/DEPLOYMENT.md; partner API docs live in docs/API.md.

2026-05-29 Image Tuning Findings

  • Jimeng image generation supports the current scale parameter, so UI presets should submit numeric text-influence values for that engine.
  • EvoLink image generation does not use Jimeng scale; the per-request engine-aware control should submit EvoLink quality instead.
  • Current local /api/health reports image.generate using EvoLink, so /create should show 生成质量 options rather than 文本影响.

2026-05-29 Account Login / SSO Findings

  • User requested account login before release so the project is safe to use.
  • Provided SSO guide recommends OAuth2 Authorization Code for Web SSO: redirect to ${AUTH_BASE}/oauth2/authorize, receive code and state, then exchange code server-side at ${AUTH_BASE}/oauth2/token.
  • OAuth client defaults in the guide use client_id=customPC and scope=server; client_secret must stay on the server.
  • Access tokens are JWTs; resource services should verify locally with JWKS from ${AUTH_BASE}/oauth2/jwks rather than calling auth on every request.
  • Minimum JWT checks from the guide: RS256 signature, exp, nbf/iat, issuer https://pig4cloud.com, OAuth client id, scope/authority requirements.
  • Logout endpoint is DELETE ${AUTH_BASE}/token/logout, but local session deletion remains required because existing JWTs may stay valid until exp.
  • Current app has no login middleware or session helper; pages are client components under a global shell.
  • Current local data store defaults all assets/jobs to DEFAULT_OWNER_ID = "demo-merchant", so account login must also address per-user owner IDs for first-party UI APIs.
  • Public API v1 already has separate API key auth through ZHINIAN_API_KEYS; SSO should preserve that server-to-server surface.
  • First-party UI APIs that currently need session ownership include /api/assets, /api/assets/upload, /api/assets/:id/*, /api/generations/image*, /api/generations/video*, and /api/settings.
  • Generation services already accept optional ownerId, so route handlers can pass the authenticated owner without rewriting provider dispatch or worker logic.
  • Retry helpers currently preserve the original request payload; they need to override ownerId on retry so a user cannot retry another user's job if they know the id.
  • /uploads/* and /generated-results/* serve local runtime files directly; middleware should protect these paths for cookie-authenticated browser sessions.
  • /api/v1/* and /api/internal/worker/tick must remain outside browser SSO middleware because they use API keys and worker tokens.
  • Implemented browser SSO with signed HttpOnly zhinian_session cookies; middleware validates the signed session instead of exposing JWTs to client JavaScript.
  • JWT access tokens are verified in the callback using RS256 and configured JWKS, with issuer, client id, expiry, not-before, issued-at, and scope checks.
  • Local file routes now resolve storagePath back to an asset record and require the current owner to match before serving bytes.
  • Public API v1 remains API-key based and can still read/download its assets through public API routes even when browser SSO protects the Web UI.

2026-05-29 Password Captcha Login Findings

  • User provided live auth configuration and a password grant sample; real secret values remain only in the ignored local environment file.
  • ${AUTH_BASE}/code/image?randomStr=... returns a PNG captcha image.
  • The password grant sample successfully returns a JWT access token, refresh token, expected client/user claims, tenant id, and server scope.
  • The local /api/auth/password endpoint verified the returned JWT with JWKS and created a signed browser session for the authenticated user.
  • Browser form login with the displayed math captcha succeeded and redirected to /create; the topbar showed the authenticated username and logout button.
  • Logout cleared the session and returned to /auth/login?loggedOut=1.

2026-05-29 Standalone Login Page Findings

  • Login routes under /auth/* should not render the shared app topbar; the login page is a standalone entry surface.
  • The login page now intentionally presents only the NIANXX logo, 智念AIGC平台, and the account/password/captcha form.
  • The visible 统一认证中心 OAuth entry was removed from the login page after user feedback.
  • The standalone login page uses the existing GSAP motion helper layer (runScopedMotion, revealChildren, pulseFeedback) for consistent app motion.
  • Browser viewport checks passed at 1280x800 and 390x844: no topbar, no SSO link text, logo and platform name present, login panel present, and no horizontal overflow.

2026-06-09 Repository and Runtime Status Findings

  • The current repository root is a Git checkout on main tracking origin/main.
  • The remote is https://git.nianxx.cn/wangxuming/NianAIGC.git.
  • The workspace was overwritten from remote and is currently clean at d98e58a docs: update public api docs.
  • The project uses npm (package-lock.json) and Next.js dev startup through npm run dev.
  • Local Node version during verification was v22.22.1, satisfying the package.json >=20 engine.
  • During startup verification, ports 3000, 3001, and 3002 were already occupied by local Node/Next processes or listeners; use a confirmed-free alternate port rather than assuming 3000.
  • npm run dev -- --hostname 127.0.0.1 --port 3003 successfully started the current project and reached Next Ready in 2.9 seconds.
  • A smoke request to http://127.0.0.1:3003/ returned 307 Temporary Redirect to /auth/login?next=%2F, confirming the login-protected app flow.
  • Current status check on 2026-06-09 found no next dev / next-server process and no listener on 3003; the project is verified startable but not currently running.

2026-07-01 Account ID Partitioning Findings

  • First-party browser APIs already pass the authenticated session user id into asset and generation flows.
  • Public API v1 currently authenticates by clientId:key, but jobs and assets are still created with ownerId = DEFAULT_OWNER_ID.
  • Public API listing/detail access filters with externalClientId and api-client:<clientId> tags, which works as an access check but keeps all API account data in one default owner partition.
  • The data store and Supabase schema already support owner_id indexes and idempotency uniqueness by (owner_id, external_client_id, idempotency_key), so the change can be made by deriving a stable account owner id from the API client id.
  • Job detail and cancel routes currently check only externalClientId; they should also require the account owner id so a client id collision cannot cross account partitions.
  • Implemented owner derivation as publicApiOwnerId(client), yielding api:<sanitizedAccountId>.
  • Public API job creation, idempotency lookup, job listing/detail/cancel, asset upload/register/list/detail/download now use the derived API account owner.
  • Documentation now states that ZHINIAN_API_KEYS uses 账号ID:key and that records are partitioned under api:<账号ID>.

2026-07-01 Password Login Captcha Finding

  • origin/main is up to date at d98e58a; relevant history includes ce358df 修改认证中心对接方式 and 288e31d 移除验证码输入框.
  • Current components/auth-login-panel.tsx does not render captcha controls and submits only username, password, and next.
  • Current app/api/auth/password/route.ts no longer requires captcha; it only forwards code and randomStr if they are present in the request body.
  • Current local .env.local points password login at https://onefeel.brother7.cn/ingress/auth with client id customPC.
  • A local login probe with fake credentials returned 验证码不能为空; a direct token request to the configured auth center with the same non-secret dummy credentials also returned 验证码不能为空.
  • Therefore the observed captcha error is coming from the configured auth center instance, not from the current AIGC frontend or password route validation.
  • The operations SSO guide defaults external projects to OAuth client app/app, recommends adding token-flow clients to security.ignore-clients, and notes customPC is a special platform-user compatibility client that skips AES password decrypt.
  • Dummy token probes showed app/app reaches normal credential validation (用户名或密码错误) while customPC is intercepted by captcha validation on the current auth center instance.
  • Updated the project defaults, docs, .env.example, and local .env.local to use app/app plus ZHINIAN_AUTH_PASSWORD_ENC_KEY=thanks,pig4cloud.
  • After restarting the dev server, local /api/auth/password with dummy credentials returns 用户名或密码错误, confirming the captcha interception is bypassed for the configured client.

2026-07-01 Internal RBAC / Account Management Findings

  • Initial requested guide /Users/inmanx/Desktop/organization-external-api.md was missing; updated guide /Users/inmanx/Desktop/organization-external-api(1).md is available and has 1310 lines.
  • Existing JWT session already stores authorities and scope on AuthUser, making it suitable for internal RBAC.
  • Before the RBAC change, navigation exposed 创作, 结果, 日志, and 设置 to every logged-in user.
  • Before the RBAC change, middleware only checked whether a user was authenticated and did not distinguish ordinary users from administrators.
  • Before the RBAC change, /api/settings checked requireAppUser() but not admin permission.
  • Before the RBAC change, /api/logs relied on middleware authentication only and did not call requireAppUser() or admin checks inside the route.
  • RBAC now hides admin navigation for ordinary users and protects /logs, /settings, /accounts, /api/logs, /api/settings, and /api/admin/*.
  • Updated guide covers organization, department, role, member, and enterprise user operation APIs.
  • Organization/member APIs are served by basic-capability-services-biz; enterprise user management APIs are exposed by hotel-staff-server-biz.
  • Member list APIs remain @Inner and require header from: Y.
  • Enterprise user APIs require Authorization and a token with administrator role 1; otherwise they return 仅管理员角色允许调用.
  • Account creation should use /adminOrganization/organizationMember/addOrganizationMemberAndCreatePlatformUser to create the enterprise user and bind the organization member in one call.
  • Password maintenance is available through /adminPcUser/resetPlatformUserPassword, with tenantId, numeric userId, newPassword, and optional mustChangePassword.
  • Updated /Users/inmanx/Desktop/organization-external-api(2).md confirms the external member list path is /adminOrganization/organizationMember/organizationMemberList through hotelStaff; only the basic service internal /organizationMember/organizationMemberList path needs from: Y.
  • The updated hotelStaff member-list proxy is reachable from the app, but the current login token can still be rejected by the upstream service with 仅管理员角色允许调用.
  • Local RBAC allow-listing ceshiop as a platform admin only controls this app's pages and APIs; it does not grant upstream hotelStaff administrator role 1 inside the authentication center token.
  • Account management now treats upstream member-list administrator denial like a recoverable member-list-only limitation: the page can still load configured organization data and keep account creation/password maintenance available when those upstream endpoints allow the token.
  • The updated organization guide exposes department creation at POST /organizationGroup/createOrganizationGroup with organizationId, groupName, optional groupDesc, and optional parentId.
  • The account page can create a department from the member form and then refresh/select the created department, so admins do not need to leave account management before creating members.

2026-07-02 Image Template Findings

  • User requested image-generation templates with selection-time effect preview and preset prompt support.
  • This should be account-managed data, not global environment configuration.
  • Existing browser image generation API already uses requireAppUser() and submits ownerId: user.id, so template APIs should use the same owner boundary.
  • Template configuration should remain inside the image generation module rather than the global settings page.
  • The create page already keeps image/video prompt state client-side, detects the active image engine from /api/health, and submits prompt, materials, size, force-single, and engine-specific tuning to /api/generations/image.
  • Implemented image templates with fields for name, category, description, preset prompt, preview image URL, width/height, force-single, and sort order.
  • New first-party routes are /api/image-templates and /api/image-templates/:id; both require the app user and use the authenticated user id as owner id.
  • Local JSON state now normalizes imageTemplates; Supabase deployments need the new image_templates table from supabase/schema.sql.
  • Browser verification used a temporary auth-disabled dev server to create one demo template, confirm the /create left template rail and template application behavior, then deleted the demo template.
  • Final dev server was restarted with the normal .env.local auth-enabled environment on 127.0.0.1:3001.

2026-07-02 Large Auth Session Finding

  • A new real account could receive a successful /api/auth/password response and still be redirected back to /auth/login?next=/create, which indicates the browser did not persist a valid session rather than an upstream password failure.
  • The session cookie stores the signed session plus access token so the app can forward the current login token to organization/staff APIs.
  • Accounts with larger JWT or authority payloads can exceed a single browser cookie's practical size limit; splitting zhinian_session into chunked cookies keeps the same signed payload while allowing middleware and server helpers to reassemble it.
  • Settings no longer exposes a template tab.
  • In image mode, /create now renders a left vertical 模板选择 rail with an icon 添加模板 button and thumbnail/name-only template cards.
  • The add-template entry opens an in-module template form modal; it is not exposed from settings.
  • Clicking a template selects it and brings its preset prompt, image size, and force-single value into the generation console on the right.
  • Desktop and narrow browser verification confirmed the template picker is an independent left-side panel beside the generation panel, not a child of the generation panel, with no horizontal overflow.
  • The image/video/edit mode switch is now contained by the generation panel, not placed above or across the far-left template module.
  • Template preview image upload now uses the same /api/assets/upload route as workbench materials, so configured OSS storage is reused instead of accepting a manually typed preview URL.
  • New template configuration no longer exposes category or remark fields; the user-facing free text field is 简介, backed by the existing template description data.
  • Template preset prompts can contain @图片1 style placeholders. The generation console parses those tokens and shows missing upload slots below the prompt.
  • Placeholder upload slots bind the uploaded asset to the exact requested token, so clicking the @图片2 slot creates/updates the @图片2 material instead of relying on upload order.
  • Material labels are preserved after removal to avoid silently breaking prompt references created by templates.
  • UI/UX skill guidance for the add-template modal was applied as a focused SaaS workspace form: strong preview region, fewer visible decisions at once, clear bottom actions, and responsive stacking on narrow screens.
  • While editing a template prompt, parsed placeholder chips are shown below the textarea so users can confirm which upload slots the template will request after selection.
  • Image templates now store the target image generation engine in settings.engine, with Jimeng using settings.scale and Image2/EvoLink using settings.quality.
  • First-party image generation now accepts a per-request engine override and passes it into submitImageJob(), so template engine choices are honored by the provider payload.
  • The generation console exposes the current image engine selector; applying a template updates this selector plus the matching parameter control.
  • Material placeholders now require an explicit number, so @图片1 and @图2 create upload slots while bare @图片 or @图片这种普通文字 stay plain prompt text.
  • Template prompt editing includes explicit placeholder insertion controls for image/video/audio slots, making the placeholder confirmation action deliberate instead of relying on unfinished @ typing.
  • Existing image templates can be reopened from the top-right edit action on each template card and saved through the account-scoped PATCH route.
  • The template rail is intentionally wider on desktop and each card separates image preview, template selection, and template editing into distinct controls.
  • Clicking a template thumbnail opens a larger preview dialog; choosing from that dialog applies the template and closes the preview.
  • Typing @ in prompt editors now opens a temporary material draft slot instead of immediately writing a partial token into the prompt body.
  • A material draft is confirmed into the prompt only by Enter or explicit option selection; confirmed values are inserted with text boundaries so subsequent Chinese text is not absorbed into the token.
  • The temporary draft slot is shared by the generation prompt and template preset prompt; invalid text such as 图片这种普通文字 stays in the slot and does not create upload requirements.
  • Confirmed numbered tokens keep using the existing visual token overlay, placeholder chips, and missing upload-slot UI.
  • The temporary material draft slot should remain visually inside the prompt editor surface, not below the input, so @ entry feels like an inline editing affordance.
  • Template preset prompts use the same token overlay as the generation prompt; confirmed placeholders such as @视频1 are visibly colored inside the input area before saving the template.
  • The image template rail now uses a wider desktop/tablet track (390-480px desktop, 315-375px tablet) and stacks above the generation panel on mobile so reference previews stay browseable.
  • Template thumbnails use a 4:3 viewport with contained images, allowing both 9:16 and 16:9 reference images to be inspected without cropping.
  • Template card application now requires the explicit 选择模板 button; thumbnail clicks open preview and template name/description text no longer selects the template.
  • The template rail remains visible in image and video generation modes; only the image-editing modes (局部重绘, 智能超清) use the standalone editor layout without the template rail.
  • Template cards are fixed compact items (138px x 184px) inside the rail list, so each template has a consistent smaller footprint.
  • The template rail height is synchronized from the right generation panel through a ResizeObserver; the rail body is split into fixed header/action rows and a scrolling template-list row.
  • The scrollbar belongs only to .image-template-rail-list; 模板选择 and 添加模板 stay outside the scroll container.
  • Template rail cards now use their preview image as a full-bleed card surface with object-fit: cover.
  • Template card title, intro, and select action sit inside a bottom floating frosted-glass overlay; the select button remains the only action that applies the template.
  • The zoom icon was removed from template cards, while the edit icon remains on the top-right corner above the image.
  • Selected template cards use a heavier layered shadow and slight upward transform to create stronger depth.
  • The template intro/description field is no longer part of the create/edit template UI or card display; old stored descriptions may still exist in data but are ignored by this surface.
  • The template edit icon now sits inside the card's frosted-glass overlay instead of on the image corner.
  • Template selection is a toggle: the first click captures the current right-side image generation state and applies the template; clicking the selected template again restores that snapshot and clears the active template state.
  • The compact full-bleed template card target is 132px x 176px; the widened desktop rail should fit three cards per row.
  • The card footer uses a two-row frosted-glass grid: title spans the first row, while the select/cancel button and edit icon share the second row to avoid cramped text or overlap.

2026-07-02 Create Task Module Findings

  • The creation console can reuse existing first-party APIs for a task list: /api/generations/image, /api/generations/video, and /api/assets.
  • GenerationJob already has the needed task fields: prompt/name fallback, status, created/updated timestamps, capability, and output asset ids.
  • Generated task thumbnails can be resolved by mapping GenerationJob.outputAssetIds to assets from /api/assets; queued/running tasks need a placeholder when no output asset exists yet.
  • The existing results page already has a task view and detail panel, so the create-page 查看详情 action deep-links to /assets?view=tasks&taskId=<id> instead of creating a separate task page.
  • Desktop create layout now supports three independent modules: left template rail, center generation console, and right task module. At narrower widths the task module drops below the main modules, and at mobile widths all modules stack without horizontal overflow.
  • The right task module now targets 560-640px on desktop/wide screens so task name, status, elapsed time, and 查看详情 can stay on one horizontal row.
  • Queued/running jobs without output assets should render a clear 生成中 thumbnail placeholder instead of a generic empty asset icon.
  • Completed image-task thumbnails are preview actions inside /create; clicking them opens the same large asset-preview surface while 查看详情 remains the route to the full task page.