更新小程序,优化单页模式下的用户引导逻辑,确保用户在朋友圈等环境中能够顺利登录和访问完整内容。调整章节内容获取逻辑,确保未授权用户无法访问完整内容。新增手机号同步功能,提升用户资料管理体验。

This commit is contained in:
Alex-larget
2026-03-10 20:20:03 +08:00
parent 3b942fd7a4
commit dc3597c906
8 changed files with 165 additions and 19 deletions

View File

@@ -370,6 +370,9 @@ Page({
this.setData({ showLeadModal: false, leadPhone: '' })
},
// 阻止弹窗内部点击事件冒泡到遮罩层
stopPropagation() {},
onLeadPhoneInput(e) {
this.setData({ leadPhone: (e.detail.value || '').trim() })
},
@@ -407,6 +410,30 @@ Page({
this.setData({ showLeadModal: false, leadPhone: '' })
if (res && res.success) {
wx.setStorageSync('lead_last_submit_ts', Date.now())
// 若用户资料中尚未保存手机号,则顺手同步到资料(不影响本次提交结果)
try {
const currentPhone = (app.globalData.userInfo?.phone || '').trim()
if (!currentPhone && userId) {
await app.request({
url: '/api/miniprogram/user/profile',
method: 'POST',
data: {
userId,
phone
}
})
if (app.globalData.userInfo) {
app.globalData.userInfo.phone = phone
wx.setStorageSync('userInfo', app.globalData.userInfo)
}
wx.setStorageSync('user_phone', phone)
}
} catch (e) {
// 资料同步失败不影响前端提示
console.log('[Index] 同步手机号到用户资料失败:', e && e.message)
}
wx.showToast({ title: res.message || '提交成功,卡若会尽快联系您', icon: 'success' })
} else {
wx.showToast({ title: (res && res.message) || '提交失败', icon: 'none' })

View File

@@ -189,7 +189,8 @@
<!-- 链接卡若 - 留资弹窗(未填手机/微信号时) -->
<view class="lead-mask" wx:if="{{showLeadModal}}" catchtap="closeLeadModal">
<view class="lead-box" catchtap="">
<!-- 使用 catchtap="stopPropagation" 阻止内部点击冒泡到遮罩层,避免点击输入框时弹窗被关闭 -->
<view class="lead-box" catchtap="stopPropagation">
<text class="lead-title">留下联系方式</text>
<text class="lead-desc">方便卡若与您联系</text>
<input class="lead-input" placeholder="请输入手机号" type="number" maxlength="11" value="{{leadPhone}}" bindinput="onLeadPhoneInput"/>

View File

@@ -898,7 +898,11 @@
.lead-btn {
flex: 1;
height: 80rpx;
line-height: 80rpx;
/* 使用 flex 垂直居中文本,避免小程序默认 padding 导致按钮文字下沉 */
display: flex;
align-items: center;
justify-content: center;
padding: 0;
border-radius: 16rpx;
font-size: 30rpx;
font-weight: 500;

View File

@@ -619,6 +619,22 @@ Page({
// 显示登录弹窗(每次打开时协议未勾选,符合审核要求)
showLogin() {
// 朋友圈等单页模式下,不直接弹登录,用官方推荐的方式引导用户「前往小程序」
try {
const sys = wx.getSystemInfoSync()
const isSinglePage = (sys && sys.mode === 'singlePage') || getApp().globalData.isSinglePageMode
if (isSinglePage) {
wx.showModal({
title: '请前往完整小程序',
content: '当前为朋友圈单页,仅支持部分体验。想登录并管理账户,请点击底部「前往小程序」后再操作。',
showCancel: false,
confirmText: '我知道了',
})
return
}
} catch (e) {
console.warn('[My] 检测单页模式失败,回退为正常登录弹窗:', e)
}
try {
this.setData({ showLoginModal: true, agreeProtocol: false })
} catch (e) {

View File

@@ -106,7 +106,9 @@ Page({
id = ch.id
} else {
try {
const chRes = await app.request({ url: `/api/miniprogram/book/chapter/by-mid/${mid}`, silent: true })
const resolveUrl = `/api/miniprogram/book/chapter/by-mid/${mid}`
const uid = app.globalData.userInfo?.id
const chRes = await app.request({ url: uid ? resolveUrl + '?userId=' + encodeURIComponent(uid) : resolveUrl, silent: true })
if (chRes && chRes.id) id = chRes.id
} catch (e) {
console.warn('[Read] by-mid 解析失败:', e)
@@ -223,11 +225,13 @@ Page({
}
this.setData({ section })
if (res && res.content) {
const { lines, segments } = contentParser.parseContent(res.content)
// 已解锁用 data.content完整内容未解锁用 content预览先 determineAccessState 再 loadContent 保证顺序正确
const displayContent = accessManager.canAccessFullContent(accessState) ? (res.data?.content ?? res.content) : res.content
if (res && displayContent) {
const { lines, segments } = contentParser.parseContent(displayContent)
const previewCount = Math.ceil(lines.length * 0.2)
const updates = {
content: res.content,
content: displayContent,
contentParagraphs: lines,
contentSegments: segments,
previewParagraphs: lines.slice(0, previewCount),
@@ -236,8 +240,8 @@ Page({
}
if (res.mid) updates.sectionMid = res.mid
this.setData(updates)
// 写入本地缓存,供离线/重试降级使用
try { wx.setStorageSync(cacheKey, res) } catch (_) {}
// 写入本地缓存(存 displayContent,供离线/重试降级使用
try { wx.setStorageSync(cacheKey, { ...res, content: displayContent }) } catch (_) {}
if (accessManager.canAccessFullContent(accessState)) {
app.markSectionAsRead(id)
}
@@ -314,15 +318,20 @@ Page({
return titles[id] || `章节 ${id}`
},
// 根据 id/mid 构造章节接口路径(优先使用 mid
// 根据 id/mid 构造章节接口路径(优先使用 mid。必须带 userId 才能让后端正确判断付费用户并返回完整内容
_getChapterUrl(params = {}) {
const { id, mid } = params
const finalMid = (mid !== undefined && mid !== null) ? mid : this.data.sectionMid
let url
if (finalMid) {
return `/api/miniprogram/book/chapter/by-mid/${finalMid}`
url = `/api/miniprogram/book/chapter/by-mid/${finalMid}`
} else {
const finalId = id || this.data.sectionId
url = `/api/miniprogram/book/chapter/${finalId}`
}
const finalId = id || this.data.sectionId
return `/api/miniprogram/book/chapter/${finalId}`
const userId = app.globalData.userInfo?.id
if (userId) url += (url.includes('?') ? '&' : '?') + 'userId=' + encodeURIComponent(userId)
return url
},
@@ -651,8 +660,8 @@ Page({
: '📚 Soul创业派对 - 真实商业故事'
return {
title: shareTitle,
path: ref ? `/pages/read/read?${q}&ref=${ref}` : `/pages/read/read?${q}`,
imageUrl: '/assets/share-cover.png'
path: ref ? `/pages/read/read?${q}&ref=${ref}` : `/pages/read/read?${q}`
// 不设置 imageUrl使用当前阅读页截图作为分享卡片中间图片
}
},
@@ -670,6 +679,22 @@ Page({
// 显示登录弹窗(每次打开协议未勾选,符合审核要求)
showLoginModal() {
// 朋友圈等单页模式下,不直接弹登录,用官方推荐的方式引导用户「前往小程序」
try {
const sys = wx.getSystemInfoSync()
const isSinglePage = (sys && sys.mode === 'singlePage') || app.globalData.isSinglePageMode
if (isSinglePage) {
wx.showModal({
title: '请前往完整小程序',
content: '当前为朋友圈单页,仅支持部分浏览。想登录继续阅读,请点击底部「前往小程序」后再操作。',
showCancel: false,
confirmText: '我知道了',
})
return
}
} catch (e) {
console.warn('[Read] 检测单页模式失败,回退为正常登录流程:', e)
}
try {
this.setData({ showLoginModal: true, agreeProtocol: false })
} catch (e) {