// UI辅助工具 - 全局用户体验优化 class UIHelper { constructor() { this.loadingCount = 0; this.toastQueue = []; this.isShowingToast = false; } // 🔥 ===== 加载状态管理 ===== // 显示加载 showLoading(title = '加载中...', mask = true) { this.loadingCount++; if (this.loadingCount === 1) { wx.showLoading({ title: title, mask: mask }); } } // 隐藏加载 hideLoading() { this.loadingCount = Math.max(0, this.loadingCount - 1); if (this.loadingCount === 0) { wx.hideLoading(); } } // 强制隐藏加载 forceHideLoading() { this.loadingCount = 0; wx.hideLoading(); } // 🔥 ===== 消息提示管理 ===== // 显示成功消息 showSuccess(title, duration = 2000) { this.showToast({ title: title, icon: 'success', duration: duration }); } // 显示错误消息 showError(title, duration = 3000) { this.showToast({ title: title, icon: 'error', duration: duration }); } // 显示警告消息 showWarning(title, duration = 2500) { this.showToast({ title: title, icon: 'none', duration: duration }); } // 显示信息消息 showInfo(title, duration = 2000) { this.showToast({ title: title, icon: 'none', duration: duration }); } // 队列化Toast显示 showToast(options) { this.toastQueue.push(options); this.processToastQueue(); } // 处理Toast队列 processToastQueue() { if (this.isShowingToast || this.toastQueue.length === 0) { return; } this.isShowingToast = true; const options = this.toastQueue.shift(); wx.showToast({ ...options, success: () => { setTimeout(() => { this.isShowingToast = false; this.processToastQueue(); }, options.duration || 2000); }, fail: () => { this.isShowingToast = false; this.processToastQueue(); } }); } // 🔥 ===== 模态框管理 ===== // 显示确认对话框 showConfirm(options) { return new Promise((resolve) => { wx.showModal({ title: options.title || '提示', content: options.content || '', showCancel: options.showCancel !== false, cancelText: options.cancelText || '取消', confirmText: options.confirmText || '确定', cancelColor: options.cancelColor || '#666666', confirmColor: options.confirmColor || '#4CAF50', success: (res) => { resolve(res.confirm); }, fail: () => { resolve(false); } }); }); } // 显示操作菜单 showActionSheet(options) { return new Promise((resolve) => { wx.showActionSheet({ itemList: options.itemList || [], itemColor: options.itemColor || '#000000', success: (res) => { resolve(res.tapIndex); }, fail: () => { resolve(-1); } }); }); } // 🔥 ===== 网络状态管理 ===== // 检查网络状态 async checkNetworkStatus() { try { const networkInfo = await this.getNetworkType(); if (networkInfo.networkType === 'none') { this.showError('网络连接不可用,请检查网络设置'); return false; } return true; } catch (error) { console.error('检查网络状态失败:', error); return true; // 默认认为网络可用 } } // 获取网络类型 getNetworkType() { return new Promise((resolve, reject) => { wx.getNetworkType({ success: resolve, fail: reject }); }); } // 🔥 ===== 页面导航管理 ===== // 安全导航到页面 navigateTo(url, options = {}) { // 检查URL格式 if (!url || typeof url !== 'string') { this.showError('页面地址无效'); return Promise.reject(new Error('Invalid URL')); } return new Promise((resolve, reject) => { wx.navigateTo({ url: url, success: resolve, fail: (error) => { console.error('页面导航失败:', error); // 如果是页面栈满了,尝试重定向 if (error.errMsg && error.errMsg.includes('limit exceed')) { wx.redirectTo({ url: url, success: resolve, fail: reject }); } else { this.showError('页面跳转失败'); reject(error); } } }); }); } // 安全重定向到页面 redirectTo(url) { return new Promise((resolve, reject) => { wx.redirectTo({ url: url, success: resolve, fail: (error) => { console.error('页面重定向失败:', error); this.showError('页面跳转失败'); reject(error); } }); }); } // 安全重启到页面 reLaunch(url) { return new Promise((resolve, reject) => { wx.reLaunch({ url: url, success: resolve, fail: (error) => { console.error('页面重启失败:', error); this.showError('页面跳转失败'); reject(error); } }); }); } // 🔥 ===== 错误处理 ===== // 处理API错误 handleApiError(error, defaultMessage = '操作失败,请重试') { console.error('API错误:', error); let message = defaultMessage; if (error && error.message) { message = error.message; } else if (typeof error === 'string') { message = error; } // 特殊错误处理 if (message.includes('网络')) { this.showError('网络连接异常,请检查网络设置'); } else if (message.includes('登录') || message.includes('认证') || message.includes('token')) { this.showError('登录已过期,请重新登录'); // 可以在这里触发重新登录逻辑 } else { this.showError(message); } } // 🔥 ===== 工具方法 ===== // 防抖函数 debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // 节流函数 throttle(func, limit) { let inThrottle; return function executedFunction(...args) { if (!inThrottle) { func.apply(this, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; } // 格式化文件大小 formatFileSize(bytes) { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } // 格式化时间 formatTime(timestamp) { const now = new Date(); const time = new Date(timestamp); const diff = now - time; // 一分钟内 if (diff < 60000) { return '刚刚'; } // 一小时内 if (diff < 3600000) { return Math.floor(diff / 60000) + '分钟前'; } // 今天 if (now.toDateString() === time.toDateString()) { return time.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }); } // 昨天 const yesterday = new Date(now); yesterday.setDate(yesterday.getDate() - 1); if (yesterday.toDateString() === time.toDateString()) { return '昨天 ' + time.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }); } // 其他 return time.toLocaleDateString('zh-CN') + ' ' + time.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }); } // 复制到剪贴板 copyToClipboard(text) { return new Promise((resolve, reject) => { wx.setClipboardData({ data: text, success: () => { this.showSuccess('已复制到剪贴板'); resolve(); }, fail: (error) => { this.showError('复制失败'); reject(error); } }); }); } // 震动反馈 vibrateShort() { wx.vibrateShort({ type: 'light' }); } // 震动反馈(长) vibrateLong() { wx.vibrateLong(); } } // 创建全局单例 const uiHelper = new UIHelper(); module.exports = uiHelper;