## 1. Scaffold and workspace wiring - [ ] 1.1 Scaffold `apps/mobile` as a Nuxt3 app `@vmall/mobile` picked up by the existing `apps/*` pnpm workspace glob, with `dev`/`build`/`preview` scripts, dev server port 3003 (mall 3000, shop-admin 3001, admin 3002), and en/zh i18n matching the mall's locale source. - [ ] 1.2 Import `@vmall/shared/theme.css` and style exclusively with shared tokens and Tailwind utilities (brand `#ca151e`, `#f5f5f5` surfaces); no private global stylesheet. - [ ] 1.3 Wire `@vmall/shared` `createApi` as the only data path — mall-consistent `runtimeConfig.public.apiBase`, `getToken` reading `localStorage["vmall.token"]`, and the same per-domain live/fixed adapter selection as the mall (reuse the existing fixed adapter instead of authoring new API glue). No app-local fetch wrapper, endpoint paths, or response types. - [ ] 1.4 Implement the session store on the mall token contract: `AuthTokens.token` in `localStorage["vmall.token"]`, user in `localStorage["vmall.user"]`, `me()` validation on load, and clearing plus `/login` redirect when the token is rejected. ## 2. Shell, tab bar, home, category, search - [ ] 2.1 Build the custom fixed bottom tab bar with exactly four tabs — Home `/`, Category `/category`, Cart `/cart`, My `/user` (首页/分类/购物车/我的) — active-tab styling on shared brand tokens, `env(safe-area-inset-bottom)` padding plus matching content padding, `env(safe-area-inset-top)` on page chrome, and a top back-bar replacing the tab bar on non-tab routes. - [ ] 2.2 Build home `/` rendering `getHomeContent()` banners, promotions, quick links and bilingual product floors in stacked mobile layout, with pull-to-refresh reload and integer-minor-unit prices through shared format helpers. - [ ] 2.3 Build category `/category`: two-panel browse (top-level rail plus children) from `listCategories()`, drilling into `/search/result` scoped to the selected category subtree. - [ ] 2.4 Build search `/search` and `/search/result`: keyword input, category/brand/sort filters, paginated product grid from `listProducts()`, empty state, pull-to-refresh. - [ ] 2.5 Point the mall top bar "Mobile"/"手机端" entry (currently a dead `NuxtLink to="/"`) at the `apps/mobile` home URL; leave the rest of the desktop shell unchanged. ## 3. Product detail, cart, checkout - [ ] 3.1 Build `/product/:id`: image gallery, bilingual name/subtitle, attribute and SKU selection with stock-aware quantity, integer-minor-unit prices, shop card, and add-to-cart via `addCartItem` with in-flight duplicate-tap guarding and anonymous → `/login` redirect returning to the product route. - [ ] 3.2 Build `/cart`: shop-grouped live cart via `getCart`/`updateCartItem`/`removeCartItem`, minor-unit totals, persistence across reload. - [ ] 3.3 Build `/checkout`: saved-address selection defaulting to the default address with inline manual address form when none exist, per-shop owned coupon selection via `listMyCoupons`, submission via `checkout(...)` (money as integer minor units throughout), payment through the shared pay contract, and success routing to the new `/orders/:id`. ## 4. User center, orders, after-sale entry, coupons, wallet - [ ] 4.1 Build `/user` "My": `getAccountSummary` balances/points, and an entry grid to orders, coupons, wallet, and after-sale, plus sign-in/register links when signed out. - [ ] 4.2 Build `/orders` (paginated `listMyOrders`, pull-to-refresh) and `/orders/:id` (`getOrder`) with status-appropriate actions through the shared client's guarded transitions: `payOrder`, `cancelOrder`, `confirmDelivered`. - [ ] 4.3 Build the after-sale entry from `/orders/:id` and `/user` backed by the `aftersale` shared-client API from `add-aftersale-refunds` (list + request detail). Dependency: if `add-aftersale-refunds` is not yet archived when this task is implemented, render a localized "Coming soon" placeholder and keep this task unchecked with a blocking note — no fixtures or invented endpoints. - [ ] 4.4 Build `/coupon` coupon center: claimable shop coupon templates and claiming via `listShopCouponTemplates`/`claimCoupon`, owned coupons via `listMyCoupons`, anonymous claim redirecting to `/login` and returning to `/coupon`. - [ ] 4.5 Build `/wallet` on the `wallet` shared-client API from `add-wallet-settlement` (balances and ledger entries). Dependency: if `add-wallet-settlement` is not yet archived when this task is implemented, render a localized "Coming soon" placeholder and keep this task unchecked with a blocking note. - [ ] 4.6 Build `/login` and `/register` on the shared auth client with mall-identical semantics: minimum 8-character registration password validated before the API call, distinct invalid-credentials vs already-registered copy, and return-to-origin routing. ## 5. Verification and OpenSpec cleanup - [ ] 5.1 Add focused integration coverage in `apps/api/tests/`, reusing the `tests/common/mod.rs` fixtures, for the existing endpoints the H5 flows consume (home content, cart → checkout → order, coupon claim, order listing/transition guards) so the mobile contract stays green; no new backend behavior is introduced by this change. - [ ] 5.2 Build the affected frontends: `pnpm --filter @vmall/mobile build` and `pnpm --filter @vmall/mall build` (top-bar link change). - [ ] 5.3 Run the API plus `apps/mobile` and browser-smoke at a mobile viewport (e.g. 390×844): tab bar navigation and safe-area padding, home floors, category → search → product → add to cart → checkout → order detail, coupon claim, pull-to-refresh, and anonymous sign-in return routing. - [ ] 5.4 Check every task in this file, then run `openspec change validate add-mobile-h5 --strict` and `openspec validate --all --strict` and fix anything until both pass.