feat: 7月迭代
All checks were successful
构建并部署前端到生产环境 / build-and-deploy (push) Successful in 1m11s

This commit is contained in:
luo
2026-07-27 18:13:19 +08:00
parent 6a794d88af
commit 4f281da778
27 changed files with 1176 additions and 167 deletions

View File

@@ -0,0 +1,23 @@
## ADDED Requirements
### Requirement: Asset views SHALL display the estimated final package expiry
Asset detail and summary views using `/api/c/v1/asset/info` SHALL prefer `estimated_final_expires_at` over `current_package_expires_at` for the user-facing final expiry. The client SHALL use `expiry_estimate_status`, `days_until_final_expiry`, and `is_expiring` when those fields are returned, and SHALL NOT calculate a replacement final expiry locally.
#### Scenario: Exact final expiry is available
- **WHEN** `expiry_estimate_status = exact` and `estimated_final_expires_at` is present
- **THEN** the client SHALL display the estimated final expiry date
- **AND** the client SHALL display the returned remaining-day value when available
#### Scenario: Asset is approaching final expiry
- **WHEN** `is_expiring = true` or the backend returns an applicable expiry level
- **THEN** the client SHALL apply the existing expiry highlight/reminder presentation
- **AND** the client SHALL use the backend value rather than recalculating the threshold
#### Scenario: Final expiry cannot be estimated
- **WHEN** `expiry_estimate_status` is `none`, `waiting_activation`, or `invalid_data`, or the estimated date is null
- **THEN** the client SHALL show the corresponding empty/pending state
- **AND** the client SHALL not present `current_package_expires_at` as if it were the final calculated expiry

View File

@@ -0,0 +1,29 @@
## ADDED Requirements
### Requirement: Real-name behavior SHALL use the effective backend asset policy
The H5/C client SHALL use `GET /api/c/v1/asset/info?identifier=...` as the source of truth for real-name behavior. It SHALL consume `effective_realname_policy`, `realname_required`, and `real_name_status` and SHALL NOT infer policy or final device real-name status from asset type, card type, device type, or frontend-only rules.
#### Scenario: Asset does not require real name
- **WHEN** asset information returns `effective_realname_policy = none` or `realname_required = false`
- **THEN** the client SHALL show the asset as not requiring real-name completion
- **AND** the client SHALL not block the normal order flow for real-name completion
#### Scenario: Real name is required before ordering
- **WHEN** asset information returns `effective_realname_policy = before_order`, `realname_required = true`, and `real_name_status` as not completed
- **THEN** the client SHALL show the real-name requirement
- **AND** the client SHALL prevent package order submission until the existing real-name flow completes
#### Scenario: Real name is required after ordering
- **WHEN** asset information returns `effective_realname_policy = after_order`
- **THEN** the client SHALL allow the policy-defined post-order flow to proceed without applying a before-order block
- **AND** the client SHALL display the returned real-name status and retain the existing real-name action entry when completion is needed
#### Scenario: Device status is resolved from server output
- **WHEN** a device has cards with different local-looking real-name states but the asset info response returns the effective device `real_name_status`
- **THEN** the client SHALL display and use that returned effective status
- **AND** the client SHALL not replace it with a card/device inference

View File

