yingsa/miniprogram/pages/user/index.wxml
ethanfly 98f9e64d91 refactor: Enhance store and user management features
- Updated user information retrieval to support store-specific points and ladder user data.
- Refactored store initialization logic to prioritize last selected store.
- Improved API endpoints for fetching matches and user data, ensuring compatibility with store context.
- Adjusted UI components to display store-related information consistently across various pages.
- Enhanced error handling and data fetching logic for better user experience.
2026-02-07 11:09:37 +08:00

310 lines
13 KiB
Plaintext
Raw Permalink 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.

<!-- 个人中心页面 - 运动感设计 -->
<view class="page-container">
<!-- 顶部装饰背景 -->
<view class="hero-bg">
<view class="hero-pattern"></view>
</view>
<!-- 用户信息区域 -->
<view class="user-section">
<!-- 已登录状态 -->
<block wx:if="{{userInfo && userInfo.phone}}">
<view class="profile-card animate-fadeInUp">
<view class="avatar-wrapper" bindtap="onTapAvatar">
<image class="avatar-xl" src="{{userInfo.avatar || '/images/avatar-default.svg'}}" mode="aspectFill"></image>
<view class="avatar-ring"></view>
<view class="avatar-edit-badge">
<text class="edit-icon">✏️</text>
</view>
</view>
<view class="user-info">
<text class="nickname">{{userInfo.nickname || '新用户'}}</text>
<view class="user-stats">
<view class="stat-item">
<text class="stat-value">{{userInfo.storePoints !== undefined ? userInfo.storePoints : (userInfo.totalPoints || 0)}}</text>
<text class="stat-label">积分</text>
</view>
<view class="stat-divider"></view>
<view class="stat-item">
<text class="stat-value highlight">{{ladderUser.powerScore || 0}}</text>
<text class="stat-label">战力</text>
</view>
<view class="stat-divider" wx:if="{{ladderUser}}"></view>
<view class="stat-item" wx:if="{{ladderUser}}">
<text class="stat-value">{{ladderUser.matchCount || 0}}</text>
<text class="stat-label">场次</text>
</view>
</view>
</view>
</view>
<!-- 会员码卡片 -->
<view class="member-card" bindtap="showMemberCode">
<view class="member-card-bg"></view>
<view class="member-card-content">
<view class="member-icon">
<image src="/images/icon-qrcode.svg" mode="aspectFit"></image>
</view>
<view class="member-info">
<text class="member-title">我的会员码</text>
<text class="member-code">{{userInfo.memberCode}}</text>
</view>
<view class="member-action">
<text class="action-text">查看</text>
<text class="action-arrow"></text>
</view>
</view>
<view class="scan-hint">出示给对方扫码挑战</view>
</view>
</block>
<!-- 未登录状态 -->
<block wx:else>
<view class="login-card animate-fadeInUp">
<view class="login-avatar-wrapper">
<image class="login-avatar" src="/images/avatar-default.svg" mode="aspectFill"></image>
<view class="login-avatar-pulse"></view>
</view>
<view class="login-content">
<text class="login-title">开启你的运动之旅</text>
<text class="login-subtitle">授权手机号,加入英飒俱乐部</text>
</view>
<button class="login-btn-primary" open-type="getPhoneNumber" bindgetphonenumber="onGetPhoneNumber">
<image class="btn-icon" src="/images/icon-phone.svg" mode="aspectFit"></image>
<text class="btn-text">手机号快捷登录</text>
</button>
</view>
</block>
</view>
<!-- 天梯信息卡片 -->
<view class="ladder-section animate-fadeInUp" style="animation-delay: 0.2s" wx:if="{{ladderUser}}">
<view class="section-header">
<text class="section-title">天梯战绩</text>
<text class="section-badge">{{currentStore.storeName}}</text>
</view>
<view class="ladder-stats">
<view class="ladder-stat-item">
<view class="stat-icon lv{{ladderUser.level}}">
<text>{{ladderUser.levelName || 'Lv' + ladderUser.level}}</text>
</view>
<text class="stat-name">{{ladderUser.realName}}</text>
</view>
<view class="ladder-progress">
<view class="progress-info">
<text class="progress-label">战力值</text>
<text class="progress-value">{{ladderUser.powerScore}}</text>
</view>
<view class="progress-bar">
<view class="progress-fill" style="width: {{ladderUser.powerScore / 30}}%;"></view>
</view>
</view>
<view class="ladder-record">
<view class="record-item">
<text class="record-value win">{{ladderUser.winCount || 0}}</text>
<text class="record-label">胜场</text>
</view>
<view class="record-item">
<text class="record-value">{{ladderUser.loseCount || 0}}</text>
<text class="record-label">负场</text>
</view>
<view class="record-item">
<text class="record-value rate">{{ladderUser.winRate || 0}}%</text>
<text class="record-label">胜率</text>
</view>
</view>
</view>
</view>
<!-- 未加入天梯提示 -->
<view class="notice-card animate-fadeInUp" style="animation-delay: 0.2s" wx:elif="{{userInfo && userInfo.phone}}">
<view class="notice-icon">
<image class="notice-icon-img" src="/images/icon-challenge.svg" mode="aspectFit"></image>
</view>
<view class="notice-content">
<text class="notice-title">尚未加入天梯系统</text>
<text class="notice-desc">请联系门店工作人员,开启你的天梯之旅</text>
</view>
</view>
<!-- 活动公告卡片列表 -->
<view
class="announcement-card animate-fadeInUp"
style="animation-delay: 0.25s"
>
<view class="announcement-header">
<view class="announcement-header-main">
<view class="announcement-icon">
<image src="/images/icon-info.svg" mode="aspectFit"></image>
</view>
<view class="announcement-text">
<text class="announcement-title">活动公告</text>
<text class="announcement-subtitle">最近 10 条活动通知</text>
</view>
</view>
<view class="announcement-more" bindtap="goAnnouncementMore">
<text class="announcement-more-text">查看更多</text>
<text class="announcement-more-arrow"></text>
</view>
</view>
<view wx:if="{{announcements.length === 0}}" class="announcement-empty">
<text class="announcement-empty-text">暂无公告</text>
</view>
<view wx:else class="announcement-list">
<view
class="announcement-item"
wx:for="{{announcements}}"
wx:key="id"
bindtap="goAnnouncementDetail"
data-id="{{item.id}}"
>
<view class="announcement-item-title-row">
<text class="announcement-item-title">{{item.title}}</text>
<view class="announcement-item-top" wx:if="{{item.isTop}}">置顶</view>
</view>
<text
class="announcement-item-time"
wx:if="{{item.timeText}}"
>{{item.timeText}}</text>
</view>
</view>
</view>
<!-- 功能菜单 -->
<view class="menu-section animate-fadeInUp" style="animation-delay: 0.3s">
<view class="menu-grid">
<view class="menu-item" bindtap="goTo" data-url="/pages/match/history/index">
<view class="menu-icon history">
<image src="/images/icon-history.svg" mode="aspectFit"></image>
</view>
<text class="menu-text">比赛记录</text>
</view>
<view class="menu-item" bindtap="goTo" data-url="/pages/points/records/index">
<view class="menu-icon points">
<image src="/images/icon-points.svg" mode="aspectFit"></image>
</view>
<text class="menu-text">积分记录</text>
</view>
<view class="menu-item" bindtap="goTo" data-url="/pages/points/order/index">
<view class="menu-icon order">
<image src="/images/icon-order.svg" mode="aspectFit"></image>
</view>
<text class="menu-text">兑换订单</text>
</view>
<view class="menu-item" bindtap="goTo" data-url="/pages/store/index">
<view class="menu-icon store">
<image src="/images/icon-store.svg" mode="aspectFit"></image>
</view>
<text class="menu-text">切换门店</text>
</view>
</view>
</view>
</view>
<!-- 注册性别选择弹窗(新用户必填) -->
<view class="gender-overlay {{showGenderModal ? 'show' : ''}}" bindtap="onCancelRegisterGender">
<view class="gender-modal {{showGenderModal ? 'show' : ''}}" catchtap="preventBubble">
<view class="gender-modal-header">
<text class="gender-modal-title">请选择性别</text>
<view class="gender-modal-close" bindtap="onCancelRegisterGender">×</view>
</view>
<view class="gender-modal-body">
<view class="gender-tip">
<text>新用户注册需填写性别</text>
</view>
<view class="gender-options">
<view class="gender-option {{registerGender === 1 ? 'active' : ''}}" bindtap="onSelectRegisterGender" data-gender="1">
<text class="gender-emoji">👦</text>
<text class="gender-text">男</text>
</view>
<view class="gender-option {{registerGender === 2 ? 'active' : ''}}" bindtap="onSelectRegisterGender" data-gender="2">
<text class="gender-emoji">👧</text>
<text class="gender-text">女</text>
</view>
</view>
</view>
<view class="gender-modal-footer">
<button class="gender-btn-cancel" bindtap="onCancelRegisterGender">取消</button>
<button class="gender-btn-confirm" bindtap="onConfirmRegisterGender">确定</button>
</view>
</view>
</view>
<!-- 会员码弹窗 -->
<view class="qrcode-overlay {{showQrcode ? 'show' : ''}}" bindtap="hideQrcode">
<view class="qrcode-modal {{showQrcode ? 'show' : ''}}" catchtap="preventBubble">
<view class="modal-header">
<text class="modal-title">我的会员码</text>
<view class="modal-close" bindtap="hideQrcode">×</view>
</view>
<view class="qrcode-wrapper">
<view class="qrcode-border">
<!-- 加载中 -->
<view class="qrcode-loading" wx:if="{{qrcodeLoading}}">
<view class="loading-spinner"></view>
<text class="loading-text">生成中...</text>
</view>
<!-- 二维码图片 -->
<image wx:else class="qrcode-image" src="{{qrcodeImage}}" mode="aspectFit" show-menu-by-longpress="{{true}}"></image>
</view>
<view class="qrcode-corners">
<view class="corner tl"></view>
<view class="corner tr"></view>
<view class="corner bl"></view>
<view class="corner br"></view>
</view>
</view>
<view class="qrcode-info">
<text class="code-label">会员码</text>
<text class="code-value">{{userInfo.memberCode}}</text>
</view>
<view class="qrcode-tips">
<view class="tip-item">
<image class="tip-icon" src="/images/icon-qrcode.svg" mode="aspectFit"></image>
<text class="tip-text">请出示给对方扫描发起挑战</text>
</view>
</view>
</view>
</view>
<!-- 完善资料弹窗 -->
<view class="profile-overlay {{showProfileModal ? 'show' : ''}}" bindtap="closeProfileModal">
<view class="profile-modal {{showProfileModal ? 'show' : ''}}" catchtap="preventBubble">
<view class="profile-modal-header">
<text class="profile-modal-title">{{isEditMode ? '修改资料' : '完善个人资料'}}</text>
<view class="profile-modal-close" bindtap="closeProfileModal">×</view>
</view>
<view class="profile-modal-body">
<!-- 提示信息 -->
<view class="profile-tips" wx:if="{{!isEditMode}}">
<image class="tips-icon" src="/images/icon-info.svg" mode="aspectFit"></image>
<text class="tips-text">完善资料后,好友可以更容易找到你</text>
</view>
<!-- 头像选择 -->
<view class="profile-avatar-section">
<text class="profile-label">头像</text>
<button class="avatar-choose-btn" open-type="chooseAvatar" bindchooseavatar="onChooseAvatarNew">
<image class="profile-avatar-preview" src="{{profileForm.avatar || '/images/avatar-default.svg'}}" mode="aspectFill"></image>
<view class="avatar-choose-badge">
<image class="choose-icon" src="/images/icon-scan.svg" mode="aspectFit"></image>
</view>
</button>
<text class="avatar-tip">点击更换头像</text>
</view>
<!-- 昵称输入 -->
<view class="profile-nickname-section">
<text class="profile-label">昵称</text>
<input class="nickname-input" type="nickname" placeholder="请输入昵称" value="{{profileForm.nickname}}" bindinput="onNicknameInput" maxlength="20" />
</view>
<!-- 性别选择 -->
<view class="profile-gender-section">
<text class="profile-label">性别</text>
<view class="gender-options-inline">
<view class="gender-chip {{profileForm.gender === 1 ? 'active' : ''}}" bindtap="onProfileGenderSelect" data-gender="1">
</view>
<view class="gender-chip {{profileForm.gender === 2 ? 'active' : ''}}" bindtap="onProfileGenderSelect" data-gender="2">
</view>
</view>
</view>
</view>
<view class="profile-modal-footer">
<button class="profile-btn-cancel" bindtap="closeProfileModal">
{{isEditMode ? '取消' : '跳过'}}
</button>
<button class="profile-btn-confirm" bindtap="saveProfile">保存</button>
</view>
</view>
</view>