Compare commits

..
1 Commits
Author SHA1 Message Date
lik 9c3e514560 tmp 2026-09-14 09:35:39 +08:00
4 changed files with 83 additions and 10 deletions
+37 -3
View File
@@ -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
View File
@@ -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}}"
/>
+29
View File
@@ -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
View File
@@ -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: {