删除不再使用的文件,包括开放 API 鉴权规范文档、数据库迁移脚本和旧版图标组件,优化项目结构和资源管理。更新小程序代码以支持代付功能,增加代付分享弹窗和支付逻辑,提升用户体验。
This commit is contained in:
@@ -13,8 +13,8 @@ const DEFAULT_WITHDRAW_TMPL_ID = 'u3MbZGPRkrZIk-I7QdpwzFxnO_CeQPaCWF2FkiIablE'
|
||||
App({
|
||||
globalData: {
|
||||
// API 基础地址:开发时修改下面一行切换环境
|
||||
baseUrl: "https://soulapi.quwanzhi.com",
|
||||
// baseUrl: 'http://localhost:8080', // 开发
|
||||
// baseUrl: "https://soulapi.quwanzhi.com",
|
||||
baseUrl: 'http://localhost:8080', // 开发
|
||||
// baseUrl: 'https://souldev.quwanzhi.com', // 测试
|
||||
// 小程序配置 - 真实AppID
|
||||
appId: DEFAULT_APP_ID,
|
||||
|
||||
@@ -124,6 +124,10 @@
|
||||
<image class="btn-icon" src="/assets/icons/share.svg" mode="aspectFit"/>
|
||||
<text>发送给好友</text>
|
||||
</button>
|
||||
<!-- 已退款:不可再分享/领取 -->
|
||||
<view wx:elif="{{detail.status === 'refunded' || detail.action === 'refunded'}}" class="footer-btn footer-btn-disabled">
|
||||
<text>已退款</text>
|
||||
</view>
|
||||
<!-- 好友 action=redeem:领取并阅读 -->
|
||||
<button wx:elif="{{!isInitiator && detail.action === 'redeem'}}" class="footer-btn redeem-btn" bindtap="doRedeem" disabled="{{redeeming}}">
|
||||
<image class="btn-icon" src="/assets/icons/arrow-right.svg" mode="aspectFit"/>
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<view class="card-row card-meta">
|
||||
<text class="quantity" wx:if="{{item.quantity > 1}}">{{item.quantity}}份</text>
|
||||
<text class="redeemed" wx:if="{{item.status === 'paid'}}">已领 {{item.redeemedCount || 0}}/{{item.quantity || 1}}</text>
|
||||
<text class="status {{item.status}}">{{item.status === 'pending' || item.status === 'pending_pay' ? '待支付' : item.status === 'paid' ? '已支付' : item.status === 'cancelled' ? '已取消' : '已过期'}}</text>
|
||||
<text class="status {{item.status}}">{{item.status === 'pending' || item.status === 'pending_pay' ? '待支付' : item.status === 'paid' ? '已支付' : item.status === 'refunded' ? '已退款' : item.status === 'cancelled' ? '已取消' : '已过期'}}</text>
|
||||
<view class="actions" wx:if="{{item.status === 'pending' || item.status === 'pending_pay'}}">
|
||||
<text class="action-text cancel" catchtap="cancelRequest" data-sn="{{item.requestSn}}">取消</text>
|
||||
</view>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<text>去阅读</text>
|
||||
</view>
|
||||
<view class="btn-link" bindtap="goToDetail">
|
||||
<text>{{detail.status === 'paid' ? '去分享' : detail.status === 'pending_pay' ? '去支付' : '查看详情'}}</text>
|
||||
<text>{{detail.status === 'paid' ? '去分享' : detail.status === 'pending_pay' ? '去支付' : detail.status === 'refunded' ? '已退款' : '查看详情'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</section>
|
||||
|
||||
@@ -35,10 +35,6 @@
|
||||
<view class="profile-name-row">
|
||||
<text class="user-name" bindtap="editNickname">{{userInfo.nickname || '点击设置昵称'}}</text>
|
||||
<view class="profile-name-actions">
|
||||
<view class="profile-edit-btn" bindtap="goToProfileShow">
|
||||
<image class="profile-edit-icon" src="/assets/icons/edit-gray.svg" mode="aspectFit"/>
|
||||
<text class="profile-edit-text">编辑</text>
|
||||
</view>
|
||||
<view class="become-member-btn {{isVip ? 'become-member-vip' : ''}}" wx:if="{{!auditMode}}" bindtap="goToVip">{{isVip ? '会员中心' : '成为会员'}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -67,7 +67,12 @@ Page({
|
||||
// 弹窗
|
||||
showShareModal: false,
|
||||
showGiftModal: false,
|
||||
giftQuantity: 1,
|
||||
giftQuantity: 6,
|
||||
giftUnitPrice: 0,
|
||||
giftTotalPrice: '0.00',
|
||||
giftPaying: false,
|
||||
giftPaid: false,
|
||||
giftRequestSn: '',
|
||||
showLoginModal: false,
|
||||
agreeProtocol: false,
|
||||
showPosterModal: false,
|
||||
@@ -82,6 +87,9 @@ Page({
|
||||
|
||||
// 审核模式:隐藏购买按钮
|
||||
auditMode: false,
|
||||
|
||||
// 好友从代付分享进入:待自动领取的 requestSn
|
||||
pendingGiftRequestSn: '',
|
||||
},
|
||||
|
||||
onShow() {
|
||||
@@ -111,13 +119,11 @@ Page({
|
||||
// 支持 scene(扫码)、mid、id、ref、gift(代付)
|
||||
const sceneStr = (options && options.scene) || ''
|
||||
const parsed = parseScene(sceneStr)
|
||||
const ref = options.ref || parsed.ref
|
||||
const isGift = options.gift === '1' || options.gift === 'true'
|
||||
// 代付统一到代付页:gift=1&ref=requestSn 时直接跳转,禁止在阅读页代付
|
||||
if (isGift && ref) {
|
||||
wx.redirectTo({ url: `/pages/gift-pay/detail?requestSn=${encodeURIComponent(ref)}` })
|
||||
return
|
||||
}
|
||||
// 代付:分享链路使用 requestSn(优先 options.requestSn;兼容旧链路 gift=1&ref=requestSn)
|
||||
const giftRequestSn = (options.requestSn || (isGift ? (options.ref || parsed.ref) : '') || '').trim()
|
||||
// 推荐码:仅在非代付链路使用 ref
|
||||
const ref = (!isGift ? (options.ref || parsed.ref) : '') || ''
|
||||
const mid = options.mid ? parseInt(options.mid, 10) : (parsed.mid || app.globalData.initialSectionMid || 0)
|
||||
let id = options.id || parsed.id || app.globalData.initialSectionId
|
||||
if (app.globalData.initialSectionMid) delete app.globalData.initialSectionMid
|
||||
@@ -149,7 +155,8 @@ Page({
|
||||
sectionId: id,
|
||||
sectionMid: mid || null,
|
||||
loading: true,
|
||||
accessState: 'unknown'
|
||||
accessState: 'unknown',
|
||||
pendingGiftRequestSn: giftRequestSn || ''
|
||||
})
|
||||
|
||||
if (ref) {
|
||||
@@ -167,8 +174,8 @@ Page({
|
||||
|
||||
// 统一:先拉章节数据,用 isFree/price===0 判断免费
|
||||
const chapterRes = await app.request({ url: this._getChapterUrl({ id, mid }), silent: true })
|
||||
const accessState = await accessManager.determineAccessState(id, chapterRes)
|
||||
const canAccess = accessManager.canAccessFullContent(accessState)
|
||||
let accessState = await accessManager.determineAccessState(id, chapterRes)
|
||||
let canAccess = accessManager.canAccessFullContent(accessState)
|
||||
|
||||
this.setData({
|
||||
accessState,
|
||||
@@ -179,6 +186,23 @@ Page({
|
||||
|
||||
// 加载内容(复用已拉取的章节数据,避免二次请求)
|
||||
await this.loadContent(id, accessState, chapterRes)
|
||||
|
||||
// 代付自动领取:好友打开阅读页时自动领取并解锁
|
||||
if (this.data.pendingGiftRequestSn) {
|
||||
const redeemed = await this._tryAutoRedeemGift(this.data.pendingGiftRequestSn)
|
||||
if (redeemed) {
|
||||
// 领取成功后刷新章节与权限(保守:重新拉章节数据 + 重新判断权限)
|
||||
await accessManager.refreshUserPurchaseStatus()
|
||||
const freshChapterRes = await app.request({ url: this._getChapterUrl({ id, mid }), silent: true })
|
||||
accessState = await accessManager.determineAccessState(id, freshChapterRes)
|
||||
canAccess = accessManager.canAccessFullContent(accessState)
|
||||
this.setData({ accessState, canAccess, showPaywall: !canAccess, pendingGiftRequestSn: '' })
|
||||
if (canAccess) {
|
||||
await this.loadContent(id, accessState, freshChapterRes)
|
||||
readingTracker.init(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 【标准流程】4. 如果有权限,初始化阅读追踪
|
||||
if (canAccess) {
|
||||
@@ -196,6 +220,58 @@ Page({
|
||||
this.setData({ loading: false })
|
||||
}
|
||||
},
|
||||
|
||||
_getGiftUnitPrice() {
|
||||
const p = this.data.section?.price
|
||||
const cfg = this.data.sectionPrice
|
||||
const v = (p != null && p !== '') ? Number(p) : Number(cfg || 0)
|
||||
return isNaN(v) ? 0 : v
|
||||
},
|
||||
|
||||
_updateGiftTotalPrice() {
|
||||
const unit = this.data.giftUnitPrice || this._getGiftUnitPrice()
|
||||
const q = parseInt(this.data.giftQuantity, 10) || 0
|
||||
const total = unit * q
|
||||
this.setData({
|
||||
giftUnitPrice: unit,
|
||||
giftTotalPrice: (isNaN(total) ? 0 : total).toFixed(2)
|
||||
})
|
||||
},
|
||||
|
||||
async _tryAutoRedeemGift(requestSn) {
|
||||
// 单页模式(朋友圈)不做自动领取,避免隐式登录/支付能力限制
|
||||
try {
|
||||
const sys = wx.getSystemInfoSync()
|
||||
const isSinglePage = (sys && sys.mode === 'singlePage') || app.globalData.isSinglePageMode
|
||||
if (isSinglePage) return false
|
||||
} catch (e) {}
|
||||
|
||||
const userId = app.globalData.userInfo?.id
|
||||
if (!userId) {
|
||||
// 记住 requestSn,登录后自动领取
|
||||
this.setData({ pendingGiftRequestSn: requestSn })
|
||||
wx.showToast({ title: '登录后将自动领取并解锁', icon: 'none', duration: 2500 })
|
||||
this.showLoginModal()
|
||||
return false
|
||||
}
|
||||
try {
|
||||
const res = await app.request({
|
||||
url: '/api/miniprogram/gift-pay/redeem',
|
||||
method: 'POST',
|
||||
data: { requestSn, userId }
|
||||
})
|
||||
if (res && res.success) return true
|
||||
// 已领取/已无名额等都视为无需再重试
|
||||
if (res && (res.error || res.message)) {
|
||||
wx.showToast({ title: res.error || res.message || '领取失败', icon: 'none' })
|
||||
}
|
||||
this.setData({ pendingGiftRequestSn: '' })
|
||||
return false
|
||||
} catch (e) {
|
||||
console.warn('[Read][Gift] 自动领取失败:', e)
|
||||
return false
|
||||
}
|
||||
},
|
||||
|
||||
// 从后端加载免费章节配置
|
||||
onPageScroll(e) {
|
||||
@@ -652,7 +728,123 @@ Page({
|
||||
wx.showToast({ title: '章节信息异常', icon: 'none' })
|
||||
return
|
||||
}
|
||||
wx.navigateTo({ url: `/pages/gift-pay/detail?sectionId=${encodeURIComponent(sectionId)}` })
|
||||
this.setData({
|
||||
showGiftModal: true,
|
||||
giftPaid: false,
|
||||
giftRequestSn: '',
|
||||
giftPaying: false,
|
||||
giftQuantity: 6
|
||||
})
|
||||
this._updateGiftTotalPrice()
|
||||
},
|
||||
|
||||
closeGiftModal() {
|
||||
this.setData({ showGiftModal: false })
|
||||
},
|
||||
|
||||
selectGiftQuantity(e) {
|
||||
const q = parseInt(e.currentTarget.dataset.q, 10)
|
||||
if (!q || q < 1) return
|
||||
this.setData({ giftQuantity: q })
|
||||
this._updateGiftTotalPrice()
|
||||
},
|
||||
|
||||
async confirmGiftPay() {
|
||||
if (this.data.giftPaying) return
|
||||
// 朋友圈单页模式禁止支付
|
||||
try {
|
||||
const sys = wx.getSystemInfoSync()
|
||||
const isSinglePage = (sys && sys.mode === 'singlePage') || app.globalData.isSinglePageMode
|
||||
if (isSinglePage) {
|
||||
wx.showModal({
|
||||
title: '朋友圈单页',
|
||||
content: '当前为朋友圈单页,无法发起代付支付。请点击底部「前往小程序」进入完整版后再操作。',
|
||||
showCancel: false
|
||||
})
|
||||
return
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
const userId = app.globalData.userInfo?.id
|
||||
if (!userId) {
|
||||
wx.showToast({ title: '请先登录', icon: 'none' })
|
||||
return
|
||||
}
|
||||
const sectionId = this.data.sectionId
|
||||
const quantity = parseInt(this.data.giftQuantity, 10)
|
||||
if (!sectionId || !quantity) {
|
||||
wx.showToast({ title: '参数异常', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
let openId = app.globalData.openId || wx.getStorageSync('openId')
|
||||
if (!openId) {
|
||||
wx.showLoading({ title: '获取支付凭证...', mask: true })
|
||||
openId = await app.getOpenId()
|
||||
wx.hideLoading()
|
||||
}
|
||||
if (!openId) {
|
||||
wx.showToast({ title: '请先登录', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
this.setData({ giftPaying: true })
|
||||
wx.showLoading({ title: '创建订单中...', mask: true })
|
||||
try {
|
||||
// 1) 创建代付请求
|
||||
const createRes = await app.request({
|
||||
url: '/api/miniprogram/gift-pay/create',
|
||||
method: 'POST',
|
||||
data: { userId, productType: 'section', productId: sectionId, quantity }
|
||||
})
|
||||
if (!createRes?.success || !createRes.requestSn) {
|
||||
throw new Error(createRes?.error || '创建失败')
|
||||
}
|
||||
const requestSn = createRes.requestSn
|
||||
|
||||
// 2) 发起人支付(微信支付)
|
||||
const payRes = await app.request({
|
||||
url: '/api/miniprogram/gift-pay/initiator-pay',
|
||||
method: 'POST',
|
||||
data: { requestSn, openId, userId }
|
||||
})
|
||||
wx.hideLoading()
|
||||
if (!payRes || !payRes.success || !payRes.data?.payParams) {
|
||||
throw new Error(payRes?.error || '创建订单失败')
|
||||
}
|
||||
const payParams = payRes.data.payParams
|
||||
const orderSn = payRes.data.orderSn
|
||||
await new Promise((resolve, reject) => {
|
||||
wx.requestPayment({
|
||||
timeStamp: payParams.timeStamp,
|
||||
nonceStr: payParams.nonceStr,
|
||||
package: payParams.package,
|
||||
signType: payParams.signType || 'RSA',
|
||||
paySign: payParams.paySign,
|
||||
success: resolve,
|
||||
fail: reject
|
||||
})
|
||||
})
|
||||
|
||||
// 3) 主动同步(与其他支付流程一致)
|
||||
if (orderSn) {
|
||||
try {
|
||||
await app.request(`/api/miniprogram/pay?orderSn=${encodeURIComponent(orderSn)}`, { silent: true })
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
wx.showToast({ title: '支付成功', icon: 'success' })
|
||||
this.setData({ giftPaid: true, giftRequestSn: requestSn, giftPaying: false })
|
||||
} catch (e) {
|
||||
wx.hideLoading()
|
||||
const msg = e?.message || e?.error || e?.errMsg || '支付失败'
|
||||
if (e?.errMsg && String(e.errMsg).includes('cancel')) {
|
||||
wx.showToast({ title: '已取消支付', icon: 'none' })
|
||||
} else {
|
||||
wx.showToast({ title: msg, icon: 'none', duration: 2500 })
|
||||
}
|
||||
this.setData({ giftPaying: false })
|
||||
}
|
||||
},
|
||||
|
||||
// 复制链接
|
||||
@@ -691,11 +883,22 @@ Page({
|
||||
},
|
||||
|
||||
// 分享到微信 - 自动带分享人ID
|
||||
onShareAppMessage() {
|
||||
onShareAppMessage(e) {
|
||||
trackClick('read', 'btn_click', '分享_' + this.data.sectionId)
|
||||
const { section, sectionId, sectionMid } = this.data
|
||||
const ref = app.getMyReferralCode()
|
||||
const q = sectionMid ? `mid=${sectionMid}` : `id=${sectionId}`
|
||||
// 代付分享按钮(支付后):好友打开阅读页自动领取解锁
|
||||
const isGiftShare = e?.from === 'button' && e?.target?.dataset?.gift === '1'
|
||||
const requestSn = (e?.target?.dataset?.requestSn || '').trim()
|
||||
if (isGiftShare && requestSn) {
|
||||
let path = `/pages/read/read?${q}&gift=1&requestSn=${encodeURIComponent(requestSn)}`
|
||||
if (ref) path += `&ref=${encodeURIComponent(ref)}`
|
||||
const t = section?.title || 'Soul创业派对'
|
||||
const title = `我已为你买单:${t.length > 18 ? t.slice(0, 18) + '...' : t}`
|
||||
return { title, path }
|
||||
}
|
||||
|
||||
const path = ref ? `/pages/read/read?${q}&ref=${ref}` : `/pages/read/read?${q}`
|
||||
const title = section?.title
|
||||
? `📚 ${section.title.length > 20 ? section.title.slice(0, 20) + '...' : section.title}`
|
||||
@@ -840,6 +1043,25 @@ Page({
|
||||
wx.showLoading({ title: '更新状态中...', mask: true })
|
||||
|
||||
try {
|
||||
// 0. 若有代付待领取,先领取再刷新购买状态
|
||||
if (this.data.pendingGiftRequestSn) {
|
||||
try {
|
||||
const userId = app.globalData.userInfo?.id
|
||||
const requestSn = this.data.pendingGiftRequestSn
|
||||
if (userId && requestSn) {
|
||||
const res = await app.request({
|
||||
url: '/api/miniprogram/gift-pay/redeem',
|
||||
method: 'POST',
|
||||
data: { requestSn, userId }
|
||||
})
|
||||
if (res && res.success) {
|
||||
this.setData({ pendingGiftRequestSn: '' })
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('[Read][Gift] 登录后自动领取失败:', e)
|
||||
}
|
||||
}
|
||||
// 1. 刷新用户购买状态(从 orders 表拉取最新)
|
||||
await accessManager.refreshUserPurchaseStatus()
|
||||
|
||||
|
||||
@@ -288,6 +288,51 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 代付分享弹窗:阅读页内发起代付并支付 -->
|
||||
<view class="modal-overlay modal-overlay-center" wx:if="{{showGiftModal}}" bindtap="closeGiftModal">
|
||||
<view class="modal-content modal-content-center gift-modal-v2" catchtap="stopPropagation">
|
||||
<view class="modal-header">
|
||||
<text class="modal-title">{{giftPaid ? '代付已完成' : '生成代付链接'}}</text>
|
||||
<view class="modal-close" bindtap="closeGiftModal"><icon name="x" size="36" color="#8e8e93"></icon></view>
|
||||
</view>
|
||||
|
||||
<view class="gift-article-card">
|
||||
<text class="gift-article-title">{{section.title || '代付商品'}}</text>
|
||||
<text class="gift-article-desc" wx:if="{{section.desc}}">{{section.desc}}</text>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{!giftPaid}}">
|
||||
<text class="gift-label">选择代付名额数</text>
|
||||
<view class="gift-spots-grid">
|
||||
<view class="gift-spot-btn {{giftQuantity===6?'gift-spot-active':''}}" bindtap="selectGiftQuantity" data-q="6">6</view>
|
||||
<view class="gift-spot-btn {{giftQuantity===30?'gift-spot-active':''}}" bindtap="selectGiftQuantity" data-q="30">30</view>
|
||||
<view class="gift-spot-btn {{giftQuantity===100?'gift-spot-active':''}}" bindtap="selectGiftQuantity" data-q="100">100</view>
|
||||
<view class="gift-spot-btn {{giftQuantity===1000?'gift-spot-active':''}}" bindtap="selectGiftQuantity" data-q="1000">1000</view>
|
||||
</view>
|
||||
|
||||
<view class="gift-price-box">
|
||||
<text class="gift-price-label">待支付总价格</text>
|
||||
<view class="gift-price-row">
|
||||
<text class="gift-price-formula">¥{{giftUnitPrice}} × {{giftQuantity}} =</text>
|
||||
<text class="gift-price-total">¥{{giftTotalPrice}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<button class="gift-pay-btn" bindtap="confirmGiftPay" disabled="{{giftPaying}}">
|
||||
{{giftPaying ? '支付中...' : '确认并支付'}}
|
||||
</button>
|
||||
<view class="gift-cancel-text" bindtap="closeGiftModal">取消</view>
|
||||
</view>
|
||||
|
||||
<view wx:else class="gift-paid-wrap">
|
||||
<text class="gift-paid-tip">支付成功,点击下方按钮直接分享给好友。好友打开阅读页将自动领取并解锁。</text>
|
||||
<button class="gift-share-btn" open-type="share" data-gift="1" data-request-sn="{{giftRequestSn}}">
|
||||
发送给好友
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 登录弹窗 - 须勾选同意协议,《用户协议》《隐私政策》可点击查看 -->
|
||||
<view class="modal-overlay" wx:if="{{showLoginModal}}" bindtap="closeLoginModal">
|
||||
<view class="modal-content login-modal" catchtap="stopPropagation">
|
||||
|
||||
@@ -600,6 +600,10 @@
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.modal-overlay-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
width: 100%;
|
||||
max-width: 750rpx;
|
||||
@@ -610,11 +614,25 @@
|
||||
animation: slideUp 0.3s ease;
|
||||
}
|
||||
|
||||
.modal-content-center {
|
||||
width: 640rpx;
|
||||
max-width: calc(100vw - 80rpx);
|
||||
border-radius: 32rpx;
|
||||
padding: 40rpx;
|
||||
padding-bottom: 40rpx;
|
||||
animation: popIn 0.18s ease-out;
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from { transform: translateY(100%); }
|
||||
to { transform: translateY(0); }
|
||||
}
|
||||
|
||||
@keyframes popIn {
|
||||
from { transform: scale(0.94); opacity: 0.6; }
|
||||
to { transform: scale(1); opacity: 1; }
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -706,6 +724,117 @@
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 阅读页内代付弹窗(v2:档位按钮 + 价格计算 + 支付后分享) */
|
||||
.gift-modal-v2 {
|
||||
padding: 40rpx;
|
||||
}
|
||||
.gift-article-card {
|
||||
padding: 28rpx;
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 24rpx;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
.gift-article-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
display: block;
|
||||
line-height: 1.3;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
.gift-article-desc {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.55);
|
||||
display: block;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.gift-spots-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 18rpx;
|
||||
margin-bottom: 28rpx;
|
||||
}
|
||||
.gift-spot-btn {
|
||||
text-align: center;
|
||||
padding: 22rpx 0;
|
||||
border-radius: 20rpx;
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.1);
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
font-weight: 600;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.gift-spot-active {
|
||||
border-color: rgba(0, 206, 209, 0.9);
|
||||
color: #00CED1;
|
||||
background: rgba(0, 206, 209, 0.12);
|
||||
}
|
||||
.gift-price-box {
|
||||
padding: 26rpx;
|
||||
border-radius: 24rpx;
|
||||
background: rgba(0, 0, 0, 0.25);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.08);
|
||||
margin-bottom: 28rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.gift-price-label {
|
||||
font-size: 22rpx;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
.gift-price-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: center;
|
||||
gap: 14rpx;
|
||||
}
|
||||
.gift-price-formula {
|
||||
font-size: 24rpx;
|
||||
color: rgba(0, 206, 209, 0.8);
|
||||
}
|
||||
.gift-price-total {
|
||||
font-size: 44rpx;
|
||||
font-weight: 800;
|
||||
color: #00CED1;
|
||||
}
|
||||
.gift-pay-btn {
|
||||
width: 100%;
|
||||
border-radius: 999rpx;
|
||||
background: #00CED1;
|
||||
color: #000;
|
||||
font-weight: 800;
|
||||
font-size: 32rpx;
|
||||
padding: 26rpx 0;
|
||||
}
|
||||
.gift-cancel-text {
|
||||
text-align: center;
|
||||
margin-top: 18rpx;
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.45);
|
||||
}
|
||||
.gift-paid-wrap {
|
||||
padding-top: 8rpx;
|
||||
}
|
||||
.gift-paid-tip {
|
||||
display: block;
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
line-height: 1.6;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
.gift-share-btn {
|
||||
width: 100%;
|
||||
border-radius: 999rpx;
|
||||
background: rgba(0, 206, 209, 0.12);
|
||||
border: 1rpx solid rgba(0, 206, 209, 0.45);
|
||||
color: #00CED1;
|
||||
font-weight: 800;
|
||||
font-size: 32rpx;
|
||||
padding: 26rpx 0;
|
||||
}
|
||||
|
||||
.share-modal-desc {
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
|
||||
@@ -85,6 +85,20 @@ Page({
|
||||
return
|
||||
}
|
||||
}
|
||||
// 支付前:若头像/昵称仍为默认值,引导先完善(仅头像+昵称)
|
||||
if (this._shouldGuideAvatarNickname()) {
|
||||
wx.showModal({
|
||||
title: '完善资料',
|
||||
content: '开通超级个体前,请先设置头像和昵称,让他人更好地认识你',
|
||||
confirmText: '去完善',
|
||||
cancelText: '稍后',
|
||||
success: (res) => {
|
||||
if (res.confirm) wx.navigateTo({ url: '/pages/avatar-nickname/avatar-nickname' })
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
this.setData({ purchasing: true })
|
||||
const amount = this.data.price
|
||||
try {
|
||||
@@ -158,12 +172,26 @@ Page({
|
||||
if (typeof p.initUserStatus === 'function') p.initUserStatus()
|
||||
else if (typeof p.updateUserStatus === 'function') p.updateUserStatus()
|
||||
})
|
||||
|
||||
// 开通成功后兜底:仍为默认头像/昵称则引导完善
|
||||
if (this._shouldGuideAvatarNickname()) {
|
||||
wx.navigateTo({ url: '/pages/avatar-nickname/avatar-nickname' })
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[VIP] 支付后同步失败:', e)
|
||||
}
|
||||
wx.hideLoading()
|
||||
},
|
||||
|
||||
_shouldGuideAvatarNickname() {
|
||||
const user = app.globalData.userInfo || {}
|
||||
const avatar = (user.avatar || user.avatarUrl || '').trim()
|
||||
const nickname = (user.nickname || user.nickName || '').trim()
|
||||
// 与 ruleEngine.checkRule_FillAvatar 保持同口径(允许前端兜底)
|
||||
if (avatar && !avatar.includes('default') && nickname && nickname !== '微信用户' && !nickname.startsWith('微信用户')) return false
|
||||
return true
|
||||
},
|
||||
|
||||
goBack() { getApp().goBackOrToHome() },
|
||||
|
||||
onShareAppMessage() {
|
||||
|
||||
Reference in New Issue
Block a user