126 lines
4.3 KiB
Plaintext
126 lines
4.3 KiB
Plaintext
<!-- pages/chat/chat.wxml — AI 对话页 -->
|
||
|
||
<!-- 加载态 -->
|
||
<view class="loading-container" wx:if="{{pageState === 'loading'}}">
|
||
<t-loading theme="circular" size="48rpx" text="加载中..." />
|
||
</view>
|
||
|
||
<!-- 正常态 -->
|
||
<view class="chat-page" wx:elif="{{pageState === 'normal' || pageState === 'empty'}}">
|
||
<!-- 消息列表 -->
|
||
<scroll-view
|
||
class="message-list"
|
||
scroll-y
|
||
scroll-into-view="{{scrollToId}}"
|
||
scroll-with-animation
|
||
enhanced
|
||
show-scrollbar="{{false}}"
|
||
>
|
||
<!-- 引用卡片(从其他页面跳转时显示) -->
|
||
<view class="reference-card" wx:if="{{referenceCard}}">
|
||
<view class="reference-header">
|
||
<t-icon name="file-copy" size="32rpx" color="var(--color-gray-7)" />
|
||
<text class="reference-source">来源:{{referenceCard.title}}</text>
|
||
</view>
|
||
<text class="reference-summary">{{referenceCard.summary}}</text>
|
||
</view>
|
||
|
||
<!-- 空对话提示 -->
|
||
<view class="empty-hint" wx:if="{{pageState === 'empty' && messages.length === 0}}">
|
||
<view class="empty-icon">🤖</view>
|
||
<text class="empty-text">你好,我是 AI 助手</text>
|
||
<text class="empty-sub">有什么可以帮你的?</text>
|
||
</view>
|
||
|
||
<!-- 消息气泡列表 -->
|
||
<block wx:for="{{messages}}" wx:key="id">
|
||
<!-- 用户消息:右对齐蓝色 -->
|
||
<view
|
||
class="message-row message-user"
|
||
wx:if="{{item.role === 'user'}}"
|
||
id="msg-{{item.id}}"
|
||
>
|
||
<view class="bubble bubble-user">
|
||
<text class="bubble-text">{{item.content}}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- AI 消息:左对齐白色 -->
|
||
<view
|
||
class="message-row message-assistant"
|
||
wx:else
|
||
id="msg-{{item.id}}"
|
||
>
|
||
<view class="ai-avatar">
|
||
<text class="ai-avatar-emoji">🤖</text>
|
||
</view>
|
||
<view class="bubble-wrapper">
|
||
<view class="bubble bubble-assistant">
|
||
<text class="bubble-text">{{item.content}}</text>
|
||
</view>
|
||
<!-- 引用卡片(AI 消息内联) -->
|
||
<view class="inline-ref-card" wx:if="{{item.referenceCard}}">
|
||
<view class="inline-ref-header">
|
||
<text class="inline-ref-type">{{item.referenceCard.type === 'customer' ? '👤 客户' : '📋 记录'}}</text>
|
||
<text class="inline-ref-title">{{item.referenceCard.title}}</text>
|
||
</view>
|
||
<text class="inline-ref-summary">{{item.referenceCard.summary}}</text>
|
||
<view class="inline-ref-data">
|
||
<view
|
||
class="ref-data-item"
|
||
wx:for="{{item.referenceCard.dataList}}"
|
||
wx:for-item="entry"
|
||
wx:key="key"
|
||
>
|
||
<text class="ref-data-key">{{entry.key}}</text>
|
||
<text class="ref-data-value">{{entry.value}}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</block>
|
||
|
||
<!-- AI 正在输入指示器 -->
|
||
<view class="message-row message-assistant" wx:if="{{isStreaming && !streamingContent}}" id="msg-typing">
|
||
<view class="ai-avatar">
|
||
<text class="ai-avatar-emoji">🤖</text>
|
||
</view>
|
||
<view class="bubble bubble-assistant typing-bubble">
|
||
<view class="typing-dots">
|
||
<view class="dot dot-1"></view>
|
||
<view class="dot dot-2"></view>
|
||
<view class="dot dot-3"></view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 底部占位,确保最后一条消息不被输入框遮挡 -->
|
||
<view class="scroll-bottom-spacer" id="scroll-bottom"></view>
|
||
</scroll-view>
|
||
|
||
<!-- 底部输入区域 -->
|
||
<view class="input-bar safe-area-bottom">
|
||
<view class="input-wrapper">
|
||
<input
|
||
class="chat-input"
|
||
value="{{inputText}}"
|
||
placeholder="输入消息..."
|
||
placeholder-class="input-placeholder"
|
||
confirm-type="send"
|
||
bindinput="onInputChange"
|
||
bindconfirm="onSendMessage"
|
||
disabled="{{isStreaming}}"
|
||
/>
|
||
</view>
|
||
<view
|
||
class="send-btn {{inputText.length > 0 && !isStreaming ? 'send-btn-active' : 'send-btn-disabled'}}"
|
||
bindtap="onSendMessage"
|
||
>
|
||
<t-icon name="send" size="40rpx" color="{{inputText.length > 0 && !isStreaming ? '#ffffff' : 'var(--color-gray-6)'}}" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<dev-fab />
|