ai-c/pages/counselor-detail/counselor-detail.wxml
2026-02-02 18:21:32 +08:00

526 lines
22 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="nav-bar" style="padding-top: {{statusBarHeight}}px; height: {{totalNavHeight}}px;">
<view class="nav-content" style="height: {{navBarHeight}}px;">
<view class="nav-back" bindtap="onBack">
<image src="/images/icon-back.png" class="back-icon" mode="aspectFit"></image>
</view>
<view class="nav-title-wrap">
<text class="nav-title">{{counselor.name}}</text>
<view class="status-badge {{counselor.status}}">
<text class="status-text">{{counselor.statusText}}</text>
</view>
</view>
<view class="nav-placeholder"></view>
</view>
</view>
<!-- 内容区域 -->
<scroll-view scroll-y class="content-scroll" style="padding-top: {{totalNavHeight}}px;" enhanced show-scrollbar="{{false}}">
<!-- 用户信息卡片 -->
<view class="profile-card">
<view class="profile-header">
<view class="profile-avatar-wrap">
<!-- 优先显示真实头像,没有则显示渐变占位符 -->
<image wx:if="{{counselor.avatar}}" src="{{counselor.avatar}}" class="profile-avatar-image" mode="aspectFill"></image>
<view wx:else class="profile-avatar-placeholder" style="background: linear-gradient(135deg, {{counselor.avatarColor || '#c984cd'}} 0%, {{counselor.avatarColorEnd || '#b06ab3'}} 100%);">
<text class="profile-avatar-text">{{counselor.name[0]}}</text>
</view>
</view>
<view class="profile-info">
<view class="profile-name-row">
<view class="name-level-wrap">
<text class="profile-name">{{counselor.name}}</text>
<!-- 等级标签放在名字后面 -->
<view class="name-level-badge level-{{counselor.levelCode}}" wx:if="{{counselor.levelName}}">
<text class="name-level-text">{{counselor.levelName}}</text>
</view>
</view>
<view class="profile-location">
<image src="/images/icon-location-pin.png" class="location-icon" mode="aspectFit"></image>
<text class="location-text">{{counselor.location}}</text>
</view>
</view>
<text class="profile-desc">{{counselor.city}} | {{counselor.age}} | {{counselor.experience}}</text>
<text class="profile-education">{{counselor.education}}</text>
</view>
</view>
<view class="profile-stats">
<view class="stat-item">
<text class="stat-value">{{counselor.serviceCount}}</text>
<text class="stat-label">服务人次</text>
</view>
<view class="stat-item">
<text class="stat-value">{{counselor.repeatCount}}</text>
<text class="stat-label">回头客</text>
</view>
<view class="stat-item">
<text class="stat-value">{{counselor.rating}}</text>
<text class="stat-label">评分</text>
</view>
</view>
<view class="profile-details">
<view class="detail-row">
<text class="detail-label">聆听寄语</text>
<text class="detail-value">{{counselor.quote}}</text>
</view>
<view class="detail-row">
<text class="detail-label">专业资质</text>
<text class="detail-value">{{counselor.certification}}</text>
</view>
</view>
</view>
<!-- 时间戳 -->
<view class="time-stamp">
<text class="time-text">{{currentTime}}</text>
</view>
<!-- 聊天消息 -->
<view class="message-list">
<view class="message-item" wx:for="{{messages}}" wx:key="id">
<view class="message-avatar">
<!-- 优先显示真实头像 -->
<image wx:if="{{counselor.avatar}}" src="{{counselor.avatar}}" class="avatar-image-small" mode="aspectFill"></image>
<view wx:else class="avatar-placeholder" style="background: linear-gradient(135deg, {{counselor.avatarColor || '#c984cd'}} 0%, {{counselor.avatarColorEnd || '#b06ab3'}} 100%);">
<text class="avatar-text">{{counselor.name[0]}}</text>
</view>
</view>
<view class="message-bubble">
<text class="message-text">{{item.content}}</text>
</view>
</view>
</view>
<!-- 服务中提示 -->
<view class="busy-notice" wx:if="{{counselor.isBusy}}">
<text class="busy-text">咨询师正在服务中,无法及时回复,您可留言</text>
<view class="remind-btn" bindtap="onRemind">
<text class="remind-text">【空闲时提醒我】</text>
</view>
</view>
</scroll-view>
<!-- 面板打开时的透明遮罩层 - 点击关闭面板 -->
<view class="panel-overlay" wx:if="{{showMorePanel || showEmoji}}" bindtap="closeMorePanel"></view>
<!-- 底部操作按钮 -->
<view class="action-buttons">
<view class="action-btn primary" bindtap="onFreeConsult">
<view class="phone-icon-wrap">
<image src="/images/icon-phone-white.png" class="phone-icon-svg" mode="aspectFit"></image>
</view>
<text class="action-text white">免费倾诉</text>
</view>
<view class="action-btn secondary" bindtap="onViewProfile">
<text class="action-emoji">📄</text>
<text class="action-text">人物介绍</text>
</view>
<view class="action-btn secondary" bindtap="onViewReviews">
<text class="action-emoji">💬</text>
<text class="action-text">查看评价</text>
</view>
</view>
<!-- 底部输入区域容器 -->
<view class="bottom-input-container {{showMorePanel || showEmoji ? 'panel-open' : ''}}">
<!-- 底部输入框 -->
<view class="input-bar">
<view class="voice-btn {{isVoiceMode ? 'active' : ''}}" bindtap="onVoiceMode">
<view class="voice-icon-wrap">
<image wx:if="{{isVoiceMode}}" src="/images/icon-keyboard.png" class="voice-icon-img" mode="aspectFit"></image>
<view wx:else class="voice-bar"></view>
</view>
</view>
<view class="input-wrap">
<!-- 文字输入模式 -->
<input wx:if="{{!isVoiceMode}}" class="message-input" placeholder="隐私保密,安心咨询" value="{{inputText}}" bindinput="onInput" bindconfirm="onSendMessage" focus="{{inputFocus}}" />
<!-- 语音输入模式 - 按住说话按钮 -->
<view wx:else class="voice-record-btn {{isRecording ? 'recording' : ''}}"
bindtouchstart="onVoiceTouchStart"
bindtouchmove="onVoiceTouchMove"
bindtouchend="onVoiceTouchEnd"
bindtouchcancel="onVoiceTouchCancel">
<text class="voice-record-text">{{isRecording ? (voiceCancelHint ? '松开取消' : '松开发送') : '按住 说话'}}</text>
</view>
</view>
<view class="emoji-btn {{showEmoji ? 'active' : ''}}" bindtap="onEmoji">
<image src="{{showEmoji ? '/images/icon-keyboard.png' : '/images/icon-emoji-gray.svg'}}" class="emoji-icon" mode="aspectFit"></image>
</view>
<view class="add-btn {{showMorePanel ? 'active' : ''}}" bindtap="onAdd">
<view class="plus-icon">
<view class="plus-h"></view>
<view class="plus-v"></view>
</view>
</view>
</view>
<!-- 表情面板 -->
<view class="emoji-panel" wx:if="{{showEmoji}}">
<scroll-view scroll-y class="emoji-scroll">
<view class="emoji-grid">
<view
class="emoji-item"
wx:for="{{emojis}}"
wx:key="*this"
data-emoji="{{item}}"
bindtap="onEmojiSelect"
>
<text class="emoji-text">{{item}}</text>
</view>
</view>
</scroll-view>
<view class="emoji-actions">
<view class="emoji-delete" bindtap="onEmojiDelete">
<image src="/images/icon-back-arrow.png" class="delete-icon" mode="aspectFit"></image>
</view>
<view class="emoji-send {{inputText.length > 0 ? 'active' : ''}}" bindtap="onSendMessage">
<text>发送</text>
</view>
</view>
</view>
<!-- 更多功能面板 - 陪聊师聊天完整功能 -->
<view class="more-panel" wx:if="{{showMorePanel}}">
<view class="more-panel-content">
<!-- 第一行 -->
<view class="more-grid">
<!-- 拍照 -->
<view class="more-item" bindtap="onTakePhoto">
<view class="more-icon-wrap">
<image class="more-icon-img" src="/images/icon-camera.png" mode="aspectFit"></image>
</view>
<text class="more-text">拍照</text>
</view>
<!-- 相册 -->
<view class="more-item" bindtap="onChooseImage">
<view class="more-icon-wrap">
<view class="album-icon">
<view class="album-frame"></view>
<view class="album-sun"></view>
<view class="album-mountain"></view>
</view>
</view>
<text class="more-text">相册</text>
</view>
<!-- 礼物 -->
<view class="more-item" bindtap="onSendGift">
<view class="more-icon-wrap">
<image class="more-icon-img" src="/images/icon-gift.png" mode="aspectFit"></image>
</view>
<text class="more-text">礼物</text>
</view>
<!-- 语音 -->
<view class="more-item" bindtap="onVoiceCall">
<view class="more-icon-wrap">
<image class="more-icon-img" src="/images/icon-phone.png" mode="aspectFit"></image>
</view>
<text class="more-text">语音</text>
</view>
</view>
<!-- 第二行 -->
<view class="more-grid second-row">
<!-- 常用语 -->
<view class="more-item" bindtap="onQuickReply">
<view class="more-icon-wrap">
<view class="quick-reply-icon">
<view class="reply-bubble1"></view>
<view class="reply-bubble2"></view>
</view>
</view>
<text class="more-text">常用语</text>
</view>
<!-- 约时间 -->
<view class="more-item" bindtap="onScheduleTime">
<view class="more-icon-wrap">
<image class="more-icon-img" src="/images/icon-clock.png" mode="aspectFit"></image>
</view>
<text class="more-text">约时间</text>
</view>
<!-- 抢红包 -->
<view class="more-item" bindtap="onRedPacket">
<view class="more-icon-wrap">
<view class="red-packet-icon">
<view class="packet-body"></view>
<view class="packet-top"></view>
<view class="packet-circle"></view>
</view>
</view>
<text class="more-text">抢红包</text>
</view>
<!-- 测结果 -->
<view class="more-item" bindtap="onTestResult">
<view class="more-icon-wrap">
<image class="more-icon-img" src="/images/icon-test.png" mode="aspectFit"></image>
<view class="new-tag">NEW</view>
</view>
<text class="more-text">测结果</text>
</view>
</view>
</view>
<!-- 底部安全区域 -->
<view class="more-panel-safe"></view>
</view>
</view>
<!-- 录音中遮罩层 -->
<view class="recording-mask" wx:if="{{isRecording}}">
<view class="recording-popup {{voiceCancelHint ? 'cancel' : ''}}">
<view class="recording-icon-wrap">
<view class="recording-wave">
<view class="wave-bar" wx:for="{{5}}" wx:key="*this"></view>
</view>
</view>
<text class="recording-tip">{{voiceCancelHint ? '松开手指,取消发送' : '手指上划,取消发送'}}</text>
<text class="recording-duration" wx:if="{{!voiceCancelHint}}">{{recordingDuration}}″</text>
</view>
</view>
<!-- 底部安全区域 -->
<view class="safe-area">
<view class="home-indicator"></view>
</view>
</view>
<!-- 下单弹窗 -->
<view class="order-modal-mask" wx:if="{{showOrderModal}}" bindtap="closeOrderModal"></view>
<view class="order-modal" wx:if="{{showOrderModal}}">
<view class="modal-header">
<text class="modal-title">选择服务</text>
<view class="modal-close" bindtap="closeOrderModal">×</view>
</view>
<!-- 服务类型选择 -->
<view class="service-type-section">
<text class="section-label">服务类型</text>
<view class="service-type-options">
<view class="service-type-item {{selectedServiceType === 'text' ? 'active' : ''}}"
bindtap="selectServiceType" data-type="text">
<text class="type-name">文字聊天</text>
<text class="type-price">¥{{counselor.textPrice}}/分钟</text>
</view>
<view class="service-type-item {{selectedServiceType === 'voice' ? 'active' : ''}}"
bindtap="selectServiceType" data-type="voice">
<text class="type-name">语音聊天</text>
<text class="type-price">¥{{counselor.voicePrice}}/分钟</text>
</view>
</view>
</view>
<!-- 时长选择 -->
<view class="duration-section">
<text class="section-label">服务时长</text>
<view class="duration-options">
<view class="duration-item {{selectedDuration === item.value ? 'active' : ''}}"
wx:for="{{durations}}" wx:key="value"
bindtap="selectDuration" data-duration="{{item.value}}">
<text class="duration-text">{{item.label}}</text>
</view>
</view>
</view>
<!-- 价格汇总 -->
<view class="price-summary">
<text class="summary-label">预计费用</text>
<text class="summary-price">¥{{(selectedServiceType === 'voice' ? counselor.voicePrice : counselor.textPrice) * selectedDuration}}</text>
</view>
<button class="confirm-btn" bindtap="confirmOrder">确认下单</button>
</view>
<!-- 人物介绍弹窗 - Figma设计 -->
<view class="profile-modal-mask" wx:if="{{showProfileModal}}" bindtap="closeProfileModal"></view>
<view class="profile-modal {{showProfileModal ? 'show' : ''}}" wx:if="{{showProfileModal}}">
<!-- 弹窗头部 -->
<view class="profile-modal-header">
<view class="profile-modal-title">人物介绍</view>
<view class="profile-modal-close" bindtap="closeProfileModal">
<text class="close-icon">×</text>
</view>
</view>
<!-- 弹窗内容 -->
<scroll-view scroll-y class="profile-modal-content" enhanced show-scrollbar="{{false}}">
<!-- 基本信息区 -->
<view class="profile-info-section">
<view class="profile-avatar-large">
<view class="avatar-placeholder-large" style="background: linear-gradient(180deg, #d8b4e6 0%, #e8d5f0 100%);">
<image wx:if="{{counselor.avatar}}" src="{{counselor.avatar}}" class="avatar-img-large" mode="aspectFill"></image>
<text wx:else class="avatar-text-large">{{counselor.name[0]}}</text>
</view>
</view>
<view class="profile-basic-info">
<view class="profile-name-large">{{counselor.name}}</view>
<view class="profile-details-list">
<view class="profile-detail-item">
<text class="detail-label-text">性别:</text>
<text class="detail-value-text">{{counselor.gender || '女'}}</text>
</view>
<view class="profile-detail-item">
<text class="detail-label-text">年龄:</text>
<text class="detail-value-text">{{counselor.age || '90后'}}</text>
</view>
<view class="profile-detail-item">
<text class="detail-label-text">地区:</text>
<text class="detail-value-text">{{counselor.city || counselor.location || '未知'}}</text>
</view>
<view class="profile-detail-item">
<text class="detail-label-text">学历:</text>
<text class="detail-value-text">{{counselor.education || '本科'}}</text>
</view>
</view>
</view>
</view>
<!-- 统计数据卡片 -->
<view class="profile-stats-card">
<view class="stats-row">
<view class="stats-item">
<view class="stats-value">{{counselor.serviceCount || 0}}</view>
<view class="stats-label">服务人次</view>
</view>
<view class="stats-divider"></view>
<view class="stats-item">
<view class="stats-value">{{counselor.repeatCount || 0}}</view>
<view class="stats-label">回头客</view>
</view>
<view class="stats-divider"></view>
<view class="stats-item">
<view class="stats-value">{{counselor.rating || 5.0}}</view>
<view class="stats-label">评分</view>
</view>
</view>
</view>
<!-- 专业资质 -->
<view class="profile-section-card">
<view class="section-title">专业资质</view>
<view class="section-content">{{counselor.certification || '心理咨询师'}}</view>
</view>
<!-- 擅长领域 -->
<view class="profile-section-card">
<view class="section-title">擅长领域</view>
<view class="expertise-tags">
<view class="expertise-tag" wx:for="{{counselor.expertiseList || ['恋爱冲突', '亲密关系不全感']}}" wx:key="*this">
<text class="tag-text">{{item}}</text>
</view>
</view>
</view>
<!-- 个人介绍 -->
<view class="profile-section-card">
<view class="section-title">个人介绍</view>
<view class="section-content">{{counselor.introduction || counselor.experience || '90后 本科 心理咨询师1年系统训练'}}</view>
</view>
<!-- 聆听寄语 -->
<view class="profile-section-card quote-card">
<view class="section-title">聆听寄语</view>
<view class="section-content">"{{counselor.quote || '生活中的每一份情绪都值得被温柔对待,我愿意陪伴您度过人生的每一个重要时刻。'}}"</view>
</view>
</scroll-view>
</view>
<!-- 查看评价弹窗 -->
<view class="review-modal-mask" wx:if="{{showReviewModal}}" bindtap="closeReviewModal"></view>
<view class="review-modal {{showReviewModal ? 'show' : ''}}" wx:if="{{showReviewModal}}">
<!-- 弹窗头部 -->
<view class="review-modal-header">
<text class="review-modal-title">全部评价</text>
<view class="review-modal-close" bindtap="closeReviewModal">
<text class="close-icon">×</text>
</view>
</view>
<!-- 评分汇总 -->
<view class="review-summary">
<view class="summary-left">
<view class="summary-avatar">
<view class="avatar-placeholder-small" style="background: linear-gradient(135deg, {{counselor.avatarColor || '#c984cd'}} 0%, {{counselor.avatarColorEnd || '#b06ab3'}} 100%);">
<text class="avatar-text-small">{{counselor.name[0]}}</text>
</view>
</view>
<view class="summary-score">
<view class="score-row">
<text class="score-value">{{counselor.rating || 4.9}}</text>
<text class="score-unit">分</text>
</view>
<view class="stars-row">
<text class="star-icon" wx:for="{{5}}" wx:key="*this">⭐</text>
</view>
<text class="review-count">{{reviewStats.totalCount || 0}}条评价</text>
</view>
</view>
<view class="summary-right">
<text class="good-rate">{{reviewStats.goodRate || 100}}%</text>
<text class="good-rate-label">好评率</text>
</view>
</view>
<!-- 评价列表 -->
<scroll-view scroll-y class="review-list" bindscrolltolower="loadMoreReviews">
<view class="review-item" wx:for="{{reviews}}" wx:key="id">
<!-- 用户信息 -->
<view class="review-user-row">
<view class="review-user-avatar">
<image wx:if="{{item.userAvatar}}" src="{{item.userAvatar}}" class="user-avatar-img" mode="aspectFill"></image>
<view wx:else class="user-avatar-placeholder">
<text class="user-avatar-text">{{item.userName[0] || '用'}}</text>
</view>
</view>
<view class="review-user-info">
<view class="user-name-row">
<text class="user-name">{{item.userName || '匿名用户'}}</text>
<text class="review-date">{{item.createdAt}}</text>
</view>
<view class="review-stars">
<text class="star-icon-small" wx:for="{{item.rating || 5}}" wx:for-item="star" wx:key="*this">⭐</text>
</view>
</view>
</view>
<!-- 评价内容 -->
<view class="review-content-wrap">
<text class="review-content {{item.expanded ? '' : 'collapsed'}}">{{item.content}}</text>
<text class="expand-btn" wx:if="{{item.content.length > 60 && !item.expanded}}" bindtap="expandReview" data-index="{{index}}">展开</text>
</view>
<!-- 评价标签 -->
<view class="review-tags" wx:if="{{item.tags && item.tags.length > 0}}">
<view class="review-tag" wx:for="{{item.tags}}" wx:for-item="tag" wx:key="*this">
<text class="review-tag-text">{{tag}}</text>
</view>
</view>
<!-- 咨询师回复 -->
<view class="counselor-reply" wx:if="{{item.reply}}">
<view class="reply-content">
<text class="reply-label">咨询师回复:</text>
<text class="reply-text">{{item.reply}}</text>
</view>
</view>
<!-- 点赞 -->
<view class="review-actions">
<view class="like-btn {{item.liked ? 'liked' : ''}}" bindtap="likeReview" data-id="{{item.id}}">
<text class="like-icon">{{item.liked ? '👍' : '👍'}}</text>
<text class="like-count">{{item.likeCount || 0}}</text>
</view>
</view>
</view>
<!-- 底部提示 -->
<view class="review-bottom-tip" wx:if="{{!hasMoreReviews}}">
<text class="bottom-tip-text">已经到底了~</text>
</view>
<!-- 加载中 -->
<view class="review-loading" wx:if="{{loadingReviews}}">
<text class="loading-text">加载中...</text>
</view>
</scroll-view>
</view>