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:
Alex-larget
2026-03-18 17:55:34 +08:00
125 changed files with 46439 additions and 2916 deletions

View File

@@ -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. 获取上传后的完整URLOSS 返回完整 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创业派对 - 我的',

View File

@@ -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">