统一排行榜对齐星雀UI,页面资源后台配置实时刷新
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
473
miniprogram/pages/sjchongzhi/sjchongzhi.js
Normal file
473
miniprogram/pages/sjchongzhi/sjchongzhi.js
Normal file
@@ -0,0 +1,473 @@
|
||||
// pages/shangjia-chongzhi/index.js
|
||||
import request from '../../utils/request';
|
||||
|
||||
Page({
|
||||
data: {
|
||||
// 商家余额
|
||||
sjyue: '0.00',
|
||||
|
||||
// 充值金额相关
|
||||
quickAmounts: [50, 100, 300, 500, 1000, 2000],
|
||||
selectedAmount: 50, // 默认选择第一个
|
||||
customAmount: '',
|
||||
inputFocus: false,
|
||||
|
||||
// 金额限制
|
||||
minAmount: 1,
|
||||
maxAmount: 10000,
|
||||
|
||||
// 支付状态
|
||||
canPay: false,
|
||||
isLoading: false,
|
||||
loadingText: '',
|
||||
|
||||
// 支付状态提示
|
||||
showStatus: false,
|
||||
statusText: '',
|
||||
statusSubtext: '',
|
||||
showAction: false,
|
||||
actionText: '',
|
||||
|
||||
// 订单ID
|
||||
currentDingdanid: '',
|
||||
|
||||
// 轮询相关
|
||||
pollingCount: 0,
|
||||
maxPollingCount: 15
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.initPage();
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.loadShangjiaBalance();
|
||||
this.registerNotificationComponent();
|
||||
},
|
||||
registerNotificationComponent() {
|
||||
const app = getApp();
|
||||
const notificationComp = this.selectComponent('#global-notification');
|
||||
|
||||
if (notificationComp && notificationComp.showNotification) {
|
||||
console.log('🏪 商城页面注册通知组件');
|
||||
app.globalData.globalNotification = {
|
||||
show: (data) => notificationComp.showNotification(data),
|
||||
hide: () => notificationComp.hideNotification()
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// 初始化页面
|
||||
initPage() {
|
||||
this.loadShangjiaBalance();
|
||||
this.checkPayCondition();
|
||||
},
|
||||
|
||||
// 从全局变量加载商家余额
|
||||
loadShangjiaBalance() {
|
||||
const app = getApp();
|
||||
const globalData = app.globalData || {};
|
||||
const shangjiaData = globalData.shangjia || {};
|
||||
|
||||
this.setData({
|
||||
sjyue: shangjiaData.sjyue || '0.00'
|
||||
});
|
||||
},
|
||||
|
||||
// 选择快捷金额
|
||||
selectAmount(e) {
|
||||
const amount = parseInt(e.currentTarget.dataset.amount);
|
||||
|
||||
this.setData({
|
||||
selectedAmount: amount,
|
||||
customAmount: '',
|
||||
inputFocus: false
|
||||
}, () => {
|
||||
this.checkPayCondition();
|
||||
});
|
||||
},
|
||||
|
||||
// 自定义金额输入
|
||||
onCustomInput(e) {
|
||||
const value = e.detail.value;
|
||||
|
||||
// 只允许输入数字和小数点
|
||||
let cleanedValue = value.replace(/[^\d.]/g, '');
|
||||
|
||||
// 只允许一个小数点
|
||||
const dotCount = cleanedValue.split('.').length - 1;
|
||||
if (dotCount > 1) {
|
||||
cleanedValue = cleanedValue.substring(0, cleanedValue.lastIndexOf('.'));
|
||||
}
|
||||
|
||||
// 限制小数点后两位
|
||||
if (cleanedValue.includes('.')) {
|
||||
const parts = cleanedValue.split('.');
|
||||
if (parts[1].length > 2) {
|
||||
cleanedValue = parts[0] + '.' + parts[1].substring(0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
this.setData({
|
||||
customAmount: cleanedValue,
|
||||
selectedAmount: null
|
||||
}, () => {
|
||||
this.checkPayCondition();
|
||||
});
|
||||
},
|
||||
|
||||
// 输入框聚焦
|
||||
onInputFocus() {
|
||||
this.setData({
|
||||
inputFocus: true,
|
||||
selectedAmount: null
|
||||
});
|
||||
},
|
||||
|
||||
// 输入框失焦
|
||||
onInputBlur() {
|
||||
this.setData({
|
||||
inputFocus: false
|
||||
}, () => {
|
||||
this.checkPayCondition();
|
||||
});
|
||||
},
|
||||
|
||||
// 检查金额是否有效
|
||||
checkAmountValid() {
|
||||
const amount = this.getSelectedAmount();
|
||||
|
||||
if (!amount || amount === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const numAmount = parseFloat(amount);
|
||||
const min = this.data.minAmount;
|
||||
const max = this.data.maxAmount;
|
||||
|
||||
if (numAmount < min || numAmount > max || isNaN(numAmount)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
// 获取选中的金额
|
||||
getSelectedAmount() {
|
||||
if (this.data.selectedAmount !== null && this.data.selectedAmount !== undefined) {
|
||||
return this.data.selectedAmount.toString();
|
||||
} else if (this.data.customAmount) {
|
||||
return this.data.customAmount;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
// 检查支付条件
|
||||
checkPayCondition() {
|
||||
const validAmount = this.checkAmountValid();
|
||||
|
||||
this.setData({
|
||||
canPay: validAmount
|
||||
});
|
||||
},
|
||||
|
||||
// ========== 支付逻辑 ==========
|
||||
|
||||
// 处理支付
|
||||
handlePay() {
|
||||
if (!this.data.canPay) {
|
||||
wx.showToast({
|
||||
title: '请选择有效金额',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const amount = this.getSelectedAmount();
|
||||
const numAmount = parseFloat(amount);
|
||||
|
||||
// 确认支付
|
||||
wx.showModal({
|
||||
title: '确认充值',
|
||||
content: `是否充值 ¥${numAmount.toFixed(2)}?`,
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.startPayment(numAmount);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 开始支付流程
|
||||
async startPayment(amount) {
|
||||
this.showLoading('发起支付中...');
|
||||
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/shangpin/sjcz',
|
||||
method: 'POST',
|
||||
data: {
|
||||
jine: amount // 关键字段:后端接口要求"jine"
|
||||
}
|
||||
});
|
||||
|
||||
if (res.data.code === 200) {
|
||||
const payParams = res.data.payParams;
|
||||
const dingdanid = res.data.dingdanid;
|
||||
|
||||
this.setData({
|
||||
currentDingdanid: dingdanid,
|
||||
pollingCount: 0
|
||||
});
|
||||
|
||||
// 调起微信支付
|
||||
await this.wechatPay(payParams);
|
||||
} else {
|
||||
this.hideLoading();
|
||||
wx.showToast({
|
||||
title: res.data.message || '支付发起失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('发起支付失败:', error);
|
||||
this.hideLoading();
|
||||
wx.showToast({
|
||||
title: '网络错误,请重试',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 微信支付
|
||||
async wechatPay(payParams) {
|
||||
this.showLoading('调起支付中...');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!payParams || !payParams.timeStamp || !payParams.paySign) {
|
||||
this.hideLoading();
|
||||
wx.showToast({
|
||||
title: '支付参数错误',
|
||||
icon: 'none'
|
||||
});
|
||||
reject(new Error('支付参数错误'));
|
||||
return;
|
||||
}
|
||||
|
||||
wx.requestPayment({
|
||||
timeStamp: payParams.timeStamp,
|
||||
nonceStr: payParams.nonceStr,
|
||||
package: payParams.package,
|
||||
signType: payParams.signType || 'MD5',
|
||||
paySign: payParams.paySign,
|
||||
success: async () => {
|
||||
this.hideLoading();
|
||||
this.showStatusMessage('支付成功', '正在确认到账...', false);
|
||||
|
||||
try {
|
||||
await this.startPolling();
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
},
|
||||
fail: async (res) => {
|
||||
this.hideLoading();
|
||||
|
||||
let errorMsg = '支付失败';
|
||||
if (res.errMsg.includes('cancel')) {
|
||||
errorMsg = '您取消了支付';
|
||||
}
|
||||
|
||||
this.showStatusMessage(errorMsg, '请重新尝试', true, '重新支付');
|
||||
|
||||
// 通知后端支付失败
|
||||
try {
|
||||
await this.notifyPaymentFailure();
|
||||
} catch (error) {
|
||||
console.error('支付失败通知失败:', error);
|
||||
}
|
||||
|
||||
reject(new Error(res.errMsg));
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// 开始轮询支付结果
|
||||
async startPolling() {
|
||||
this.setData({ pollingCount: 0 });
|
||||
|
||||
const poll = async () => {
|
||||
if (this.data.pollingCount >= this.data.maxPollingCount) {
|
||||
this.showStatusMessage('确认超时', '请联系客服确认到账情况', true, '联系客服');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 🟢 修改开始:修改checkPaymentStatus的调用和返回值处理
|
||||
const result = await this.checkPaymentStatus();
|
||||
|
||||
if (result.success) {
|
||||
// 🟢 修改:更新全局变量中的商家余额
|
||||
const app = getApp();
|
||||
if (app.globalData && app.globalData.shangjia) {
|
||||
// 🟢 注意:后端返回yue,前端全局变量使用sjyue,保留两位小数
|
||||
app.globalData.shangjia.sjyue = result.yue.toFixed(2);
|
||||
console.log('🟢 全局变量商家余额已更新:', app.globalData.shangjia.sjyue);
|
||||
}
|
||||
|
||||
this.showStatusMessage('充值成功', '余额已到账', true, '完成');
|
||||
this.refreshBalance();
|
||||
return;
|
||||
}
|
||||
// 🟢 修改结束
|
||||
|
||||
this.setData({
|
||||
pollingCount: this.data.pollingCount + 1
|
||||
});
|
||||
|
||||
const delay = this.calculatePollingDelay();
|
||||
setTimeout(poll, delay);
|
||||
} catch (error) {
|
||||
console.error('轮询失败:', error);
|
||||
this.setData({
|
||||
pollingCount: this.data.pollingCount + 1
|
||||
});
|
||||
setTimeout(poll, 2000);
|
||||
}
|
||||
};
|
||||
|
||||
poll();
|
||||
},
|
||||
|
||||
// 计算轮询延迟
|
||||
calculatePollingDelay() {
|
||||
const count = this.data.pollingCount;
|
||||
if (count < 3) return 1000;
|
||||
if (count < 6) return 2000;
|
||||
if (count < 9) return 3000;
|
||||
return 5000;
|
||||
},
|
||||
|
||||
// 检查支付状态
|
||||
async checkPaymentStatus() {
|
||||
const dingdanid = this.data.currentDingdanid;
|
||||
|
||||
if (!dingdanid) {
|
||||
throw new Error('订单ID缺失');
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/shangpin/sjcg',
|
||||
method: 'POST',
|
||||
data: {
|
||||
dingdanid: dingdanid // 后端接口要求"dingdanid"
|
||||
}
|
||||
});
|
||||
|
||||
// 🟢 修改开始:返回对象,包含成功状态和余额
|
||||
if (res.data.code === 200) {
|
||||
return {
|
||||
success: true,
|
||||
yue: res.data.yue // 🟢 注意:后端返回字段是yue
|
||||
};
|
||||
} else {
|
||||
return { success: false };
|
||||
}
|
||||
// 🟢 修改结束
|
||||
} catch (error) {
|
||||
console.error('检查支付状态失败:', error);
|
||||
return { success: false };
|
||||
}
|
||||
},
|
||||
|
||||
// 通知支付失败
|
||||
async notifyPaymentFailure() {
|
||||
const dingdanid = this.data.currentDingdanid;
|
||||
|
||||
if (!dingdanid) return;
|
||||
|
||||
try {
|
||||
await request({
|
||||
url: '/shangpin/sjshibai',
|
||||
method: 'POST',
|
||||
data: {
|
||||
dingdanid: dingdanid // 后端接口要求"dingdanid"
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('支付失败通知失败:', error);
|
||||
}
|
||||
},
|
||||
|
||||
// 刷新余额
|
||||
async refreshBalance() {
|
||||
try {
|
||||
this.loadShangjiaBalance();
|
||||
} catch (error) {
|
||||
console.error('刷新余额失败:', error);
|
||||
}
|
||||
},
|
||||
|
||||
// ========== 状态提示 ==========
|
||||
|
||||
// 显示状态消息
|
||||
showStatusMessage(title, desc, showAction = false, actionBtnText = '') {
|
||||
this.setData({
|
||||
showStatus: true,
|
||||
statusText: title,
|
||||
statusSubtext: desc,
|
||||
showAction: showAction,
|
||||
actionText: actionBtnText
|
||||
});
|
||||
},
|
||||
|
||||
// 处理状态按钮点击
|
||||
handleStatusAction() {
|
||||
const actionText = this.data.actionText;
|
||||
|
||||
if (actionText === '重新支付' || actionText === '重试') {
|
||||
this.setData({ showStatus: false });
|
||||
setTimeout(() => {
|
||||
this.handlePay();
|
||||
}, 300);
|
||||
} else if (actionText === '联系客服') {
|
||||
wx.showModal({
|
||||
title: '联系客服',
|
||||
content: '联系客服',
|
||||
showCancel: false,
|
||||
confirmText: '我知道了'
|
||||
});
|
||||
} else if (actionText === '完成') {
|
||||
this.setData({ showStatus: false });
|
||||
this.refreshBalance();
|
||||
}
|
||||
},
|
||||
|
||||
// ========== 工具方法 ==========
|
||||
|
||||
// 显示加载
|
||||
showLoading(text = '加载中...') {
|
||||
this.setData({
|
||||
isLoading: true,
|
||||
loadingText: text
|
||||
});
|
||||
},
|
||||
|
||||
// 隐藏加载
|
||||
hideLoading() {
|
||||
this.setData({
|
||||
isLoading: false
|
||||
});
|
||||
},
|
||||
|
||||
// 页面卸载时清理
|
||||
onUnload() {
|
||||
this.setData({
|
||||
showStatus: false,
|
||||
isLoading: false
|
||||
});
|
||||
}
|
||||
});
|
||||
13
miniprogram/pages/sjchongzhi/sjchongzhi.json
Normal file
13
miniprogram/pages/sjchongzhi/sjchongzhi.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"navigationBarTitleText": "商家充值",
|
||||
"navigationBarBackgroundColor": "#0a0e17",
|
||||
"navigationBarTextStyle": "white",
|
||||
"backgroundColor": "#0a0e17",
|
||||
"backgroundTextStyle": "light",
|
||||
"enablePullDownRefresh": false,
|
||||
"usingComponents": {
|
||||
"global-notification": "/components/global-notification/global-notification"
|
||||
},
|
||||
"navigationStyle": "default",
|
||||
"disableScroll": true
|
||||
}
|
||||
129
miniprogram/pages/sjchongzhi/sjchongzhi.wxml
Normal file
129
miniprogram/pages/sjchongzhi/sjchongzhi.wxml
Normal file
@@ -0,0 +1,129 @@
|
||||
<view class="shangjia-chongzhi-page">
|
||||
<!-- 顶部余额展示 -->
|
||||
<view class="balance-card">
|
||||
<view class="balance-header">
|
||||
<view class="balance-title">
|
||||
<text class="title-text">商家余额</text>
|
||||
<view class="title-decoration">
|
||||
<view class="decoration-line"></view>
|
||||
<view class="decoration-dot"></view>
|
||||
<view class="decoration-line"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="balance-chip">
|
||||
<text class="chip-text">VIP商家账户</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="balance-amount">
|
||||
<text class="currency">¥</text>
|
||||
<text class="amount" data-amount="{{sjyue}}">{{sjyue}}</text>
|
||||
<text class="unit">元</text>
|
||||
</view>
|
||||
|
||||
<view class="balance-footer">
|
||||
<view class="balance-tag">
|
||||
<text class="tag-text">资金安全</text>
|
||||
</view>
|
||||
<view class="balance-tag">
|
||||
<text class="tag-text">实时到账</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 机甲装饰元素 -->
|
||||
<view class="mech-decoration">
|
||||
<view class="mech-line line-1"></view>
|
||||
<view class="mech-line line-2"></view>
|
||||
<view class="mech-corner corner-1"></view>
|
||||
<view class="mech-corner corner-2"></view>
|
||||
<view class="mech-corner corner-3"></view>
|
||||
<view class="mech-corner corner-4"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 充值金额选择区域 -->
|
||||
<view class="amount-section">
|
||||
<view class="section-header">
|
||||
<text class="section-title">充值金额</text>
|
||||
<view class="section-subtitle">
|
||||
<text class="subtitle-text">选择或输入充值金额</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 快捷金额按钮 -->
|
||||
<view class="quick-amount-grid">
|
||||
<block wx:for="{{quickAmounts}}" wx:key="index">
|
||||
<view
|
||||
class="amount-item {{selectedAmount == item ? 'active' : ''}}"
|
||||
data-amount="{{item}}"
|
||||
bindtap="selectAmount"
|
||||
>
|
||||
<text class="amount-text">¥{{item}}</text>
|
||||
<view class="amount-halo" wx:if="{{selectedAmount == item}}"></view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!-- 自定义金额输入 -->
|
||||
<view class="custom-amount">
|
||||
<view class="custom-input-wrapper">
|
||||
<text class="input-label">¥</text>
|
||||
<input
|
||||
class="custom-input"
|
||||
type="digit"
|
||||
placeholder="输入其他金额"
|
||||
placeholder-class="placeholder"
|
||||
value="{{customAmount}}"
|
||||
bindinput="onCustomInput"
|
||||
bindfocus="onInputFocus"
|
||||
bindblur="onInputBlur"
|
||||
maxlength="6"
|
||||
/>
|
||||
<view class="input-line {{inputFocus ? 'active' : ''}}"></view>
|
||||
</view>
|
||||
<text class="amount-hint">
|
||||
单次充值范围:¥{{minAmount}} - ¥{{maxAmount}}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 支付按钮 - 改为view更好控制 -->
|
||||
<view class="pay-section">
|
||||
<view class="pay-button-wrapper">
|
||||
<view
|
||||
class="pay-button {{canPay ? 'active' : ''}}"
|
||||
bindtap="handlePay"
|
||||
>
|
||||
<view class="button-content">
|
||||
<text class="button-text">立即充值</text>
|
||||
</view>
|
||||
<!-- 闪光特效 -->
|
||||
<view class="pay-button-shine"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 支付状态提示 -->
|
||||
<view class="payment-status" wx:if="{{showStatus}}">
|
||||
<view class="status-content">
|
||||
<text class="status-text">{{statusText}}</text>
|
||||
<text class="status-subtext">{{statusSubtext}}</text>
|
||||
|
||||
<view class="status-actions" wx:if="{{showAction}}">
|
||||
<view class="action-button" bindtap="handleStatusAction">
|
||||
<text class="action-text">{{actionText}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载遮罩 -->
|
||||
<view class="loading-mask" wx:if="{{isLoading}}">
|
||||
<view class="loading-content">
|
||||
<view class="loading-spinner"></view>
|
||||
<text class="loading-text">{{loadingText}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<global-notification id="global-notification" />
|
||||
|
||||
</view>
|
||||
1024
miniprogram/pages/sjchongzhi/sjchongzhi.wxss
Normal file
1024
miniprogram/pages/sjchongzhi/sjchongzhi.wxss
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user