优化小程序阅读页面,新增好友优惠展示逻辑,支持通过推荐人获取折扣。调整价格计算方式,确保用户在购买章节时能看到实际优惠。更新相关样式以提升用户体验。
This commit is contained in:
@@ -7,9 +7,9 @@ App({
|
||||
globalData: {
|
||||
// API基础地址 - 连接真实后端
|
||||
// baseUrl: 'https://soulapi.quwanzhi.com',
|
||||
// baseUrl: 'https://souldev.quwanzhi.com',
|
||||
baseUrl: 'https://souldev.quwanzhi.com',
|
||||
// baseUrl: 'http://localhost:3006',
|
||||
baseUrl: 'http://localhost:8080',
|
||||
// baseUrl: 'http://localhost:8080',
|
||||
|
||||
// 小程序配置 - 真实AppID
|
||||
appId: 'wxb8bbb2b10dec74aa',
|
||||
|
||||
@@ -56,6 +56,12 @@ Page({
|
||||
sectionPrice: 1,
|
||||
fullBookPrice: 9.9,
|
||||
totalSections: 62,
|
||||
// 好友优惠展示
|
||||
userDiscount: 5,
|
||||
hasReferralDiscount: false,
|
||||
showDiscountHint: false,
|
||||
displaySectionPrice: 1,
|
||||
displayFullBookPrice: 9.9,
|
||||
|
||||
// 弹窗
|
||||
showShareModal: false,
|
||||
@@ -131,11 +137,34 @@ Page({
|
||||
}
|
||||
|
||||
try {
|
||||
const config = await accessManager.fetchLatestConfig()
|
||||
const userId = app.globalData.userInfo?.id
|
||||
const [config, purchaseRes] = await Promise.all([
|
||||
accessManager.fetchLatestConfig(),
|
||||
userId ? app.request(`/api/miniprogram/user/purchase-status?userId=${userId}`) : Promise.resolve(null)
|
||||
])
|
||||
const sectionPrice = config.prices?.section ?? 1
|
||||
const fullBookPrice = config.prices?.fullbook ?? 9.9
|
||||
const userDiscount = config.userDiscount ?? 5
|
||||
// 有推荐人 = ref/ referral_code 或 用户信息中有推荐人绑定
|
||||
const hasReferral = !!(wx.getStorageSync('referral_code') || ref || purchaseRes?.data?.hasReferrer)
|
||||
const hasReferralDiscount = hasReferral && userDiscount > 0
|
||||
const showDiscountHint = userDiscount > 0
|
||||
const displaySectionPrice = hasReferralDiscount
|
||||
? Math.round(sectionPrice * (1 - userDiscount / 100) * 100) / 100
|
||||
: sectionPrice
|
||||
const displayFullBookPrice = hasReferralDiscount
|
||||
? Math.round(fullBookPrice * (1 - userDiscount / 100) * 100) / 100
|
||||
: fullBookPrice
|
||||
this.setData({
|
||||
freeIds: config.freeChapters,
|
||||
sectionPrice: config.prices?.section ?? 1,
|
||||
fullBookPrice: config.prices?.fullbook ?? 9.9
|
||||
sectionPrice,
|
||||
fullBookPrice,
|
||||
userDiscount,
|
||||
hasReferralDiscount,
|
||||
showDiscountHint: userDiscount > 0,
|
||||
displaySectionPrice,
|
||||
displayFullBookPrice,
|
||||
purchasedCount: purchaseRes?.data?.purchasedSections?.length ?? this.data.purchasedCount ?? 0
|
||||
})
|
||||
|
||||
// 先拉取章节获取 id(mid 时必需;id 时可直接用)
|
||||
@@ -157,7 +186,8 @@ Page({
|
||||
accessState,
|
||||
canAccess,
|
||||
isLoggedIn: !!app.globalData.userInfo?.id,
|
||||
showPaywall: !canAccess
|
||||
showPaywall: !canAccess,
|
||||
purchasedCount: purchaseRes?.data?.purchasedSections?.length ?? 0
|
||||
})
|
||||
|
||||
await this.loadContent(mid, resolvedId, accessState, prefetchedChapter)
|
||||
@@ -621,9 +651,34 @@ Page({
|
||||
// 1. 刷新用户购买状态(从 orders 表拉取最新)
|
||||
await accessManager.refreshUserPurchaseStatus()
|
||||
|
||||
// 2. 重新拉取免费列表(极端情况:刚登录时当前章节可能改免费了)
|
||||
const config = await accessManager.fetchLatestConfig()
|
||||
this.setData({ freeIds: config.freeChapters })
|
||||
// 2. 重新拉取免费列表、价格与用户推荐人状态
|
||||
const userId = app.globalData.userInfo?.id
|
||||
const [config, purchaseRes] = await Promise.all([
|
||||
accessManager.fetchLatestConfig(),
|
||||
userId ? app.request(`/api/miniprogram/user/purchase-status?userId=${userId}`) : Promise.resolve(null)
|
||||
])
|
||||
const sectionPrice = config.prices?.section ?? this.data.sectionPrice ?? 1
|
||||
const fullBookPrice = config.prices?.fullbook ?? this.data.fullBookPrice ?? 9.9
|
||||
const userDiscount = config.userDiscount ?? 5
|
||||
const hasReferral = !!(wx.getStorageSync('referral_code') || purchaseRes?.data?.hasReferrer)
|
||||
const hasReferralDiscount = hasReferral && userDiscount > 0
|
||||
const displaySectionPrice = hasReferralDiscount
|
||||
? Math.round(sectionPrice * (1 - userDiscount / 100) * 100) / 100
|
||||
: sectionPrice
|
||||
const displayFullBookPrice = hasReferralDiscount
|
||||
? Math.round(fullBookPrice * (1 - userDiscount / 100) * 100) / 100
|
||||
: fullBookPrice
|
||||
this.setData({
|
||||
freeIds: config.freeChapters,
|
||||
sectionPrice,
|
||||
fullBookPrice,
|
||||
userDiscount,
|
||||
hasReferralDiscount,
|
||||
showDiscountHint: userDiscount > 0,
|
||||
displaySectionPrice,
|
||||
displayFullBookPrice,
|
||||
purchasedCount: purchaseRes?.data?.purchasedSections?.length ?? this.data.purchasedCount ?? 0
|
||||
})
|
||||
|
||||
// 3. 重新判断当前章节权限
|
||||
const newAccessState = await accessManager.determineAccessState(
|
||||
@@ -1235,9 +1290,33 @@ Page({
|
||||
wx.showLoading({ title: '重试中...', mask: true })
|
||||
|
||||
try {
|
||||
// 重新拉取配置
|
||||
const config = await accessManager.fetchLatestConfig()
|
||||
this.setData({ freeIds: config.freeChapters })
|
||||
const userId = app.globalData.userInfo?.id
|
||||
const [config, purchaseRes] = await Promise.all([
|
||||
accessManager.fetchLatestConfig(),
|
||||
userId ? app.request(`/api/miniprogram/user/purchase-status?userId=${userId}`) : Promise.resolve(null)
|
||||
])
|
||||
const sectionPrice = config.prices?.section ?? this.data.sectionPrice ?? 1
|
||||
const fullBookPrice = config.prices?.fullbook ?? this.data.fullBookPrice ?? 9.9
|
||||
const userDiscount = config.userDiscount ?? 5
|
||||
const hasReferral = !!(wx.getStorageSync('referral_code') || purchaseRes?.data?.hasReferrer)
|
||||
const hasReferralDiscount = hasReferral && userDiscount > 0
|
||||
const displaySectionPrice = hasReferralDiscount
|
||||
? Math.round(sectionPrice * (1 - userDiscount / 100) * 100) / 100
|
||||
: sectionPrice
|
||||
const displayFullBookPrice = hasReferralDiscount
|
||||
? Math.round(fullBookPrice * (1 - userDiscount / 100) * 100) / 100
|
||||
: fullBookPrice
|
||||
this.setData({
|
||||
freeIds: config.freeChapters,
|
||||
sectionPrice,
|
||||
fullBookPrice,
|
||||
userDiscount,
|
||||
hasReferralDiscount,
|
||||
showDiscountHint: userDiscount > 0,
|
||||
displaySectionPrice,
|
||||
displayFullBookPrice,
|
||||
purchasedCount: purchaseRes?.data?.purchasedSections?.length ?? this.data.purchasedCount ?? 0
|
||||
})
|
||||
|
||||
// 重新判断权限
|
||||
const newAccessState = await accessManager.determineAccessState(
|
||||
|
||||
@@ -166,7 +166,16 @@
|
||||
<!-- 购买本章 - 直接调起支付 -->
|
||||
<view class="purchase-btn purchase-section" bindtap="handlePurchaseSection">
|
||||
<text class="btn-label">购买本章</text>
|
||||
<text class="btn-price brand-color">¥{{section && section.price != null ? section.price : sectionPrice}}</text>
|
||||
<view class="btn-price-row" wx:if="{{hasReferralDiscount}}">
|
||||
<text class="btn-original-price">¥{{section && section.price != null ? section.price : sectionPrice}}</text>
|
||||
<text class="btn-price brand-color">¥{{displaySectionPrice}}</text>
|
||||
<text class="btn-discount-tag">省{{userDiscount}}%</text>
|
||||
</view>
|
||||
<view class="btn-price-row" wx:elif="{{showDiscountHint}}">
|
||||
<text class="btn-price brand-color">¥{{section && section.price != null ? section.price : sectionPrice}}</text>
|
||||
<text class="btn-discount-tag">好友链接立省{{userDiscount}}%</text>
|
||||
</view>
|
||||
<text wx:else class="btn-price brand-color">¥{{section && section.price != null ? section.price : sectionPrice}}</text>
|
||||
</view>
|
||||
|
||||
<!-- 解锁全书 - 只有购买超过3章才显示 -->
|
||||
@@ -176,8 +185,9 @@
|
||||
<text class="btn-label">解锁全部 {{totalSections}} 章</text>
|
||||
</view>
|
||||
<view class="btn-right">
|
||||
<text class="btn-price">¥{{fullBookPrice || 9.9}}</text>
|
||||
<text class="btn-discount">省82%</text>
|
||||
<text class="btn-original-price" wx:if="{{hasReferralDiscount}}">¥{{fullBookPrice || 9.9}}</text>
|
||||
<text class="btn-price">¥{{hasReferralDiscount ? displayFullBookPrice : (fullBookPrice || 9.9)}}</text>
|
||||
<text class="btn-discount">{{hasReferralDiscount ? '省' + userDiscount + '%' : '省82%'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -273,6 +273,23 @@
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.purchase-section .btn-price-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.btn-original-price {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.55);
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.btn-discount-tag {
|
||||
font-size: 22rpx;
|
||||
color: #00CED1;
|
||||
}
|
||||
|
||||
.brand-color {
|
||||
color: #00CED1;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@ Page({
|
||||
pendingEarnings: 0, // 待结算收益(保留兼容)
|
||||
shareRate: 90, // 分成比例(90%),从 referral/data 或 config 获取
|
||||
minWithdrawAmount: 10, // 最低提现金额,从 referral/data 获取
|
||||
bindingDays: 30, // 绑定期天数,从 referral/data 获取
|
||||
withdrawFee: 5, // 提现手续费%,从 referral/data 获取
|
||||
bindingDays: 30, // 绑定期天数,从 referral/data 获取
|
||||
userDiscount: 5, // 好友购买优惠%,从 referral/data 获取
|
||||
hasWechatId: false, // 是否已绑定微信号(未绑定时需引导去设置)
|
||||
|
||||
@@ -199,6 +200,7 @@ Page({
|
||||
pendingEarnings: formatMoney(realData?.pendingEarnings || 0),
|
||||
shareRate: realData?.shareRate ?? 90,
|
||||
minWithdrawAmount: minWithdrawAmount,
|
||||
withdrawFee: realData?.withdrawFee ?? 5,
|
||||
bindingDays: realData?.bindingDays ?? 30,
|
||||
userDiscount: realData?.userDiscount ?? 5,
|
||||
|
||||
@@ -565,9 +567,16 @@ Page({
|
||||
return
|
||||
}
|
||||
|
||||
const withdrawFee = this.data.withdrawFee ?? 5
|
||||
const actualAmount = withdrawFee > 0
|
||||
? Math.round(availableEarnings * (1 - withdrawFee / 100) * 100) / 100
|
||||
: availableEarnings
|
||||
const feeText = withdrawFee > 0
|
||||
? `\n扣除 ${withdrawFee}% 手续费后,实际到账 ¥${actualAmount.toFixed(2)}`
|
||||
: ''
|
||||
wx.showModal({
|
||||
title: '确认提现',
|
||||
content: `将提现 ¥${availableEarnings.toFixed(2)} 到您的微信零钱`,
|
||||
content: `申请提现 ¥${availableEarnings.toFixed(2)} 到您的微信零钱${feeText}`,
|
||||
confirmText: '立即提现',
|
||||
success: async (res) => {
|
||||
if (!res.confirm) return
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
<view class="withdraw-btn {{availableEarningsNum < minWithdrawAmount || !hasWechatId ? 'btn-disabled' : ''}}" bindtap="handleWithdraw">
|
||||
{{availableEarningsNum < minWithdrawAmount ? '满' + minWithdrawAmount + '元可提现' : !hasWechatId ? '请先绑定微信号' : '申请提现 ¥' + availableEarnings}}
|
||||
</view>
|
||||
<text class="withdraw-fee-tip" wx:if="{{withdrawFee > 0}}">提现将扣除 {{withdrawFee}}% 手续费</text>
|
||||
<text class="wechat-tip" wx:if="{{availableEarningsNum > 0 && !hasWechatId}}">为便于提现到账,请先到「设置」中绑定微信号</text>
|
||||
<view class="withdraw-records-link" bindtap="goToWithdrawRecords">查看提现记录</view>
|
||||
</view>
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
.withdraw-btn { padding: 28rpx; background: linear-gradient(135deg, #00CED1 0%, #20B2AA 100%); color: #fff; font-size: 32rpx; font-weight: 600; text-align: center; border-radius: 24rpx; box-shadow: 0 8rpx 24rpx rgba(0,206,209,0.3); }
|
||||
.withdraw-btn.btn-disabled { background: rgba(0,206,209,0.2); color: rgba(255,255,255,0.3); box-shadow: none; }
|
||||
.withdraw-fee-tip { display: block; font-size: 24rpx; color: rgba(255,255,255,0.5); margin-top: 12rpx; text-align: center; }
|
||||
.wechat-tip { display: block; font-size: 24rpx; color: rgba(255,165,0,0.9); margin-top: 16rpx; text-align: center; }
|
||||
.withdraw-records-link { display: block; margin-top: 16rpx; text-align: center; font-size: 26rpx; color: #00CED1; }
|
||||
|
||||
|
||||
@@ -23,12 +23,33 @@
|
||||
"condition": {
|
||||
"miniprogram": {
|
||||
"list": [
|
||||
{
|
||||
"name": "pages/referral/referral",
|
||||
"pathName": "pages/referral/referral",
|
||||
"query": "",
|
||||
"scene": null,
|
||||
"launchMode": "default"
|
||||
},
|
||||
{
|
||||
"name": "pages/read/read",
|
||||
"pathName": "pages/read/read",
|
||||
"query": "mid=11",
|
||||
"launchMode": "default",
|
||||
"scene": null
|
||||
},
|
||||
{
|
||||
"name": "pages/referral/referral",
|
||||
"pathName": "pages/referral/referral",
|
||||
"query": "",
|
||||
"launchMode": "default",
|
||||
"scene": null
|
||||
},
|
||||
{
|
||||
"name": "ces",
|
||||
"pathName": "pages/read/read",
|
||||
"query": "scene=mid%3D3&ref%3DogpTW5a9ex",
|
||||
"scene": null,
|
||||
"launchMode": "default"
|
||||
"launchMode": "default",
|
||||
"scene": null
|
||||
},
|
||||
{
|
||||
"name": "pages/chapters/chapters",
|
||||
|
||||
@@ -26,17 +26,18 @@ class ChapterAccessManager {
|
||||
if (res.success && res.freeChapters) {
|
||||
return {
|
||||
freeChapters: res.freeChapters,
|
||||
prices: res.prices || { section: 1, fullbook: 9.9 }
|
||||
prices: res.prices || { section: 1, fullbook: 9.9 },
|
||||
userDiscount: (typeof res.userDiscount === 'number' ? res.userDiscount : 5)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('[AccessManager] 获取配置失败,使用默认配置:', e)
|
||||
}
|
||||
|
||||
// 默认配置
|
||||
|
||||
return {
|
||||
freeChapters: ['preface', 'epilogue', '1.1', 'appendix-1', 'appendix-2', 'appendix-3'],
|
||||
prices: { section: 1, fullbook: 9.9 }
|
||||
prices: { section: 1, fullbook: 9.9 },
|
||||
userDiscount: 5
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user