Gate record features and storage entry points with invitation guidance; enforce record access in the backend. Add homepage greetings, right-swipe profile dismissal, and move the smoking switch to settings. Simplify API base configuration and remove the unused legacy tab bar component.
152 lines
8.5 KiB
Plaintext
152 lines
8.5 KiB
Plaintext
<view wx:if="{{!recordAccessBlocked}}" capture-bind:tap="onLoginSubscribeTap" class="app-shell app-shell--secondary" style="{{layoutStyle}}">
|
|
<launch-transition />
|
|
<!-- pages/checkin-detail/checkin-detail.wxml - 打卡详情 -->
|
|
<app-nav title="打卡详情" back="{{true}}" />
|
|
<scroll-view class="page-bg" scroll-y show-scrollbar="{{false}}" bounces="{{true}}" bindscrolltolower="loadMoreLogs" lower-threshold="120" style="height:100vh;" bindtouchstart="onTouchStart" bindtouchend="onTouchEnd">
|
|
<view class="c-body">
|
|
<page-state wx:if="{{loading}}" kind="loading" title="正在加载详情" /><page-state wx:elif="{{loadError}}" kind="error" title="详情加载失败" action="重试" bind:action="retryDetail" />
|
|
<block wx:else>
|
|
|
|
<!-- 打卡信息卡片(与列表卡片一致) -->
|
|
<view class="detail-card" wx:if="{{item}}">
|
|
<!-- 主题 -->
|
|
<view class="card-row card-theme">
|
|
<text class="card-icon" wx:if="{{item.icon && item.icon !== '✅'}}">{{item.icon}}</text><image wx:else class="card-icon" src="/images/check.svg" mode="aspectFit" />
|
|
<text class="card-title">{{item.title}}</text>
|
|
</view>
|
|
<!-- 打卡频率 -->
|
|
<view class="card-row">
|
|
<text class="card-label">打卡频率</text>
|
|
<text class="card-value">{{freqLabel}}</text>
|
|
</view>
|
|
<!-- 参与人(双人:双方昵称+头像 / 单人:对应昵称+头像) -->
|
|
<view class="card-row" wx:if="{{item.type == 'both'}}">
|
|
<text class="card-label">参与人</text>
|
|
<view class="card-users">
|
|
<view class="user-chip">
|
|
<image wx:if="{{myAvatar}}" class="chip-avatar" src="{{myAvatar}}" mode="aspectFill" />
|
|
<text wx:else class="chip-avatar-fallback">{{myName ? myName.charAt(0) : '我'}}</text>
|
|
<text class="chip-name">{{myName}}</text>
|
|
</view>
|
|
<text class="chip-sep">·</text>
|
|
<view class="user-chip">
|
|
<image wx:if="{{partnerAvatar}}" class="chip-avatar" src="{{partnerAvatar}}" mode="aspectFill" />
|
|
<text wx:else class="chip-avatar-fallback">{{partnerName ? partnerName.charAt(0) : 'TA'}}</text>
|
|
<text class="chip-name">{{partnerName}}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="card-row" wx:elif="{{item.type == 'first' || item.type == 'her'}}">
|
|
<text class="card-label">参与人</text>
|
|
<view class="card-users">
|
|
<view class="user-chip">
|
|
<image wx:if="{{item.type == 'first' && myAvatar}}" class="chip-avatar" src="{{myAvatar}}" mode="aspectFill" />
|
|
<image wx:elif="{{item.type == 'her' && partnerAvatar}}" class="chip-avatar" src="{{partnerAvatar}}" mode="aspectFill" />
|
|
<text wx:else class="chip-avatar-fallback">{{item.type == 'first' ? (myName ? myName.charAt(0) : '我') : (partnerName ? partnerName.charAt(0) : 'TA')}}</text>
|
|
<text class="chip-name">{{item.type == 'first' ? myName : partnerName}}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- 创建人 -->
|
|
<view class="card-row">
|
|
<text class="card-label">创建人</text>
|
|
<view class="card-creator-info">
|
|
<image wx:if="{{item.creator_avatar_url}}" class="creator-avatar" src="{{item.creator_avatar_url}}" mode="aspectFill" />
|
|
<text wx:else class="creator-avatar-fallback">{{item.creator_name ? item.creator_name.charAt(0) : '?'}}</text>
|
|
<text class="creator-name">{{item.creator_name || '未知'}}</text>
|
|
</view>
|
|
</view>
|
|
<!-- 连续统计卡片 -->
|
|
<view class="streak-section">
|
|
<!-- 我的连续(根据权限控制显示) -->
|
|
<view class="streak-card" wx:if="{{showMyStats}}">
|
|
<view class="streak-header">
|
|
<image wx:if="{{myAvatar}}" class="streak-avatar" src="{{myAvatar}}" mode="aspectFill" />
|
|
<text wx:else class="streak-avatar-fallback">{{myName ? myName.charAt(0) : '我'}}</text>
|
|
<text class="streak-user">{{myName}}</text>
|
|
</view>
|
|
<view class="streak-grid">
|
|
<view class="streak-item"><text class="streak-num">{{myToday}}</text><text class="streak-label">当天</text></view>
|
|
<view class="streak-item"><text class="streak-num">{{myWeek}}</text><text class="streak-label">本周</text></view>
|
|
<view class="streak-item"><text class="streak-num">{{myMonth}}</text><text class="streak-label">本月</text></view>
|
|
<view class="streak-item"><text class="streak-num">{{myYear}}</text><text class="streak-label">今年</text></view>
|
|
</view>
|
|
</view>
|
|
<!-- TA连续(根据权限控制显示) -->
|
|
<view class="streak-card" wx:if="{{showPartnerStats}}">
|
|
<view class="streak-header">
|
|
<image wx:if="{{partnerAvatar}}" class="streak-avatar" src="{{partnerAvatar}}" mode="aspectFill" />
|
|
<text wx:else class="streak-avatar-fallback">{{partnerName ? partnerName.charAt(0) : 'TA'}}</text>
|
|
<text class="streak-user">{{partnerName}}</text>
|
|
</view>
|
|
<view class="streak-grid">
|
|
<view class="streak-item"><text class="streak-num">{{partnerToday}}</text><text class="streak-label">当天</text></view>
|
|
<view class="streak-item"><text class="streak-num">{{partnerWeek}}</text><text class="streak-label">本周</text></view>
|
|
<view class="streak-item"><text class="streak-num">{{partnerMonth}}</text><text class="streak-label">本月</text></view>
|
|
<view class="streak-item"><text class="streak-num">{{partnerYear}}</text><text class="streak-label">今年</text></view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- 打卡按钮(独立居中,匹配全局UI) -->
|
|
<button class="detail-checkin-btn" wx:if="{{item.can_checkin}}" bindtap="showCheckinModal" hover-class="none">记录这一次</button>
|
|
|
|
<!-- 打卡记录列表 -->
|
|
<text class="section-title">打卡记录 · {{logsTotal}} 条</text>
|
|
<view class="log-list" wx:if="{{logs.length > 0}}">
|
|
<view class="log-item" wx:for="{{logs}}" wx:key="id">
|
|
<view class="log-dot" style="background:{{item.avatar ? '#B74768' : '#9C27B0'}};"></view>
|
|
<view class="log-card">
|
|
<view class="log-row">
|
|
<text class="log-user">{{item.nickname || '我们'}}</text>
|
|
<text class="log-time">{{item.time}}</text>
|
|
</view>
|
|
<text wx:if="{{item.note}}" class="log-note">{{item.note}}</text>
|
|
<view wx:if="{{item.photo && item.photoUrl}}" class="log-photo-wrap" bindtap="previewPhoto" data-url="{{item.photoUrl}}">
|
|
<image src="{{item.photoUrl}}" mode="aspectFill" class="log-photo" />
|
|
<view class="log-photo-polaroid">
|
|
<text class="polaroid-date">{{item.time}}</text>
|
|
<text class="polaroid-icon">📸</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="empty-state" wx:else>
|
|
<text>📭</text>
|
|
<text>暂无打卡记录</text>
|
|
</view>
|
|
<view class="logs-footer" wx:if="{{logs.length > 0}}">
|
|
<text wx:if="{{logsLoading}}">正在加载…</text>
|
|
<text wx:elif="{{logsError}}" bindtap="loadMoreLogs">加载失败,点击重试</text>
|
|
<text wx:elif="{{logsHasMore}}" bindtap="loadMoreLogs">加载更多</text>
|
|
<text wx:else>已加载全部记录</text>
|
|
</view>
|
|
</block>
|
|
</view>
|
|
|
|
</scroll-view>
|
|
|
|
<!-- 打卡弹窗 -->
|
|
<view class="modal-overlay" wx:if="{{showCheckModal}}" bindtap="hideCheckModal">
|
|
<view class="modal" catchtap="noop" style="max-width:600rpx;">
|
|
<text class="title">{{item.icon || '✅'}} {{item.title}}</text>
|
|
<text class="modal-subtitle">记录这一刻</text>
|
|
<view class="input-group"><label>备注</label><textarea placeholder-class="handwritten-placeholder" class="input" style="min-height:100rpx;" placeholder="一句话..." value="{{checkNote}}" bindinput="onCheckNoteInput" maxlength="60" /></view>
|
|
<view class="input-group"><label>照片</label>
|
|
<view class="photo-upload-box" bindtap="chooseCheckPhoto">
|
|
<image wx:if="{{checkPhoto}}" src="{{checkPhoto}}" mode="aspectFill" class="photo-upload-img" />
|
|
<view wx:else class="photo-upload-placeholder"><text>+</text><text>添加照片</text></view>
|
|
</view>
|
|
</view>
|
|
<view class="modal-actions">
|
|
<button class="btn btn-outline" bindtap="hideCheckModal" hover-class="none">取消</button>
|
|
<button class="btn btn-primary" bindtap="submitCheck" hover-class="none">确认打卡</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
</view>
|