feat: new

This commit is contained in:
luo
2026-09-16 16:32:08 +08:00
parent 6a1543f9f6
commit 8bd9de15cd
22 changed files with 2502 additions and 33 deletions

View File

@@ -0,0 +1,52 @@
## ADDED Requirements
### Requirement: H5 SHALL query popup candidates once per page entry
The system SHALL call `GET /api/c/v1/popup-candidates` exactly once per page entry with the current page and asset identifier, and SHALL render the returned candidate or stay silent when none exists. The query SHALL NOT be prefetched, polled, or repeated inside one entry.
#### Scenario: Candidate exists on page entry
- **WHEN** the user enters `home`, `package_purchase`, or `asset_wallet_recharge` and the backend returns a candidate
- **THEN** the system SHALL show the candidate title/body popup
#### Scenario: No candidate on page entry
- **WHEN** the backend returns an empty candidate
- **THEN** the system SHALL show no popup
- **AND** the page SHALL continue its normal flow
#### Scenario: Same notification id within one day
- **WHEN** a later page entry returns the same `notification_id` already handled this session
- **THEN** the system SHALL NOT re-popup the same notification
### Requirement: Popup actions SHALL use a frontend whitelist
The system SHALL map `action_type` through a frontend whitelist only and SHALL NOT accept URLs or routes from the backend. `package_purchase` routes to the package purchase page, `asset_wallet_recharge` routes to the wallet page, and an empty value shows no action.
#### Scenario: package_purchase action
- **WHEN** the candidate `action_type` is `package_purchase`
- **THEN** the popup SHALL navigate to the package purchase page
#### Scenario: asset_wallet_recharge action
- **WHEN** the candidate `action_type` is `asset_wallet_recharge`
- **THEN** the popup SHALL navigate to the asset wallet page
#### Scenario: No action
- **WHEN** `action_type` is empty
- **THEN** the popup SHALL show no action button
### Requirement: Popup dismissal SHALL mark the notification read
The system SHALL call `PUT /api/c/v1/notifications/{id}/read` with the candidate `notification_id` when the popup is dismissed or when its action is taken. Popup closing and action-taking SHALL NOT use `read-all`.
#### Scenario: User closes the popup
- **WHEN** the user closes the popup
- **THEN** the notification SHALL be marked read
#### Scenario: User takes the popup action
- **WHEN** the user taps the action button
- **THEN** the notification SHALL be marked read
- **AND** the mapped page SHALL open
### Requirement: Resource-invisible responses SHALL be silent
The system SHALL treat HTTP 400 / `code=1180` responses uniformly as resource-invisible and SHALL NOT branch UI, show special prompts, or distinguish asset-missing from not-owned states.
#### Scenario: Invisible asset on popup query
- **WHEN** the popup query returns an invisible-asset error
- **THEN** the system SHALL show no popup
- **AND** the page SHALL continue its normal flow

View File

@@ -0,0 +1,28 @@
## ADDED Requirements
### Requirement: Risk-exchange popup SHALL collect a shipping address
The system SHALL present a shipping address form when the candidate `popup_type` is `risk_exchange`, collecting recipient name, recipient phone, and full address, and SHALL submit them to `POST /api/c/v1/risk-exchanges/{asset_id}/address` using the candidate `asset_id` (never derived from the H5 identifier).
#### Scenario: Valid address submission
- **WHEN** the user fills the required fields and submits
- **THEN** the risk-exchange request SHALL be submitted with the candidate `asset_id`
- **AND** the system SHALL show the returned exchange number and status
#### Scenario: Invalid or incomplete fields
- **WHEN** the user submits empty or invalid fields
- **THEN** the system SHALL block submission and prompt for the missing fields
### Requirement: Address submission SHALL be idempotent
The system SHALL NOT provide an edit-address UI. Repeated or concurrent submissions return the first-created exchange order and address without overwriting.
#### Scenario: Repeated submission
- **WHEN** the user submits the address again for the same asset
- **THEN** the system SHALL return the first-created exchange order and address
### Requirement: Risk-exchange failures SHALL keep the user in place
The system SHALL keep the address form open on failure and treat invisible-asset failures uniformly without UI branching.
#### Scenario: Submission failure
- **WHEN** the address submission fails
- **THEN** the system SHALL keep the form open
- **AND** the user SHALL be able to retry

View File

@@ -0,0 +1,36 @@
## MODIFIED Requirements
### Requirement: Personal notification list SHALL preserve backend ordering
The system SHALL display personal notifications in the backend-fixed order (created time and notification id descending) and SHALL NOT re-sort items client-side by severity or priority.
#### Scenario: Backend returns a fixed order
- **WHEN** the notification list is loaded
- **THEN** the items SHALL be rendered in the returned order
### Requirement: Notification items SHALL pass through popup fields and types
The system SHALL render items with the new `type` values `h5.popup.risk_exchange` and `h5.popup.operation` (category `system`) and SHALL keep `popup_snapshot` available for popup-related actions without treating it as a route.
#### Scenario: List contains a popup notification
- **WHEN** an item has `type` `h5.popup.risk_exchange` or `h5.popup.operation`
- **THEN** the item SHALL render as a normal system-category notification
### Requirement: Unread badge SHALL reflect popup notifications
The system SHALL count popup notifications in the unread badge and collapse the badge to `99+` above 99 per the `display_count` contract.
#### Scenario: Popup notification unread
- **WHEN** a popup notification is unread
- **THEN** the unread badge SHALL increase accordingly
### Requirement: Mark-read SHALL include the notification id and be idempotent
The system SHALL send the notification `id` in the mark-read request body and SHALL treat success responses idempotently.
#### Scenario: Mark-read an already-read notification
- **WHEN** the notification is already read or owned by another customer
- **THEN** the request SHALL still succeed
### Requirement: read-all SHALL NOT close popups implicitly in the popup chain
The system SHALL NOT call `read-all` from any popup display path because it also marks today's popup notifications read.
#### Scenario: Popup display flow
- **WHEN** the popup candidate flow runs
- **THEN** the system SHALL NOT call `read-all`