@@ -0,0 +1,70 @@
## ADDED Requirements
### Requirement: Payment options SHALL be rendered from backend permissions
The H5/C client SHALL use `allowed_payment_methods` from asset information and the recharge-check response to determine which payment methods are visible and selectable. It SHALL support the backend values `wallet`, `wechat`, and `alipay` where returned, and SHALL not hard-code a card/device payment-method matrix.
#### Scenario: Asset payment methods are returned
- **WHEN** asset information returns a non-empty `allowed_payment_methods` list
- **THEN** the package payment UI SHALL render exactly the methods allowed by that list
- **AND** the client SHALL not offer a method absent from the list
#### Scenario: Recharge permissions differ from asset permissions
- **WHEN** `/api/c/v1/wallet/recharge-check` returns its own `allowed_payment_methods` value
- **THEN** the wallet recharge UI SHALL use the recharge-check value for that recharge attempt
- **AND** the client SHALL not reuse a stale package-payment method list
### Requirement: Payment creation SHALL submit the selected method and the required WeChat app type
The client SHALL submit `identifier`, the relevant package or amount fields, and the user-selected `payment_method` to the applicable creation endpoint. It SHALL submit `app_type` only when `payment_method = wechat`, using the endpoint-defined value `official_account` or `miniapp`.
#### Scenario: Create a package order
- **WHEN** the user submits an allowed package payment method
- **THEN** the client SHALL call `POST /api/c/v1/orders/create` with `identifier`, `package_ids`, and the selected `payment_method`
- **AND** the client SHALL include `app_type` for WeChat payment as required
#### Scenario: Create a wallet recharge
- **WHEN** the user submits an allowed recharge method and an amount within backend limits
- **THEN** the client SHALL call `POST /api/c/v1/wallet/recharge` with the integer amount in cents, identifier, and selected payment method
- **AND** the client SHALL include `app_type` only for WeChat payment
#### Scenario: User-facing currency conversion
- **WHEN** an amount is returned by an API in cents
- **THEN** the client SHALL display the corresponding yuan value
- **AND** the client SHALL submit the original integer-cent representation to the API
### Requirement: Recharge submission SHALL honor the backend pre-check
The client SHALL call `GET /api/c/v1/wallet/recharge-check?identifier=...` before starting a recharge. When `need_force_recharge = true`, it SHALL use `force_recharge_amount`, `min_amount`, `max_amount`, and `message` from the response to guide or block the recharge flow.
#### Scenario: Force recharge is required
- **WHEN** recharge-check returns `need_force_recharge = true`
- **THEN** the client SHALL present the backend force-recharge amount and message
- **AND** the client SHALL not submit a normal recharge that violates the returned requirement
#### Scenario: Recharge is permitted normally
- **WHEN** recharge-check returns `need_force_recharge = false` and the amount is within the returned range
- **THEN** the client SHALL allow the user to select an allowed method and submit the recharge order
### Requirement: Payment results SHALL be confirmed by backend order state
After order creation, the client SHALL preserve existing handling for `pay_config` and `payment_link`, and SHALL use an order or recharge status query to confirm completion. A successful frontend redirect or payment-link return alone SHALL not be treated as proof of payment.
#### Scenario: Backend returns WeChat payment parameters
- **WHEN** a creation response contains `pay_config`
- **THEN** the client SHALL invoke the existing WeChat payment flow
- **AND** the client SHALL refresh backend payment status after the flow returns
#### Scenario: Backend returns a web payment link
- **WHEN** a creation response contains `payment_link`
- **THEN** the client SHALL use the existing payment-link presentation/handling
- **AND** the client SHALL confirm the resulting order or recharge state through the backend

View File

@@ -0,0 +1,23 @@
## ADDED Requirements
### Requirement: C-end login SHALL honor asset verification access decisions
The H5/C client SHALL call `POST /api/c/v1/auth/verify-asset` before continuing the asset login flow. A business failure or C-end login restriction returned by the endpoint SHALL be shown using the backend business message, and the client SHALL NOT continue to obtain, persist, or use an asset token for that login attempt.
#### Scenario: Asset verification allows login
- **WHEN** asset verification succeeds and returns an asset token
- **THEN** the client SHALL persist the identifier and returned asset token and continue the existing login flow
#### Scenario: Shop forbids a new C-end login
- **WHEN** asset verification returns a business failure indicating that the shop has forbidden C-end login
- **THEN** the client SHALL display the backend error message
- **AND** the client SHALL stop the current login flow before WeChat authorization or token persistence
- **AND** the client SHALL not revoke an already-issued token as a side effect
#### Scenario: Asset verification fails without a usable token
- **WHEN** the verification request returns an error response or no usable asset token
- **THEN** the client SHALL display the existing request/business error
- **AND** the client SHALL leave the current login attempt unauthenticated

View File

@@ -0,0 +1,55 @@
## ADDED Requirements
### Requirement: H5/C SHALL surface unread customer notifications
The H5/C client SHALL use `GET /api/c/v1/notifications/unread-count` for the homepage or notification-entry badge and `GET /api/c/v1/notifications` for the notification list. It SHALL consume the existing personal-notification contract and SHALL not add a separate API for expiry or exchange reminders.
#### Scenario: Unread notifications exist
- **WHEN** the unread-count endpoint returns a positive count
- **THEN** the homepage or notification entry SHALL display the unread indicator using that count
- **AND** the notification list entry SHALL remain available
#### Scenario: No unread notifications exist
- **WHEN** the unread-count endpoint returns zero
- **THEN** the client SHALL clear the unread indicator
- **AND** the notification entry SHALL not show a stale count
### Requirement: Expiry and exchange notices SHALL use the shared notification channel
The client SHALL display package-expiry and exchange-related notifications returned for the authenticated customer through the shared notification list or reminder popup. The backend notification data SHALL determine the expiry trigger and severity; the client SHALL not create independent timers that send business notifications.
#### Scenario: Package reaches a reminder threshold
- **WHEN** the notification service returns an unread package-expiry notice for the 15-day, 7-day, or 3-day threshold
- **THEN** the client SHALL display it through the existing H5/C notification entry or popup
- **AND** the client SHALL use the returned expiry level for presentation
#### Scenario: Critical expiry notice has highest priority
- **WHEN** unread expiry notices include a notice for 0 to 3 remaining days
- **THEN** the client SHALL give that notice the highest reminder priority
- **AND** the client SHALL not downgrade it based on a client-side date calculation
#### Scenario: Exchange notification is returned
- **WHEN** an exchange-related unread notice is returned after an exchange is created
- **THEN** the notification entry/list SHALL display the notice
- **AND** the client SHALL not call a separate marketing, ERP, or salesperson notification endpoint
### Requirement: Viewing a notification SHALL support marking it read
When the user views or activates a notification, the client SHALL call `PUT /api/c/v1/notifications/{id}/read` for that notification and reconcile the local unread count after a successful response. Repeated read actions SHALL remain safe according to the existing notification API contract.
#### Scenario: User reads an unread notice
- **WHEN** the user opens or advances to an unread expiry or exchange notification
- **THEN** the client SHALL mark that notification read through the existing endpoint
- **AND** the badge/list state SHALL reflect the read result
#### Scenario: Notification read request fails
- **WHEN** marking a notification read fails
- **THEN** the client SHALL retain the unread state or refresh it from the backend
- **AND** the failure SHALL not prevent the user from viewing other asset or notification content

