Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c3e514560 |
+37
-3
@@ -6,6 +6,7 @@ Page({
|
||||
inputValue: '',
|
||||
isTyping: false,
|
||||
scrollToMessage: '',
|
||||
expandedIds: {},
|
||||
quickQuestions: [
|
||||
'今日待处理订单有哪些?',
|
||||
'最近客户反馈统计',
|
||||
@@ -17,6 +18,13 @@ Page({
|
||||
messageIdCounter: 0,
|
||||
socket: null,
|
||||
|
||||
// 生成消息 id:保证计数器始终为数字,避免出现 msg_NaN
|
||||
genId() {
|
||||
const n = Number(this.messageIdCounter)
|
||||
this.messageIdCounter = Number.isFinite(n) ? n + 1 : 1
|
||||
return `msg_${this.messageIdCounter}`
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.loadChatHistory()
|
||||
this.initSocket()
|
||||
@@ -66,13 +74,18 @@ Page({
|
||||
lastMessage.content += data.content || ''
|
||||
messages = this.data.messages
|
||||
}
|
||||
if (lastMessage.type === 'ai' && data.source == "subagent" && lastMessage.source == data.source) {
|
||||
lastMessage.content += '' + data.content || ''
|
||||
messages = this.data.messages
|
||||
}
|
||||
}
|
||||
|
||||
if (!messages) {
|
||||
const aiResponse = {
|
||||
id: `msg_${++this.messageIdCounter}`,
|
||||
id: this.genId(),
|
||||
_serverId: data.id,
|
||||
type: 'ai',
|
||||
source: data.source,
|
||||
contentType: 'text',
|
||||
content: data.content || '',
|
||||
time: this.formatTime(new Date())
|
||||
@@ -97,6 +110,19 @@ Page({
|
||||
try {
|
||||
const history = wx.getStorageSync('admin_ai_chat_history')
|
||||
if (history && history.length > 0) {
|
||||
// 清洗历史中的无效/重复 id(如 msg_NaN),并把计数器拨到最大 id 之后
|
||||
let max = 0
|
||||
const seen = new Set()
|
||||
history.forEach((m, i) => {
|
||||
const n = parseInt(String(m.id).slice(4), 10)
|
||||
if (Number.isFinite(n) && !seen.has(n)) {
|
||||
seen.add(n)
|
||||
if (n > max) max = n
|
||||
} else {
|
||||
m.id = `msg_h${Date.now()}_${i}`
|
||||
}
|
||||
})
|
||||
this.messageIdCounter = max
|
||||
this.setData({ messages: history })
|
||||
this.scrollToBottom()
|
||||
}
|
||||
@@ -132,7 +158,7 @@ Page({
|
||||
if (!content) return
|
||||
|
||||
const userMessage = {
|
||||
id: `msg_${++this.messageIdCounter}`,
|
||||
id: this.genId(),
|
||||
type: 'user',
|
||||
contentType: 'text',
|
||||
content: content,
|
||||
@@ -187,7 +213,7 @@ Page({
|
||||
|
||||
handleAIError(errorMessage) {
|
||||
const errorResponse = {
|
||||
id: `msg_${++this.messageIdCounter}`,
|
||||
id: this.genId(),
|
||||
type: 'ai',
|
||||
contentType: 'text',
|
||||
content: errorMessage,
|
||||
@@ -203,6 +229,14 @@ Page({
|
||||
this.scrollToBottom()
|
||||
},
|
||||
|
||||
// 展开/折叠 subagent 消息(默认折叠,key 不存在即为折叠态)
|
||||
toggleSubagent(e) {
|
||||
const id = e.currentTarget.dataset.id
|
||||
this.setData({
|
||||
[`expandedIds.${id}`]: !this.data.expandedIds[id]
|
||||
})
|
||||
},
|
||||
|
||||
scrollToBottom() {
|
||||
setTimeout(() => {
|
||||
const lastMessage = this.data.messages[this.data.messages.length - 1]
|
||||
|
||||
+11
-1
@@ -15,8 +15,18 @@
|
||||
</view>
|
||||
<view class="message-content">
|
||||
<view class="message-bubble {{item.type}}-bubble">
|
||||
<!-- subagent 消息:引用卡片样式,默认折叠 -->
|
||||
<block wx:if="{{item.source === 'subagent'}}">
|
||||
<view class="subagent-header" data-id="{{item.id}}" bindtap="toggleSubagent">
|
||||
<text class="subagent-label">思考中...</text>
|
||||
<text class="subagent-arrow {{expandedIds[item.id] ? 'expanded' : ''}}">▸</text>
|
||||
</view>
|
||||
<view class="subagent-body" wx:if="{{expandedIds[item.id]}}">
|
||||
<t-chat-markdown class="message-markdown" content="{{item.content}}" />
|
||||
</view>
|
||||
</block>
|
||||
<t-chat-markdown
|
||||
wx:if="{{item.contentType === 'text' && item.type === 'ai'}}"
|
||||
wx:elif="{{item.contentType === 'text' && item.type === 'ai'}}"
|
||||
class="message-markdown"
|
||||
content="{{item.content}}"
|
||||
/>
|
||||
|
||||
@@ -230,6 +230,35 @@ page {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* subagent 引用卡片(默认折叠) */
|
||||
.subagent-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 4rpx 0;
|
||||
}
|
||||
|
||||
.subagent-label {
|
||||
font-size: 24rpx;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.subagent-arrow {
|
||||
font-size: 24rpx;
|
||||
color: #9ca3af;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.subagent-arrow.expanded {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.subagent-body {
|
||||
margin-top: 12rpx;
|
||||
padding-top: 12rpx;
|
||||
border-top: 1rpx solid #e5e7eb;
|
||||
}
|
||||
|
||||
.typing-indicator {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
+6
-6
@@ -2,12 +2,12 @@ const request = require('./request.js')
|
||||
|
||||
const API = {
|
||||
user: {
|
||||
wxGetPhoneNumber: (data) => request.post('/user/wxgetphonenumber', data),
|
||||
wxSignin: (data) => request.post('/user/wxsignin', data, { skipAuthWait: true }),
|
||||
signout: (data) => request.post('/user/signout', data),
|
||||
update: (data) => request.post('/user/update', data),
|
||||
userInfo: (data) => request.post('/user/userInfo', data),
|
||||
userList: (data) => request.post('/user/list', data),
|
||||
wxGetPhoneNumber: (data) => request.post('https://api.huashengtec.com/user/wxgetphonenumber', data),
|
||||
wxSignin: (data) => request.post('https://api.huashengtec.com/user/wxsignin', data, { skipAuthWait: true }),
|
||||
signout: (data) => request.post('https://api.huashengtec.com/user/signout', data),
|
||||
update: (data) => request.post('https://api.huashengtec.com/user/update', data),
|
||||
userInfo: (data) => request.post('https://api.huashengtec.com/user/userInfo', data),
|
||||
userList: (data) => request.post('https://api.huashengtec.com/user/list', data),
|
||||
},
|
||||
|
||||
escort: {
|
||||
|
||||
Reference in New Issue
Block a user