feat: add notification feature

This commit is contained in:
luo
2026-07-29 10:25:13 +08:00
parent d115363115
commit d060edb698
11 changed files with 785 additions and 10 deletions

View File

@@ -0,0 +1,29 @@
## Context
The notification API returns the response payload through the existing request wrapper, so frontend API methods should expose the typed `data` payload directly. The home page is shared by agent and enterprise accounts and is loaded after login through `/pages/agent-system/home/index`.
## Goals / Non-Goals
- Goals: expose notifications, show the newest unread message after login, and keep server read state aligned with what the user has actually seen.
- Non-Goals: notification target resolution, controlled-resource routing, push notifications, or a separate manual read button.
## Decisions
- Decision: add a dedicated notification page for the notification entry. The entry is placed in the home page's top user-information card, and the page renders notification content only; notification rows have no click navigation.
- Decision: the login page writes a short-lived pending-reminder marker after storing a valid session. The home page consumes the marker after loading the authenticated user and requests the newest unread notification.
- Decision: use `GET /api/admin/notifications/unread-count` for the entry badge and `GET /api/admin/notifications?is_read=false&page=1&page_size=1` for the login reminder. The notification page requests the newest notification page with `page_size=50`.
- Decision: call `PUT /api/admin/notifications/{id}/read` as soon as an unread notification becomes visible in the reminder or notification list, update local state optimistically, and treat the API as idempotent.
- Decision: if the unread-count or reminder request fails, keep the home page usable and do not show a fabricated notification. The normal request interceptor continues to handle authentication failures.
## Risks / Trade-offs
- Marking on render means a message can become read before the user finishes reading it; this follows the requested “seen means read” behavior.
- A notification page displays the first 50 newest records; additional pagination is outside this change unless the API data requires it.
## Migration Plan
No data migration is needed. Deploy the frontend after the notification endpoints and icon asset are available. Rolling back removes the entry and UI without changing notification records.
## Open Questions
- None for the stated behavior. The entry opens the notification page, while notification content itself never navigates to a controlled target.

View File

@@ -0,0 +1,20 @@
# Change: Add notification entry and unread reminder
## Why
The backend notification contract is documented in `docs/通知.md`, but the frontend does not expose notifications to authenticated agent or enterprise users. Users also have no immediate way to notice newly issued unread messages after signing in.
## What Changes
- Add a notification shortcut to the home page using `src/static/icons/通知.png`.
- Add a notification page that lists the current account's notifications in newest-first order.
- Show the newest unread notification in a reminder modal after a successful login redirects to the home page.
- Mark a notification as read when it is rendered as visible to the user; no manual “mark as read” action is required.
- Do not resolve `target` data and do not navigate from a notification to any controlled resource.
- Display the unread count on the home-page notification entry when it is available.
## Impact
- Affected specs: `notifications` (new capability)
- Affected code: `src/api/notifications.ts`, `src/pages/agent-system/home/index.vue`, `src/pages/agent-system/notifications/index.vue`, `src/pages.json`, and the login-to-home session flow
- Existing user-supplied assets remain in place: `docs/通知.md` and `src/static/icons/通知.png`

View File

