Files
MBTI_wang/miniprogram/pages/profile/index.wxml
Ghost d7137f9349 微信小程序:自定义底栏接入 AI 入口(含图标与样式)、AI 聊天相关页面与历史/报告等能力;审核模式与配置联动;资料/企业/首页/授权等页面与 app 入口配合调整。
后端 API:AI 对话/报告/余额告警 等服务与路由;小程序 tabBar 配置与分润相关能力;出站推送 Webhook 与管理端调试;飞书留资、小程序数据分析 等支撑;多份 数据库迁移(AI 聊天、灵魂文章、tabBar、分润等)。
管理端 / 超管:看板、用户/订单/分销/财务、设置与 小程序 tabBar 管理、分润规则、灵魂文章、AI 配置与监控 等大量页面与能力扩展;主题与布局更新。
抖音小程序:与微信侧在 结果页/购买/个人中心 等方向做了同步或优化。
另含 部署/脚本、开发文档 等配套更新。
邀请码与解锁:后端 分销/邀请码 接口与 add_invite_codes 等 SQL;小程序侧 邀请码弹窗组件、个人中心/推广/多类结果页 的填写入口与 解锁门控(inviteCodeGate、unlockGate);并补充 《小程序解锁引导与邀请码方案》 文档。
超管后台:路由与 企业中心(EnterpriseHub) 等交互与结构优化。
小程序体验:在 首页结果、推广、各测评结果页 上继续打磨;与 邀请码门控、审核门控 小步联动。
2026-04-23 11:28:16 +08:00

255 lines
11 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.

