docs: add mini program prototype redesign spec

This commit is contained in:
2026-05-01 23:35:23 +08:00
parent ced0bd14df
commit 52071d0d77
@@ -0,0 +1,749 @@
# Mini Program Prototype Redesign Design
Date: 2026-05-01
Status: Draft approved for planning
## Context
The prototype directory `mini-program-prototype/开心OS-UI设计/开心OS-UI设计` contains eight new design references:
- `人生轨迹-首页.png`
- `人生轨迹-记录界面.png`
- `人生轨迹-内容界面.png`
- `人生轨迹-编辑资料.png`
- `爽文生成-灵感模式.png`
- `爽文生成-剧本列表.png`
- `爽文生成-大纲.png`
- `爽文生成-正文.png`
The current mini program already has the core functional modules:
- `mini-program/src/pages/main/index.vue`
- `mini-program/src/pages/main/RecordView.vue`
- `mini-program/src/pages/main/ScriptView.vue`
- `mini-program/src/pages/main/ScriptDetailView.vue`
- `mini-program/src/pages/main/PathView.vue`
- `mini-program/src/pages/profile/index.vue`
- `mini-program/src/pages/onboarding/index.vue`
- `mini-program/src/stores/app.js`
- `mini-program/src/services/lifeEvent.js`
- `mini-program/src/services/epicScript.js`
- `mini-program/src/services/lifePath.js`
- `mini-program/src/services/userProfile.js`
The backend already has script generation support under:
- `backend-single/src/main/java/com/emotion/controller/EpicScriptController.java`
- `backend-single/src/main/java/com/emotion/service/EpicScriptService.java`
- `backend-single/src/main/java/com/emotion/service/impl/EpicScriptServiceImpl.java`
- `backend-single/src/main/java/com/emotion/dto/request/EpicScriptCreateRequest.java`
The missing product capability is a complete inspiration-mode flow. The backend currently exposes generic script creation, but it does not expose dedicated endpoints for inspiration recommendations, random inspiration, or one-sentence inspiration generation.
## Goals
1. Redesign the mini-program pages to match the new prototype visual direction: dark cosmic background, purple glass panels, glowing primary actions, rounded bottom navigation, and stronger card hierarchy.
2. Keep the existing product functions largely unchanged.
3. Complete the functional flow from life events to script generation to script detail to path realization.
4. Add backend inspiration-mode APIs in `backend-single`.
5. Make the implementation modular enough to land in batches without leaving broken flows.
## Non-Goals
1. Do not build a full content-management system for scripts.
2. Do not introduce a new frontend framework or state library.
3. Do not require new production image assets before the flow can work.
4. Do not redesign unrelated admin or web projects.
5. Do not change authentication semantics.
## Information Architecture
The main mini-program experience will be organized around three tabs:
1. `人生轨迹`
- Timeline home
- Life event recording
- Life event detail
2. `爽文生成`
- Inspiration mode
- Custom mode
- My scripts list
- Script detail with article and outline views
3. `我的`
- Profile overview
- Profile editing
`PathView.vue` remains part of the script-to-life-path flow. It can stay reachable after selecting a script, but it does not need to be a bottom-tab item if the new navigation follows the prototype's three-tab model.
## Frontend Design
### Shared Shell
`pages/main/index.vue` should provide the unified app shell:
- Safe-area-aware page container.
- Cosmic dark background with restrained purple glow.
- Shared fixed bottom navigation with three tabs.
- Shared page padding and scroll constraints.
- Shared user/profile entry point where needed.
The app shell should remove the current emoji-based tab icons and replace them with consistent visual icons using existing SVG assets where possible. If assets are insufficient, use simple text/icon-font compatible placeholders without relying on emoji as primary UI.
### Visual Tokens
Core colors:
- Background top: near-black navy.
- Background middle: deep purple black.
- Surface: translucent blue-purple.
- Surface border: low-opacity violet.
- Primary: violet to electric purple gradient.
- Secondary accent: blue, green, and amber chips for event categories.
- Text primary: warm white.
- Text secondary: lavender gray.
- Text muted: low-opacity lavender.
Spacing:
- Page horizontal padding: 28-36rpx.
- Card padding: 28-40rpx.
- Major vertical rhythm: 32-48rpx.
- Touch targets: at least 80rpx high for primary controls.
Shape:
- Major panels: 32-44rpx radius.
- Pills/chips: 999rpx or 24-32rpx radius.
- Nested input surfaces: 20-28rpx radius.
Effects:
- Use thin borders, subtle inner glow, and one meaningful outer shadow per major card.
- Avoid excessive nested cards.
- Avoid decorative motion that impacts scroll performance.
### 人生轨迹 Home
Primary file: `RecordView.vue`, with helper components if the file becomes too large.
The page should become the timeline home shown in `人生轨迹-首页.png`:
- Profile hero card:
- Avatar
- Nickname
- Status text
- Star sign
- MBTI
- Profession
- Hobbies
- Edit profile action
- Timeline header:
- Title `人生轨迹`
- Subtitle
- Optional map button as UI affordance
- Filters:
- `全部`
- `童年`
- `高光`
- `低谷`
- `美好的瞬间`
- Custom/add action
- Timeline list:
- Date and age column
- Vertical glowing line and nodes
- Event card with title, tag, summary, image/placeholder, and chevron
- Floating or bottom primary action:
- `记录人生经历`
- Opens the recording page.
Data source:
- Existing `store.events`.
- Existing life-event service transforms.
- If an event lacks image data, show a deterministic gradient/illustration placeholder.
### Life Event Recording
New or refactored page, based on `人生轨迹-记录界面.png`.
Fields:
- Time section:
- Specific date
- Year/month
- Season
- Timeline range
- Event title:
- 30 character limit in UI.
- Event content:
- 500 character limit in UI.
- `AI 帮我写` action.
- Tags:
- Growth
- Study
- Work
- Travel
- Relationship
- Family
- Friendship
- Challenge
- Breakthrough
- Harvest
- Moving
- Confusion
- Custom tag
- Submit:
- Calls existing life-event creation.
- Refreshes `store.events`.
- Navigates back to timeline.
First implementation can keep `AI 帮我写` as an assisted placeholder or call an existing AI chat endpoint if the current backend already supports a compatible authenticated chat API. It must not block event creation.
### Life Event Detail
New page based on `人生轨迹-内容界面.png`.
Sections:
- Event summary card:
- Year/date range
- Tag
- Title
- Location if available
- Image or placeholder
- Event description:
- Full event content
- Collapse/expand affordance if content is long
- AI analysis:
- Mental state interpretation
- Growth meaning
- Possible challenges
- Suggestion
- Related tags.
- Bottom actions:
- Edit
- Favorite
- Chat about this life event
- Share
Functional priority:
1. Event detail display.
2. Edit entry.
3. Chat/favorite/share UI feedback.
If the existing event model only has a single `aiFeedback` string, the UI should split it into analysis blocks only when parseable. Otherwise, show it as one AI analysis block with graceful empty states.
### 爽文生成 Entry
Primary file: `ScriptView.vue`, with extraction into components if needed.
The page should follow `爽文生成-灵感模式.png`.
Header:
- Title `爽文生成`
- Subtitle
- Right action `我的剧本`
Mode switch:
- `灵感模式`
- `自定义模式`
Inspiration mode:
- Large prompt textarea, 500 character limit.
- Placeholder examples.
- Character count.
- Voice input button as a visual affordance.
- Random inspiration button.
- Main CTA `生成我的人生剧本`.
- Daily remaining count.
- Inspiration recommendation grid.
- Recent generated script card.
Custom mode:
- Keep current custom fields:
- Basic persona
- Theme
- NPC/persona
- Style
- Length
- Restyle fields to match the prototype, but keep the existing data shape unless backend changes are required.
### My Scripts List
Can be a separate page or a mode within `ScriptView.vue`, based on `爽文生成-剧本列表.png`.
Required UI:
- Header `我的剧本`
- Search/menu actions
- New script action
- Top filters:
- Long
- Short
- Style
- Status filters:
- All
- In progress
- Completed
- Draft
- Favorites
- Sort control.
- Script cards:
- Cover
- Title
- Length badge
- Status badge
- Tags
- Summary
- Chapter count
- Word count
- Last updated
- Progress bar or favorite state
Data source:
- Existing `store.scripts`.
- Missing fields should be derived where possible or shown with defaults.
### Script Detail
Primary file: `ScriptDetailView.vue`, based on `爽文生成-大纲.png` and `爽文生成-正文.png`.
Header:
- Back action.
- Title.
- More action as UI affordance.
Script hero:
- Cover or placeholder.
- Main tag.
- Title.
- Edit title/action affordance.
- Category tags.
- Summary.
- Expand summary action.
Stats:
- Chapter count.
- Word count.
- Popularity if available, otherwise hidden or derived placeholder.
- Reading progress if available, otherwise default.
Tabs:
- `正文`
- `大纲`
Article tab:
- Chapter title.
- Time/location metadata if available.
- Body text rendered with the existing Markdown component.
- `开开解读` insight card.
- Bottom action bar:
- Night mode
- Font size
- Continue reading
- Rewrite plot
- Share
Outline tab:
- Chapter timeline.
- Chapter card:
- Chapter number
- Title
- Status
- Summary
- Word count
- Menu affordance
- Sticky bottom action:
- Table of contents
- Continue reading
- Generate next chapter
Data handling:
- Prefer structured data from `plotJson` if available.
- If unavailable, parse `plotJson.fullContent` or `content` into sections.
- If parsing fails, show a single chapter containing the full content.
### Profile and Edit Profile
`profile/index.vue` should align with the shared dark/glass system and the new bottom navigation.
`onboarding/index.vue` or a dedicated edit page should follow `人生轨迹-编辑资料.png`:
- Header:
- Back
- Title `编辑资料`
- Save
- Hero profile card:
- Avatar
- Nickname
- Status/signature
- Basic information:
- Nickname
- Gender
- Birthday if supported
- City if supported
- Zodiac
- MBTI
- Career information:
- Profession
- Industry if supported
- Company if supported
- Personality tags.
- Interests.
- Personal intro.
Existing persisted fields:
- `nickname`
- `gender`
- `mbti`
- `zodiac`
- `profession`
- `hobbies`
- existing future/memory fields if already supported
Fields not supported by current backend should not silently vanish. The implementation should either:
1. Hide unsupported fields in the first pass, or
2. Store them only after confirming backend support.
Recommendation: keep unsupported fields out of the first implementation unless the backend schema already supports them.
## Backend Design
### Endpoint Summary
Add inspiration-mode endpoints under the existing script domain:
1. `GET /epicScript/inspiration/recommendations`
2. `GET /epicScript/inspiration/random`
3. `POST /epicScript/inspiration/generate`
These can live in `EpicScriptController` or a new `EpicScriptInspirationController`. A dedicated controller is cleaner if the codebase already tolerates feature-specific controllers. Reusing `EpicScriptController` is acceptable for a smaller change.
### Request DTO
Create `EpicScriptInspirationRequest`.
Fields:
- `prompt: String`
- Required for generation.
- Max 500 characters.
- `mode: String`
- Default `inspiration`.
- `style: String`
- Optional.
- Defaults to current service behavior.
- `length: String`
- Optional.
- Defaults to current service behavior.
- `characterInfo: String`
- Optional.
- `lifeEventsSummary: String`
- Optional.
- `source: String`
- Optional, for analytics or future differentiation.
### Response DTOs
Create `InspirationSuggestionResponse`.
Fields:
- `text`
- `tag`
- `category`
Create `EpicScriptInspirationResponse`.
Fields:
- `script: EpicScriptResponse`
- `prompt`
- `remainingCount`
- `suggestions`
The generate endpoint can also simply return `Result<EpicScriptResponse>` if the project prefers minimal DTOs, but a dedicated response is better for exposing remaining count.
### Service Behavior
Add service methods to `EpicScriptService` or a dedicated `EpicScriptInspirationService`:
- `List<InspirationSuggestionResponse> getRecommendations()`
- `List<InspirationSuggestionResponse> getRandomSuggestions(Integer size)`
- `EpicScriptInspirationResponse generateFromInspiration(EpicScriptInspirationRequest request)`
Recommendation: add a dedicated `EpicScriptInspirationService` if implementation grows beyond simple static suggestions. For first pass, adding methods to `EpicScriptService` is acceptable if scoped.
Generation algorithm:
1. Validate authenticated user via existing user context.
2. Validate `prompt`.
3. Check daily generation limit.
4. Convert inspiration request into `EpicScriptCreateRequest`:
- `title` derived from prompt, capped safely.
- `theme` set to prompt.
- `style` and `length` from request or defaults.
- `characterInfo` from request.
- `lifeEventsSummary` from request.
- `plotJson` contains metadata:
- `mode: inspiration`
- `prompt`
- `source`
5. Reuse `EpicScriptService.createScript`.
6. Return the created script plus remaining count.
### Daily Limit
Prototype shows `今日剩余生成次数:3次`.
First-pass recommendation:
- Limit to 3 inspiration generations per user per day.
- Count records where:
- current user owns script
- create date is today
- `plotJson.mode == inspiration`, if queryable
If JSON querying is not convenient in the current persistence layer, use one of these simpler options:
1. Count all scripts created today by the current user.
2. Store a simple marker in an existing string field if acceptable.
3. Use Redis if already configured and stable in this backend.
Recommendation: count all scripts created today for the current user in the first pass. It is stricter but simple and reliable.
### Error Handling
- Empty prompt: validation error.
- Prompt longer than 500: validation error.
- Unauthenticated user: existing auth handling.
- Daily limit exceeded: business error with clear message.
- AI workflow failure:
- Prefer returning an error for inspiration generation, because the user explicitly asked to generate.
- If preserving current behavior, create a draft script with a clear fallback summary and `plotJson.aiStatus = failed`.
Recommendation: return an error and do not create a fake successful inspiration script if AI fails.
## Frontend Data Flow
### App Load
`main/index.vue` calls:
- `store.initialize()`
- `store.fetchUserProfile()`
- `store.fetchEvents()`
- `store.fetchScripts()`
- `store.fetchPaths()`
Avoid repeated fetches when switching tabs unless data changed.
### Life Event Flow
1. User taps `记录人生经历`.
2. Event form opens.
3. User fills date/title/content/tags.
4. Frontend calls `lifeEvent.createEvent`.
5. Store refreshes events.
6. User returns to timeline.
7. User taps event.
8. Detail page loads from store or backend detail.
### Inspiration Script Flow
1. `ScriptView.vue` loads recommendations.
2. User types prompt or taps random suggestion.
3. User taps generate.
4. Frontend calls `epicScript.generateFromInspiration`.
5. Store refreshes scripts.
6. User is taken to script detail or sees the new script in recent generation.
### Custom Script Flow
Existing custom generation remains available:
1. User switches to custom mode.
2. User edits persona/theme/NPC/style/length.
3. Existing `createScript` flow runs.
4. Store refreshes scripts.
### Script Detail Flow
1. User opens script.
2. Detail page attempts to load by id.
3. It renders hero, stats, tabs.
4. It extracts outline chapters from structured or parsed content.
5. Selecting a script still calls existing `selectScript`.
6. Path realization remains connected to selected script.
## File-Level Implementation Plan Preview
This is not the implementation plan, but it defines expected ownership boundaries.
Mini program:
- `src/pages/main/index.vue`
- Shared shell and bottom navigation.
- `src/pages/main/RecordView.vue`
- Timeline home.
- `src/pages/main/LifeEventFormView.vue` or `src/pages/life-event/form.vue`
- New event form.
- `src/pages/main/LifeEventDetailView.vue` or `src/pages/life-event/detail.vue`
- New event detail.
- `src/pages/main/ScriptView.vue`
- Inspiration/custom generation entry.
- `src/pages/main/ScriptListView.vue` if separated.
- My scripts list.
- `src/pages/main/ScriptDetailView.vue`
- Article/outline detail.
- `src/pages/profile/index.vue`
- Profile overview.
- `src/pages/onboarding/index.vue`
- Edit-profile alignment, unless a new edit page is more practical.
- `src/services/epicScript.js`
- Add inspiration API calls.
- `src/stores/app.js`
- Add inspiration recommendations state and generation action if needed.
- `src/pages.json`
- Add new routes.
Backend:
- `EpicScriptController.java` or new `EpicScriptInspirationController.java`
- `EpicScriptService.java`
- `EpicScriptServiceImpl.java` or new service
- `EpicScriptInspirationRequest.java`
- `EpicScriptInspirationResponse.java`
- `InspirationSuggestionResponse.java`
- Tests for validation and happy path.
## Accessibility and Mobile UX
- All primary tap targets should be at least 80rpx high.
- Bottom actions must include safe-area padding.
- Long titles should wrap or clamp predictably.
- Cards must not create horizontal scrolling.
- Text contrast should remain readable over glass backgrounds.
- Loading states should be visible for script generation.
- Disabled states must be visually distinct and non-interactive.
## Risks
### Chinese Encoding
Many files displayed mojibake in terminal output. Before editing production copy, implementation must verify whether files are actually corrupted or only decoded incorrectly by the terminal. Do not propagate mojibake into new code.
### Scope Size
This is a complete visual and flow redesign across several frontend pages plus backend additions. Even though the desired scope is full, implementation should land in clear batches:
1. Backend inspiration API.
2. Frontend services/store wiring.
3. Shared shell and navigation.
4. Life track pages.
5. Script generation/list/detail pages.
6. Profile/edit pages.
7. Final QA/build pass.
### Assets
The prototypes use rich illustrated covers and planets. If production assets are missing, first pass should use:
- Existing static images.
- Deterministic gradient placeholders.
- Existing SVG assets.
Do not block core flow on image generation or asset sourcing.
### Backend AI Failure
Existing script generation catches AI failures. Inspiration mode should be explicit: either return a clear error or create a draft with failed AI status. The recommended behavior is clear error with no fake success.
## Verification
Frontend verification:
- Mini-program build passes.
- Main bottom navigation switches between three tabs.
- Life events list renders as a timeline.
- User can create a life event.
- User can open life event detail.
- Inspiration recommendations load.
- Random inspiration updates the prompt or suggestion list.
- Inspiration generation creates a script.
- Script list shows generated scripts.
- Script detail shows article and outline.
- Profile page and edit profile page render without overlap.
- Common 375px wide viewport has no horizontal scroll, clipped text, or bottom nav overlap.
Backend verification:
- Recommendation endpoint returns suggestions for authenticated users.
- Random endpoint returns suggestions.
- Generate endpoint rejects empty prompt.
- Generate endpoint rejects prompt over 500 chars.
- Generate endpoint respects authenticated user context.
- Generate endpoint enforces daily limit.
- Generate endpoint calls existing script generation path and returns created script.
## Open Questions
1. Should unsupported profile fields from the prototype, such as birthday, city, industry, company, and intro, be hidden in the first pass or added to backend persistence?
2. Should inspiration generation failure return an error, or save a failed/draft script?
3. Should `PathView.vue` remain reachable only after selecting a script, or should it stay as a visible third/fourth tab?
Recommended answers for first implementation:
1. Hide unsupported profile fields unless backend support already exists.
2. Return a clear generation error and do not save fake success.
3. Keep path realization reachable after selecting a script, not as a primary bottom tab.