1、request.js - 网络请求封装
// utils/request.js// 导入环境配置const { API_BASE_URL, TIMEOUT } = require('../config/env.js')// 请求拦截器(统一处理)const request = (options) => { return new Promise((resolve, reject) => { // 显示加载提示(可选) if (options.showLoading !== false) { wx.showLoading({ title: '加载中...', mask: true }) } wx.request({ url: API_BASE_URL + options.url, method: options.method || 'GET', data: options.data || {}, timeout: TIMEOUT || 10000, header: { 'content-type': 'application/json', ...options.header }, success: (res) => { wx.hideLoading() // 统一处理业务状态码 if (res.statusCode === 200) { if (res.data.code === 0) { resolve(res.data.data) } else { // 业务错误提示 wx.showToast({ title: res.data.message || '请求失败', icon: 'none' }) reject(res.data) } } else { // HTTP错误处理 handleHttpError(res.statusCode) reject(res) } }, fail: (err) => { wx.hideLoading() wx.showToast({ title: '网络开小差了', icon: 'error' }) reject(err) } }) })}// HTTP错误码处理const handleHttpError = (statusCode) => { const errorMap = { 400: '请求参数错误', 401: '登录已过期,请重新登录', 403: '没有权限访问', 404: '请求的资源不存在', 500: '服务器开小差了' } wx.showToast({ title: errorMap[statusCode] || '请求失败', icon: 'none' })}// GET请求快捷方法const get = (url, data = {}) => { return request({ url, method: 'GET', data })}// POST请求快捷方法const post = (url, data = {}) => { return request({ url, method: 'POST', data })}module.exports = { request, get, post}
2、storage.js - 本地存储封装
// utils/storage.js// 存储键名常量(统一管理,避免冲突)const KEYS = { USER_INFO: 'user_info', TOKEN: 'token', SETTINGS: 'settings', PRACTICE_RECORD: 'practice_record', WRONG_QUESTIONS: 'wrong_questions', STUDY_PROGRESS: 'study_progress'}// 设置存储(带过期时间)const set = (key, data, expireTime = null) => { const storeData = { data: data, timestamp: Date.now(), expireTime: expireTime } wx.setStorageSync(key, storeData)}// 获取存储const get = (key) => { const storeData = wx.getStorageSync(key) if (!storeData) return null // 检查是否过期 if (storeData.expireTime && Date.now() - storeData.timestamp > storeData.expireTime) { wx.removeStorageSync(key) return null } return storeData.data}// 删除存储const remove = (key) => { wx.removeStorageSync(key)}// 清空所有存储const clear = () => { wx.clearStorageSync()}// 批量设置const multiSet = (dataList) => { dataList.forEach(item => { set(item.key, item.data, item.expireTime) })}module.exports = { KEYS, set, get, remove, clear, multiSet}
3、format.js - 格式化工具
// utils/format.js// 格式化时间戳为可读日期const formatTime = (timestamp, format = 'YYYY-MM-DD HH:mm:ss') => { if (!timestamp) return '' const date = new Date(timestamp) const year = date.getFullYear() const month = date.getMonth() + 1 const day = date.getDate() const hour = date.getHours() const minute = date.getMinutes() const second = date.getSeconds() const formatMap = { 'YYYY': year, 'MM': month.toString().padStart(2, '0'), 'DD': day.toString().padStart(2, '0'), 'HH': hour.toString().padStart(2, '0'), 'mm': minute.toString().padStart(2, '0'), 'ss': second.toString().padStart(2, '0') } let result = format Object.keys(formatMap).forEach(key => { result = result.replace(key, formatMap[key]) }) return result}// 格式化刷题时间(秒 -> 分钟:秒)const formatDuration = (seconds) => { const mins = Math.floor(seconds / 60) const secs = seconds % 60 return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`}// 格式化正确率(0.67 -> 67%)const formatAccuracy = (accuracy) => { if (typeof accuracy === 'number') { return `${Math.round(accuracy * 100)}%` } return '0%'}// 数字千分位格式化(12345 -> 12,345)const formatNumber = (num) => { if (!num) return '0' return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')}// 截断文本(超过长度显示...)const truncateText = (text, maxLength = 20) => { if (!text) return '' if (text.length <= maxLength) return text return text.substring(0, maxLength) + '...'}module.exports = { formatTime, formatDuration, formatAccuracy, formatNumber, truncateText}