2026-03-16 15:47:55 +08:00
|
|
|
|
<!-- 聊天页面 -->
|
|
|
|
|
|
<view class="chat-container">
|
|
|
|
|
|
<!-- 消息列表 -->
|
|
|
|
|
|
<scroll-view
|
|
|
|
|
|
class="message-list"
|
|
|
|
|
|
scroll-y="{{true}}"
|
|
|
|
|
|
scroll-into-view="{{lastMessageId}}"
|
|
|
|
|
|
enable-back-to-top="{{true}}"
|
2026-03-31 11:04:43 +08:00
|
|
|
|
bindscrolltolower="loadMoreHistory"
|
2026-03-16 15:47:55 +08:00
|
|
|
|
>
|
2026-03-31 11:04:43 +08:00
|
|
|
|
<!-- 系统消息 -->
|
|
|
|
|
|
<view wx:if="{{messages.length === 0}}" class="empty-message">
|
|
|
|
|
|
<text class="empty-text">开始与智控未来的对话吧</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 历史消息提示 -->
|
|
|
|
|
|
<view wx:if="{{showHistoryTip}}" class="history-tip">
|
|
|
|
|
|
<text>已加载历史消息</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 消息项 -->
|
2026-03-16 15:47:55 +08:00
|
|
|
|
<view
|
|
|
|
|
|
wx:for="{{messages}}"
|
|
|
|
|
|
wx:key="id"
|
|
|
|
|
|
id="{{item.id}}"
|
|
|
|
|
|
class="message-item {{item.isMe ? 'message-right' : 'message-left'}}"
|
2026-03-31 11:04:43 +08:00
|
|
|
|
bindlongpress="onMessageLongPress"
|
|
|
|
|
|
data-message-id="{{item.id}}"
|
2026-03-16 15:47:55 +08:00
|
|
|
|
>
|
|
|
|
|
|
<view class="message-avatar">
|
|
|
|
|
|
<image src="{{item.avatar}}" mode="aspectFill"></image>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="message-content">
|
2026-03-31 11:04:43 +08:00
|
|
|
|
<view wx:if="{{!item.isMe && item.nickname}}" class="message-header">
|
2026-03-16 15:47:55 +08:00
|
|
|
|
<text class="message-nickname">{{item.nickname}}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="message-body">
|
2026-03-31 11:04:43 +08:00
|
|
|
|
<!-- 文本消息 -->
|
|
|
|
|
|
<view wx:if="{{item.type === 'text' || item.type === 'richText'}}" class="message-text-container">
|
|
|
|
|
|
<rich-text wx:if="{{item.type === 'richText'}}" nodes="{{item.content}}"></rich-text>
|
|
|
|
|
|
<text wx:else class="message-text">{{item.content}}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 图片消息 -->
|
|
|
|
|
|
<image wx:if="{{item.type === 'image'}}" class="message-image" src="{{item.content}}" mode="widthFix" bindtap="previewImage" data-url="{{item.content}}"></image>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 代码块 -->
|
|
|
|
|
|
<view wx:if="{{item.type === 'code'}}" class="message-code">
|
|
|
|
|
|
<view class="code-header">
|
|
|
|
|
|
<text class="code-language">{{item.language || '代码'}}</text>
|
|
|
|
|
|
<button class="copy-btn" bindtap="copyCode" data-content="{{item.content}}">
|
|
|
|
|
|
<text class="copy-icon">📋</text>
|
|
|
|
|
|
<text class="copy-text">复制</text>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="code-body">
|
|
|
|
|
|
<text class="code-text">{{item.content}}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 按钮卡片 -->
|
|
|
|
|
|
<view wx:if="{{item.type === 'buttonCard'}}" class="message-button-card">
|
|
|
|
|
|
<view class="card-title">{{item.title}}</view>
|
|
|
|
|
|
<view class="card-buttons">
|
|
|
|
|
|
<button
|
|
|
|
|
|
wx:for="{{item.buttons}}"
|
|
|
|
|
|
wx:key="id"
|
|
|
|
|
|
class="card-button"
|
|
|
|
|
|
bindtap="onCardButtonTap"
|
|
|
|
|
|
data-action="{{item.buttons[index].action}}"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{item.buttons[index].text}}
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="message-footer">
|
|
|
|
|
|
<text class="message-time">{{item.time}}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 加载中动画 -->
|
|
|
|
|
|
<view wx:if="{{isTyping}}" class="typing-container">
|
|
|
|
|
|
<view class="message-item message-left">
|
|
|
|
|
|
<view class="message-avatar">
|
|
|
|
|
|
<image src="/assets/images/ai-avatar.png" mode="aspectFill"></image>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="message-content">
|
|
|
|
|
|
<view class="message-body">
|
|
|
|
|
|
<view class="typing-indicator">
|
|
|
|
|
|
<view class="typing-dot"></view>
|
|
|
|
|
|
<view class="typing-dot"></view>
|
|
|
|
|
|
<view class="typing-dot"></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<text class="typing-text">正在输入...</text>
|
|
|
|
|
|
</view>
|
2026-03-16 15:47:55 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</scroll-view>
|
|
|
|
|
|
|
2026-04-21 13:46:20 +08:00
|
|
|
|
<!-- 输入区域(tab-bar 聊天模式时由 tab-bar 接管,此处隐藏) -->
|
|
|
|
|
|
<view class="input-container" wx:if="{{false}}">
|
2026-03-16 15:47:55 +08:00
|
|
|
|
<view class="input-wrapper">
|
|
|
|
|
|
<input
|
|
|
|
|
|
class="message-input"
|
|
|
|
|
|
placeholder="请输入消息..."
|
|
|
|
|
|
value="{{inputValue}}"
|
|
|
|
|
|
bindinput="onInputChange"
|
|
|
|
|
|
bindconfirm="sendMessage"
|
|
|
|
|
|
confirm-type="send"
|
|
|
|
|
|
adjust-position="{{true}}"
|
2026-03-31 11:04:43 +08:00
|
|
|
|
maxlength="2000"
|
2026-03-16 15:47:55 +08:00
|
|
|
|
/>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="send-btn"
|
|
|
|
|
|
bindtap="sendMessage"
|
|
|
|
|
|
disabled="{{!inputValue.trim()}}"
|
|
|
|
|
|
loading="{{sending}}"
|
|
|
|
|
|
>
|
|
|
|
|
|
发送
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2026-04-21 13:46:20 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- 授权提示组件 -->
|
|
|
|
|
|
<auth-prompt
|
|
|
|
|
|
show="{{showAuthPrompt}}"
|
|
|
|
|
|
auth-type="{{authType}}"
|
|
|
|
|
|
bind:authSuccess="onAuthSuccess"
|
|
|
|
|
|
bind:authFail="onAuthFail"
|
|
|
|
|
|
bind:authCancel="onAuthCancel"
|
|
|
|
|
|
bind:settingsOpen="onSettingsOpen"
|
|
|
|
|
|
/>
|
2026-03-16 15:47:55 +08:00
|
|
|
|
</view>
|