# Design Document ## Overview 本设计文档描述将 supermart-mini 微信小程序迁移到 React Native/Expo iOS 应用的技术方案。迁移遵循以下原则: 1. 保持与小程序一致的视觉样式和交互体验 2. 复用小程序的 CDN 图片资源(通过 Images 常量配置) 3. 对接相同的后端 API 接口 4. 使用 React Native 的 ImageBackground 组件实现背景图效果 ## Architecture ```mermaid graph TB subgraph "React Native App" subgraph "Pages (app/)" Tabs["Tab Pages
(tabs)"] Login["Login Page"] Address["Address Pages"] Orders["Order Pages"] Product["Product Pages"] end subgraph "Components" Home["Home Components"] ProductComp["Product Components"] Common["Common Components"] end subgraph "Services" UserService["user.ts"] MallService["mall.ts"] AwardService["award.ts"] AddressService["address.ts"] BaseService["base.ts"] end subgraph "Constants" Images["images.ts"] Theme["theme.ts"] end subgraph "Contexts" AuthContext["AuthContext"] end end subgraph "Backend API" API["REST API Server"] end Tabs --> Services Login --> UserService Address --> AddressService Orders --> MallService Product --> MallService Services --> API Pages --> Images Pages --> Components ``` ## Components and Interfaces ### 1. 页面组件结构 #### Login Page (`app/login.tsx`) ```typescript interface LoginScreenProps {} // 状态 - phone: string // 手机号 - verifyCode: string // 验证码 - agreeFlag: boolean // 协议同意状态 - loading: boolean // 登录加载状态 - countdown: number // 验证码倒计时 // 方法 - handleGetVerifyCode() // 获取验证码 - handleLogin() // 登录 - goBack() // 返回 ``` #### Mine Page (`app/(tabs)/mine.tsx`) ```typescript interface MineScreenProps {} interface IndexData { couponCount?: number; inventoryCount?: number; magicBalance?: number; treasureBoxCount?: number; } // 状态 - userInfo: UserInfo | null - indexData: IndexData | null // 方法 - loadData() // 加载用户数据 - handleLogin() // 跳转登录 - handleCopy(text) // 复制文本 - handleMenuPress(route) // 菜单点击 - showNumber(key) // 格式化数字显示 ``` #### Address List Page (`app/address/index.tsx`) ```typescript interface Address { id: string; contactName: string; contactNo: string; province: string; city: string; district: string; address: string; defaultFlag: number; } // 方法 - loadData() // 加载地址列表 - selectAddress(item) // 选择地址 - setDefault(item) // 设为默认 - handleDelete(item) // 删除地址 - editAddress(item) // 编辑地址 - addNewAddress() // 新增地址 ``` #### Orders Page (`app/orders/index.tsx`) ```typescript interface OrderItem { tradeNo: string; status: number; statusText: string; goodsName: string; goodsCover: string; quantity: number; paymentAmount: number; createTime: string; } // Tab 配置 const tabs = [ { label: '全部', value: undefined }, { label: '待付款', value: 1 }, { label: '待发货', value: 2 }, { label: '待收货', value: 3 }, { label: '已完成', value: 4 }, ]; ``` ### 2. 服务层接口 #### Address Service (`services/address.ts`) ```typescript // API 端点 const apis = { LIST: '/api/addressBook', ADD: '/api/addressBook/add', DELETE: '/api/addressBook/delete/{id}', DEFAULT: '/api/addressBook/getDefault', UPDATE: '/api/addressBook/update', GET_AREA: '/api/area', }; // 方法 export const getAddressList: () => Promise export const getDefaultAddress: () => Promise
export const addAddress: (params) => Promise export const updateAddress: (params) => Promise export const deleteAddress: (id) => Promise export const getArea: (pid) => Promise ``` #### Award Service (`services/award.ts`) ```typescript // 新增方法 export const getMagicIndex: () => Promise export const getPoolList: (params) => Promise export const getPoolDetail: (poolId) => Promise export const getIPList: () => Promise ``` ## Data Models ### User Info ```typescript interface UserInfo { id: string; nickname: string; avatar: string; phone?: string; realName?: string; idNum?: string; balance?: number; } ``` ### Address ```typescript interface Address { id: string; contactName: string; contactNo: string; location?: string; province: string; city: string; district: string; address: string; defaultFlag: number; // 0: 非默认, 1: 默认 } ``` ### Order ```typescript interface OrderItem { tradeNo: string; status: number; statusText: string; goodsName: string; goodsCover: string; quantity: number; paymentAmount: number; createTime: string; } interface OrderDetail extends OrderItem { address?: { contactName: string; contactNo: string; province: string; city: string; district: string; address: string; }; expressInfo?: ExpressInfo[]; } ``` ### Pool (奖池) ```typescript interface PoolItem { id: string; name: string; cover: string; price: number; mode: string; } interface PoolDetail extends PoolItem { description?: string; prizes?: PrizeItem[]; boxCount?: number; } ``` ## Correctness Properties *A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.* Property 1: Login API call with correct parameters *For any* valid phone number and verify code combination, when the login function is called, it SHALL send a request with loginWay, mobile, and verifycode parameters to the login API endpoint. **Validates: Requirements 1.3** Property 2: Navigation after login success *For any* successful login response, the system SHALL navigate back if needInfo is false, or navigate to user-info page if needInfo is true. **Validates: Requirements 1.4** Property 3: User profile data display *For any* user info object with avatar, nickname, id, and phone fields, the mine page SHALL render all these fields in the appropriate UI elements. **Validates: Requirements 2.2** Property 4: Statistics data display *For any* index data object, the mine page SHALL display couponCount, inventoryCount, magicBalance, and treasureBoxCount values. **Validates: Requirements 2.3** Property 5: Function entry navigation *For any* function entry tap with a valid route, the system SHALL trigger navigation to that route. **Validates: Requirements 2.4, 2.5** Property 6: Address list rendering *For any* list of addresses, the address list page SHALL render each address with contactName, contactNo, and full address (province + city + district + address). **Validates: Requirements 3.2** Property 7: Address save API call *For any* valid address form submission, the system SHALL call the add or update API and navigate back on success. **Validates: Requirements 3.5** Property 8: Order item rendering *For any* order item, the orders page SHALL display tradeNo, statusText, goodsCover, goodsName, paymentAmount, quantity, and createTime. **Validates: Requirements 4.2** Property 9: Order navigation *For any* order item tap, the system SHALL navigate to the order detail page with the correct tradeNo. **Validates: Requirements 4.3** Property 10: Order action handling *For any* order with status 1 (待付款), the pay action SHALL be available; for status 3 (待收货), the confirm receipt action SHALL be available. **Validates: Requirements 4.4** Property 11: Welfare room navigation *For any* room entry tap with type 0, 1, or 2, the system SHALL navigate to the corresponding welfare page (room, catchDoll, or wish). **Validates: Requirements 6.3** Property 12: Image constants consistency *For any* image key used in the app, the Images constant SHALL provide a valid CDN URL matching the ossurl configuration. **Validates: Requirements 8.1, 8.2** Property 13: API service function mapping *For any* service function call, the request SHALL be sent to the correct API endpoint matching the mini-program service configuration. **Validates: Requirements 9.1** Property 14: API error handling *For any* failed API call, the system SHALL catch the error and not crash, optionally displaying an error message. **Validates: Requirements 9.2** Property 15: Authentication token inclusion *For any* authenticated API request, the HTTP headers SHALL include the authorization token. **Validates: Requirements 9.3** ## Error Handling ### API 错误处理 ```typescript // HTTP 请求封装中的错误处理 try { const response = await fetch(url, options); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); if (data.code === '401') { // Token 过期,跳转登录 router.push('/login'); return { success: false, code: '401' }; } return data; } catch (error) { console.error('API Error:', error); return { success: false, error }; } ``` ### 页面错误处理 - 加载失败时显示重试按钮 - 网络错误时显示提示信息 - 表单验证失败时显示具体错误 ## Testing Strategy ### 单元测试 - 使用 Jest 进行单元测试 - 测试服务层函数的参数处理和返回值 - 测试工具函数(如数字格式化) ### 属性测试 - 使用 fast-check 进行属性测试 - 每个属性测试运行至少 100 次迭代 - 测试标注格式:`**Feature: miniapp-to-rn-migration, Property {number}: {property_text}**` ### 测试覆盖范围 1. 服务层 API 调用测试 2. 页面组件渲染测试 3. 导航逻辑测试 4. 表单验证测试 5. 错误处理测试