统一排行榜对齐星雀UI,页面资源后台配置实时刷新

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-06-27 01:26:11 +08:00
parent 1ab2e2080a
commit 21112173f2
292 changed files with 64010 additions and 81 deletions

View 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
});
}
});

View 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
}

View 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>

File diff suppressed because it is too large Load Diff