// pages/dashou-chongzhi/index.js import request from '../../utils/request'; // 引入弹窗服务(路径根据实际调整) import PopupService from '../../services/popupService.js'; Page({ data: { // ========== 全局数据 ========== clubmber: [], // 会员列表(注意:全局变量中是 clumber,这里保持原样) yajin: 0, // 押金 jifen: 0, // 积分(注意:全局变量中是 jinfen) jifenProgress: 0, // 积分进度条角度 // ========== 会员商品列表 ========== huiyuanList: [], // 从后端获取的会员列表 currentHuiyuanIndex: 0, // 当前选中的会员索引 currentHuiyuan: {}, // 当前选中的会员详情 // ========== 押金充值相关 ========== showYajinModal: false, // 显示押金弹窗 yajinAmount: '100', // 押金金额 // ========== 支付相关 ========== payLoading: false, // 支付加载状态 loadingText: '支付中...', // ========== 订单ID记录 ========== currentDingdanid: '', // 当前操作的订单ID // ========== 计算高度 ========== huiyuanListHeight: 120, // ========== 会员详情规则 ========== detailRules: [ '会员有效期为30天,从购买当天开始计算', '会员期间享受优先接单特权', '可享受专属客服服务', '会员到期前3天会有提醒', '支持随时续费,续费天数叠加' ], // ========== 新增:跳转参数处理 ========== // 用于接收从其他页面跳转过来的参数,决定是否自动滚动 jumpParams: {}, // ========== 新增:支付方式选择 ========== showPayMethodModal: false, // 支付方式选择弹窗 currentBuyType: null, // 当前购买类型:1会员 2押金 3积分 currentHuiyuanId: null, // 当前选中的会员ID(用于会员购买) currentYajinAmount: null, // 当前押金金额(用于押金购买) // ========== 新增:余额抵扣身份选择 ========== showBalanceModal: false, // 余额抵扣身份选择弹窗 balanceOptions: [], // 后端返回的身份列表 selectedBalanceId: null, // 选中的身份ID // ========== 新增:余额抵扣确认弹窗 ========== showConfirmModal: false, // 余额抵扣确认弹窗 selectedBalanceInfo: null, // 选中的身份详情(用于确认弹窗) // ========== 新增:会员详情弹窗 ========== showMemberModal: false, currentMemberDetail: null, }, // ========== 生命周期函数 ========== onLoad(options) { //console.log('页面加载,跳转参数:', options); // ✅ 新增:保存跳转参数 this.setData({ jumpParams: options || {} }); this.initPage(); }, // pages/tijiao/tijiao.js 中添加 onHide 方法(如果已有则合并内容) onHide() { const popupComp = this.selectComponent('#popupNotice'); if (popupComp && popupComp.cleanup) { popupComp.cleanup(); } }, onShow() { // 每次显示页面都刷新数据 this.registerNotificationComponent(); this.loadFromGlobalData(); this.checkAndRefreshData(); // 调用统一弹窗组件检查并展示公告 PopupService.checkAndShow(this, 'dashouchongzhi'); }, // 注册通知组件(原有,保持不变) registerNotificationComponent() { const app = getApp(); const notificationComp = this.selectComponent('#global-notification'); if (notificationComp && notificationComp.showNotification) { app.globalData.globalNotification = { show: (data) => notificationComp.showNotification(data), hide: () => notificationComp.hideNotification() }; } }, onReady() { // ✅ 新增:页面渲染完成后处理自动滚动 this.handleAutoScroll(); }, // ========== 初始化页面 ========== async initPage() { // 从全局数据加载 this.loadFromGlobalData(); // 获取会员商品列表 await this.fetchHuiyuanList(); // 计算会员列表高度 this.calculateHuiyuanHeight(); }, // ========== 从全局变量加载数据 ========== loadFromGlobalData() { const app = getApp(); const globalData = app.globalData || {}; // ✅ 重要:保持字段对应关系 // 全局变量中是 clumber,页面中是 clubmber // 全局变量中是 jinfen,页面中是 jifen this.setData({ clubmber: globalData.clumber || [], yajin: globalData.yajin || 0, jifen: globalData.jinfen || 0 // ✅ 注意:这里从 jinfen 读取 }); // 计算积分进度条 this.calculateJifenProgress(); }, // ========== 计算积分进度条角度 ========== calculateJifenProgress() { const jifen = this.data.jifen || 0; const progress = (jifen / 10) * 360; // 满分10分 this.setData({ jifenProgress: progress }); }, // ========== 计算会员列表高度 ========== calculateHuiyuanHeight() { const clubmber = this.data.clubmber || []; const itemHeight = 100; // 每个会员标签高度 const maxHeight = 300; // 最大高度(3个会员) let height = clubmber.length * itemHeight; height = Math.min(height, maxHeight); this.setData({ huiyuanListHeight: height }); }, // ========== 获取会员商品列表 ========== async fetchHuiyuanList() { try { const res = await request({ url: '/shangpin/dshyhq', method: 'POST', data: {} }); if (res.data.code === 200) { const huiyuanList = res.data.data || []; // 处理数据,标记已购买的会员 const processedList = this.processHuiyuanList(huiyuanList); this.setData({ huiyuanList: processedList, currentHuiyuan: processedList[0] || {} }); } else { wx.showToast({ title: res.data.message || '获取会员列表失败', icon: 'none' }); } } catch (error) { console.error('获取会员列表失败:', error); wx.showToast({ title: '网络错误,请重试', icon: 'none' }); } }, // ========== 处理会员列表,标记已购买的会员 ========== processHuiyuanList(huiyuanList) { const clubmber = this.data.clubmber || []; return huiyuanList.map(item => { // 检查是否已购买(注意:会员ID字段是 id) const boughtItem = clubmber.find(c => c.huiyuanid === item.id); return { ...item, isBought: !!boughtItem, buyInfo: boughtItem || null }; }); }, // ========== Swiper切换事件 ========== onSwiperChange(e) { const current = e.detail.current; const huiyuanList = this.data.huiyuanList || []; this.setData({ currentHuiyuanIndex: current, currentHuiyuan: huiyuanList[current] || {} }); }, // ========== 手动选择会员 ========== selectHuiyuan(e) { const index = e.currentTarget.dataset.index; const huiyuanList = this.data.huiyuanList || []; this.setData({ currentHuiyuanIndex: index, currentHuiyuan: huiyuanList[index] || {} }); }, // ========== 格式化到期时间 ========== formatDaoqiTime(daoqi) { if (!daoqi) return ''; try { // 如果是标准日期格式,格式化为 YYYY-MM-DD if (daoqi.includes(' ')) { const dateStr = daoqi.split(' ')[0]; const dateParts = dateStr.split('-'); if (dateParts.length === 3) { return `${dateParts[0]}-${dateParts[1]}-${dateParts[2]}`; } } return daoqi; } catch (error) { console.error('格式化到期时间错误:', error); return daoqi; } }, // ========== 计算剩余时间 ========== formatRemainTime(daoqi) { if (!daoqi) return ''; try { const now = new Date(); const end = new Date(daoqi); const diff = end - now; if (diff <= 0) return '已过期'; const days = Math.floor(diff / (1000 * 60 * 60 * 24)); if (days > 0) { return `${days}天`; } const hours = Math.floor(diff / (1000 * 60 * 60)); if (hours > 0) { return `${hours}小时`; } return '即将到期'; } catch (error) { console.error('计算剩余时间错误:', error); return '时间错误'; } }, // ========== 处理自动滚动 ========== handleAutoScroll() { const { jumpParams } = this.data; if (!jumpParams || !jumpParams.needScroll) return; setTimeout(() => { let scrollTop = 0; if (jumpParams.scrollTo === 'bottom') { scrollTop = 2000; } else if (jumpParams.scrollTo === 'member') { return; } if (scrollTop > 0) { wx.pageScrollTo({ scrollTop: scrollTop, duration: 300 }); } }, 800); }, // ========== 押金充值相关 ========== showYajinModal() { this.setData({ showYajinModal: true, yajinAmount: '100' }); }, hideYajinModal() { this.setData({ showYajinModal: false }); }, onYajinInput(e) { let value = e.detail.value; value = value.replace(/[^\d]/g, ''); if (value) { const num = parseInt(value); if (num < 1) value = '1'; if (num > 10000) value = '10000'; } this.setData({ yajinAmount: value }); }, setYajinAmount(e) { const amount = e.currentTarget.dataset.amount; this.setData({ yajinAmount: amount }); }, async handleYajinPay() { const amount = this.data.yajinAmount; if (!amount || amount < 1 || amount > 10000) { wx.showToast({ title: '请输入1-10000元的金额', icon: 'none' }); return; } this.showLoading('发起支付中...'); try { const res = await request({ url: '/shangpin/yajingoumai', method: 'POST', data: { jine: parseInt(amount) } }); if (res.data.code === 200) { const payParams = res.data.payParams; const dingdanid = res.data.dingdanid; this.setData({ currentDingdanid: dingdanid }); await this.wechatPay(payParams, 'yajin'); } else { wx.showToast({ title: res.data.message || '支付发起失败', icon: 'none' }); } } catch (error) { console.error('押金支付失败:', error); wx.showToast({ title: '支付失败,请重试', icon: 'none' }); } finally { this.hideLoading(); } }, // ========== 积分充值相关 ========== // 🔥 修改点1:增加积分已满的硬拦截,不弹任何提示,直接返回 onJifenClick(e) { // 优先判断积分是否已满(10分为满分) if (this.data.jifen >= 10) { // 积分已满,不弹窗,不提示,静默返回 return; } // 检查是否有会员 const clubmber = this.data.clubmber || []; if (clubmber.length === 0) { wx.showToast({ title: '请先购买会员才能充值积分', icon: 'none', duration: 3000 }); return; } // 积分未满,正常打开支付方式选择 this.setData({ currentBuyType: 3, showPayMethodModal: true }); }, // ========== 会员购买相关 ========== async handleHuiyuanBuy(e) { const huiyuanId = e.currentTarget.dataset.id; if (!huiyuanId) { wx.showToast({ title: '会员信息错误', icon: 'none' }); return; } this.showLoading('发起会员支付中...'); try { const res = await request({ url: '/shangpin/huiyuangm', method: 'POST', data: { huiyuanid: huiyuanId } }); if (res.data.code === 200) { const payParams = res.data.payParams; const dingdanid = res.data.dingdanid; this.setData({ currentDingdanid: dingdanid }); await this.wechatPay(payParams, 'huiyuan', huiyuanId); } else { wx.showToast({ title: res.data.message || '会员支付发起失败', icon: 'none' }); } } catch (error) { console.error('会员支付失败:', error); wx.showToast({ title: '支付失败,请重试', icon: 'none' }); } finally { this.hideLoading(); } }, // ========== 积分购买(微信支付)—— 已替换为正确的后端接口 ========== async handleJifenBuy(e) { const disabled = e.currentTarget.dataset.disabled; // 检查积分是否已满 if (disabled === 'true') { wx.showToast({ title: '积分已满,无需补充', icon: 'none' }); return; } // 检查是否有会员 const clubmber = this.data.clubmber || []; if (clubmber.length === 0) { wx.showToast({ title: '请先购买会员才能充值积分', icon: 'none', duration: 3000 }); return; } this.showLoading('发起积分支付中...'); try { const res = await request({ url: '/shangpin/jifenbc', // 正确的积分下单接口 method: 'POST', data: {} }); if (res.data.code === 200) { const payParams = res.data.payParams; const dingdanid = res.data.dingdanid; this.setData({ currentDingdanid: dingdanid }); await this.wechatPay(payParams, 'jifen'); } else { wx.showToast({ title: res.data.message || '积分支付发起失败', icon: 'none' }); } } catch (error) { wx.showToast({ title: '支付失败,请重试', icon: 'none' }); } finally { this.hideLoading(); } }, // ========== 微信支付封装 ========== async wechatPay(payParams, payType, extraData = null) { return new Promise((resolve, reject) => { if (!payParams || !payParams.timeStamp || !payParams.paySign) { wx.showToast({ title: '支付参数错误', icon: 'none' }); reject(new Error('支付参数错误')); return; } this.showLoading('调起支付中...'); wx.requestPayment({ timeStamp: payParams.timeStamp, nonceStr: payParams.nonceStr, package: payParams.package, signType: payParams.signType || 'MD5', paySign: payParams.paySign, success: async () => { this.hideLoading(); wx.showToast({ title: '支付成功!确认中...', icon: 'none', duration: 2000 }); try { await this.startPolling(payType, extraData); resolve(); } catch (error) { reject(error); } }, fail: async (res) => { this.hideLoading(); let errorMsg = '支付失败'; if (res.errMsg.includes('cancel')) { errorMsg = '您取消了支付'; } else if (res.errMsg.includes('fail')) { errorMsg = '支付失败,请重试'; } wx.showToast({ title: errorMsg, icon: 'none' }); try { await this.handlePayFailure(payType, extraData); } catch (error) { console.error('支付失败通知失败:', error); } reject(new Error(res.errMsg)); } }); }); }, // ========== 开始轮询支付结果 ========== async startPolling(payType, extraData = null) { const maxRetries = 10; const interval = 2000; const dingdanid = this.data.currentDingdanid; if (!dingdanid) { wx.showToast({ title: '订单号缺失', icon: 'none' }); return; } this.showLoading('确认支付结果中...'); for (let i = 0; i < maxRetries; i++) { try { const pollResult = await this.checkPayStatus(payType, dingdanid, extraData); if (pollResult.success) { this.hideLoading(); await this.updateAfterPayment(payType, extraData, pollResult.data); wx.showToast({ title: this.getSuccessMessage(payType), icon: 'success', duration: 2000 }); return; } await this.sleep(interval); } catch (error) { console.error(`轮询失败第${i + 1}次:`, error); } } this.hideLoading(); wx.showToast({ title: '支付确认超时,请联系客服', icon: 'none' }); }, // ========== 检查支付状态 ========== async checkPayStatus(payType, dingdanid, extraData = null) { let url = ''; let data = { dingdanid: dingdanid }; switch (payType) { case 'yajin': url = '/shangpin/yajinlunxun'; break; case 'jifen': url = '/shangpin/jifenlunxun'; break; case 'huiyuan': url = '/shangpin/huiyuanlx'; data.huiyuanid = extraData; break; default: throw new Error('未知的支付类型'); } try { const res = await request({ url, method: 'POST', data }); return { success: res.data.code === 200, data: res.data }; } catch (error) { console.error('检查支付状态失败:', error); return { success: false, data: null }; } }, // ========== 支付失败处理 ========== async handlePayFailure(payType, extraData = null) { let url = ''; let data = { dingdanid: this.data.currentDingdanid }; switch (payType) { case 'yajin': url = '/shangpin/yajinshibai'; break; case 'jifen': url = '/shangpin/jifenshibai'; break; case 'huiyuan': url = '/shangpin/huiyuanshibai'; data.huiyuanid = extraData; break; default: return; } try { await request({ url, method: 'POST', data }); } catch (error) { console.error('支付失败通知失败:', error); } }, // ========== 支付成功后更新数据 ========== async updateAfterPayment(payType, extraData = null, responseData = null) { const app = getApp(); switch (payType) { case 'yajin': if (responseData && responseData.yajin !== undefined) { app.globalData.yajin = responseData.yajin; } await this.refreshYajinData(); break; case 'jifen': if (responseData && responseData.jifen !== undefined) { app.globalData.jinfen = responseData.jifen; } await this.refreshJifenData(); break; case 'huiyuan': if (responseData && responseData.huiyuan) { app.globalData.jinfen = responseData.jifen; await this.updateClubmberData(responseData.huiyuan); } await this.refreshHuiyuanData(extraData); break; } this.loadFromGlobalData(); }, // ========== 刷新押金数据 ========== async refreshYajinData() { this.loadFromGlobalData(); }, // ========== 刷新积分数据 ========== async refreshJifenData() { this.loadFromGlobalData(); }, // ========== 刷新会员数据 ========== async refreshHuiyuanData(huiyuanId) { this.loadFromGlobalData(); await this.fetchHuiyuanList(); }, // ========== 更新会员数据到全局变量 ========== async updateClubmberData(huiyuanData) { const app = getApp(); const globalClubmber = app.globalData.clumber || []; const { huiyuanid, huiyuanming, daoqi } = huiyuanData; const index = globalClubmber.findIndex(item => item.huiyuanid === huiyuanid); if (index >= 0) { globalClubmber[index].daoqi = daoqi; } else { globalClubmber.push({ huiyuanid: huiyuanid, huiyuanming: huiyuanming, daoqi: daoqi }); } app.globalData.clumber = globalClubmber; this.setData({ clubmber: [...globalClubmber] }); }, // ========== 检查并刷新数据 ========== async checkAndRefreshData() { this.loadFromGlobalData(); }, // ========== 工具方法 ========== getSuccessMessage(payType) { switch (payType) { case 'yajin': return '押金充值成功'; case 'jifen': return '积分补充成功'; case 'huiyuan': return '会员购买成功'; default: return '支付成功'; } }, showLoading(text = '加载中...') { this.setData({ payLoading: true, loadingText: text }); }, hideLoading() { this.setData({ payLoading: false }); }, sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }, // ========== 新增功能(余额抵扣等) ========== onBuyHuiyuanClick(e) { const huiyuanId = e.currentTarget.dataset.id; this.setData({ currentBuyType: 1, currentHuiyuanId: huiyuanId, showPayMethodModal: true }); }, onYajinClick() { this.showYajinModal(); }, onYajinConfirm() { const amount = this.data.yajinAmount; if (!amount || amount < 1 || amount > 10000) { wx.showToast({ title: '请输入1-10000元的金额', icon: 'none' }); return; } this.hideYajinModal(); this.setData({ currentBuyType: 2, currentYajinAmount: amount, showPayMethodModal: true }); }, hidePayMethodModal() { this.setData({ showPayMethodModal: false }); }, // 🔥 修改点2:选择支付方式时再次校验积分状态(防止异步过程中积分变化) onPayMethodSelect(e) { const method = e.currentTarget.dataset.method; const { currentBuyType, currentHuiyuanId, currentYajinAmount, jifen } = this.data; this.hidePayMethodModal(); // 如果是积分购买,且积分已满,直接拒绝 if (currentBuyType === 3 && jifen >= 10) { wx.showToast({ title: '积分已满,无需补充', icon: 'none' }); return; } if (method === 'wx') { if (currentBuyType === 1) { this.handleHuiyuanBuy({ currentTarget: { dataset: { id: currentHuiyuanId } } }); } else if (currentBuyType === 2) { this.setData({ yajinAmount: currentYajinAmount }, () => { this.handleYajinPay(); }); } else if (currentBuyType === 3) { // ✅ 调用已修正的积分支付函数 this.handleJifenBuy({ currentTarget: { dataset: { disabled: 'false' } } }); } } else if (method === 'balance') { this.fetchBalanceOptions(); } }, // 🔥 修改点3:请求余额抵扣选项前校验积分状态 async fetchBalanceOptions() { const { currentBuyType, currentHuiyuanId, currentYajinAmount, jifen } = this.data; // 如果是积分购买,且积分已满,拒绝发起余额抵扣 if (currentBuyType === 3 && jifen >= 10) { wx.showToast({ title: '积分已满,无需补充', icon: 'none' }); return; } this.showLoading('获取抵扣信息...'); try { const res = await request({ url: '/shangpin/czhqdy', method: 'POST', data: { leixing: currentBuyType, huiyuan_id: currentBuyType === 1 ? currentHuiyuanId : undefined, yajin_jine: currentBuyType === 2 ? parseInt(currentYajinAmount) : undefined, } }); if (res.data.code === 200) { const options = res.data.data || []; this.setData({ balanceOptions: options, showBalanceModal: true }); } else { wx.showToast({ title: res.data.message || '获取失败', icon: 'none' }); } } catch (error) { console.error('获取抵扣身份失败:', error); wx.showToast({ title: '网络错误', icon: 'none' }); } finally { this.hideLoading(); } }, hideBalanceModal() { this.setData({ showBalanceModal: false }); }, onBalanceSelect(e) { const identityId = e.currentTarget.dataset.id; const selected = this.data.balanceOptions.find(opt => opt.id === identityId); if (!selected) return; this.setData({ selectedBalanceId: identityId, selectedBalanceInfo: selected, showConfirmModal: true, showBalanceModal: false }); }, hideConfirmModal() { this.setData({ showConfirmModal: false }); }, async confirmBalancePay() { const { selectedBalanceId, currentBuyType, currentHuiyuanId, currentYajinAmount } = this.data; if (!selectedBalanceId) return; this.hideConfirmModal(); this.showLoading('抵扣支付中...'); try { const res = await request({ url: '/shangpin/dsqrgmdh', method: 'POST', data: { leixing: currentBuyType, shenfen_id: selectedBalanceId, huiyuan_id: currentBuyType === 1 ? currentHuiyuanId : undefined, yajin_jine: currentBuyType === 2 ? parseInt(currentYajinAmount) : undefined, } }); if (res.data.code === 200) { const responseData = res.data.data || {}; await this.updateAfterPayment( currentBuyType === 1 ? 'huiyuan' : (currentBuyType === 2 ? 'yajin' : 'jifen'), currentBuyType === 1 ? currentHuiyuanId : null, responseData ); wx.showToast({ title: '购买成功', icon: 'success' }); } else { wx.showToast({ title: res.data.message || '购买失败', icon: 'none' }); } } catch (error) { console.error('抵扣支付失败:', error); wx.showToast({ title: '网络错误', icon: 'none' }); } finally { this.hideLoading(); } }, showMemberDetail(e) { const item = e.currentTarget.dataset.item; this.setData({ currentMemberDetail: item, showMemberModal: true }); }, hideMemberModal() { this.setData({ showMemberModal: false }); }, });