更新服务器信息为新的 IP 地址,调整相关文档和代码中的默认配置,确保部署和连接的一致性。同时,优化订单管理界面,增强商品信息的格式化逻辑,提升用户体验。

This commit is contained in:
2026-02-05 21:08:28 +08:00
parent 1a95aee112
commit 3ccf331e12
61 changed files with 11231 additions and 311 deletions

View File

@@ -14,6 +14,7 @@ Page({
statusBarHeight: 44,
isLoggedIn: false,
userInfo: null,
isLoading: false, // 加载状态
// === 核心可见数据 ===
bindingCount: 0, // 绑定用户数(当前有效)
@@ -23,10 +24,14 @@ Page({
expiredCount: 0, // 已过期人数
// === 收益数据 ===
earnings: 0, // 已结算收益
pendingEarnings: 0, // 待结算收益
totalCommission: 0, // 累计佣金总额(所有获得的佣金)
availableEarnings: 0, // 可提现金额(未申请提现的佣金)
pendingWithdrawAmount: 0, // 待审核金额(已申请提现但未审核)
withdrawnEarnings: 0, // 已提现金额
earnings: 0, // 已结算收益(保留兼容)
pendingEarnings: 0, // 待结算收益(保留兼容)
shareRate: 90, // 分成比例90%
minWithdrawAmount: 10, // 最低提现金额(从后端获取)
// === 统计数据 ===
referralCount: 0, // 总推荐人数
@@ -70,6 +75,9 @@ Page({
async initData() {
const { isLoggedIn, userInfo } = app.globalData
if (isLoggedIn && userInfo) {
// 显示加载状态
this.setData({ isLoading: true })
// 生成邀请码
const referralCode = userInfo.referralCode || 'SOUL' + (userInfo.id || Date.now().toString(36)).toUpperCase().slice(-6)
@@ -126,8 +134,11 @@ Page({
status: type,
daysRemaining: user.daysRemaining || 0,
bindingDate: user.bindingDate ? this.formatDate(user.bindingDate) : '--',
expiryDate: user.expiryDate ? this.formatDate(user.expiryDate) : '--',
commission: (user.commission || 0).toFixed(2),
orderAmount: (user.orderAmount || 0).toFixed(2)
orderAmount: (user.orderAmount || 0).toFixed(2),
purchaseCount: user.purchaseCount || 0,
conversionDate: user.conversionDate ? this.formatDate(user.conversionDate) : '--'
}
console.log('[Referral] 格式化用户:', formatted.nickname, formatted.status, formatted.daysRemaining + '天')
return formatted
@@ -150,10 +161,14 @@ Page({
expiredCount,
// 收益数据 - 格式化为两位小数
totalCommission: formatMoney(realData?.totalCommission || 0),
availableEarnings: formatMoney(realData?.availableEarnings || 0),
pendingWithdrawAmount: formatMoney(realData?.pendingWithdrawAmount || 0),
withdrawnEarnings: formatMoney(realData?.withdrawnEarnings || 0),
earnings: formatMoney(realData?.earnings || 0),
pendingEarnings: formatMoney(realData?.pendingEarnings || 0),
withdrawnEarnings: formatMoney(realData?.withdrawnEarnings || 0),
shareRate: realData?.shareRate || 90,
minWithdrawAmount: realData?.minWithdrawAmount || 10,
// 统计
referralCount: realData?.referralCount || realData?.stats?.totalBindings || activeBindings.length + convertedBindings.length,
@@ -167,19 +182,33 @@ Page({
totalBindings: activeBindings.length + convertedBindings.length + expiredBindings.length,
// 收益明细
earningsDetails: (realData?.earningsDetails || []).map(item => ({
id: item.id,
productType: item.productType,
commission: (item.commission || 0).toFixed(2),
payTime: item.payTime ? this.formatDate(item.payTime) : '--',
buyerNickname: item.buyerNickname
}))
earningsDetails: (realData?.earningsDetails || []).map(item => {
// 解析商品描述,获取书名和章节
const productInfo = this.parseProductDescription(item.description, item.productType)
return {
id: item.id,
productType: item.productType,
bookTitle: productInfo.bookTitle,
chapterTitle: productInfo.chapterTitle,
commission: (item.commission || 0).toFixed(2),
payTime: item.payTime ? this.formatDate(item.payTime) : '--',
buyerNickname: item.buyerNickname || '用户',
buyerAvatar: item.buyerAvatar
}
})
})
console.log('[Referral] ✅ 数据设置完成')
console.log('[Referral] - 绑定中:', this.data.bindingCount)
console.log('[Referral] - 即将过期:', this.data.expiringCount)
console.log('[Referral] - 收益:', this.data.earnings)
// 隐藏加载状态
this.setData({ isLoading: false })
} else {
// 未登录时也隐藏loading
this.setData({ isLoading: false })
}
},
@@ -550,23 +579,33 @@ Page({
})
},
// 提现 - 直接到微信零钱(无门槛)
// 提现 - 直接到微信零钱
async handleWithdraw() {
const pendingEarnings = parseFloat(this.data.pendingEarnings) || 0
const availableEarnings = parseFloat(this.data.availableEarnings) || 0
const minWithdrawAmount = this.data.minWithdrawAmount || 10
if (pendingEarnings <= 0) {
if (availableEarnings <= 0) {
wx.showToast({ title: '暂无可提现收益', icon: 'none' })
return
}
// 检查是否达到最低提现金额
if (availableEarnings < minWithdrawAmount) {
wx.showToast({
title: `${minWithdrawAmount}元可提现`,
icon: 'none'
})
return
}
// 确认提现
wx.showModal({
title: '确认提现',
content: `将提现 ¥${pendingEarnings.toFixed(2)} 到您的微信零钱`,
content: `将提现 ¥${availableEarnings.toFixed(2)} 到您的微信零钱`,
confirmText: '立即提现',
success: async (res) => {
if (res.confirm) {
await this.doWithdraw(pendingEarnings)
await this.doWithdraw(availableEarnings)
}
}
})
@@ -668,6 +707,32 @@ Page({
wx.navigateBack()
},
// 解析商品描述,获取书名和章节
parseProductDescription(description, productType) {
if (!description) {
return {
bookTitle: '未知商品',
chapterTitle: ''
}
}
// 匹配格式:《书名》- 章节名
const match = description.match(/《(.+?)》(?:\s*-\s*(.+))?/)
if (match) {
return {
bookTitle: match[1] || '未知书籍',
chapterTitle: match[2] || (productType === 'fullbook' ? '全书购买' : '')
}
}
// 如果匹配失败,直接返回原始描述
return {
bookTitle: description.split('-')[0] || description,
chapterTitle: description.split('-')[1] || ''
}
},
// 格式化日期
formatDate(dateStr) {
if (!dateStr) return '--'

View File

@@ -18,7 +18,15 @@
</view>
<view style="height: {{statusBarHeight + 44}}px;"></view>
<view class="content">
<!-- 加载状态 -->
<view class="loading-overlay" wx:if="{{isLoading}}">
<view class="loading-content">
<view class="loading-spinner"></view>
<text class="loading-text">加载中...</text>
</view>
</view>
<view class="content {{isLoading ? 'content-loading' : ''}}">
<!-- 过期提醒横幅 -->
<view class="expiring-banner" wx:if="{{expiringCount > 0}}">
<view class="banner-icon">
@@ -40,17 +48,17 @@
<image class="icon-wallet" src="/assets/icons/wallet.svg" mode="aspectFit"></image>
</view>
<view class="earnings-info">
<text class="earnings-label">累计收益</text>
<text class="earnings-label">累计佣金</text>
<text class="commission-rate">{{shareRate}}% 返利</text>
</view>
</view>
<view class="earnings-right">
<text class="earnings-value">¥{{earnings}}</text>
<text class="pending-text">待结算: ¥{{pendingEarnings}}</text>
<text class="earnings-value">¥{{totalCommission}}</text>
<text class="pending-text">待审核: ¥{{pendingWithdrawAmount}}</text>
</view>
</view>
<view class="withdraw-btn {{earnings < 10 ? 'btn-disabled' : ''}}" bindtap="handleWithdraw">
{{earnings < 10 ? '满10元可提现' : '申请提现'}}
<view class="withdraw-btn {{availableEarnings < minWithdrawAmount ? 'btn-disabled' : ''}}" bindtap="handleWithdraw">
{{availableEarnings < minWithdrawAmount ? '满' + minWithdrawAmount + '元可提现' : '申请提现 ¥' + availableEarnings}}
</view>
</view>
</view>
@@ -147,11 +155,15 @@
<view class="user-status">
<block wx:if="{{item.status === 'converted'}}">
<text class="status-amount">+¥{{item.commission}}</text>
<text class="status-order">订单 ¥{{item.orderAmount}}</text>
<text class="status-order">已购{{item.purchaseCount || 1}}</text>
</block>
<block wx:elif="{{item.status === 'expired'}}">
<text class="status-tag tag-gray">已过期</text>
<text class="status-time">{{item.expiryDate}}</text>
</block>
<block wx:else>
<text class="status-tag {{item.daysRemaining <= 3 ? 'tag-red' : item.daysRemaining <= 7 ? 'tag-orange' : 'tag-green'}}">
{{item.status === 'expired' ? '已过期' : item.daysRemaining + '天'}}
{{item.daysRemaining}}
</text>
</block>
</view>
@@ -197,23 +209,38 @@
</view>
</view>
<!-- 收益明细 - 移到分享按钮后面 -->
<!-- 收益明细 - 增强版 -->
<view class="earnings-detail-card" wx:if="{{earningsDetails.length > 0}}">
<view class="detail-header">
<text class="detail-title">收益明细</text>
</view>
<view class="detail-list">
<view class="detail-item" wx:for="{{earningsDetails}}" wx:key="id">
<view class="detail-left">
<view class="detail-icon">
<image class="icon-gift" src="/assets/icons/gift.svg" mode="aspectFit"></image>
</view>
<view class="detail-info">
<text class="detail-type">{{item.productType === 'fullbook' ? '整本书购买' : '单节购买'}}</text>
<text class="detail-time">{{item.payTime}}</text>
<!-- 买家头像 -->
<view class="detail-avatar-wrap">
<image
class="detail-avatar"
wx:if="{{item.buyerAvatar}}"
src="{{item.buyerAvatar}}"
mode="aspectFill"
/>
<view class="detail-avatar-text" wx:else>
{{item.buyerNickname.charAt(0)}}
</view>
</view>
<text class="detail-amount">+¥{{item.commission}}</text>
<!-- 详细信息 -->
<view class="detail-content">
<view class="detail-top">
<text class="detail-buyer">{{item.buyerNickname}}</text>
<text class="detail-amount">+¥{{item.commission}}</text>
</view>
<view class="detail-product">
<text class="detail-book">{{item.bookTitle}}</text>
<text class="detail-chapter" wx:if="{{item.chapterTitle}}"> - {{item.chapterTitle}}</text>
</view>
<text class="detail-time">{{item.payTime}}</text>
</view>
</view>
</view>
</view>
@@ -265,7 +292,7 @@
<text class="poster-stat-label">好友优惠</text>
</view>
<view class="poster-stat">
<text class="poster-stat-value poster-stat-pink">90%</text>
<text class="poster-stat-value poster-stat-pink">{{shareRate}}%</text>
<text class="poster-stat-label">你的收益</text>
</view>
</view>

View File

@@ -216,3 +216,149 @@
.empty-gift-icon { width: 64rpx; height: 64rpx; display: block; filter: brightness(0) saturate(100%) invert(60%) sepia(0%) saturate(0%) hue-rotate(0deg) brightness(95%) contrast(85%); }
.empty-title { font-size: 30rpx; font-weight: 500; color: #fff; display: block; margin-bottom: 16rpx; }
.empty-desc { font-size: 26rpx; color: rgba(255,255,255,0.6); display: block; line-height: 1.5; }
/* ===== T<><54>rGm<18>5<EFBFBD><35> ?===== */
.loading-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
backdrop-filter: blur(10rpx);
z-index: 999;
display: flex;
align-items: center;
justify-content: center;
}
.loading-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 24rpx;
}
.loading-spinner {
width: 80rpx;
height: 80rpx;
border: 6rpx solid rgba(56, 189, 172, 0.2);
border-top-color: #38bdac;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading-text {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.8);
font-weight: 500;
}
.content-loading {
opacity: 0.3;
pointer-events: none;
}
/* ===== <00><>AR<41><6C>^<5E>|<7C>o<EFBFBD>p<EFBFBD><>\!} ===== */
.detail-item {
display: flex;
align-items: center;
gap: 24rpx;
padding: 24rpx;
background: rgba(255, 255, 255, 0.02);
border-radius: 16rpx;
margin-bottom: 16rpx;
transition: all 0.3s;
}
.detail-item:active {
background: rgba(255, 255, 255, 0.05);
}
.detail-avatar-wrap {
flex-shrink: 0;
}
.detail-avatar {
width: 88rpx;
height: 88rpx;
border-radius: 50%;