- Added checks for audit mode in VIP navigation and member detail pages, preventing access and displaying appropriate messages. - Updated UI elements to conditionally render based on audit mode, enhancing user experience by hiding VIP-related options when in audit mode. - Introduced loading indicators on the VIP page to manage user expectations during content validation. - Enhanced error handling for image uploads in the article editor, ensuring a smoother content creation process. This update aims to improve the overall user experience by enforcing access restrictions and providing clear feedback in audit mode.
1032 lines
39 KiB
JavaScript
1032 lines
39 KiB
JavaScript
/**
|
||
* 卡若创业派对 - 首页
|
||
* 开发: 卡若
|
||
* 技术支持: 存客宝
|
||
*/
|
||
|
||
const app = getApp()
|
||
const { trackClick } = require('../../utils/trackClick')
|
||
const { cleanSingleLineField } = require('../../utils/contentParser')
|
||
const { navigateMpPath } = require('../../utils/mpNavigate.js')
|
||
const { isSafeImageSrc } = require('../../utils/imageUrl.js')
|
||
const {
|
||
submitCkbLead,
|
||
getReferralCodeForPay,
|
||
requestWxJsapiPayment,
|
||
syncOrderStatusQuery,
|
||
} = require('../../utils/soulBridge')
|
||
|
||
const DEFAULT_TIP_GIFTS = [
|
||
{ id: 'gift_lite', name: '小心心', price: 9.9, emoji: '❤️', icon: '', micOrder: 1, iconScale: 1, micFeatured: true },
|
||
{ id: 'gift_star', name: '人气票', price: 99, emoji: '🎫', icon: '', micOrder: 0, iconScale: 1, micFeatured: false },
|
||
{ id: 'gift_super', name: '嘉年华', price: 1980, emoji: '🎡', icon: '', micOrder: 2, iconScale: 1, micFeatured: false },
|
||
]
|
||
|
||
/** 置顶人物无头像时的占位图 */
|
||
const DEFAULT_KARUO_LINK_AVATAR = '/assets/images/karuo-link-avatar.png'
|
||
|
||
/** 与首页固定「卡若」获客位重复时从横滑列表剔除(含历史误写「卡路」) */
|
||
function isKaruoHostDuplicateName(displayName) {
|
||
const s = String(displayName || '').trim()
|
||
return s === '卡若' || s === '卡路'
|
||
}
|
||
|
||
/** 超级个体无头像占位:仅展示中文首字,避免头像圆里出现英文字母 */
|
||
function superAvatarLetter(displayName) {
|
||
const s = String(displayName || '').trim()
|
||
if (!s) return '会'
|
||
const ch = s[0]
|
||
return /[\u4e00-\u9fff]/.test(ch) ? ch : '会'
|
||
}
|
||
|
||
/** 旧 OSS 存 16personalities .svg 时改为 png 目录,与后端 resolveAvatarURL 一致 */
|
||
function normalizeLegacyMbtiAvatarUrl(u) {
|
||
if (!u || typeof u !== 'string') return u
|
||
const lower = u.toLowerCase()
|
||
if (!lower.includes('mbti-avatar')) return u
|
||
let s = u.replace(/mbti-avatars-16personalities-male/g, 'mbti-avatars-png-male')
|
||
s = s.replace(/mbti-avatars-16personalities-female/g, 'mbti-avatars-png-female')
|
||
if (/\.svg$/i.test(s)) s = s.replace(/\.svg$/i, '.png')
|
||
return s
|
||
}
|
||
|
||
function parseTimeToMinutes(t) {
|
||
const m = String(t || '').trim().match(/^(\d{1,2}):(\d{2})$/)
|
||
if (!m) return null
|
||
const h = parseInt(m[1], 10)
|
||
const min = parseInt(m[2], 10)
|
||
if (h < 0 || h > 23 || min < 0 || min > 59) return null
|
||
return h * 60 + min
|
||
}
|
||
|
||
/** 是否在直播上麦时段(支持跨午夜 end < start) */
|
||
function isNowInMicWindow(startStr, endStr) {
|
||
const a = parseTimeToMinutes(startStr)
|
||
const b = parseTimeToMinutes(endStr)
|
||
if (a == null || b == null) return false
|
||
const now = new Date()
|
||
const cur = now.getHours() * 60 + now.getMinutes()
|
||
if (a <= b) return cur >= a && cur < b
|
||
return cur >= a || cur < b
|
||
}
|
||
|
||
function normCfgBool(v) {
|
||
return v === true || v === 1 || v === '1' || String(v).toLowerCase() === 'true'
|
||
}
|
||
|
||
function normalizeTipGifts(raw) {
|
||
const base = DEFAULT_TIP_GIFTS
|
||
if (!Array.isArray(raw) || raw.length === 0) return base.map((g) => ({ ...g }))
|
||
return raw.map((row, i) => {
|
||
const dFallback = base[Math.min(i, base.length - 1)]
|
||
const rn = String(row.name != null ? row.name : '').trim()
|
||
let id = row.id != null ? String(row.id).trim() : ''
|
||
let d = dFallback
|
||
// 无 id / 空 id 时禁止按下标套默认 id:后台顺序多为「人气票、小心心、嘉年华」,下标1会变成 gift_star,
|
||
// 导致中间显示小心心¥9.9 却带 gift_star 去支付变成¥29.8。优先按礼物名称、再按 micOrder 对齐默认档。
|
||
if (!id) {
|
||
const byName = rn ? base.find((g) => g.name === rn) : undefined
|
||
if (byName) {
|
||
d = byName
|
||
id = byName.id
|
||
} else {
|
||
let mo = row.micOrder != null ? parseInt(String(row.micOrder), 10) : NaN
|
||
if (!Number.isNaN(mo)) {
|
||
const byOrder = base.find((g) => Number(g.micOrder) === mo)
|
||
if (byOrder) {
|
||
d = byOrder
|
||
id = byOrder.id
|
||
}
|
||
}
|
||
if (!id) {
|
||
d = dFallback
|
||
id = d.id
|
||
}
|
||
}
|
||
}
|
||
const name = String(row.name != null ? row.name : d.name).trim() || d.name
|
||
let price = parseFloat(row.price)
|
||
if (Number.isNaN(price) || price <= 0) price = d.price
|
||
const emoji = String(row.emoji != null ? row.emoji : d.emoji).trim() || d.emoji
|
||
const icon = String(row.icon != null ? row.icon : '').trim()
|
||
let micOrder = row.micOrder != null ? parseInt(String(row.micOrder), 10) : NaN
|
||
if (Number.isNaN(micOrder)) micOrder = 999
|
||
let iconScale = parseFloat(row.iconScale)
|
||
if (Number.isNaN(iconScale) || iconScale <= 0) iconScale = 1
|
||
const micFeatured =
|
||
row.micFeatured === true ||
|
||
row.micFeatured === 1 ||
|
||
row.micFeatured === '1' ||
|
||
String(row.micFeatured).toLowerCase() === 'true'
|
||
return { id, name, price, emoji, icon, micOrder, iconScale, micFeatured }
|
||
})
|
||
}
|
||
|
||
function sortGiftsForMic(arr) {
|
||
return [...arr].sort((a, b) => {
|
||
const oa = a.micOrder != null && !Number.isNaN(Number(a.micOrder)) ? Number(a.micOrder) : 999
|
||
const ob = b.micOrder != null && !Number.isNaN(Number(b.micOrder)) ? Number(b.micOrder) : 999
|
||
if (oa !== ob) return oa - ob
|
||
return 0
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 上麦横排:按礼物 micOrder 排序,最多 3 档;默认档优先 micFeatured,否则中间位
|
||
* micEmojiRpx:默认档再乘 liveMicSchedule.micCenterEmojiScale
|
||
*/
|
||
function layoutMicHorizontalSlots(gifts, liveMicSchedule) {
|
||
const fallback = DEFAULT_TIP_GIFTS.map((g) => ({ ...g }))
|
||
let arr = Array.isArray(gifts) && gifts.length ? gifts : fallback
|
||
arr = sortGiftsForMic(arr)
|
||
const slotsRaw = arr.slice(0, 3)
|
||
let defaultIndex = slotsRaw.length >= 2 ? 1 : 0
|
||
const fi = slotsRaw.findIndex(
|
||
(g) => g.micFeatured === true || g.micFeatured === 1 || g.micFeatured === '1' || String(g.micFeatured).toLowerCase() === 'true'
|
||
)
|
||
if (fi >= 0) defaultIndex = fi
|
||
const def = slotsRaw[defaultIndex]
|
||
const defaultId = def && def.id ? def.id : ''
|
||
let centerScale = 1.55
|
||
if (liveMicSchedule && liveMicSchedule.micCenterEmojiScale != null) {
|
||
const v = parseFloat(String(liveMicSchedule.micCenterEmojiScale))
|
||
if (!Number.isNaN(v) && v >= 1) centerScale = Math.min(v, 2.4)
|
||
}
|
||
const n = slotsRaw.length
|
||
/** 几何中间列:3 档为 index 1;2 档为 index 1;1 档为 0 */
|
||
const centerIdx = n <= 1 ? 0 : Math.floor(n / 2)
|
||
const baseRpx = 44
|
||
const slots = slotsRaw.map((g, idx) => {
|
||
const per = g.iconScale != null && Number(g.iconScale) > 0 ? Number(g.iconScale) : 1
|
||
const isDef = g.id === defaultId
|
||
const isCenterSlot = idx === centerIdx
|
||
let rpx = Math.round(baseRpx * per * (isDef ? centerScale : 1))
|
||
if (isCenterSlot) rpx = Math.round(rpx * 1.22)
|
||
rpx = Math.max(32, Math.min(110, rpx))
|
||
const iconStr = String(g.icon || '').trim()
|
||
const micShowIcon = !!(iconStr && isSafeImageSrc(iconStr))
|
||
return { ...g, micEmojiRpx: rpx, micShowIcon, micIsCenterSlot: isCenterSlot }
|
||
})
|
||
return { slots, defaultId }
|
||
}
|
||
|
||
Page({
|
||
data: {
|
||
// 系统信息
|
||
statusBarHeight: 44,
|
||
navBarHeight: 88,
|
||
|
||
// 用户信息
|
||
isLoggedIn: false,
|
||
hasFullBook: false,
|
||
readCount: 0,
|
||
|
||
// 书籍数据(totalSections 来自 book/parts,初始用 app.getTotalSections() 兜底)
|
||
totalSections: 0, // onLoad 后由 loadBookData 更新
|
||
bookData: [],
|
||
|
||
// 推荐章节(来自 recommended/hot API,初始为空避免占位错误)
|
||
featuredSections: [],
|
||
|
||
// Banner 推荐(优先用 recommended API 第一条,回退 latest-chapters)
|
||
bannerSection: null,
|
||
/** 首屏 Banner 请求完成前为 true;完成后为 false,避免接口全失败时长期显示「加载中」 */
|
||
bannerLoading: true,
|
||
latestLabel: '最新更新',
|
||
|
||
// 内容概览
|
||
partsList: [
|
||
{ id: 'part-1', number: '一', title: '真实的人', subtitle: '人与人之间的底层逻辑' },
|
||
{ id: 'part-2', number: '二', title: '真实的行业', subtitle: '电商、内容、传统行业解析' },
|
||
{ id: 'part-3', number: '三', title: '真实的错误', subtitle: '我和别人犯过的错' },
|
||
{ id: 'part-4', number: '四', title: '真实的赚钱', subtitle: '底层结构与真实案例' },
|
||
{ id: 'part-5', number: '五', title: '真实的社会', subtitle: '未来职业与商业生态' }
|
||
],
|
||
|
||
// 超级个体(VIP会员)
|
||
superMembers: [],
|
||
superMembersLoading: true,
|
||
|
||
// 收益排行榜
|
||
earningsBoard: [],
|
||
earningsBoardEnabled: false,
|
||
|
||
// 最新新增章节(完整列表 + 展示列表,用于展开/折叠)
|
||
latestChapters: [],
|
||
displayLatestChapters: [],
|
||
|
||
// 篇章数(从 bookData 计算)
|
||
partCount: 0,
|
||
|
||
// 加载状态
|
||
loading: true,
|
||
|
||
// 展开状态(首页精选/最新)
|
||
featuredExpanded: false,
|
||
latestExpanded: false,
|
||
featuredSectionsFull: [], // 精选排行榜全量(最多 50),默认只展示前 3 条
|
||
|
||
// 功能配置(搜索开关)
|
||
searchEnabled: true,
|
||
|
||
// 审核模式:隐藏支付相关入口
|
||
auditMode: false,
|
||
|
||
// mp_config.mpUi.homePage(后台系统设置 mpUi)
|
||
mpUiLogoTitle: '卡若创业派对',
|
||
mpUiLogoSubtitle: '来自派对房的真实故事',
|
||
/** 仅当有置顶 @人物时展示,文案与头像由 _applyHomeMpUi 写入 */
|
||
mpUiLinkKaruoText: '',
|
||
mpUiLinkKaruoDisplay: DEFAULT_KARUO_LINK_AVATAR,
|
||
mpUiSearchPlaceholder: '搜索章节标题或内容...',
|
||
mpUiBannerTag: '推荐',
|
||
mpUiBannerReadMore: '点击阅读',
|
||
mpUiSuperTitle: '超级个体',
|
||
mpUiPickTitle: '精选推荐',
|
||
mpUiLatestTitle: '最新新增',
|
||
|
||
/** 后台 @列表置顶人物:有则右上角展示绑定用户头像 + @名称,点击走 ckb/lead */
|
||
homePinnedPerson: null,
|
||
|
||
/** 首页入口:打赏 + 直播时段上麦(mpUi.homePage.linkKaruoReward / liveMicSchedule) */
|
||
linkKaruoRewardEnabled: false,
|
||
linkKaruoRewardUi: {
|
||
entryButtonText: '支持一下',
|
||
modalTitle: '打赏支持',
|
||
modalSubtitle: '感谢支持,任选礼物与数量',
|
||
payButtonText: '立即支付',
|
||
leadLinkText: '留下联系方式',
|
||
afterPayToast: '支付成功,感谢支持!',
|
||
},
|
||
liveMicSchedule: {
|
||
enabled: false,
|
||
micStart: '18:00',
|
||
micEnd: '21:00',
|
||
micEmoji: '🎤',
|
||
micButtonText: '申请上麦',
|
||
micModalTitle: '申请上麦',
|
||
micModalContent: '',
|
||
micAfterSubmitToast: '支付成功,感谢支持!',
|
||
micCenterEmojiScale: 1.55,
|
||
},
|
||
homeMicEligible: false,
|
||
tipGifts: [],
|
||
showTipModal: false,
|
||
tipHomeMicMode: false,
|
||
tipModalTitle: '',
|
||
tipModalSubtitle: '',
|
||
selectedTipGiftId: '',
|
||
tipQty: 1,
|
||
tipLineTotal: '0.00',
|
||
/** 上麦弹窗横排礼物(与后台 gifts 顺序一致) */
|
||
micHorizontalSlots: [],
|
||
micDefaultGiftId: '',
|
||
/** 右上角唯一入口:由置顶超级个体决定 */
|
||
headerCornerAction: { show: false, kind: '', label: '', emoji: '', avatar: '' },
|
||
|
||
/** 文旅/落地体验链:未登录时弹一键登录,成功后继续打赏/上麦/留资 */
|
||
showLoginModal: false,
|
||
showPrivacyModal: false,
|
||
loginModalDesc: '登录后可参与打赏、上麦与链接嘉宾',
|
||
pendingAfterLogin: null,
|
||
},
|
||
|
||
onLoad(options) {
|
||
console.log('[Index] ===== onLoad 触发 =====')
|
||
|
||
// 获取系统信息
|
||
this.setData({
|
||
statusBarHeight: app.globalData.statusBarHeight,
|
||
navBarHeight: app.globalData.navBarHeight
|
||
})
|
||
|
||
// 处理分享参数(推荐码绑定)
|
||
if (options && options.ref) {
|
||
console.log('[Index] 检测到推荐码:', options.ref)
|
||
app.handleReferralCode({ query: options })
|
||
}
|
||
|
||
wx.showShareMenu({ withShareTimeline: true })
|
||
this.loadFeatureConfig()
|
||
this.initData()
|
||
},
|
||
|
||
async onShow() {
|
||
console.log('[Index] onShow 触发')
|
||
try {
|
||
await app.getConfig(true)
|
||
} catch (_) {}
|
||
this.setData({ auditMode: app.globalData.auditMode || false })
|
||
this._refreshHomeEntryFlags()
|
||
void this.loadHomePinnedPerson()
|
||
// 首页 tab 再次展示时重拉超级个体(避免首进网络失败或仅 onLoad 拉一次后长期空白)
|
||
if (!app.globalData.auditMode) {
|
||
void this.loadSuperMembers()
|
||
}
|
||
|
||
// 设置TabBar选中状态
|
||
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
||
const tabBar = this.getTabBar()
|
||
console.log('[Index] TabBar 组件:', tabBar ? '已找到' : '未找到')
|
||
|
||
// 主动触发配置加载
|
||
if (tabBar && tabBar.loadFeatureConfig) {
|
||
console.log('[Index] 主动调用 TabBar.loadFeatureConfig()')
|
||
tabBar.loadFeatureConfig()
|
||
}
|
||
|
||
// 更新选中状态
|
||
if (tabBar && tabBar.updateSelected) {
|
||
tabBar.updateSelected()
|
||
} else if (tabBar) {
|
||
tabBar.setData({ selected: 0 })
|
||
}
|
||
} else {
|
||
console.log('[Index] TabBar 组件未找到或 getTabBar 方法不存在')
|
||
}
|
||
|
||
// 更新用户状态
|
||
this.updateUserStatus()
|
||
},
|
||
|
||
// 初始化数据:首次进页面并行异步加载,加快首屏展示
|
||
initData() {
|
||
this.setData({ loading: false })
|
||
this.loadBookData()
|
||
this.loadFeaturedAndLatest()
|
||
this.loadSuperMembers()
|
||
this.loadEarningsBoard()
|
||
},
|
||
|
||
async loadSuperMembers() {
|
||
this.setData({ superMembersLoading: true })
|
||
try {
|
||
// 仅走后端 VIP 列表排序(vip_sort、vip_activated_at),不在端上拼普通用户
|
||
const vipRes = await app.request({ url: '/api/miniprogram/vip/members?limit=24', silent: true }).catch(() => null)
|
||
let members = []
|
||
if (vipRes && vipRes.success && Array.isArray(vipRes.data) && vipRes.data.length > 0) {
|
||
members = vipRes.data.map(u => {
|
||
const raw = u.name || u.nickname || u.vipName || u.vip_name || '会员'
|
||
const name = cleanSingleLineField(raw) || '会员'
|
||
return {
|
||
id: u.id,
|
||
name,
|
||
avatar: u.avatar || '',
|
||
isVip: true,
|
||
avatarLetter: superAvatarLetter(name)
|
||
}
|
||
}).filter((m) => !isKaruoHostDuplicateName(m.name))
|
||
console.log('[Index] 超级个体(后端排序):', members.length, '人')
|
||
}
|
||
this.setData({ superMembers: members, superMembersLoading: false })
|
||
} catch (e) {
|
||
console.log('[Index] 加载超级个体失败:', e)
|
||
this.setData({ superMembersLoading: false })
|
||
}
|
||
},
|
||
|
||
async loadEarningsBoard() {
|
||
try {
|
||
const res = await app.request({ url: '/api/miniprogram/earnings/leaderboard', silent: true }).catch(() => null)
|
||
if (res && res.success && res.enabled && Array.isArray(res.data) && res.data.length > 0) {
|
||
const board = res.data.map(item => ({
|
||
rank: item.rank,
|
||
nickname: item.nickname || '分享达人',
|
||
avatar: normalizeLegacyMbtiAvatarUrl(item.avatar || ''),
|
||
avatarLetter: superAvatarLetter(item.nickname || '创')
|
||
}))
|
||
this.setData({ earningsBoard: board, earningsBoardEnabled: true })
|
||
console.log('[Index] 收益排行榜:', board.length, '人')
|
||
} else {
|
||
this.setData({ earningsBoardEnabled: res && res.enabled === false ? false : true })
|
||
}
|
||
} catch (e) {
|
||
console.log('[Index] 加载收益排行榜失败:', e)
|
||
}
|
||
},
|
||
|
||
// 精选推荐 + 最新更新 + 最新列表:顺序以后端为准(recommended=排行榜算法,latest=updated_at)
|
||
async loadFeaturedAndLatest() {
|
||
this.setData({ bannerLoading: true })
|
||
try {
|
||
const tagClassForTag = (tag) => (tag === '热门' ? 'tag-hot' : 'tag-rec')
|
||
const toSectionFromRanking = (s) => {
|
||
const tag = s.tag || '精选'
|
||
return {
|
||
id: s.id || s.section_id,
|
||
mid: s.mid ?? s.MID ?? 0,
|
||
title: s.section_title || s.sectionTitle || s.title || s.chapterTitle || '',
|
||
part: (s.part_title || s.partTitle || '').replace(/[_||]/g, ' ').trim(),
|
||
tag,
|
||
tagClass: tagClassForTag(tag)
|
||
}
|
||
}
|
||
const fallbackTags = ['热门', '推荐', '精选']
|
||
const toSectionFromHot = (s, i) => {
|
||
const tag = fallbackTags[i % 3]
|
||
return {
|
||
id: s.id || s.section_id,
|
||
mid: s.mid ?? s.MID ?? 0,
|
||
title: s.section_title || s.sectionTitle || s.title || s.chapterTitle || '',
|
||
part: (s.part_title || s.partTitle || '').replace(/[_||]/g, ' ').trim(),
|
||
tag,
|
||
tagClass: tagClassForTag(tag)
|
||
}
|
||
}
|
||
|
||
const [recRes, latestRes] = await Promise.all([
|
||
app.request({ url: '/api/miniprogram/book/recommended?limit=50', silent: true }).catch(() => null),
|
||
app.request({ url: '/api/miniprogram/book/latest-chapters', silent: true }).catch(() => null)
|
||
])
|
||
|
||
// 1. 精选推荐:一次拉全量(≤50),默认只显示 3 条;点列表下三角展开(与「最新新增」一致)
|
||
let featuredFull = []
|
||
if (recRes && recRes.success && Array.isArray(recRes.data) && recRes.data.length > 0) {
|
||
featuredFull = recRes.data.map((s) => toSectionFromRanking(s))
|
||
}
|
||
if (featuredFull.length === 0) {
|
||
try {
|
||
const hotRes = await app.request({ url: '/api/miniprogram/book/hot?limit=50', silent: true })
|
||
const hotList = (hotRes && hotRes.data) ? hotRes.data : []
|
||
if (hotList.length > 0) featuredFull = hotList.map((s, i) => toSectionFromHot(s, i))
|
||
} catch (e) { console.log('[Index] book/hot 兜底失败:', e) }
|
||
}
|
||
if (featuredFull.length > 0) {
|
||
this.setData({
|
||
featuredSectionsFull: featuredFull,
|
||
featuredSections: featuredFull.slice(0, 3),
|
||
featuredExpanded: false
|
||
})
|
||
} else {
|
||
this.setData({
|
||
featuredSectionsFull: [],
|
||
featuredSections: [],
|
||
featuredExpanded: false
|
||
})
|
||
}
|
||
|
||
// 2. Banner 推荐:优先取 recommended 第一条,回退 latest 第一条
|
||
const rawList = (latestRes && latestRes.data) ? latestRes.data : []
|
||
// 按更新时间倒序,最新在前(与后台展示一致)
|
||
const latestList = [...rawList].sort((a, b) => {
|
||
const ta = new Date(a.updatedAt || a.updated_at || 0).getTime()
|
||
const tb = new Date(b.updatedAt || b.updated_at || 0).getTime()
|
||
return tb - ta
|
||
})
|
||
if (featuredFull.length > 0) {
|
||
this.setData({ bannerSection: featuredFull[0] })
|
||
} else if (latestList.length > 0) {
|
||
const l = latestList[0]
|
||
this.setData({
|
||
bannerSection: {
|
||
id: l.id,
|
||
mid: l.mid ?? l.MID ?? 0,
|
||
title: l.section_title || l.sectionTitle || l.title || l.chapterTitle || '',
|
||
part: l.part_title || l.partTitle || ''
|
||
}
|
||
})
|
||
}
|
||
const latestChapters = latestList.slice(0, 20).map(c => {
|
||
const d = new Date(c.updatedAt || c.updated_at || Date.now())
|
||
const title = c.section_title || c.sectionTitle || c.title || c.chapterTitle || ''
|
||
return {
|
||
id: c.id,
|
||
mid: c.mid ?? c.MID ?? 0,
|
||
title,
|
||
desc: '',
|
||
price: c.price ?? 1,
|
||
dateStr: `${d.getMonth() + 1}/${d.getDate()}`
|
||
}
|
||
})
|
||
const display = this.data.latestExpanded ? latestChapters : latestChapters.slice(0, 5)
|
||
this.setData({ latestChapters, displayLatestChapters: display })
|
||
} catch (e) {
|
||
console.log('[Index] 从服务端加载推荐失败:', e)
|
||
} finally {
|
||
this.setData({ bannerLoading: false })
|
||
}
|
||
},
|
||
|
||
async loadBookData() {
|
||
try {
|
||
const res = await app.request({ url: '/api/miniprogram/book/parts', silent: true })
|
||
if (res?.success) {
|
||
const total = res.totalSections ?? 0
|
||
const parts = res.parts || []
|
||
app.globalData.totalSections = (total != null && total > 0) ? total : app.getTotalSections()
|
||
this.setData({
|
||
totalSections: app.globalData.totalSections,
|
||
partCount: parts.length || 5
|
||
})
|
||
}
|
||
} catch (e) {
|
||
this.setData({ totalSections: app.getTotalSections(), partCount: 5 })
|
||
}
|
||
},
|
||
|
||
// 更新用户状态(已读数 = 用户实际打开过的章节数,仅统计有权限阅读的)
|
||
updateUserStatus() {
|
||
const { isLoggedIn, hasFullBook, purchasedSections } = app.globalData
|
||
const readCount = Math.min(app.getReadCount(), this.data.totalSections || app.getTotalSections())
|
||
this.setData({
|
||
isLoggedIn,
|
||
hasFullBook,
|
||
readCount
|
||
})
|
||
},
|
||
|
||
// 跳转到目录
|
||
goToChapters() {
|
||
trackClick('home', 'nav_click', '阅读进度')
|
||
wx.switchTab({ url: '/pages/chapters/chapters' })
|
||
},
|
||
|
||
_applyHomeMpUi() {
|
||
const h = app.globalData.configCache?.mpConfig?.mpUi?.homePage || {}
|
||
const baseTitle = String(h.logoTitle || '卡若创业派对').trim() || '卡若创业派对'
|
||
const prefix = String(h.pinnedTitlePrefix != null ? h.pinnedTitlePrefix : '派对会员').trim()
|
||
const tpl = String(h.pinnedMainTitleTemplate || '').trim()
|
||
const patch = {
|
||
mpUiLogoTitle: baseTitle,
|
||
mpUiLogoSubtitle: String(h.logoSubtitle || '来自派对房的真实故事').trim() || '来自派对房的真实故事',
|
||
mpUiSearchPlaceholder: String(h.searchPlaceholder || '搜索章节标题或内容...').trim() || '搜索章节标题或内容...',
|
||
mpUiBannerTag: String(h.bannerTag || '推荐').trim() || '推荐',
|
||
mpUiBannerReadMore: String(h.bannerReadMoreText || '点击阅读').trim() || '点击阅读',
|
||
mpUiSuperTitle: String(h.superSectionTitle || '超级个体').trim() || '超级个体',
|
||
mpUiPickTitle: String(h.pickSectionTitle || '精选推荐').trim() || '精选推荐',
|
||
mpUiLatestTitle: String(h.latestSectionTitle || '最新新增').trim() || '最新新增',
|
||
}
|
||
const pinned = this.data.homePinnedPerson
|
||
if (pinned && pinned.token) {
|
||
const displayAv =
|
||
pinned.avatar && isSafeImageSrc(pinned.avatar) ? pinned.avatar : DEFAULT_KARUO_LINK_AVATAR
|
||
const nm = pinned.name || '好友'
|
||
patch.mpUiLinkKaruoText = `点击链接${nm}`
|
||
patch.mpUiLinkKaruoDisplay = displayAv
|
||
let mainTitle = baseTitle
|
||
if (tpl) {
|
||
mainTitle = tpl
|
||
.replace(/\{\{name\}\}/g, nm)
|
||
.replace(/\{\{prefix\}\}/g, prefix)
|
||
.trim() || baseTitle
|
||
} else if (prefix) {
|
||
mainTitle = baseTitle
|
||
} else {
|
||
mainTitle = `@${nm}`
|
||
}
|
||
patch.mpUiLogoTitle = mainTitle
|
||
} else {
|
||
patch.mpUiLinkKaruoText = ''
|
||
patch.mpUiLinkKaruoDisplay = DEFAULT_KARUO_LINK_AVATAR
|
||
}
|
||
this.setData(patch, () => {
|
||
try {
|
||
wx.setNavigationBarTitle({ title: patch.mpUiLogoTitle || '首页' })
|
||
} catch (_) {}
|
||
this._syncHeaderCornerAction()
|
||
})
|
||
},
|
||
|
||
/** 拉取后台置顶 @人物,合并到首页右上角「链接」区;同时拿到该人的 homeEntryConfig */
|
||
async loadHomePinnedPerson() {
|
||
let pinnedPerson = null
|
||
let override
|
||
try {
|
||
const res = await app.request({ url: '/api/miniprogram/ckb/pinned-person', silent: true })
|
||
if (res && res.success && res.data && res.data.token) {
|
||
const name = cleanSingleLineField(res.data.name) || '好友'
|
||
let av = String(res.data.avatar || '').trim()
|
||
if (!isSafeImageSrc(av)) av = ''
|
||
pinnedPerson = {
|
||
token: String(res.data.token).trim(),
|
||
name,
|
||
avatar: av,
|
||
homeEntryConfig: res.data.homeEntryConfig || null,
|
||
}
|
||
if (pinnedPerson.homeEntryConfig) {
|
||
override = {}
|
||
if (pinnedPerson.homeEntryConfig.linkKaruoReward) override.linkKaruoReward = pinnedPerson.homeEntryConfig.linkKaruoReward
|
||
if (pinnedPerson.homeEntryConfig.liveMicSchedule) override.liveMicSchedule = pinnedPerson.homeEntryConfig.liveMicSchedule
|
||
}
|
||
} else {
|
||
pinnedPerson = null
|
||
}
|
||
} catch (e) {
|
||
console.log('[Index] pinned-person:', e)
|
||
pinnedPerson = null
|
||
}
|
||
this.setData({ homePinnedPerson: pinnedPerson }, () => {
|
||
this._applyHomeMpUi()
|
||
this._refreshHomeEntryFlags(override)
|
||
})
|
||
},
|
||
|
||
async loadFeatureConfig() {
|
||
try {
|
||
await app.getConfig(true)
|
||
const res = app.globalData.configCache
|
||
if (res) {
|
||
const features = res.features || (res.data && res.data.features) || {}
|
||
const searchEnabled = features.searchEnabled !== false
|
||
if (!app.globalData.features) app.globalData.features = {}
|
||
app.globalData.features.searchEnabled = searchEnabled
|
||
if (typeof features.matchEnabled === 'boolean') app.globalData.features.matchEnabled = features.matchEnabled
|
||
if (typeof features.referralEnabled === 'boolean') app.globalData.features.referralEnabled = features.referralEnabled
|
||
const mp = res.mpConfig || {}
|
||
app.globalData.auditMode = !!mp.auditMode
|
||
}
|
||
await app.getAuditMode()
|
||
const searchEnabled = app.globalData.features?.searchEnabled !== false
|
||
this.setData({
|
||
searchEnabled,
|
||
auditMode: app.globalData.auditMode || false
|
||
})
|
||
this._applyHomeMpUi()
|
||
this._refreshHomeEntryFlags()
|
||
} catch (e) {
|
||
try {
|
||
await app.getAuditMode()
|
||
} catch (_) {}
|
||
this.setData({
|
||
searchEnabled: app.globalData.features?.searchEnabled !== false,
|
||
auditMode: app.globalData.auditMode || false
|
||
})
|
||
this._applyHomeMpUi()
|
||
this._refreshHomeEntryFlags()
|
||
}
|
||
await this.loadHomePinnedPerson()
|
||
},
|
||
|
||
_refreshHomeEntryFlags(override) {
|
||
const audit = !!app.globalData.auditMode
|
||
// 有置顶人物时:入口开关严格按该人物配置,不再回退全局,避免“人字拖未开上麦却显示申请上麦”。
|
||
// 无置顶人物时:沿用全局 mpUi.homePage。
|
||
const hasPinned = !!(this.data.homePinnedPerson && this.data.homePinnedPerson.token)
|
||
const personCfg = override || ((this.data.homePinnedPerson && this.data.homePinnedPerson.homeEntryConfig) || null)
|
||
const h = app.globalData.configCache?.mpConfig?.mpUi?.homePage || {}
|
||
const rw = hasPinned
|
||
? ((personCfg && personCfg.linkKaruoReward) || {})
|
||
: (h.linkKaruoReward || {})
|
||
const schReal = hasPinned
|
||
? ((personCfg && personCfg.liveMicSchedule) || {})
|
||
: (h.liveMicSchedule || {})
|
||
const rewardEnabled = normCfgBool(rw.enabled)
|
||
const micEnabled = normCfgBool(schReal.enabled)
|
||
const inWindow = isNowInMicWindow(schReal.micStart, schReal.micEnd)
|
||
const homeMicEligible = !audit && micEnabled && inWindow
|
||
const gifts = normalizeTipGifts(Array.isArray(rw.gifts) && rw.gifts.length ? rw.gifts : null)
|
||
const tipGifts = gifts.length ? gifts : DEFAULT_TIP_GIFTS.map((g) => ({ ...g }))
|
||
this.setData({
|
||
linkKaruoRewardEnabled: rewardEnabled,
|
||
linkKaruoRewardUi: {
|
||
entryButtonText: String(rw.entryButtonText || '支持一下').trim() || '支持一下',
|
||
modalTitle: String(rw.modalTitle || '打赏支持').trim() || '打赏支持',
|
||
modalSubtitle: String(rw.modalSubtitle || '感谢支持,任选礼物与数量').trim() || '感谢支持,任选礼物与数量',
|
||
payButtonText: String(rw.payButtonText || '立即支付').trim() || '立即支付',
|
||
leadLinkText: String(rw.leadLinkText || '留下联系方式').trim() || '留下联系方式',
|
||
afterPayToast: String(rw.afterPayToast || '支付成功,感谢支持!').trim() || '支付成功,感谢支持!',
|
||
},
|
||
liveMicSchedule: {
|
||
enabled: micEnabled,
|
||
micStart: String(schReal.micStart || '18:00').trim() || '18:00',
|
||
micEnd: String(schReal.micEnd || '21:00').trim() || '21:00',
|
||
micEmoji: String(schReal.micEmoji || '🎤').trim() || '🎤',
|
||
micButtonText: String(schReal.micButtonText || '申请上麦').trim() || '申请上麦',
|
||
micModalTitle: String(schReal.micModalTitle || '申请上麦').trim() || '申请上麦',
|
||
micModalContent: String(
|
||
schReal.micModalContent || '当前为直播时段,提交后工作人员将按顺序处理连麦申请。',
|
||
).trim(),
|
||
micAfterSubmitToast: String(schReal.micAfterSubmitToast || '支付成功,感谢支持!').trim() || '支付成功,感谢支持!',
|
||
micCenterEmojiScale: (() => {
|
||
const v = parseFloat(String(schReal.micCenterEmojiScale != null ? schReal.micCenterEmojiScale : '1.55'))
|
||
if (Number.isNaN(v) || v < 1) return 1.55
|
||
return Math.min(v, 2.4)
|
||
})(),
|
||
},
|
||
homeMicEligible,
|
||
tipGifts,
|
||
})
|
||
this._syncHeaderCornerAction()
|
||
},
|
||
|
||
/** 右上角单一入口:上麦时段 > 置顶超级个体 > 打赏 */
|
||
_syncHeaderCornerAction() {
|
||
if (app.globalData.auditMode) {
|
||
this.setData({ headerCornerAction: { show: false, kind: '', label: '', emoji: '', avatar: '' } })
|
||
return
|
||
}
|
||
const mic = !!this.data.homeMicEligible
|
||
const pinned = !!(this.data.homePinnedPerson && this.data.homePinnedPerson.token)
|
||
const reward = !!this.data.linkKaruoRewardEnabled
|
||
const sch = this.data.liveMicSchedule || {}
|
||
let show = false, kind = '', label = '', emoji = '', avatar = ''
|
||
if (mic) {
|
||
show = true; kind = 'mic'
|
||
label = String(sch.micButtonText || '申请上麦').trim() || '申请上麦'
|
||
emoji = String(sch.micEmoji || '🎤').trim() || '🎤'
|
||
} else if (pinned) {
|
||
show = true; kind = 'ckb'
|
||
label = String(this.data.mpUiLinkKaruoText || '').trim() || '链接卡若'
|
||
avatar = this.data.mpUiLinkKaruoDisplay || DEFAULT_KARUO_LINK_AVATAR
|
||
} else if (reward) {
|
||
show = true; kind = 'reward'
|
||
const rwUi = this.data.linkKaruoRewardUi || {}
|
||
label = String(rwUi.entryButtonText || '支持一下').trim() || '支持一下'
|
||
emoji = ''
|
||
}
|
||
this.setData({ headerCornerAction: { show, kind, label, emoji, avatar } })
|
||
},
|
||
|
||
/** 右上角统一点击 */
|
||
onHeaderCornerTap() {
|
||
const a = this.data.headerCornerAction
|
||
if (!a || !a.show) return
|
||
if (a.kind === 'ckb') {
|
||
this.onLinkKaruo()
|
||
return
|
||
}
|
||
this._openHorizontalGiftModal(a.kind === 'mic' ? 'live_mic' : 'home_reward')
|
||
},
|
||
|
||
/**
|
||
* 体验环节未登录:弹公用 login-modal(单页模式仍引导「前往小程序」)
|
||
* @param {{ type: 'tip', tipSource: string } | { type: 'link_karuo' }} pending
|
||
*/
|
||
_showHomeLoginModal(pending, desc) {
|
||
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('[Index] 检测单页模式失败,回退为登录弹窗:', e)
|
||
}
|
||
this.setData({
|
||
pendingAfterLogin: pending,
|
||
loginModalDesc: desc || '登录后可参与打赏、上麦与链接嘉宾',
|
||
showLoginModal: true,
|
||
})
|
||
},
|
||
|
||
onLoginModalClose() {
|
||
this.setData({ showLoginModal: false, showPrivacyModal: false, pendingAfterLogin: null })
|
||
},
|
||
onLoginModalPrivacyAgree() {
|
||
this.setData({ showPrivacyModal: false })
|
||
},
|
||
onLoginModalSuccess() {
|
||
const pending = this.data.pendingAfterLogin
|
||
this.setData({ showLoginModal: false, pendingAfterLogin: null })
|
||
this.updateUserStatus()
|
||
wx.showToast({ title: '登录成功', icon: 'success' })
|
||
if (!pending) return
|
||
const run = (fn) => {
|
||
if (typeof wx.nextTick === 'function') wx.nextTick(fn)
|
||
else setTimeout(fn, 0)
|
||
}
|
||
if (pending.type === 'tip' && pending.tipSource) {
|
||
run(() => this._openHorizontalGiftModal(pending.tipSource))
|
||
} else if (pending.type === 'link_karuo') {
|
||
run(() => this.onLinkKaruo())
|
||
}
|
||
},
|
||
|
||
/** 打开横排礼物弹窗(上麦/打赏统一入口) */
|
||
_openHorizontalGiftModal(tipSource) {
|
||
if (app.globalData.auditMode) return
|
||
const label = tipSource === 'live_mic' ? '申请上麦' : '打赏支持'
|
||
trackClick('home', tipSource === 'live_mic' ? 'live_mic_request' : 'btn_click', label)
|
||
if (!app.globalData.isLoggedIn) {
|
||
const desc =
|
||
tipSource === 'live_mic'
|
||
? '登录后可申请上麦并完成礼遇支付'
|
||
: '登录后可打赏支持'
|
||
this._showHomeLoginModal({ type: 'tip', tipSource }, desc)
|
||
return
|
||
}
|
||
const sch = this.data.liveMicSchedule
|
||
const gifts = this.data.tipGifts || []
|
||
const { slots, defaultId } = layoutMicHorizontalSlots(gifts, sch)
|
||
const title = tipSource === 'live_mic'
|
||
? String(sch.micModalTitle || '申请上麦').trim()
|
||
: String(this.data.linkKaruoRewardUi.modalTitle || '打赏支持').trim()
|
||
const sub = tipSource === 'live_mic'
|
||
? String(sch.micModalContent || '当前为直播时段,提交后工作人员将按顺序处理连麦申请。').trim()
|
||
: String(this.data.linkKaruoRewardUi.modalSubtitle || '感谢支持,点选礼物直接支付').trim()
|
||
this.setData({
|
||
showTipModal: true,
|
||
tipHomeMicMode: tipSource === 'live_mic',
|
||
tipModalTitle: title,
|
||
tipModalSubtitle: sub,
|
||
micHorizontalSlots: slots,
|
||
micDefaultGiftId: defaultId,
|
||
selectedTipGiftId: defaultId,
|
||
tipQty: 1,
|
||
})
|
||
},
|
||
|
||
closeTipModal() {
|
||
this.setData({ showTipModal: false, micHorizontalSlots: [], micDefaultGiftId: '' })
|
||
},
|
||
|
||
stopTipModalBubble() {},
|
||
|
||
/** 横排礼物卡片点击 → 直接调起微信支付 */
|
||
onHorizontalTipPay(e) {
|
||
const id = e.currentTarget.dataset.id
|
||
if (!id) return
|
||
const src = this.data.tipHomeMicMode ? 'live_mic' : 'home_reward'
|
||
this._executeLinkKaruoTipPay(src, id, 1)
|
||
},
|
||
|
||
async _executeLinkKaruoTipPay(tipSource, giftId, qty) {
|
||
const gid = String(giftId || '').trim()
|
||
const q = Math.max(1, parseInt(String(qty), 10) || 1)
|
||
if (!gid) {
|
||
wx.showToast({ title: '请选择礼物', icon: 'none' })
|
||
return
|
||
}
|
||
if (!app.globalData.isLoggedIn || !app.globalData.userInfo?.id) {
|
||
wx.showToast({ title: '请先登录', icon: 'none' })
|
||
return
|
||
}
|
||
const openId = await app.ensurePayOpenId()
|
||
if (!openId) {
|
||
wx.showModal({
|
||
title: '无法拉起支付',
|
||
content: '未获取到微信支付标识,请完全关闭小程序后重新进入,或退出账号重新登录。',
|
||
showCancel: false,
|
||
})
|
||
return
|
||
}
|
||
const g = (this.data.tipGifts || []).find((x) => String(x.id) === gid)
|
||
const amount = g && Number(g.price) > 0 ? Math.round(Number(g.price) * q * 100) / 100 : 0
|
||
if (amount <= 0) {
|
||
wx.showToast({ title: '礼物价格无效', icon: 'none' })
|
||
return
|
||
}
|
||
wx.showLoading({ title: '下单中...', mask: true })
|
||
try {
|
||
const referralCode = getReferralCodeForPay(app) || undefined
|
||
const res = await app.request({
|
||
url: '/api/miniprogram/pay',
|
||
method: 'POST',
|
||
silent: true,
|
||
data: {
|
||
openId,
|
||
productType: 'link_karuo_tip',
|
||
productId: tipSource === 'live_mic' ? `live_mic|${gid}|${q}` : `${gid}|${q}`,
|
||
amount,
|
||
description: tipSource === 'live_mic' ? '上麦礼遇' : '首页打赏',
|
||
userId: app.globalData.userInfo.id,
|
||
referralCode,
|
||
tipSource: tipSource === 'live_mic' ? 'live_mic' : 'home_reward',
|
||
},
|
||
})
|
||
wx.hideLoading()
|
||
if (!res || !res.success || !res.data || !res.data.payParams) {
|
||
const errText = (res && (res.error || res.message)) || '下单失败'
|
||
wx.showToast({ title: String(errText).slice(0, 36), icon: 'none' })
|
||
return
|
||
}
|
||
await requestWxJsapiPayment(res.data.payParams)
|
||
const sn = res.data.orderSn
|
||
if (sn) {
|
||
try {
|
||
await syncOrderStatusQuery(app, sn)
|
||
} catch (_) {}
|
||
}
|
||
const toast =
|
||
tipSource === 'live_mic'
|
||
? this.data.liveMicSchedule.micAfterSubmitToast || '支付成功'
|
||
: this.data.linkKaruoRewardUi.afterPayToast || '支付成功'
|
||
wx.showToast({ title: toast, icon: 'success' })
|
||
this.closeTipModal()
|
||
} catch (e) {
|
||
wx.hideLoading()
|
||
const msg = (e && e.errMsg) || (e && e.message) || '支付失败'
|
||
if (String(msg).indexOf('cancel') >= 0) {
|
||
wx.showToast({ title: '已取消支付', icon: 'none' })
|
||
return
|
||
}
|
||
wx.showToast({ title: String(msg).slice(0, 28), icon: 'none' })
|
||
}
|
||
},
|
||
|
||
// 跳转到搜索页
|
||
goToSearch() {
|
||
if (!this.data.searchEnabled) return
|
||
trackClick('home', 'nav_click', '搜索')
|
||
wx.navigateTo({ url: '/pages/search/search' })
|
||
},
|
||
|
||
// 跳转到阅读页(传 mid,与分享一致;无 mid 时传 id)
|
||
goToRead(e) {
|
||
const id = e.currentTarget.dataset.id
|
||
const mid = e.currentTarget.dataset.mid
|
||
trackClick('home', 'card_click', id || '章节')
|
||
const q = mid ? `mid=${mid}` : `id=${id}`
|
||
wx.navigateTo({ url: `/pages/read/read?${q}` })
|
||
},
|
||
|
||
// 跳转到匹配页
|
||
goToMatch() {
|
||
wx.switchTab({ url: '/pages/match/match' })
|
||
},
|
||
|
||
goToVip() {
|
||
if (app.globalData.auditMode) {
|
||
wx.showToast({ title: '当前为体验版,暂无法访问', icon: 'none' })
|
||
return
|
||
}
|
||
trackClick('home', 'btn_click', '加入创业派对')
|
||
wx.navigateTo({ url: '/pages/vip/vip' })
|
||
},
|
||
|
||
async onLinkKaruo() {
|
||
const pinned = this.data.homePinnedPerson
|
||
if (!pinned || !pinned.token) return
|
||
trackClick('home', 'btn_click', '置顶@人物留资')
|
||
if (!app.globalData.isLoggedIn) {
|
||
this._showHomeLoginModal({ type: 'link_karuo' }, '登录后可向嘉宾留下联系方式')
|
||
return
|
||
}
|
||
await submitCkbLead(getApp(), {
|
||
targetUserId: pinned.token,
|
||
targetNickname: pinned.name,
|
||
source: 'home_pinned_person',
|
||
})
|
||
},
|
||
|
||
goToSuperList() {
|
||
wx.switchTab({ url: '/pages/match/match' })
|
||
},
|
||
|
||
// 精选推荐:列表下方小三角展开(数据已在 loadFeaturedAndLatest 一次拉齐)
|
||
expandFeaturedChapters() {
|
||
if (this.data.featuredExpanded) return
|
||
const full = this.data.featuredSectionsFull || []
|
||
if (full.length <= 3) return
|
||
trackClick('home', 'tab_click', '精选展开_底部三角')
|
||
this.setData({ featuredExpanded: true, featuredSections: full })
|
||
},
|
||
|
||
// 最新新增:列表下方小三角展开(无「收起」,展开后整页向下滚动查看)
|
||
expandLatestChapters() {
|
||
if (this.data.latestExpanded) return
|
||
trackClick('home', 'tab_click', '最新展开_底部三角')
|
||
const full = this.data.latestChapters || []
|
||
this.setData({
|
||
latestExpanded: true,
|
||
displayLatestChapters: full
|
||
})
|
||
},
|
||
|
||
goToMemberDetail(e) {
|
||
const id = e.currentTarget.dataset.id
|
||
trackClick('home', 'card_click', '超级个体_' + (id || ''))
|
||
wx.navigateTo({ url: `/pages/member-detail/member-detail?id=${id}` })
|
||
},
|
||
|
||
// 跳转到我的页面
|
||
goToMy() {
|
||
wx.switchTab({ url: '/pages/my/my' })
|
||
},
|
||
|
||
// 下拉刷新(等待各异步加载完成后再结束)
|
||
async onPullDownRefresh() {
|
||
try {
|
||
await app.getConfig(true)
|
||
} catch (_) {}
|
||
this.setData({ auditMode: app.globalData.auditMode || false })
|
||
this._refreshHomeEntryFlags()
|
||
await Promise.all([
|
||
this.loadBookData(),
|
||
this.loadFeaturedAndLatest(),
|
||
this.loadSuperMembers()
|
||
])
|
||
this.updateUserStatus()
|
||
wx.stopPullDownRefresh()
|
||
},
|
||
|
||
onShareAppMessage() {
|
||
const ref = app.getMyReferralCode()
|
||
return {
|
||
title: '卡若创业派对 - 真实商业故事',
|
||
path: ref ? `/pages/index/index?ref=${ref}` : '/pages/index/index'
|
||
}
|
||
},
|
||
|
||
onShareTimeline() {
|
||
const ref = app.getMyReferralCode()
|
||
return { title: '卡若创业派对 - 真实商业故事', query: ref ? `ref=${ref}` : '' }
|
||
}
|
||
})
|