<!--pages/profile/index.wxml-->
<view class="page tabbar-pad">
<!-- 顶部栏 -->
<view class="topbar">
<text class="topbar-title">我的</text>
<view class="topbar-actions">
<!-- <view class="settings-btn" bindtap="goToSettings">
<text class="settings-icon">⚙️</text>
</view> -->
</view>
</view>
<!-- 用户卡片:未登录点击登录,已登录点击进入个人资料(合并双态) -->
<view class="user-card" bindtap="onUserCardTap">
<!-- 头像区:已登录显示用户头像 + 在线点,未登录仅字母圆 -->
<view class="avatar-wrap">
<view class="avatar-ring">
<image wx:if="{{hasLogin && userInfo && (userInfo.avatarUrl || userInfo.avatar)}}"
class="avatar-img"
src="{{userInfo.avatarUrl || userInfo.avatar}}"
mode="aspectFill"/>
<view wx:else class="avatar-letter-wrap" style="background:{{avatarBgColor}}">
<text class="avatar-letter">{{avatarLetter}}</text>
</view>
</view>
<view wx:if="{{hasLogin}}" class="online-dot"></view>
</view>
<!-- 元信息:已登录昵称+标签;未登录登录提示 -->
<view class="user-meta">
<block wx:if="{{hasLogin}}">
<text class="nickname-text">{{nicknameDisplay || '点击设置昵称'}}</text>
<scroll-view scroll-x class="tags-scroll">
<view class="tags-row">
<view class="tag tag-purple" wx:if="{{mbtiType && permMbti}}">
<text class="tag-text">{{mbtiType}}</text>
</view>
<view class="tag tag-sbti" wx:if="{{sbtiType && permSbti}}">
<text class="tag-text">{{sbtiType}}</text>
</view>
<view class="tag tag-blue" wx:if="{{discType && permDisc}}">
<text class="tag-text">{{discType}}</text>
</view>
<view class="tag tag-orange" wx:if="{{pdpType && permPdp}}">
<text class="tag-text">{{pdpType}}</text>
</view>
<view class="tag tag-gray" wx:if="{{showEmptyPersonalityTags}}">
<text class="tag-text">暂无测试记录</text>
</view>
</view>
</scroll-view>
</block>
<block wx:else>
<text class="user-name" wx:if="{{loginLoading}}">登录中...</text>
<text class="user-name" wx:elif="{{loginFailed}}">登录失败,点击重试</text>
<text class="user-name" wx:else>点击登录</text>
<text class="user-sub">登录后查看你的测试结果</text>
</block>
</view>
<text class="chevron"></text>
</view>
<!-- 数据条:测试数 / 邀请 / 收益 / 可提现(营销数据融入身份,不再独立突兀卡) -->
<view class="user-stats" wx:if="{{hasLogin}}">
<view class="user-stat" bindtap="goToHistory">
<text class="user-stat__v">{{testCount || 0}}</text>
<text class="user-stat__l">测评记录</text>
</view>
<view
class="user-stat"
wx:if="{{promoDistributionEnabled && !reviewMode && !mpAuditMode && permDistribution}}"
bindtap="goToPromo"
>
<text class="user-stat__v">{{promoTotalInvite || 0}}</text>
<text class="user-stat__l">邀请好友</text>
</view>
<!-- 第三格:可提现 → 分销中心 -->
<view
class="user-stat user-stat--highlight"
wx:if="{{promoDistributionEnabled && !reviewMode && !mpAuditMode && permDistribution}}"
bindtap="goToPromo"
>
<text class="user-stat__v">¥{{promoWithdrawable || '0.00'}}</text>
<text class="user-stat__l">可提现 </text>
</view>
<!-- 第四格:累计 → 提现记录 -->
<view
class="user-stat user-stat--sub"
wx:if="{{promoDistributionEnabled && !reviewMode && !mpAuditMode && permDistribution}}"
bindtap="goToPromoWithdrawals"
>
<text class="user-stat__v user-stat__v--sm">¥{{promoTotalEarned || '0.00'}}</text>
<text class="user-stat__l">累计 </text>
</view>
</view>
<!-- <view
class="invite-strip"
wx:if="{{hasLogin && permDistribution && !reviewMode && !mpAuditMode}}"
bindtap="onInviteStripTap"
>
<view class="invite-strip__text">
<text class="invite-strip__label">我的邀请码</text>
<text wx:if="{{myInviteCodeLoadState === 'loading'}}" class="invite-strip__muted">加载中…</text>
<text wx:elif="{{myInviteCodeLoadState === 'error'}}" class="invite-strip__err">{{myInviteCodeErrMsg}}</text>
<text wx:elif="{{myInviteCodeLoadState === 'ready' && myInviteCode}}" class="invite-strip__code">{{myInviteCode}}</text>
<text wx:else class="invite-strip__err">{{myInviteCodeHint}}</text>
</view>
<view class="invite-strip__side">
<button
wx:if="{{myInviteCodeLoadState === 'ready' && myInviteCode}}"
class="invite-strip__copy"
hover-class="none"
catchtap="copyMyInviteCode"
>复制</button>
<text wx:elif="{{myInviteCodeLoadState === 'error'}}" class="invite-strip__retry-hint">点击重试</text>
<text wx:else class="invite-strip__hint">{{myInviteCodeLoadState === 'loading' ? '请稍候' : '解锁付费前填写 '}}</text>
</view>
</view> -->
<!-- <view
class="invite-fill-row"
wx:if="{{hasLogin && permDistribution && !reviewMode && !mpAuditMode}}"
bindtap="openInviteCodeFill"
>
<text class="invite-fill-row__label">我有好友邀请码</text>
<text class="invite-fill-row__arrow"></text>
</view> -->
<!-- 我的测评:最新测试横滑 + 功能图标网格Soul 风:图标网格代替长列表) -->
<view class="section px-section" wx:if="{{hasLogin}}">
<view class="sec-head">
<text class="sec-head__title">我的测评</text>
<view class="sec-head__link" bindtap="goToHistory">
<text>全部<text wx:if="{{testCount > 0}}"> · {{testCount}}</text></text>
<text class="sec-head__chev"></text>
</view>
</view>
<view class="depth-unified-card">
<scroll-view wx:if="{{showLatestTestRow}}" scroll-x class="cards-scroll cards-scroll--in-card" enhanced show-scrollbar="{{false}}">
<view class="cards-row cards-row--in-card">
<view class="result-card card-purple {{mbtiType ? '' : 'result-card--placeholder'}}" bindtap="viewMBTI" wx:if="{{permMbti}}">
<view class="card-deco"></view>
<view class="card-icon-wrap card-icon-purple">
<text class="card-icon">🧠</text>
</view>
<text class="card-label">MBTI性格</text>
<text class="card-value">{{mbtiType || '未测评'}}</text>
<text class="card-time">{{mbtiTime || '—'}}</text>
</view>
<view class="result-card card-sbti {{sbtiType ? '' : 'result-card--placeholder'}}" bindtap="viewSBTI" wx:if="{{permSbti}}">
<view class="card-deco"></view>
<view class="card-icon-wrap card-icon-sbti">
<text class="card-icon">🎭</text>
</view>
<text class="card-label">SBTI</text>
<text class="card-value">{{sbtiType || '未测评'}}</text>
<text class="card-time">{{sbtiTime || '—'}}</text>
</view>
<view class="result-card card-orange {{pdpType ? '' : 'result-card--placeholder'}}" bindtap="viewPDP" wx:if="{{permPdp}}">
<view class="card-deco"></view>
<view class="card-icon-wrap card-icon-orange">
<text class="card-icon">🦁</text>
</view>
<text class="card-label">PDP行为</text>
<text class="card-value">{{pdpType || '未测评'}}</text>
<text class="card-time">{{pdpTime || '—'}}</text>
</view>
<view class="result-card card-blue {{discType ? '' : 'result-card--placeholder'}}" bindtap="viewDISC" wx:if="{{permDisc}}">
<view class="card-deco"></view>
<view class="card-icon-wrap card-icon-blue">
<text class="card-icon">📊</text>
</view>
<text class="card-label">DISC测评</text>
<text class="card-value">{{discType || '未测评'}}</text>
<text class="card-time">{{discTime || '—'}}</text>
</view>
<view class="result-card card-teal {{(gallupPreview || aiType) ? '' : 'result-card--placeholder'}}" bindtap="viewGallup" wx:if="{{!reviewMode && !mpAuditMode && permFace}}">
<view class="card-deco"></view>
<view class="card-icon-wrap card-icon-teal">
<text class="card-icon">⭐</text>
</view>
<text class="card-label">盖洛普优势</text>
<text class="card-value card-value--small">{{gallupPreview || (aiType ? '见面相报告' : '未测评')}}</text>
<text class="card-time">{{aiTime || '—'}}</text>
</view>
<view class="result-card card-rose {{aiType ? '' : 'result-card--placeholder'}}" bindtap="viewAI" wx:if="{{!reviewMode && !mpAuditMode && permFace}}">
<view class="card-deco"></view>
<view class="card-icon-wrap card-icon-rose">
<text class="card-icon">👁️</text>
</view>
<text class="card-label">面相分析</text>
<text class="card-value">{{aiType || '未测评'}}</text>
<text class="card-time">{{aiTime || '—'}}</text>
</view>
</view>
</scroll-view>
</view>
</view>
<!-- 快捷入口图标网格Soul 风2×N 图标 + 短标题) -->
<view class="section px-section" wx:if="{{hasLogin}}">
<view class="quick-grid quick-grid--4">
<view class="quick-grid__item" bindtap="goToTestSelect">
<view class="quick-grid__ic quick-grid__ic--purple">🧠</view>
<text class="quick-grid__label">性格测试</text>
</view>
<view class="quick-grid__item" bindtap="goToOrders">
<view class="quick-grid__ic quick-grid__ic--emerald">🧾</view>
<text class="quick-grid__label">我的订单</text>
</view>
<view class="quick-grid__item" wx:if="{{showDeepPricingEntry}}" bindtap="goToDeepService">
<view class="quick-grid__ic quick-grid__ic--indigo">💎</view>
<text class="quick-grid__label">了解自己</text>
</view>
<view class="quick-grid__item" bindtap="goToMatchJob">
<view class="quick-grid__ic quick-grid__ic--blue">💼</view>
<text class="quick-grid__label">匹配工作</text>
</view>
</view>
</view>
<!-- Soul 引流:超管「我的页展示首条」+ 当前推荐第 1 篇 -->
<view class="section px-section profile-reco-wrap" wx:if="{{hasLogin && profileRecoShow}}">
<view
class="profile-reco-card"
hover-class="profile-reco-card--press"
bindtap="onTapProfileReco"
data-id="{{profileRecoArticle.id}}"
data-url="{{profileRecoArticle.url}}"
data-title="{{profileRecoArticle.title}}"
data-source-id="{{profileRecoArticle.sourceId}}"
>
<text class="profile-reco-label">{{profileRecoSectionLabel}}</text>
<view class="profile-reco-row">
<text class="profile-reco-title">{{profileRecoArticle.title}}</text>
<text class="profile-reco-chev"></text>
</view>
</view>
</view>
<!-- 分销/提现入口已上移至数据条下方promo-quick-bar -->
<invite-code-dialog
visible="{{showInviteCodeDialog}}"
bind:skip="onInviteCodeSkip"
bind:success="onInviteCodeSuccess"
/>
<view class="bottom-safe"></view>
<custom-tab-bar />
</view>