docs(account): specify account collections client design

This commit is contained in:
2026-05-18 19:24:21 +08:00
parent c877f0551e
commit 82d097330a
2 changed files with 316 additions and 0 deletions
@@ -0,0 +1,315 @@
# Spark Account Collections Client Design
## Goal
Extend the Spark Store account experience across the backend and Electron/Vue client so users can log in or register through the forum identity flow, see account management data, use comments and favorites when logged in, sync store-recognized installed apps, and batch install apps from cloud favorites without breaking anonymous browsing, installation, removal, or update features.
## Scope
### Included
1. Clone or prepare a clean working copy of `https://gitee.com/erotica-rbqs/spark-store` for client implementation.
2. Extend the existing FastAPI backend at `https://gitee.com/erotica-rbqs/spark-unionid-server` with account data APIs for favorite folders, favorite items, downloaded records, and richer user profile data.
3. Keep login identity based on the Flarum forum. The client posts credentials directly to Flarum, then sends only the Flarum token and user id to the backend.
4. The login modal provides a register action by opening the forum registration page in the system browser.
5. Replace the upper-left SparkStore title area with an account entry while preserving the logo. After login, replace the logo with the user's avatar and show the username.
6. Add a logged-in account quick menu with user management, favorites, forum home, edit forum profile, and logout actions.
7. Keep anonymous base usage intact: browsing, searching, detail viewing, software install, software uninstall, update center, and installed-app viewing must work without login.
8. Gate account-only features: comments, favorites, cloud favorite management, downloaded record history, and cloud sync require login and show a login/register prompt when used anonymously.
9. Convert app details from modal overlay to a main-content detail page that fills the current app-list area, with a back button returning to the previous list state.
10. Add favorite actions from the detail page. Users can select a favorite folder; if none exists, the backend creates a default folder.
11. Store favorites as application-level identities, not a fixed Spark/APM variant. Batch install selects the currently preferred available variant according to the active priority configuration.
12. Record logged-in user downloads to the cloud when the user clicks download. Downloads made while anonymous are not backfilled after login.
13. On each client start, refresh installed package lists in the background. For logged-in users, ask once before enabling automatic cloud sync; remember the choice.
14. Build the sync list only from store-recognized listed applications, including Spark and APM apps, excluding unknown packages and dependencies.
15. User management shows avatar, nickname, Flarum user level, forum home link, and forum profile edit link.
16. Users can manage multiple favorite folders with custom names, remove invalid/downlisted apps, select all apps in a folder, and send selected installable apps to the existing download/install queue.
17. Favorite folder entries that are not available on the current platform or architecture remain visible with status labels. Downlisted entries remain visible and can be batch removed.
### Excluded
1. Client-side Flarum account creation forms. Registration is a browser link to the forum registration page.
2. Forum profile editing inside the client. The client opens the forum profile page externally.
3. Offline-first conflict resolution for favorites. Backend state is authoritative; client caches may improve UX but do not merge conflicting edits.
4. Automatic install on startup. Users must explicitly send favorites or restore items to the download queue.
5. Admin moderation, report handling, or anti-spam systems.
## Existing Context
The current client is an Electron + Vue 3 + TypeScript application. The target repository is `https://gitee.com/erotica-rbqs/spark-store`.
Important existing integration points:
1. `src/App.vue` coordinates tabs, app loading, install queue integration, detail opening, installed-app modal, and update center.
2. `src/components/AppHeader.vue` owns the top search/settings/about area.
3. `src/components/AppSidebar.vue` owns the current upper-left logo/title area and category navigation.
4. `src/components/AppDetailModal.vue` currently renders app details as an overlay modal. It already handles Spark/APM merged apps and source switching.
5. `src/components/InstalledAppsModal.vue` renders installed apps and origin switching.
6. `src/modules/processInstall.ts` creates download queue items and sends `queue-install` IPC messages.
7. `src/global/storeConfig.ts` owns store URLs and hybrid priority rules through `getHybridDefaultOrigin`.
8. `electron/main/backend/install-manager.ts` exposes install, remove, `check-installed`, `list-installed`, and availability IPC handlers.
9. `list-installed` already supports optimized Spark checks with a `pkgnameList`, and full APM listing marks dependencies by desktop-entry availability. Sync filtering should reuse these facts rather than scanning arbitrary system packages.
The Spark developer manual identifies this repository as the current Electron GUI store (`apm-app-store` behavior), while `amber-pm` owns package-management semantics after commands leave the GUI.
## Backend Design
### User Profile Extension
The existing backend auth flow remains unchanged at the boundary: `POST /auth/flarum` receives `flarum_user_id` and `flarum_token`, validates the token owner, upserts the local user, and returns a Spark Store JWT.
The Flarum validation service should also extract user group data from the authenticated actor when available. The backend stores a compact `forum_level` string and optional `forum_groups` JSON/text summary. If Flarum does not expose groups, `forum_level` falls back to `论坛用户`.
`GET /me` should return existing profile fields plus the forum level fields needed by the client. Existing clients remain compatible because new fields are additive.
### Favorite Folders
Add backend tables:
1. `favorite_folders`: id, user_id, name, created_at, updated_at. Folder names are user-scoped and unique per user. A folder named `默认收藏夹` is created on first favorite action if the user has no folders.
2. `favorite_items`: id, folder_id, app_key, pkgname, name, category, icon_url, created_at. Items are unique per folder and `app_key`.
Favorites are stored as app-level identities. The canonical app key for favorites should be stable across Spark/APM variants when the same user-facing app exists in both sources:
```text
favorite_app_key = app:{category}:{pkgname}
```
The item keeps `pkgname`, display `name`, `category`, and optional `icon_url`. It does not permanently bind to Spark or APM. During install, the client resolves the current catalog entry and chooses Spark/APM according to current availability and priority rules.
Backend endpoints:
1. `GET /me/favorite-folders`: list folders with item counts.
2. `POST /me/favorite-folders`: create folder with custom name.
3. `PATCH /me/favorite-folders/{folder_id}`: rename folder.
4. `DELETE /me/favorite-folders/{folder_id}`: delete folder and its items.
5. `GET /me/favorite-folders/{folder_id}/items`: list items.
6. `POST /me/favorite-folders/{folder_id}/items`: add or idempotently keep an app favorite.
7. `DELETE /me/favorite-folders/{folder_id}/items/{item_id}`: remove one item.
8. `POST /me/favorite-folders/{folder_id}/items/bulk-delete`: remove selected items, including invalid/downlisted entries.
All endpoints require JWT.
### Downloaded Records
Add `downloaded_apps`: id, user_id, app_key, pkgname, name, category, selected_origin, version, package_arch, downloaded_at.
Client behavior:
1. If the user is logged in when clicking download, the client posts a downloaded record after queuing the install task.
2. If the user is anonymous, the download proceeds normally and no cloud record is written.
3. Logging in later does not backfill anonymous downloads.
Backend endpoints:
1. `GET /me/downloaded-apps`: list newest downloaded records with pagination.
2. `POST /me/downloaded-apps`: upsert or append a downloaded record. MVP can append history; duplicate suppression by `user_id`, `app_key`, and `selected_origin` is acceptable if tests define it.
### Installed Sync List
The existing `GET /me/app-list` and `PUT /me/app-list` endpoints remain the default cloud installed-app list.
Client sync payload contains only store-recognized listed apps:
1. App must exist in the current loaded Spark/APM catalog.
2. `category !== "unknown"`.
3. `isDependency !== true`.
4. App has usable `pkgname` and `origin`.
Unknown system packages, dependencies, and packages not in the store catalog are excluded.
## Client Design
### Account Entry And Login
Move the account entry into the upper-left logo/title area currently owned by the sidebar. The logo remains visible while anonymous. The title text becomes `登录 / 注册` with helper text `星火账号`.
After login:
1. The logo image is replaced by the user's avatar when available.
2. The main text is the user's display name or username.
3. Clicking the account entry opens a quick menu.
4. The quick menu includes: `用户管理`, `我的收藏`, `论坛首页`, `修改论坛资料`, and `退出登录`.
Login modal:
1. Contains forum account and password inputs.
2. Posts credentials directly to Flarum `/api/token`.
3. Sends the returned Flarum token and user id to the backend.
4. Provides `注册账号` button that opens the Flarum registration page externally.
5. Never logs or stores the forum password.
### Anonymous Behavior
Anonymous users can still:
1. Browse homepage and categories.
2. Search.
3. View app details.
4. Download/install apps.
5. Remove installed apps.
6. Use update center.
7. View installed apps.
When anonymous users use account-only actions, show a login/register prompt instead of blocking the whole page. Account-only actions are comments, submit review, favorite, cloud favorites, downloaded history, and cloud sync.
### Detail Page
Replace the overlay detail modal with a main-content detail page inside the same area currently used by `AppGrid` and `HomeView`.
State model:
1. `currentView` or equivalent distinguishes `list`, `home`, and `detail`.
2. Opening an app stores the previous list context and selected app.
3. Back returns to the prior list/search/category state.
4. Screen preview can remain an overlay because it is secondary media UI.
The detail page keeps existing detail capabilities:
1. Spark/APM merged app source switch.
2. Install/open/remove actions.
3. Metadata and screenshots.
4. Download count.
New detail capabilities:
1. Favorite button.
2. Favorite folder selector.
3. Comments/reviews panel with login prompt for anonymous users.
4. Download click writes a cloud downloaded record only when logged in.
### Favorites Management
The user management area includes favorite folder management.
Users can:
1. List favorite folders.
2. Create folders with custom names.
3. Rename folders.
4. Delete folders.
5. View folder items.
6. Remove selected items.
7. Batch remove invalid/downlisted items.
8. Select all available items and send them to the download queue.
Availability resolution is client-side because it depends on the current catalog, architecture, Spark/APM availability, store filter, and priority rules.
Favorite item states:
1. `installable`: found in catalog and current source/architecture can install a preferred variant.
2. `installed`: already installed locally.
3. `platform-unavailable`: item exists but neither Spark nor APM variant is usable under current store filter/capability.
4. `arch-unavailable`: item exists in catalog metadata but not for the current architecture.
5. `downlisted`: item no longer exists in the loaded catalog.
Batch install uses current preference:
1. If only one usable variant exists, use it.
2. If both Spark and APM variants exist, use `getHybridDefaultOrigin` and the current store filter/availability to choose.
3. If the preferred variant is unavailable, use the other usable variant.
4. If no usable variant exists, do not queue it and show the reason.
### Downloaded Records
When a logged-in user clicks download/install from detail, favorites, restore, or installed sync restore flows, the client records the selected app to the backend after the queue item is created.
Downloaded records are visible in user management. They are informational and do not alter the install queue automatically.
### Startup Installed Sync
On startup, the client refreshes installed packages in the background after the catalog is loaded enough to provide package lists.
Flow:
1. Load Spark/APM catalog as normal.
2. Call existing `list-installed` IPC for enabled origins. Use optimized package-name checks where possible for Spark and full APM listing where needed, following the current installed modal/update-center patterns.
3. Merge results with catalog metadata.
4. Filter to store-recognized non-dependency apps.
5. If logged in and the user has not made a cloud sync decision, ask once whether to enable automatic installed-list sync.
6. If enabled, upload the default app list via `PUT /me/app-list`.
7. If disabled or anonymous, keep the refreshed list local only.
The confirmation preference is stored locally. A user can later change it from user management.
## Data Flow
### Login
1. User opens login modal from the upper-left account entry.
2. Client posts credentials to Flarum `/api/token`.
3. Flarum returns token and user id.
4. Client posts token and user id to backend `/auth/flarum`.
5. Backend validates token owner, stores profile and forum level, and returns Spark JWT.
6. Client stores Spark JWT and profile in local auth state.
### Favorite Add
1. Logged-in user clicks favorite on detail page.
2. Client fetches or creates favorite folders if needed.
3. User selects a folder.
4. Client posts app-level identity to backend favorite item endpoint.
5. UI updates folder item count and favorite state.
### Batch Install From Favorites
1. User opens a favorite folder.
2. Client resolves each favorite item against current catalog and install facts.
3. UI shows installable, installed, unavailable, arch-unavailable, and downlisted states.
4. User selects installable items or clicks select all installable.
5. Client maps each item to the chosen Spark/APM `App` object based on current priority rules.
6. Client calls existing `handleInstall(app)` for each selected item.
7. If logged in, client records downloaded apps to backend after queueing.
## Error Handling
1. Login failure from Flarum or backend shows a local error in the login modal and clears partial auth state.
2. Expired backend JWT logs the user out or prompts re-login when an account endpoint returns `401`.
3. Favorites and downloaded-record failures do not block base install; show a non-fatal account sync error.
4. Startup sync failure does not block app startup; it shows a user-management warning and can be retried manually.
5. Batch install skips unavailable/downlisted items and reports counts per state.
6. Backend rejects extra fields and invalid lengths with `422`.
## Testing And Verification
Backend tests:
1. Favorite folder creation, default folder creation, rename, delete, and user isolation.
2. Favorite item add/remove/idempotency and folder scoping.
3. Downloaded record create/list and user isolation.
4. Forum level extraction fallback.
5. Existing auth/reviews/app-list tests remain passing.
6. Alembic migration upgrade succeeds.
Client tests:
1. Account entry anonymous/logged-in rendering and quick menu actions.
2. Login modal emits login and opens register URL.
3. Auth state persistence and backend token handling.
4. Detail page replaces the list area and back returns to list state.
5. Favorite folder selector login gating and folder selection.
6. Favorite availability resolver for installable, installed, platform-unavailable, arch-unavailable, and downlisted states.
7. Batch install selects Spark/APM variant according to current priority rules.
8. Startup sync filtering includes only store-listed non-dependency Spark/APM apps.
9. User management renders profile, forum level, forum links, favorite folders, downloaded records, and sync preference.
10. Existing install, update center, installed apps, search, and grid tests remain passing.
Final client verification:
1. `npm run test`
2. `npm run lint`
3. `npm run build:vite`
Final backend verification:
1. `.venv/bin/pytest -v`
2. `DATABASE_URL=<fresh test url> .venv/bin/alembic upgrade head`
## Implementation Notes
1. Use a clean client worktree or fresh clone from `https://gitee.com/erotica-rbqs/spark-store` before implementing. Do not mix previous untracked planning artifacts into code commits.
2. Keep backend and client commits separate.
3. Add `.superpowers/` to `.gitignore` so visual companion artifacts remain local.
4. Preserve existing IPC contracts for install and update flows.
5. Do not change `amber-pm` package-management behavior; only reuse GUI-side install queue paths.
6. Keep UI components focused: account entry/menu, login modal, detail page, favorite selector, user management, and favorite folder manager should be separate components rather than expanding `App.vue` further.