Files
soul-yongping/miniprogram/pages/my/my.wxml
卡若 5724fba877 feat: 小程序超级个体/个人资料/CKB获客;VIP列表展示过滤;管理端与API联调
- 超级个体:去掉首位特例;列表仅展示有头像且非微信默认昵称(vip.go)
- 个人资料:居中头像、低调联系方式、点头像优先走存客宝 lead(ckbLeadToken)
- 阅读页分享朋友圈复制与 toast 去重
- soul-api: miniprogram users 带 ckbLeadToken;其它 handler 与路由调整
- 脚本:content_upload、miniprogram 上传辅助等

Made-with: Cursor
2026-03-22 08:34:28 +08:00

250 lines
12 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- 我的页 - 设计稿 1:1 还原 -->
<view class="page">
<!-- 顶部导航:左侧资料编辑 + 标题 -->
<view class="nav-bar" style="padding-top: {{statusBarHeight}}px;">
<view class="nav-settings" bindtap="goToProfileEdit">
<image class="nav-settings-icon" src="/assets/icons/edit-gray.svg" mode="aspectFit"/>
</view>
<text class="nav-title">我的</text>
</view>
<view class="nav-placeholder" style="height: {{statusBarHeight + 44}}px;"></view>
<!-- 未登录:引导登录 -->
<view class="guest-block" wx:if="{{!isLoggedIn}}">
<view class="guest-avatar">
<image wx:if="{{guestAvatar}}" class="guest-avatar-img" src="{{guestAvatar}}" mode="aspectFill"/>
<text wx:else class="guest-avatar-text">{{guestNickname[0] || '游'}}</text>
</view>
<text class="guest-name">{{guestNickname}}</text>
<view class="guest-login-btn" bindtap="showLogin">手机号一键登录</view>
</view>
<!-- 已登录:用户卡片(设计稿布局) -->
<view class="profile-card" wx:else>
<view class="profile-card-inner">
<view class="profile-top-row">
<view class="avatar-wrap">
<view class="avatar-inner {{isVip ? 'avatar-vip' : ''}}">
<image wx:if="{{userInfo.avatar}}" class="avatar-img" src="{{userInfo.avatar}}" mode="aspectFill"/>
<text wx:else class="avatar-text">{{userInfo.nickname ? userInfo.nickname[0] : '?'}}</text>
</view>
<view class="vip-badge" wx:if="{{isVip}}">VIP</view>
<view class="vip-badge vip-badge-gray" wx:else>VIP</view>
<button class="avatar-overlay-btn" open-type="chooseAvatar" bindchooseavatar="onChooseAvatar"></button>
</view>
<view class="profile-meta">
<view class="profile-name-row">
<text class="user-name" bindtap="editNickname">{{userInfo.nickname || '点击设置昵称'}}</text>
<view class="profile-name-actions">
<view class="become-member-btn {{isVip ? 'become-member-vip' : ''}}" wx:if="{{!auditMode}}" bindtap="goToVip">{{isVip ? '会员中心' : '成为会员'}}</view>
</view>
</view>
<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>
</view>
<text class="user-wechat" wx:if="{{userWechat}}" bindtap="copyUserId">微信号: {{userWechat}}</text>
</view>
</view>
<view class="profile-stats-row">
<view class="profile-stat" bindtap="goToChapters">
<text class="profile-stat-val">{{readCountText || '0'}}</text>
<text class="profile-stat-label">已读章节</text>
</view>
<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" wx:if="{{!auditMode}}" bindtap="goToMatch">
<text class="profile-stat-val">{{matchHistoryText}}</text>
<text class="profile-stat-label">匹配伙伴</text>
</view>
<view class="profile-stat" wx:if="{{!auditMode}}" bindtap="goToReferral">
<text class="profile-stat-val">{{pendingEarnings || '0.00'}}</text>
<text class="profile-stat-label">我的收益</text>
</view>
</view>
</view>
</view>
<!-- 已登录:内容区 -->
<view class="main-content" wx:if="{{isLoggedIn}}">
<!-- 一键收款(仅在有待确认收款时显示;审核模式隐藏) -->
<view class="card receive-card" wx:if="{{pendingConfirmList.length > 0 && !auditMode}}">
<view class="receive-top">
<view class="receive-left">
<view class="receive-title-row">
<image class="card-icon-img" src="/assets/icons/wallet.svg" mode="aspectFit"/>
<text class="card-title">一键收款</text>
</view>
<text class="receive-sub">
待收款 {{pendingConfirmList.length}} 笔 · 合计 ¥{{pendingConfirmAmount}}
</text>
</view>
<view class="receive-btn {{receivingAll ? 'receive-btn-disabled' : ''}}" bindtap="handleOneClickReceive">
<text class="receive-btn-text">{{receivingAll ? '收款中...' : '立即收款'}}</text>
</view>
</view>
<view class="receive-bottom">
<text class="receive-tip">将依次调起微信收款页完成领取</text>
<text class="receive-link" bindtap="handleMenuTap" data-id="withdrawRecords">查看提现记录 </text>
</view>
</view>
<!-- 快捷入口:我的订单 + 我的代付 -->
<view class="card stats-card">
<view class="card-header">
<image class="card-icon-img" src="/assets/icons/eye-teal.svg" mode="aspectFit"/>
<text class="card-title">快捷入口</text>
</view>
<view class="stats-grid">
<view class="stat-box" bindtap="handleMenuTap" data-id="orders">
<image class="stat-icon-img" src="/assets/icons/list-teal.svg" mode="aspectFit"/>
<text class="stat-num">订单</text>
<text class="stat-label">我的订单</text>
</view>
<view class="stat-box" bindtap="handleMenuTap" data-id="giftPay">
<image class="stat-icon-img" src="/assets/icons/share-teal.svg" mode="aspectFit"/>
<text class="stat-num">代付</text>
<text class="stat-label">我的代付</text>
</view>
<view class="stat-box" bindtap="handleMenuTap" data-id="wallet">
<image class="stat-icon-img" src="/assets/icons/wallet-teal.svg" mode="aspectFit"/>
<text class="stat-num">{{walletBalanceText}}</text>
<text class="stat-label">我的余额</text>
</view>
</view>
</view>
<!-- 已解锁:仅低调图标区(无标题文案);默认 5 条 + 倒三角展开;倒序由接口/JS 保证 -->
<view class="card recent-card unlocked-card" wx:if="{{unlockedChaptersFull.length > 0}}">
<view class="unlocked-section-head">
<image class="unlocked-section-icon" src="/assets/icons/unlock-muted-teal.svg" mode="aspectFit"/>
</view>
<view class="recent-list">
<view
class="recent-item"
wx:for="{{displayUnlockedChapters}}"
wx:key="id"
bindtap="goToRead"
data-id="{{item.id}}"
data-mid="{{item.mid}}"
>
<view class="recent-left">
<text class="recent-index">{{index + 1}}</text>
<text class="recent-title">{{item.title}}</text>
</view>
<text class="recent-link">阅读</text>
</view>
</view>
<view
class="unlocked-expand-hint"
wx:if="{{unlockedChaptersFull.length > 5 && !unlockedExpanded}}"
bindtap="expandUnlockedChapters"
hover-class="unlocked-expand-hint-hover"
hover-stay-time="80"
>
<view class="unlocked-expand-triangle"></view>
</view>
</view>
<!-- 最近阅读 -->
<view class="card recent-card">
<view class="card-header">
<image class="card-icon-img" src="/assets/icons/book-arrow-teal.svg" mode="aspectFit"/>
<text class="card-title">最近阅读</text>
</view>
<view class="recent-list" wx:if="{{recentChapters.length > 0}}">
<view
class="recent-item"
wx:for="{{recentChapters}}"
wx:key="id"
bindtap="goToRead"
data-id="{{item.id}}"
data-mid="{{item.mid}}"
>
<view class="recent-left">
<text class="recent-index">{{index + 1}}</text>
<text class="recent-title">{{item.title}}</text>
</view>
<text class="recent-link">继续阅读</text>
</view>
</view>
<view class="recent-empty" wx:else>
<text class="recent-empty-text">暂无阅读记录</text>
<view class="recent-empty-btn" bindtap="goToChapters">去阅读 →</view>
</view>
</view>
<!-- 设置 -->
<view class="card menu-card" wx:if="{{showSettingsEntry}}">
<view class="menu-item" 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>
<icon name="chevron-right" size="28" color="rgba(255,255,255,0.35)" customClass="menu-arrow"></icon>
</view>
</view>
</view>
<!-- 登录弹窗(公用组件) -->
<login-modal
show="{{showLoginModal}}"
desc="登录后可购买章节、解锁更多内容"
showPrivacyModal="{{showPrivacyModal}}"
showCancel="{{true}}"
bind:close="onLoginModalClose"
bind:success="onLoginModalSuccess"
bind:privacyagree="onLoginModalPrivacyAgree"
/>
<!-- 手机/微信号弹窗 -->
<view class="modal-overlay contact-modal-overlay" wx:if="{{showContactModal}}" bindtap="closeContactModal">
<view class="contact-modal" catchtap="stopPropagation">
<text class="contact-modal-title">请完善联系方式</text>
<view class="contact-modal-hint">需完善手机号或微信号才能使用提现和找伙伴功能</view>
<view class="form-input-wrap">
<text class="form-label">手机号</text>
<view class="form-input-inner">
<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">
<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>
<view class="contact-modal-btn" bindtap="saveContactInfo" disabled="{{contactSaving}}">{{contactSaving ? '保存中...' : '保存'}}</view>
<text class="contact-modal-cancel" bindtap="closeContactModal">取消</text>
</view>
</view>
<!-- 修改昵称弹窗 -->
<view class="modal-overlay" wx:if="{{showNicknameModal}}" bindtap="closeNicknameModal">
<view class="modal-content nickname-modal" catchtap="stopPropagation">
<view class="modal-close" bindtap="closeNicknameModal"><icon name="x" size="36" color="#8e8e93"></icon></view>
<view class="modal-header">
<icon name="pencil" size="48" color="#00CED1" customClass="modal-icon"></icon>
<text class="modal-title">修改昵称</text>
</view>
<view class="nickname-input-wrap">
<view class="nickname-input-inner">
<input class="nickname-input" type="nickname" value="{{editingNickname}}" placeholder="点击输入昵称" placeholder-class="nickname-placeholder" bindchange="onNicknameChange" bindinput="onNicknameInput" maxlength="20"/>
</view>
<text class="input-tip">微信用户可点击自动填充昵称</text>
</view>
<view class="modal-actions">
<view class="modal-btn modal-btn-cancel" bindtap="closeNicknameModal">取消</view>
<view class="modal-btn modal-btn-confirm" bindtap="confirmNickname">确定</view>
</view>
</view>
</view>
<view class="bottom-space"></view>
</view>