Merge branch 'yongxu-dev' into devlop
# Conflicts: # miniprogram/app.js # miniprogram/app.json # miniprogram/pages/chapters/chapters.js # miniprogram/pages/chapters/chapters.wxml # miniprogram/pages/chapters/chapters.wxss # miniprogram/pages/index/index.js # miniprogram/pages/index/index.wxml # miniprogram/pages/match/match.js # miniprogram/pages/my/my.js # miniprogram/pages/my/my.wxml # miniprogram/pages/read/read.js # miniprogram/pages/read/read.wxml # miniprogram/pages/read/read.wxss # miniprogram/pages/referral/referral.js # miniprogram/pages/search/search.js # miniprogram/pages/vip/vip.js # miniprogram/pages/wallet/wallet.wxml # miniprogram/project.private.config.json # soul-admin/dist/index.html # soul-admin/src/pages/dashboard/DashboardPage.tsx # soul-admin/src/pages/settings/SettingsPage.tsx # soul-api/go.mod # soul-api/internal/handler/admin_dashboard.go # soul-api/internal/handler/db.go # soul-api/wechat/info.log # 开发文档/10、项目管理/运营与变更.md # 开发文档/README.md
This commit is contained in:
@@ -5,8 +5,8 @@
|
||||
*/
|
||||
|
||||
const app = getApp()
|
||||
const { formatStatNum } = require('../../utils/util.js')
|
||||
const { trackClick } = require('../../utils/trackClick')
|
||||
const { checkAndExecute } = require('../../utils/ruleEngine')
|
||||
|
||||
Page({
|
||||
data: {
|
||||
@@ -19,7 +19,7 @@ Page({
|
||||
userInfo: null,
|
||||
|
||||
// 统计数据
|
||||
totalSections: 0,
|
||||
totalSections: 62,
|
||||
readCount: 0,
|
||||
referralCount: 0,
|
||||
earnings: '-',
|
||||
@@ -30,12 +30,18 @@ Page({
|
||||
// 阅读统计
|
||||
totalReadTime: 0,
|
||||
matchHistory: 0,
|
||||
readCountText: '0',
|
||||
totalReadTimeText: '0',
|
||||
matchHistoryText: '0',
|
||||
|
||||
// 最近阅读
|
||||
recentChapters: [],
|
||||
|
||||
// 功能配置
|
||||
matchEnabled: false,
|
||||
referralEnabled: true,
|
||||
auditMode: false,
|
||||
searchEnabled: true,
|
||||
|
||||
// VIP状态
|
||||
isVip: false,
|
||||
@@ -72,26 +78,29 @@ Page({
|
||||
contactSaving: false,
|
||||
pendingWithdraw: false,
|
||||
|
||||
// 我的余额(wallet 页入口展示)
|
||||
walletBalance: 0,
|
||||
// 设置入口:开发版、体验版显示
|
||||
showSettingsEntry: false,
|
||||
|
||||
// 我的代付链接
|
||||
giftList: [],
|
||||
// 我的余额
|
||||
walletBalanceText: '--',
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
wx.showShareMenu({ withShareTimeline: true })
|
||||
const accountInfo = wx.getAccountInfoSync ? wx.getAccountInfoSync() : null
|
||||
const envVersion = accountInfo?.miniProgram?.envVersion || ''
|
||||
const showSettingsEntry = envVersion === 'develop' || envVersion === 'trial'
|
||||
this.setData({
|
||||
statusBarHeight: app.globalData.statusBarHeight,
|
||||
navBarHeight: app.globalData.navBarHeight
|
||||
navBarHeight: app.globalData.navBarHeight,
|
||||
showSettingsEntry
|
||||
})
|
||||
this.loadFeatureConfig()
|
||||
this.initUserStatus()
|
||||
// 规则引擎:登录后检查(填头像等)
|
||||
checkAndExecute('after_login', this)
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.setData({ auditMode: app.globalData.auditMode || false })
|
||||
// 设置TabBar选中状态(根据 matchEnabled 动态设置)
|
||||
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
||||
const tabBar = this.getTabBar()
|
||||
@@ -107,12 +116,19 @@ Page({
|
||||
|
||||
async loadFeatureConfig() {
|
||||
try {
|
||||
const res = await app.request('/api/miniprogram/config')
|
||||
const res = await app.getConfig()
|
||||
const features = (res && res.features) || (res && res.data && res.data.features) || {}
|
||||
this.setData({ matchEnabled: features.matchEnabled === true })
|
||||
const matchEnabled = features.matchEnabled === true
|
||||
const referralEnabled = features.referralEnabled !== false
|
||||
const searchEnabled = features.searchEnabled !== false
|
||||
const mp = (res && res.mpConfig) || {}
|
||||
const auditMode = !!mp.auditMode
|
||||
app.globalData.auditMode = auditMode
|
||||
app.globalData.features = { matchEnabled, referralEnabled, searchEnabled }
|
||||
this.setData({ matchEnabled, referralEnabled, searchEnabled, auditMode })
|
||||
} catch (error) {
|
||||
console.log('加载功能配置失败:', error)
|
||||
this.setData({ matchEnabled: false })
|
||||
this.setData({ matchEnabled: false, referralEnabled: true, searchEnabled: true })
|
||||
}
|
||||
},
|
||||
|
||||
@@ -138,27 +154,33 @@ Page({
|
||||
earningsLoading: true,
|
||||
recentChapters: [],
|
||||
totalReadTime: 0,
|
||||
matchHistory: 0
|
||||
matchHistory: 0,
|
||||
readCountText: '0',
|
||||
totalReadTimeText: '0',
|
||||
matchHistoryText: '0'
|
||||
})
|
||||
this.loadDashboardStats()
|
||||
this.loadMyEarnings()
|
||||
this.loadPendingConfirm()
|
||||
this.loadVipStatus()
|
||||
this.loadWalletBalance()
|
||||
this.loadGiftList()
|
||||
} else {
|
||||
const guestReadCount = app.getReadCount()
|
||||
this.setData({
|
||||
isLoggedIn: false,
|
||||
userInfo: null,
|
||||
userIdShort: '',
|
||||
readCount: app.getReadCount(),
|
||||
readCount: guestReadCount,
|
||||
readCountText: formatStatNum(guestReadCount),
|
||||
referralCount: 0,
|
||||
earnings: '-',
|
||||
pendingEarnings: '-',
|
||||
earningsLoading: false,
|
||||
recentChapters: [],
|
||||
totalReadTime: 0,
|
||||
matchHistory: 0
|
||||
matchHistory: 0,
|
||||
totalReadTimeText: '0',
|
||||
matchHistoryText: '0'
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -182,15 +204,21 @@ Page({
|
||||
const recentChapters = Array.isArray(res.data.recentChapters)
|
||||
? res.data.recentChapters.map((item) => ({
|
||||
id: item.id,
|
||||
mid: item.mid || app.getSectionMid(item.id),
|
||||
mid: item.mid,
|
||||
title: item.title || `章节 ${item.id}`
|
||||
}))
|
||||
: []
|
||||
|
||||
const readCount = Number(res.data.readCount || 0)
|
||||
const totalReadTime = Number(res.data.totalReadMinutes || 0)
|
||||
const matchHistory = Number(res.data.matchHistory || 0)
|
||||
this.setData({
|
||||
readCount: Number(res.data.readCount || 0),
|
||||
totalReadTime: Number(res.data.totalReadMinutes || 0),
|
||||
matchHistory: Number(res.data.matchHistory || 0),
|
||||
readCount,
|
||||
totalReadTime,
|
||||
matchHistory,
|
||||
readCountText: formatStatNum(readCount),
|
||||
totalReadTimeText: formatStatNum(totalReadTime),
|
||||
matchHistoryText: formatStatNum(matchHistory),
|
||||
recentChapters
|
||||
})
|
||||
} catch (e) {
|
||||
@@ -300,6 +328,7 @@ Page({
|
||||
|
||||
// 一键收款:逐条调起微信收款页(有上一页则返回,无则回首页)
|
||||
async handleOneClickReceive() {
|
||||
trackClick('my', 'btn_click', '一键收款')
|
||||
if (!this.data.isLoggedIn) { this.showLogin(); return }
|
||||
if (this.data.receivingAll) return
|
||||
|
||||
@@ -466,9 +495,8 @@ Page({
|
||||
})
|
||||
})
|
||||
|
||||
// 2. 获取上传后的完整URL(OSS 返回完整 URL,本地返回相对路径)
|
||||
const rawUrl = uploadRes.data.url || ''
|
||||
const avatarUrl = rawUrl.startsWith('http://') || rawUrl.startsWith('https://') ? rawUrl : app.globalData.baseUrl + rawUrl
|
||||
// 2. 获取上传后的完整URL
|
||||
const avatarUrl = app.globalData.baseUrl + uploadRes.data.url
|
||||
console.log('[My] 头像上传成功:', avatarUrl)
|
||||
|
||||
// 3. 更新本地头像
|
||||
@@ -643,7 +671,7 @@ Page({
|
||||
|
||||
// 显示登录弹窗(每次打开时协议未勾选,符合审核要求)
|
||||
showLogin() {
|
||||
trackClick('my', 'btn_click', '登录')
|
||||
trackClick('my', 'btn_click', '点击登录')
|
||||
// 朋友圈等单页模式下,不直接弹登录,用官方推荐的方式引导用户「前往小程序」
|
||||
try {
|
||||
const sys = wx.getSystemInfoSync()
|
||||
@@ -691,7 +719,6 @@ Page({
|
||||
|
||||
// 微信登录(须已勾选同意协议,且做好错误处理避免审核报错)
|
||||
async handleWechatLogin() {
|
||||
trackClick('my', 'btn_click', '微信登录')
|
||||
if (!this.data.agreeProtocol) {
|
||||
wx.showToast({ title: '请先阅读并同意用户协议和隐私政策', icon: 'none' })
|
||||
return
|
||||
@@ -744,20 +771,20 @@ Page({
|
||||
|
||||
// 点击菜单
|
||||
handleMenuTap(e) {
|
||||
trackClick('my', 'btn_click', e.currentTarget.dataset.id || '菜单')
|
||||
const id = e.currentTarget.dataset.id
|
||||
trackClick('my', 'nav_click', id || '菜单')
|
||||
|
||||
if (!this.data.isLoggedIn && id !== 'about') {
|
||||
if (!this.data.isLoggedIn) {
|
||||
this.showLogin()
|
||||
return
|
||||
}
|
||||
|
||||
const routes = {
|
||||
wallet: '/pages/wallet/wallet',
|
||||
orders: '/pages/purchases/purchases',
|
||||
giftPay: '/pages/gift-pay/list',
|
||||
referral: '/pages/referral/referral',
|
||||
withdrawRecords: '/pages/withdraw-records/withdraw-records',
|
||||
about: '/pages/about/about',
|
||||
wallet: '/pages/wallet/wallet',
|
||||
settings: '/pages/settings/settings'
|
||||
}
|
||||
|
||||
@@ -769,35 +796,32 @@ Page({
|
||||
// 跳转到阅读页(优先传 mid,与分享逻辑一致)
|
||||
goToRead(e) {
|
||||
const id = e.currentTarget.dataset.id
|
||||
const mid = e.currentTarget.dataset.mid || app.getSectionMid(id)
|
||||
trackClick('my', 'card_click', id || '章节')
|
||||
const mid = e.currentTarget.dataset.mid
|
||||
const q = mid ? `mid=${mid}` : `id=${id}`
|
||||
wx.navigateTo({ url: `/pages/read/read?${q}` })
|
||||
},
|
||||
|
||||
// 跳转到目录
|
||||
goToChapters() {
|
||||
trackClick('my', 'nav_click', '目录')
|
||||
trackClick('my', 'nav_click', '已读章节')
|
||||
wx.switchTab({ url: '/pages/chapters/chapters' })
|
||||
},
|
||||
|
||||
// 跳转到关于页
|
||||
goToAbout() {
|
||||
wx.navigateTo({ url: '/pages/about/about' })
|
||||
},
|
||||
|
||||
// 跳转到匹配
|
||||
goToMatch() {
|
||||
trackClick('my', 'nav_click', '匹配')
|
||||
trackClick('my', 'nav_click', '匹配伙伴')
|
||||
wx.switchTab({ url: '/pages/match/match' })
|
||||
},
|
||||
|
||||
// 跳转到推广中心(需登录)
|
||||
goToReferral() {
|
||||
trackClick('my', 'nav_click', '推广')
|
||||
trackClick('my', 'nav_click', '推广中心')
|
||||
if (!this.data.isLoggedIn) {
|
||||
this.showLogin()
|
||||
return
|
||||
}
|
||||
if (!this.data.referralEnabled) return
|
||||
wx.navigateTo({ url: '/pages/referral/referral' })
|
||||
},
|
||||
|
||||
@@ -816,46 +840,6 @@ Page({
|
||||
})
|
||||
},
|
||||
|
||||
async loadWalletBalance() {
|
||||
if (!app.globalData.isLoggedIn || !app.globalData.userInfo) return
|
||||
const userId = app.globalData.userInfo.id
|
||||
try {
|
||||
const res = await app.request({ url: `/api/miniprogram/balance?userId=${userId}`, silent: true })
|
||||
if (res && res.data) {
|
||||
this.setData({ walletBalance: (res.data.balance || 0).toFixed(2) })
|
||||
}
|
||||
} catch (e) {}
|
||||
},
|
||||
|
||||
async loadGiftList() {
|
||||
if (!app.globalData.isLoggedIn || !app.globalData.userInfo) return
|
||||
const userId = app.globalData.userInfo.id
|
||||
try {
|
||||
const res = await app.request({ url: `/api/miniprogram/balance/gifts?userId=${userId}`, silent: true })
|
||||
if (res?.success && res.data?.gifts) {
|
||||
this.setData({ giftList: res.data.gifts })
|
||||
}
|
||||
} catch (e) {}
|
||||
},
|
||||
|
||||
onGiftShareTap(e) {
|
||||
const giftCode = e.currentTarget.dataset.code
|
||||
const title = e.currentTarget.dataset.title || '精选文章'
|
||||
const sectionId = e.currentTarget.dataset.sectionId
|
||||
this._pendingGiftShare = { giftCode, title, sectionId }
|
||||
wx.showModal({
|
||||
title: '分享代付链接',
|
||||
content: `将「${title}」的免费阅读链接分享给好友`,
|
||||
confirmText: '立即分享',
|
||||
cancelText: '取消',
|
||||
success: (r) => {
|
||||
if (r.confirm) {
|
||||
wx.shareAppMessage()
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// VIP状态查询(注意:hasFullBook=9.9 买断,不等同 VIP)
|
||||
async loadVipStatus() {
|
||||
const userId = app.globalData.userInfo?.id
|
||||
@@ -879,6 +863,18 @@ Page({
|
||||
} catch (e) { console.log('[My] VIP查询失败', e) }
|
||||
},
|
||||
|
||||
async loadWalletBalance() {
|
||||
const userId = app.globalData.userInfo?.id
|
||||
if (!userId) return
|
||||
try {
|
||||
const res = await app.request({ url: `/api/miniprogram/balance?userId=${userId}`, silent: true })
|
||||
if (res?.success && res.data) {
|
||||
const balance = res.data.balance || 0
|
||||
this.setData({ walletBalanceText: balance.toFixed(2) })
|
||||
}
|
||||
} catch (e) { console.log('[My] 余额查询失败', e) }
|
||||
},
|
||||
|
||||
// 头像点击:已登录弹出选项(微信头像 / 相册)
|
||||
onAvatarTap() {
|
||||
if (!this.data.isLoggedIn) { this.showLogin(); return }
|
||||
@@ -918,8 +914,7 @@ Page({
|
||||
fail: (e) => reject(e)
|
||||
})
|
||||
})
|
||||
const rawAvatarUrl = uploadRes.data.url || ''
|
||||
const avatarUrl = rawAvatarUrl.startsWith('http://') || rawAvatarUrl.startsWith('https://') ? rawAvatarUrl : app.globalData.baseUrl + rawAvatarUrl
|
||||
const avatarUrl = app.globalData.baseUrl + uploadRes.data.url
|
||||
const userInfo = this.data.userInfo
|
||||
userInfo.avatar = avatarUrl
|
||||
this.setData({ userInfo })
|
||||
@@ -937,18 +932,25 @@ Page({
|
||||
},
|
||||
|
||||
goToVip() {
|
||||
trackClick('my', 'nav_click', 'VIP')
|
||||
trackClick('my', 'btn_click', '会员中心')
|
||||
if (!this.data.isLoggedIn) { this.showLogin(); return }
|
||||
wx.navigateTo({ url: '/pages/vip/vip' })
|
||||
},
|
||||
|
||||
// 进入个人资料编辑页(stitch_soul)
|
||||
goToProfileEdit() {
|
||||
trackClick('my', 'nav_click', '设置')
|
||||
trackClick('my', 'nav_click', '资料编辑')
|
||||
if (!this.data.isLoggedIn) { this.showLogin(); return }
|
||||
wx.navigateTo({ url: '/pages/profile-edit/profile-edit' })
|
||||
},
|
||||
|
||||
// 进入个人资料展示页(enhanced_professional_profile),展示页内可再进编辑
|
||||
goToProfileShow() {
|
||||
trackClick('my', 'btn_click', '编辑')
|
||||
if (!this.data.isLoggedIn) { this.showLogin(); return }
|
||||
wx.navigateTo({ url: '/pages/profile-show/profile-show' })
|
||||
},
|
||||
|
||||
async handleWithdraw() {
|
||||
if (!this.data.isLoggedIn) { this.showLogin(); return }
|
||||
const amount = parseFloat(this.data.pendingEarnings)
|
||||
@@ -1047,17 +1049,6 @@ Page({
|
||||
stopPropagation() {},
|
||||
|
||||
onShareAppMessage() {
|
||||
if (this._pendingGiftShare) {
|
||||
const { giftCode, title, sectionId } = this._pendingGiftShare
|
||||
this._pendingGiftShare = null
|
||||
const ref = app.getMyReferralCode()
|
||||
let path = `/pages/read/read?id=${sectionId}&gift=${giftCode}`
|
||||
if (ref) path += `&ref=${ref}`
|
||||
return {
|
||||
title: `🎁 好友已为你解锁:${title}`,
|
||||
path
|
||||
}
|
||||
}
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 我的',
|
||||
|
||||
@@ -34,9 +34,15 @@
|
||||
<view class="profile-meta">
|
||||
<view class="profile-name-row">
|
||||
<text class="user-name" bindtap="editNickname">{{userInfo.nickname || '点击设置昵称'}}</text>
|
||||
<view class="become-member-btn {{isVip ? 'become-member-vip' : ''}}" bindtap="goToVip">{{isVip ? '会员中心' : '成为会员'}}</view>
|
||||
<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>
|
||||
<view class="vip-tags">
|
||||
<view class="vip-tags" wx:if="{{!auditMode}}">
|
||||
<text class="vip-tag {{isVip ? 'vip-tag-active' : ''}}" bindtap="goToVip">会员</text>
|
||||
<text class="vip-tag {{isVip ? 'vip-tag-active' : ''}}" bindtap="goToMatch">匹配</text>
|
||||
<text class="vip-tag {{isVip ? 'vip-tag-active' : ''}}" bindtap="goToVip">排行</text>
|
||||
@@ -46,19 +52,19 @@
|
||||
</view>
|
||||
<view class="profile-stats-row">
|
||||
<view class="profile-stat" bindtap="goToChapters">
|
||||
<text class="profile-stat-val">{{readCount}}</text>
|
||||
<text class="profile-stat-val">{{readCountText}}</text>
|
||||
<text class="profile-stat-label">已读章节</text>
|
||||
</view>
|
||||
<view class="profile-stat" bindtap="goToReferral">
|
||||
<view class="profile-stat" wx:if="{{referralEnabled}}" bindtap="goToReferral">
|
||||
<text class="profile-stat-val">{{referralCount}}</text>
|
||||
<text class="profile-stat-label">推荐好友</text>
|
||||
</view>
|
||||
<view class="profile-stat" bindtap="goToReferral">
|
||||
<view class="profile-stat" wx:if="{{referralEnabled}}" bindtap="goToReferral">
|
||||
<text class="profile-stat-val">{{earnings === '-' ? '--' : earnings}}</text>
|
||||
<text class="profile-stat-label">我的收益</text>
|
||||
</view>
|
||||
<view class="profile-stat" bindtap="handleMenuTap" data-id="wallet">
|
||||
<text class="profile-stat-val">{{walletBalance > 0 ? '¥' + walletBalance : '0'}}</text>
|
||||
<view class="profile-stat" wx:if="{{!auditMode}}" bindtap="handleMenuTap" data-id="wallet">
|
||||
<text class="profile-stat-val">{{walletBalanceText}}</text>
|
||||
<text class="profile-stat-label">我的余额</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -67,8 +73,8 @@
|
||||
|
||||
<!-- 已登录:内容区 -->
|
||||
<view class="main-content" wx:if="{{isLoggedIn}}">
|
||||
<!-- 一键收款(仅在有待确认收款时显示) -->
|
||||
<view class="card receive-card" wx:if="{{pendingConfirmList.length > 0}}">
|
||||
<!-- 一键收款(仅在有待确认收款时显示;审核模式隐藏) -->
|
||||
<view class="card receive-card" wx:if="{{pendingConfirmList.length > 0 && !auditMode}}">
|
||||
<view class="receive-top">
|
||||
<view class="receive-left">
|
||||
<view class="receive-title-row">
|
||||
@@ -85,7 +91,10 @@
|
||||
</view>
|
||||
<view class="receive-bottom">
|
||||
<text class="receive-tip">将依次调起微信收款页完成领取</text>
|
||||
<text class="receive-link" bindtap="handleMenuTap" data-id="withdrawRecords">查看提现记录 ›</text>
|
||||
<view class="receive-link" bindtap="handleMenuTap" data-id="withdrawRecords">
|
||||
<text>查看提现记录</text>
|
||||
<icon name="chevron-right" size="24" color="rgba(255,255,255,0.6)" customClass="receive-link-arrow"></icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -98,17 +107,17 @@
|
||||
<view class="stats-grid">
|
||||
<view class="stat-box" bindtap="goToChapters">
|
||||
<image class="stat-icon-img" src="/assets/icons/book-open-teal.svg" mode="aspectFit"/>
|
||||
<text class="stat-num">{{readCount}}</text>
|
||||
<text class="stat-num">{{readCountText}}</text>
|
||||
<text class="stat-label">已读章节</text>
|
||||
</view>
|
||||
<view class="stat-box" bindtap="goToChapters">
|
||||
<image class="stat-icon-img" src="/assets/icons/clock-teal.svg" mode="aspectFit"/>
|
||||
<text class="stat-num">{{totalReadTime}}</text>
|
||||
<text class="stat-num">{{totalReadTimeText}}</text>
|
||||
<text class="stat-label">阅读分钟</text>
|
||||
</view>
|
||||
<view class="stat-box" bindtap="goToMatch">
|
||||
<image class="stat-icon-img" src="/assets/icons/users-teal.svg" mode="aspectFit"/>
|
||||
<text class="stat-num">{{matchHistory}}</text>
|
||||
<text class="stat-num">{{matchHistoryText}}</text>
|
||||
<text class="stat-label">匹配伙伴</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -138,52 +147,32 @@
|
||||
</view>
|
||||
<view class="recent-empty" wx:else>
|
||||
<text class="recent-empty-text">暂无阅读记录</text>
|
||||
<view class="recent-empty-btn" bindtap="goToChapters">去阅读 →</view>
|
||||
<view class="recent-empty-btn" bindtap="goToChapters">去阅读 <icon name="chevron-right" size="24" color="#00CED1" customClass="recent-empty-arrow"></icon></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 我的代付链接 -->
|
||||
<view class="card gift-card" wx:if="{{giftList.length > 0}}">
|
||||
<view class="card-header">
|
||||
<image class="card-icon-img" src="/assets/icons/wallet.svg" mode="aspectFit"/>
|
||||
<text class="card-title">我的代付链接</text>
|
||||
</view>
|
||||
<view class="gift-list">
|
||||
<view class="gift-item" wx:for="{{giftList}}" wx:key="giftCode">
|
||||
<view class="gift-left">
|
||||
<text class="gift-title">{{item.sectionTitle}}</text>
|
||||
<text class="gift-meta">¥{{item.amount}} · {{item.status === 'pending' ? '待领取' : '已领取'}} · {{item.createdAt}}</text>
|
||||
</view>
|
||||
<view class="gift-action" wx:if="{{item.status === 'pending'}}" bindtap="onGiftShareTap" data-code="{{item.giftCode}}" data-title="{{item.sectionTitle}}" data-section-id="{{item.sectionId}}">
|
||||
<text class="gift-share-btn">分享</text>
|
||||
</view>
|
||||
<text class="gift-done" wx:else>已送出</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 我的订单 + 关于作者 + 设置 -->
|
||||
<!-- 我的订单 + 设置 -->
|
||||
<view class="card menu-card">
|
||||
<view class="menu-item" bindtap="handleMenuTap" data-id="orders">
|
||||
<view class="menu-left">
|
||||
<view class="menu-icon-wrap icon-teal"><image class="menu-icon-img" src="/assets/icons/folder-teal.svg" mode="aspectFit"/></view>
|
||||
<text class="menu-text">我的订单</text>
|
||||
</view>
|
||||
<text class="menu-arrow">›</text>
|
||||
<icon name="chevron-right" size="28" color="rgba(255,255,255,0.35)" customClass="menu-arrow"></icon>
|
||||
</view>
|
||||
<view class="menu-item" bindtap="handleMenuTap" data-id="about">
|
||||
<view class="menu-item" bindtap="handleMenuTap" data-id="giftPay">
|
||||
<view class="menu-left">
|
||||
<view class="menu-icon-wrap icon-blue"><image class="menu-icon-img" src="/assets/icons/info-blue.svg" mode="aspectFit"/></view>
|
||||
<text class="menu-text">关于作者</text>
|
||||
<view class="menu-icon-wrap icon-gold"><image class="menu-icon-img" src="/assets/icons/gift.svg" mode="aspectFit"/></view>
|
||||
<text class="menu-text">我的代付</text>
|
||||
</view>
|
||||
<text class="menu-arrow">›</text>
|
||||
<icon name="chevron-right" size="28" color="rgba(255,255,255,0.35)" customClass="menu-arrow"></icon>
|
||||
</view>
|
||||
<view class="menu-item" bindtap="handleMenuTap" data-id="settings">
|
||||
<view class="menu-item" wx:if="{{showSettingsEntry}}" bindtap="handleMenuTap" data-id="settings">
|
||||
<view class="menu-left">
|
||||
<view class="menu-icon-wrap icon-gray"><image class="menu-icon-img" src="/assets/icons/settings-gray.svg" mode="aspectFit"/></view>
|
||||
<text class="menu-text">设置</text>
|
||||
</view>
|
||||
<text class="menu-arrow">›</text>
|
||||
<icon name="chevron-right" size="28" color="rgba(255,255,255,0.35)" customClass="menu-arrow"></icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -191,8 +180,8 @@
|
||||
<!-- 登录弹窗 -->
|
||||
<view class="modal-overlay" wx:if="{{showLoginModal}}" bindtap="closeLoginModal">
|
||||
<view class="modal-content login-modal-content" catchtap="stopPropagation">
|
||||
<view class="modal-close" bindtap="closeLoginModal">✕</view>
|
||||
<view class="login-icon">🔐</view>
|
||||
<view class="modal-close" bindtap="closeLoginModal"><icon name="x" size="36" color="#8e8e93"></icon></view>
|
||||
<view class="login-icon"><icon name="lock" size="80" color="#00CED1"></icon></view>
|
||||
<text class="login-title">登录 Soul创业派对</text>
|
||||
<text class="login-desc">登录后可购买章节、解锁更多内容</text>
|
||||
<button class="btn-wechat {{agreeProtocol ? '' : 'btn-wechat-disabled'}}" bindtap="handleWechatLogin" disabled="{{isLoggingIn || !agreeProtocol}}">
|
||||
@@ -201,7 +190,7 @@
|
||||
</button>
|
||||
<view class="login-modal-cancel" bindtap="closeLoginModal">取消</view>
|
||||
<view class="login-agree-row" catchtap="toggleAgree">
|
||||
<view class="agree-checkbox {{agreeProtocol ? 'agree-checked' : ''}}">{{agreeProtocol ? '✓' : ''}}</view>
|
||||
<view class="agree-checkbox {{agreeProtocol ? 'agree-checked' : ''}}"><icon wx:if="{{agreeProtocol}}" name="check" size="24" color="#34C759"></icon></view>
|
||||
<text class="agree-text">我已阅读并同意</text>
|
||||
<text class="agree-link" catchtap="openUserProtocol">《用户协议》</text>
|
||||
<text class="agree-text">和</text>
|
||||
@@ -218,14 +207,14 @@
|
||||
<view class="form-input-wrap">
|
||||
<text class="form-label">手机号</text>
|
||||
<view class="form-input-inner">
|
||||
<text class="form-icon">📱</text>
|
||||
<icon name="smartphone" size="36" color="#8e8e93" customClass="form-icon"></icon>
|
||||
<input class="form-input" type="tel" placeholder="请输入您的手机号" value="{{contactPhone}}" bindinput="onContactPhoneInput"/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-input-wrap">
|
||||
<text class="form-label">微信号</text>
|
||||
<view class="form-input-inner">
|
||||
<text class="form-icon">💬</text>
|
||||
<icon name="message-circle" size="36" color="#8e8e93" customClass="form-icon"></icon>
|
||||
<input class="form-input" type="text" placeholder="请输入您的微信号" value="{{contactWechat}}" bindinput="onContactWechatInput"/>
|
||||
</view>
|
||||
</view>
|
||||
@@ -237,7 +226,7 @@
|
||||
<!-- 头像弹窗:必须点击 button 才能获取微信头像(隐私规范) -->
|
||||
<view class="modal-overlay" wx:if="{{showAvatarModal}}" bindtap="closeAvatarModal">
|
||||
<view class="modal-content avatar-modal" catchtap="stopPropagation">
|
||||
<view class="modal-close" bindtap="closeAvatarModal">✕</view>
|
||||
<view class="modal-close" bindtap="closeAvatarModal"><icon name="x" size="36" color="#8e8e93"></icon></view>
|
||||
<text class="avatar-modal-title">获取微信头像</text>
|
||||
<text class="avatar-modal-desc">点击下方按钮使用你的微信头像</text>
|
||||
<button class="btn-choose-avatar" open-type="chooseAvatar" bindchooseavatar="onChooseAvatar">使用微信头像</button>
|
||||
@@ -248,9 +237,9 @@
|
||||
<!-- 修改昵称弹窗 -->
|
||||
<view class="modal-overlay" wx:if="{{showNicknameModal}}" bindtap="closeNicknameModal">
|
||||
<view class="modal-content nickname-modal" catchtap="stopPropagation">
|
||||
<view class="modal-close" bindtap="closeNicknameModal">✕</view>
|
||||
<view class="modal-close" bindtap="closeNicknameModal"><icon name="x" size="36" color="#8e8e93"></icon></view>
|
||||
<view class="modal-header">
|
||||
<text class="modal-icon">✏️</text>
|
||||
<icon name="pencil" size="48" color="#00CED1" customClass="modal-icon"></icon>
|
||||
<text class="modal-title">修改昵称</text>
|
||||
</view>
|
||||
<view class="nickname-input-wrap">
|
||||
|
||||
Reference in New Issue
Block a user