const { withRecordAccess } = require('../../utils/record-access'); const { withDataCache } = require('../../utils/page-cache'); const { tryLoginRenewal } = require('../../utils/subscribe'); const { getLayout } = require('../../utils/layout'); const { api } = require('../../utils/request'); function formatBytes(bytes) { bytes = bytes || 0; if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'; if (bytes < 1024 * 1024 * 1024) return (bytes / 1024 / 1024).toFixed(1) + ' MB'; return (bytes / 1024 / 1024 / 1024).toFixed(2) + ' GB'; } Page(withRecordAccess(withDataCache({ onLoginSubscribeTap: function() { return tryLoginRenewal(); }, onResize: function () { this.setData(getLayout()); }, data: { loading: true, error: false, usedBytes: 0, usedText: '0 MB', freeMb: 200, freeText: '200 MB', percent: 0, overQuota: false, isVip: false, isUnlimited:false, quotaText:"200 MB", vipExpireText: '', plans: [], paying: false, }, onLoad: function () { this._unloaded = false; this.setData(getLayout()); }, onUnload: function () { this._unloaded = true; }, onShow: function () { this.loadInfo(); }, onPullDownRefresh: function () { this.loadInfo().then(function () { wx.stopPullDownRefresh(); }); }, loadInfo: function () { var self = this; this.setData({ loading: true, error: false }); return api.storageInfo().then(function (d) { var freeBytes = d.quota_bytes != null ? d.quota_bytes : (d.quotaBytes != null ? d.quotaBytes : (d.free_bytes || d.freeBytes || 0)); var unlimited=!!(d.is_unlimited || d.isUnlimited); var usedBytes = d.used_bytes || d.usedBytes || 0; var percent = freeBytes > 0 ? Math.min(100, Math.round(usedBytes / freeBytes * 100)) : 0; var overQuota = usedBytes > freeBytes; var plans = (d.plans || []).map(function (p) { var cents = p.price_cents || p.priceCents || 0; return { key: p.key, name: p.name, priceCents:cents, version:p.updated_at || p.updatedAt, priceText: (cents / 100).toFixed(2), unit: (p.months || (p.key==='year'?12:1))+'个月', description: (Number(p.quota_mb != null ? p.quota_mb : p.quotaMb || 0)===0 ? '无限空间' : formatBytes(Number(p.quota_mb != null ? p.quota_mb : p.quotaMb)*1024*1024))+' · 有效期'+(p.months || (p.key==='year'?12:1))+'个月', }; }); var vipExpireText = ''; if (d.is_vip || d.isVip) { var expire = d.vip_expire_at || d.vipExpireAt ? String(d.vip_expire_at || d.vipExpireAt).slice(0, 10) : ''; vipExpireText = expire ? ('有效期至 ' + expire) : '已开通容量套餐'; } self.setData({ loading: false, usedBytes: usedBytes, usedText: formatBytes(usedBytes), freeMb: d.free_mb != null ? d.free_mb : (d.freeMb != null ? d.freeMb : 200), freeText: formatBytes(freeBytes), percent: percent, overQuota: overQuota, isVip: !!(d.is_vip || d.isVip), isUnlimited:unlimited, quotaText:unlimited?"无限空间":formatBytes(freeBytes), vipExpireText: vipExpireText, plans: plans, }); }).catch(function (e) { self.setData({ loading: false, error: true }); console.error('加载存储信息失败', e); }); }, buyPlan: function (e) { var key = e.currentTarget.dataset.key; var self = this; if (this.data.paying) return; var plan = null; for (var i = 0; i < this.data.plans.length; i++) { if (this.data.plans[i].key === key) { plan = this.data.plans[i]; break; } } if (!plan) return; wx.showLoading({ title: '下单中...', mask: true }); this.setData({ paying: true }); api.storageCreateOrder({ plan_key: key, expected_price_cents:plan.priceCents, expected_plan_version:plan.version }).then(function (order) { wx.hideLoading(); if (order && order.pay_provider === 'wechat' && order.payment) { self.callWechatPay(order); return; } self.setData({ paying: false }); wx.showToast({ title: '支付参数不完整,请重新下单', icon: 'none' }); }).catch(function (err) { wx.hideLoading(); self.setData({ paying: false }); wx.showToast({ title: (err && err.error) || '下单失败', icon: 'none' }); }); }, callWechatPay: function (order) { var self = this; var payment = order.payment; if (!wx.requestPayment) { this.setData({ paying: false }); wx.showToast({ title: '当前环境不支持微信支付,请使用微信真机', icon: 'none' }); return; } wx.requestPayment({ timeStamp: payment.time_stamp, nonceStr: payment.nonce_str, package: payment.package, signType: payment.sign_type, paySign: payment.pay_sign, success: function () { return self.confirmWechatPayment(order.out_trade_no); }, fail: function (error) { // Even a cashier error can occur after payment; query the server once. var message = String(error && error.errMsg || '').indexOf('cancel') >= 0 ? '已取消支付' : '支付未完成'; return self.confirmWechatPayment(order.out_trade_no, message); } }); }, confirmWechatPayment: async function (number, failureMessage) { if (this._confirming) return; this._confirming = true; try { for (var attempt = 0; attempt < (failureMessage ? 1 : 5); attempt++) { var result = await api.storageOrderStatus(number); if (this._unloaded) return; if (result.status === 'success') { wx.showToast({ title: '支付成功,会员已开通', icon: 'success' }); await this.loadInfo(); return; } if (result.status === 'closed') { wx.showToast({ title: '订单已关闭,请重新下单', icon: 'none' }); return; } if (!failureMessage && attempt < 4) await new Promise(function (resolve) { setTimeout(resolve, 1200); }); } if (!this._unloaded) wx.showToast({ title: failureMessage || '支付结果确认中,请稍后刷新', icon: 'none' }); } catch (e) { if (!this._unloaded) wx.showToast({ title: '支付结果暂未确认,请稍后刷新', icon: 'none' }); } finally { this._confirming = false; if (!this._unloaded) this.setData({ paying: false }); } }, }, {loadInfo:['storageInfo']})));