@@ -0,0 +1,91 @@
## ADDED Requirements
### Requirement: Home notification entry
The authenticated home page SHALL expose a notification entry for both supported account types. The entry MUST use `src/static/icons/通知.png`, display the current unread count when available, and open the notification page. Notification content MUST NOT resolve controlled targets or navigate to business resources.
#### Scenario: Agent sees notification entry
- **GIVEN** an authenticated agent is viewing the home page
- **WHEN** the unread-count request succeeds
- **THEN** the home page shows the notification icon and the returned unread badge text
- **AND** activating the entry opens the notification page without resolving a target
#### Scenario: Enterprise sees notification entry
- **GIVEN** an authenticated enterprise user is viewing the home page
- **WHEN** the home page renders its shortcuts
- **THEN** the notification entry is available with the same icon and behavior
#### Scenario: Unread-count failure does not block home
- **GIVEN** the authenticated home page has loaded
- **WHEN** the unread-count request fails
- **THEN** the home page remains usable
- **AND** no fabricated unread count is displayed
### Requirement: Notification list display
The notification page SHALL request the current account's non-expired notifications from `GET /api/admin/notifications`, display them newest first using the server order, and show each notification's title, body, category, severity, and creation time. Notification rows MUST be display-only and MUST NOT invoke `GET /api/admin/notifications/{id}/target` or navigate to another business page.
#### Scenario: Latest notifications are displayed
- **GIVEN** the notification page is opened
- **WHEN** the notification list request succeeds
- **THEN** the newest notification is rendered first
- **AND** each rendered notification shows its text content and read state
#### Scenario: No notifications
- **GIVEN** the notification page is opened
- **WHEN** the server returns an empty item list
- **THEN** the page shows an empty state
- **AND** it does not attempt target resolution
### Requirement: Post-login unread reminder
After a successful login redirects to the home page, the system SHALL request the newest unread notification and show it in a reminder modal when one exists. The newest unread notification MUST be the default displayed message. The reminder MUST not navigate to a controlled target.
#### Scenario: Newest unread notification is shown after login
- **GIVEN** a user has successfully logged in and is redirected to the home page
- **AND** at least one unread notification exists
- **WHEN** the home page finishes loading the authenticated session
- **THEN** a reminder modal displays the newest unread notification's title and body by default
#### Scenario: No unread notification
- **GIVEN** a user has successfully logged in and is redirected to the home page
- **WHEN** the unread notification query returns no items
- **THEN** no reminder modal is shown
#### Scenario: Reminder query failure
- **GIVEN** a user has successfully logged in and is redirected to the home page
- **WHEN** the newest unread notification query fails
- **THEN** the home page remains usable
- **AND** no reminder modal is shown
### Requirement: Read on visibility
The system SHALL mark an unread notification as read when its content becomes visible in the reminder modal or notification list. The UI MUST NOT require a manual read button, and it MUST update the local read state after initiating the read request.
#### Scenario: Reminder marks visible notification read
- **GIVEN** the newest unread notification is shown in the post-login reminder modal
- **WHEN** the modal becomes visible
- **THEN** the client calls `PUT /api/admin/notifications/{id}/read` for that notification
- **AND** the notification is treated as read locally without a manual action
#### Scenario: List marks visible unread notifications read
- **GIVEN** the notification page renders one or more unread notifications
- **WHEN** those notification rows become visible
- **THEN** the client initiates an idempotent read request for each visible unread notification
- **AND** no manual read control is rendered
#### Scenario: Read request is idempotent
- **GIVEN** a notification has already been marked read
- **WHEN** the client repeats the read request
- **THEN** the UI remains in the read state and the repeated request does not create a user-visible error

View File

@@ -0,0 +1,18 @@
## 1. API and session flow
- [x] 1.1 Add typed notification models and list, unread-count, and single-read API methods from `docs/通知.md`.
- [x] 1.2 Set a pending notification-reminder marker after a valid login session is stored.
## 2. Notification UI
- [x] 2.1 Add the notification page and register it in `src/pages.json`.
- [x] 2.2 Add the notification shortcut and unread badge to the top user-information card using `src/static/icons/通知.png`.
- [x] 2.3 Render notification content without target resolution or controlled-resource navigation.
- [x] 2.4 Show the newest unread notification in a post-login home-page reminder modal.
- [x] 2.5 Mark each notification read when it becomes visible and remove the manual read action.
## 3. Verification
- [x] 3.1 Run `pnpm type-check`.
- [x] 3.2 Run the relevant ESLint and style checks.
- [x] 3.3 Verify the login-to-home reminder, newest-first display, entry badge, and read-on-visible behavior.