View File

@@ -0,0 +1,38 @@
## ADDED Requirements
### Requirement: Discontinued packages SHALL remain renewable only for eligible existing customers
The H5/C client SHALL keep discontinued packages out of the ordinary package catalog shown to new customers and agents. An eligible existing customer SHALL be able to use a valid `current_package_id` from asset info or `package_ids` from a historical order to continue a package renewal.
#### Scenario: New customer opens the package catalog
- **WHEN** the package catalog contains a discontinued package that is not the customer's current package
- **THEN** the client SHALL not display that package as an ordinary purchase option
#### Scenario: Existing customer is using a discontinued current package
- **WHEN** asset info returns a discontinued package through `current_package_id`
- **THEN** the client SHALL expose that ID only in the eligible renewal context
- **AND** the client SHALL allow the customer to continue through the existing package-order flow
#### Scenario: Existing customer renews from a historical order
- **WHEN** a historical order returns one or more valid `package_ids`
- **THEN** the client SHALL use those IDs for the renewal selection when the existing renewal flow provides that entry
- **AND** the client SHALL preserve the historical order data unchanged
### Requirement: Renewal SHALL reuse the standard order creation contract
The client SHALL create a renewal by calling `POST /api/c/v1/orders/create` with the selected package ID or IDs, the asset `identifier`, and a currently allowed `payment_method`. It SHALL not invent or call a dedicated discontinued-package renewal endpoint.
#### Scenario: Submit a discontinued-package renewal
- **WHEN** an eligible customer confirms a renewal with an allowed payment method
- **THEN** the client SHALL submit the selected package IDs, identifier, and payment method to the standard order endpoint
- **AND** the client SHALL follow the standard payment response handling
#### Scenario: No eligible package ID is available
- **WHEN** neither asset info nor the relevant historical order supplies a valid package ID
- **THEN** the client SHALL show that renewal is unavailable
- **AND** the client SHALL not guess an ID from the ordinary package catalog

View File

@@ -0,0 +1,47 @@
## ADDED Requirements
### Requirement: Order views SHALL display backend role and asset snapshots
The H5/C client SHALL use `GET /api/c/v1/orders` and `GET /api/c/v1/orders/{id}` as the source of truth for order display. Order list and detail views SHALL display the backend `purchase_role` and `asset_identifier` values when present.
#### Scenario: Order includes a purchase role
- **WHEN** an order response returns `purchase_role`
- **THEN** the order list and detail view SHALL render that role
- **AND** the client SHALL not infer the role from the current user or asset type
#### Scenario: Card order includes an asset identifier
- **WHEN** a card order returns an `asset_identifier` snapshot
- **THEN** the client SHALL display the returned card identifier, such as ICCID, without replacing it with a current asset lookup
### Requirement: Device order identifiers SHALL prefer virtual number over IMEI
For device orders, the client SHALL display `virtual_no`/`VirtualNo` when it is non-empty, and SHALL use `imei` only when the virtual number is empty. The client SHALL not use `sn` as a substitute for the order asset identifier.
#### Scenario: Device has a virtual number
- **WHEN** a device order response contains a non-empty virtual number and an IMEI
- **THEN** the client SHALL display the virtual number
- **AND** the client SHALL not display SN as the order device identifier
#### Scenario: Device virtual number is empty
- **WHEN** a device order response has an empty virtual number and a non-empty IMEI
- **THEN** the client SHALL display the IMEI
#### Scenario: Historical identifier data is empty
- **WHEN** both the virtual number and IMEI are absent or empty
- **THEN** the client SHALL show the existing empty placeholder
- **AND** the client SHALL not fabricate an identifier from SN or a new asset-info request
### Requirement: Order amounts SHALL use the common currency display rule
Order list and detail views SHALL display `total_amount` and package prices converted from integer cents to yuan while preserving the integer-cent values in API requests and response state.
#### Scenario: Display an order amount
- **WHEN** an order response returns an amount in cents
- **THEN** the client SHALL render the corresponding yuan value
- **AND** the client SHALL not expose the raw cent value as the user-facing amount