# Design Document ## Overview 本设计文档描述前端 API 接口调用重构的技术方案。核心目标是将分散在页面和组件中的接口调用统一收敛到 `common/server/` 模块,实现接口集中管理、统一错误处理,并在改造过程中生成完整的 API 清单用于核对 C# 后端迁移完整性。 ## Architecture ### 整体架构 ``` ┌─────────────────────────────────────────────────────────────┐ │ Pages / Components │ │ (pages/shouye/*.vue, pages/user/*.vue, components/*.vue) │ └─────────────────────────────┬───────────────────────────────┘ │ import { funcName } from '@/common/server/xxx.js' ▼ ┌─────────────────────────────────────────────────────────────┐ │ Server Modules │ │ common/server/ │ │ ├── auth.js (登录、注册、绑定) │ │ ├── user.js (用户信息、VIP) │ │ ├── goods.js (商品列表、详情、奖品) │ │ ├── order.js (订单、抽奖) │ │ ├── warehouse.js (仓库、回收、发货) │ │ ├── coupon.js (优惠券) │ │ ├── welfare.js (福利屋、签到、任务) │ │ ├── collection.js(收藏) │ │ ├── address.js (收货地址) - 已有 userAddress.js │ │ ├── config.js (系统配置) - 已有 │ │ ├── rank.js (排行榜) │ │ ├── invitation.js(邀请) │ │ ├── redeem.js (兑换码) │ │ └── pay.js (支付) │ └─────────────────────────────┬───────────────────────────────┘ │ RequestManager.get/post() ▼ ┌─────────────────────────────────────────────────────────────┐ │ RequestManager │ │ common/request.js │ │ - 统一请求封装 │ │ - 签名机制 │ │ - 错误处理 │ │ - Content-Type: application/json │ └─────────────────────────────┬───────────────────────────────┘ │ HTTP Request ▼ ┌─────────────────────────────────────────────────────────────┐ │ C# Backend API │ │ http://localhost:5238/api/* │ └─────────────────────────────────────────────────────────────┘ ``` ### 调用流程 ```mermaid sequenceDiagram participant P as Page/Component participant S as Server Module participant R as RequestManager participant B as Backend API P->>S: import { getGoodsList } from '@/common/server/goods.js' P->>S: await getGoodsList({ page: 1, type: 0 }) S->>R: RequestManager.post('/goods_list', data) R->>R: 添加签名参数 (timestamp, nonce, sign) R->>B: POST /api/goods_list (JSON) B-->>R: { status: 1, data: {...} } R-->>S: response S->>S: 统一错误处理 S-->>P: 标准格式结果 ``` ## Components and Interfaces ### 1. RequestManager (已有,需修改) **文件**: `honey_box/common/request.js` **修改内容**: POST 请求 Content-Type 改为 `application/json` ```javascript // 修改前 if (method.toUpperCase() == 'POST') { header = { 'content-type': 'application/x-www-form-urlencoded', // ... } } // 修改后 if (method.toUpperCase() == 'POST') { header = { 'content-type': 'application/json', // ... } } ``` **接口保持不变**: - `static get(url, data, showLoading)` - GET 请求 - `static post(url, data, showLoading)` - POST 请求 - `static getCache(url, data, showLoading)` - 带缓存的 GET 请求 ### 2. Server Module 标准结构 每个 Server Module 遵循统一的结构: ```javascript // common/server/xxx.js import RequestManager from '../request'; /** * 函数名使用语义化命名 * @param {Object} params 请求参数 * @returns {Promise} 标准响应格式 */ export const getFunctionName = async (params = {}) => { const res = await RequestManager.post('/api_endpoint', params); return res; }; // 如需数据处理 export const getProcessedData = async (params = {}) => { const res = await RequestManager.post('/api_endpoint', params); if (res.status === 1 && res.data) { // 数据处理逻辑 return res.data; } return null; }; ``` ### 3. Server Modules 详细设计 #### 3.1 auth.js (认证模块) ```javascript // 微信登录 export const wxLogin = async (code, userInfo) => {...} // 手机号登录 export const mobileLogin = async (mobile, code) => {...} // 微信绑定手机号 export const bindMobileByWx = async (encryptedData, iv) => {...} // 验证码绑定手机号 export const bindMobileByCode = async (mobile, code) => {...} // 记录登录 export const recordLogin = async () => {...} // 账号注销 export const logOff = async () => {...} ``` #### 3.2 user.js (用户模块 - 扩展已有) ```javascript // 已有 export const getUserInfo = async () => {...} // 新增 export const updateUserInfo = async (data) => {...} export const getVipList = async () => {...} export const getProfitMoney = async (page) => {...} export const getProfitIntegral = async (page) => {...} export const getProfitScore = async (page) => {...} export const getProfitPay = async (page) => {...} ``` #### 3.3 goods.js (商品模块) ```javascript // 商品列表 export const getGoodsList = async (params) => {...} // 商品详情 export const getGoodsDetail = async (goodsId) => {...} // 子奖品列表 export const getGoodsChildren = async (goodsId) => {...} // 商品扩展配置 export const getGoodsExtend = async (goodsId) => {...} // 箱号列表 export const getGoodsNumList = async (goodsId) => {...} // 箱号详情 export const getGoodsNumDetail = async (goodsId, goodsNum) => {...} // 奖品数量统计 export const getGoodsPrizeCount = async (goodsId) => {...} // 奖品内容 export const getGoodsPrizeContent = async (goodsId, shangId) => {...} // 中奖记录 export const getGoodsPrizeLogs = async (params) => {...} ``` #### 3.4 order.js (订单模块 - 扩展已有) ```javascript // 一番赏金额计算 export const calcOrderMoney = async (params) => {...} // 一番赏下单 export const createOrder = async (params) => {...} // 无限赏金额计算 export const calcInfiniteOrderMoney = async (params) => {...} // 无限赏下单 export const createInfiniteOrder = async (params) => {...} // 商城金额计算 export const calcMallOrderMoney = async (params) => {...} // 订单列表 export const getOrderList = async (page, pageSize) => {...} // 订单详情 export const getOrderDetail = async (orderId) => {...} // 抽奖结果 export const getPrizeOrderLog = async (orderId) => {...} // 无限赏抽奖结果 export const getInfinitePrizeOrderLog = async (orderId) => {...} // 道具卡抽奖 export const useItemCard = async (params) => {...} ``` #### 3.5 warehouse.js (仓库模块) ```javascript // 仓库首页 export const getWarehouseIndex = async (params) => {...} // 回收奖品 export const recoveryPrize = async (ids) => {...} // 发货奖品 export const sendPrize = async (params) => {...} // 确认发货 export const confirmSend = async (params) => {...} // 发货记录 export const getSendRecord = async (page) => {...} // 发货详情 export const getSendRecordDetail = async (id) => {...} // 回收记录 export const getRecoveryRecord = async (page) => {...} // 物流信息 export const getLogistics = async (orderId) => {...} ``` #### 3.6 coupon.js (优惠券模块) ```javascript // 优惠券列表 export const getCouponList = async (params) => {...} // 优惠券详情 export const getCouponDetail = async (couponId) => {...} // 领取优惠券 export const receiveCoupon = async (couponId) => {...} // 分享优惠券 export const shareCoupon = async (couponId) => {...} // 合成优惠券 export const synthesisCoupon = async (ids) => {...} // 计算合成 export const calcSynthesis = async (ids) => {...} ``` #### 3.7 welfare.js (福利模块) ```javascript // 福利屋列表 export const getWelfareHouseList = async () => {...} // 福利屋详情 export const getWelfareHouseDetail = async (goodsId) => {...} // 福利屋下单 export const buyWelfareHouse = async (params) => {...} // 签到信息 export const getSignInfo = async () => {...} // 执行签到 export const doSign = async () => {...} // 任务列表 export const getTaskList = async () => {...} // 领取任务奖励 export const receiveTaskReward = async (taskId) => {...} ``` #### 3.8 collection.js (收藏模块) ```javascript // 收藏列表 export const getCollectionList = async (page) => {...} // 添加收藏 export const addCollection = async (goodsId) => {...} // 取消收藏 export const cancelCollection = async (goodsId) => {...} // 收藏状态 export const getCollectionStatus = async (goodsId) => {...} ``` #### 3.9 rank.js (排行榜模块) ```javascript // 排行榜列表 export const getRankList = async (type, page) => {...} ``` #### 3.10 invitation.js (邀请模块) ```javascript // 邀请信息 export const getInvitationInfo = async () => {...} // 邀请记录 export const getInvitationRecord = async (page) => {...} ``` #### 3.11 redeem.js (兑换码模块) ```javascript // 使用兑换码 export const useRedeemCode = async (code) => {...} ``` #### 3.12 pay.js (支付模块) ```javascript // 微信支付 export const wxPay = async (orderId) => {...} // 余额支付 export const balancePay = async (orderId) => {...} // 充值 export const recharge = async (amount) => {...} ``` ## Data Models ### 标准响应格式 ```typescript interface ApiResponse { status: number; // 1=成功, 0=失败, -1=未登录, -9=需绑定手机号 msg: string; // 提示信息 data: T; // 业务数据 } interface PaginatedResponse { status: number; msg: string; data: { data: T[]; // 列表数据 total: number; // 总数 currentPage: number; lastPage: number; }; } ``` ### 状态码定义 | 状态码 | 含义 | 处理方式 | |-------|------|---------| | 1 | 成功 | 返回数据 | | 0 | 业务失败 | 显示 msg 提示 | | -1 | 未登录 | 跳转登录页 | | -9 | 需绑定手机号 | 跳转绑定页 | | 2222 | 特殊状态 | 返回数据 | ## 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: POST 请求使用 JSON 格式 *For any* POST 请求通过 RequestManager 发送, 请求头的 Content-Type 应为 `application/json` **Validates: Requirements 1.1** ### Property 2: 签名机制一致性 *For any* 请求数据对象, 生成的签名应与原有算法保持一致:参数按键名排序 → 拼接为 key=value& 格式 → 添加密钥(host+timestamp) → MD5 加密 **Validates: Requirements 1.2** ### Property 3: 响应格式一致性 *For any* API 响应, 返回格式应包含 status、msg、data 三个字段,且 status 为数字类型 **Validates: Requirements 1.3** ### Property 4: 错误处理统一性 *For any* 接口调用返回 status !== 1 的响应, Server Module 应返回包含 status 和 msg 的标准格式对象 **Validates: Requirements 2.3, 6.2** ## Error Handling ### RequestManager 层错误处理 RequestManager 已实现以下错误处理逻辑(保持不变): 1. **网络异常**: 显示 "网络连接异常,请检查网络" 2. **status = 0**: 显示 msg 提示 3. **status = -1**: 清除 token,跳转登录页 4. **status = -9**: 显示 msg,跳转绑定手机号页面 5. **请求失败**: 显示错误信息 ### Server Module 层错误处理 Server Module 不额外处理错误,直接返回 RequestManager 的响应: ```javascript export const getGoodsList = async (params) => { // 直接返回,错误由 RequestManager 统一处理 return await RequestManager.post('/goods_list', params); }; ``` 如需数据转换,在成功时处理: ```javascript export const getUserInfo = async () => { const res = await RequestManager.post('/user'); if (res.status === 1 && res.data) { // 数据处理 res.data.money = common.removeTrailingZeros(res.data.money); return res.data; } return null; }; ``` ## Testing Strategy ### 单元测试 由于前端 UniApp 项目的特殊性,主要通过以下方式验证: 1. **手动测试**: 在开发环境使用 eruda 调试工具检查请求 2. **接口测试**: 使用 Postman/curl 验证接口响应格式 ### 测试用例 | 测试项 | 预期结果 | |-------|---------| | POST 请求 Content-Type | application/json | | 签名参数存在 | timestamp, nonce, sign | | 成功响应格式 | { status: 1, msg: "...", data: {...} } | | 错误响应处理 | 显示 msg 提示 | | 未登录处理 | 跳转登录页 | | 需绑定手机号处理 | 跳转绑定页 | ### 集成测试清单 按模块逐一测试: 1. **认证模块**: 登录、绑定手机号 2. **用户模块**: 获取用户信息、VIP 信息 3. **商品模块**: 商品列表、详情、奖品 4. **订单模块**: 下单、支付、抽奖结果 5. **仓库模块**: 回收、发货 6. **优惠券模块**: 列表、领取、合成 7. **福利模块**: 签到、任务 8. **其他模块**: 收藏、排行榜、邀请、兑换码