与牧同行-小程序用户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

493 lines
12 KiB

import http from '../../../utils/api'
Page({
data: {
// 当前时间
currentTime: '',
// 聊天消息
messages: [],
// 输入框相关
inputValue: '',
autoFocus: false,
inputHeight: 60,
isKeyboardShow: false,
// 滚动控制
scrollIntoView: 'welcome-message',
scrollAnimation: true,
isUserScrolling: false, // 用户是否正在手动滚动
scrollTimer: null, // 滚动定时器
lastMessageCount: 0, // 上次消息数量
// 症状选择
quickSymptoms: [],
wzsearch: {},
selectedSymptoms: [],
showSymptomSelector: false,
// 状态控制
isAIThinking: false,
isLoading: false,
loadingText: '',
showMoreMenu: false
},
onLoad() {
this.initData();
this.getInquiry();
// 监听键盘高度变化
wx.onKeyboardHeightChange(this.onKeyboardHeightChange.bind(this));
},
onUnload() {
// 页面卸载时移除监听
wx.offKeyboardHeightChange(this.onKeyboardHeightChange);
// 清除定时器
if (this.data.scrollTimer) {
clearTimeout(this.data.scrollTimer);
}
},
// 监听滚动事件
onScroll(e) {
// 检测用户是否在手动滚动
const scrollTop = e.detail.scrollTop;
// 获取滚动容器和底部元素的位置
const query = wx.createSelectorQuery();
query.select('#scrollBottom').boundingClientRect();
query.select('#chatScroll').boundingClientRect();
query.exec((res) => {
if (res[0] && res[1]) {
const bottomPosition = res[0].top - res[1].top + res[1].height;
// 如果滚动位置不在底部(偏差超过50px),认为是用户手动滚动
if (Math.abs(scrollTop - bottomPosition) > 100) {
if (!this.data.isUserScrolling) {
this.setData({
isUserScrolling: true
});
}
// 清除之前的定时器
if (this.data.scrollTimer) {
clearTimeout(this.data.scrollTimer);
}
// 5秒后重置用户滚动状态
const timer = setTimeout(() => {
this.setData({
isUserScrolling: false
});
// 重置后检查是否需要滚动到底部
this.checkAndScrollToBottom();
}, 5000);
this.setData({ scrollTimer: timer });
}
}
});
},
// 滚动到底部事件
onScrollToLower() {
// 用户滚动到底部时,重置滚动状态
this.setData({
isUserScrolling: false
});
},
// 键盘高度变化监听
onKeyboardHeightChange(res) {
if (res.height > 0) {
// 键盘弹起
this.setData({
isKeyboardShow: true
});
// 强制滚动到底部
this.scrollToBottom(true);
} else {
// 键盘收起
this.setData({
isKeyboardShow: false
});
}
},
// 检查并滚动到底部
checkAndScrollToBottom() {
// 如果用户没有手动滚动,则滚动到底部
if (!this.data.isUserScrolling) {
this.scrollToBottom(true);
}
},
// AI问诊快捷字列表
getInquiry() {
http.inquiry({
data: {},
success: res => {
console.log('快捷症状列表', res);
this.setData({
quickSymptoms: res.rows
});
}
});
},
onShow() {
this.updateCurrentTime();
// 延迟设置焦点,避免影响滚动
setTimeout(() => {
this.setData({
autoFocus: true
});
}, 300);
},
// 初始化数据
initData() {
// 设置当前时间
this.updateCurrentTime();
// 定时更新当前时间
setInterval(() => {
this.updateCurrentTime();
}, 60000);
// 初始化消息数量
this.setData({
lastMessageCount: this.data.messages.length
});
},
// 更新当前时间
updateCurrentTime() {
const now = new Date();
const timeString = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
this.setData({
currentTime: timeString
});
},
// 滚动到底部
scrollToBottom(force = false) {
// 如果用户正在手动滚动且不是强制滚动,则不滚动
if (this.data.isUserScrolling && !force) {
console.log('用户正在手动滚动,跳过自动滚动');
return;
}
// 获取最新消息的ID
let targetId = 'scrollBottom';
// 优先滚动到最新的消息
if (this.data.messages.length > 0) {
targetId = `msg-${this.data.messages.length - 1}`;
} else {
targetId = 'welcome-message';
}
console.log('滚动到:', targetId);
// 先重置scrollIntoView,确保能触发滚动
this.setData({
scrollIntoView: '',
scrollAnimation: true
}, () => {
// 延迟一下再设置滚动目标,确保视图更新
setTimeout(() => {
this.setData({
scrollIntoView: targetId,
scrollAnimation: true
});
}, 50);
});
// 多重保障滚动
setTimeout(() => {
if (!this.data.isUserScrolling || force) {
this.setData({
scrollIntoView: targetId
});
}
}, 150);
setTimeout(() => {
if (!this.data.isUserScrolling || force) {
this.setData({
scrollIntoView: targetId
});
}
}, 300);
},
// 输入框行数变化
onInputLineChange(e) {
// 输入框高度变化时,确保滚动到底部
if (this.data.isKeyboardShow) {
this.scrollToBottom();
}
},
// 输入框聚焦
onInputFocus(e) {
this.setData({
autoFocus: true,
isKeyboardShow: true
});
// 延迟滚动到底部,等待键盘完全弹起
setTimeout(() => {
this.scrollToBottom(true);
}, 300);
},
// 输入框失焦
onInputBlur(e) {
this.setData({
autoFocus: false,
isKeyboardShow: false
});
},
// 输入框变化
onInput(e) {
this.setData({
inputValue: e.detail.value
});
},
// 发送消息
sendMessage() {
const message = this.data.inputValue.trim();
if (!message) return;
// 添加用户消息
const userMessage = {
id: Date.now(),
type: 'user',
content: message,
time: this.getCurrentTime()
};
// 更新消息列表
const newMessages = [...this.data.messages, userMessage];
this.setData({
inputValue: '',
autoFocus: true,
inputHeight: 60,
messages: newMessages,
isUserScrolling: false, // 发送消息时重置用户滚动状态
lastMessageCount: newMessages.length
});
// 立即滚动到底部
this.scrollToBottom(true);
// 显示AI思考状态
this.setData({
isAIThinking: true
});
// 滚动到底部(显示思考状态后)
setTimeout(() => {
this.scrollToBottom(true);
}, 100);
// 模拟AI思考时间
setTimeout(() => {
this.generateAIResponse(message);
}, 1500 + Math.random() * 1000);
},
// 获取当前时间
getCurrentTime() {
const now = new Date();
return `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
},
// 生成AI响应
generateAIResponse(userMessage) {
console.log('发送消息:', userMessage);
http.search({
data: {
keyword: userMessage
},
success: res => {
console.log('AI响应:', res);
let aiMessage;
if (res.rows && res.rows.length > 0) {
const wzsearch = res.rows[0];
aiMessage = {
id: Date.now() + 1,
type: 'assistant',
content: '根据您的描述,' + (wzsearch.title || '已收到您的症状描述'),
diagnosis: wzsearch,
time: this.getCurrentTime()
};
} else {
aiMessage = {
id: Date.now() + 1,
type: 'assistant',
content: '已收到您的症状描述',
diagnosis: {
possibleDiseases: '暂无匹配诊断',
severityLevel: '未知',
suggestions: '建议您提供更详细的症状描述,或直接咨询专业兽医'
},
time: this.getCurrentTime()
};
}
// 添加AI消息
const newMessages = [...this.data.messages, aiMessage];
this.setData({
messages: newMessages,
isAIThinking: false,
isUserScrolling: false, // 收到新消息时强制重置用户滚动状态
lastMessageCount: newMessages.length
}, () => {
// 消息添加后立即滚动到底部
console.log('AI消息已添加,滚动到底部');
this.scrollToBottom(true);
// 多重保险滚动
setTimeout(() => {
this.scrollToBottom(true);
}, 100);
setTimeout(() => {
this.scrollToBottom(true);
}, 300);
setTimeout(() => {
this.scrollToBottom(true);
}, 500);
});
},
fail: err => {
console.error('API请求失败:', err);
const aiMessage = {
id: Date.now() + 1,
type: 'assistant',
content: '已收到您的症状描述',
diagnosis: {
possibleDiseases: '网络请求失败',
severityLevel: '未知',
suggestions: '请检查网络连接后重试,或直接联系兽医'
},
time: this.getCurrentTime()
};
const newMessages = [...this.data.messages, aiMessage];
this.setData({
messages: newMessages,
isAIThinking: false,
isUserScrolling: false,
lastMessageCount: newMessages.length
}, () => {
this.scrollToBottom(true);
});
},
complete: () => {
if (this.data.isAIThinking) {
this.setData({
isAIThinking: false
});
}
}
});
},
// 选择快捷症状
selectQuickSymptom(e) {
const symptom = e.currentTarget.dataset.symptom.keywords;
this.setData({
inputValue: symptom
});
this.sendMessage();
},
// 返回
goBack() {
wx.navigateBack();
},
// 显示更多菜单
showMoreMenu() {
this.setData({
showMoreMenu: true
});
},
// 关闭更多菜单
closeMoreMenu() {
this.setData({
showMoreMenu: false
});
},
// 阻止事件冒泡
stopPropagation() {},
// 清空记录
clearHistory() {
wx.showModal({
title: '提示',
content: '确定要清空所有聊天记录吗?',
success: (res) => {
if (res.confirm) {
this.setData({
messages: [],
selectedSymptoms: [],
isUserScrolling: false,
lastMessageCount: 0
}, () => {
// 清空后滚动到欢迎消息
this.setData({
scrollIntoView: 'welcome-message'
});
});
this.closeMoreMenu();
}
}
});
},
// 导出记录
exportChat() {
wx.showToast({
title: '记录已保存到本地',
icon: 'success'
});
this.closeMoreMenu();
},
// 联系兽医
contactDoctor() {
wx.showModal({
title: '联系兽医',
content: '确定要拨打兽医热线吗?',
success: (res) => {
if (res.confirm) {
wx.makePhoneCall({
phoneNumber: '400-123-4567'
});
}
}
});
this.closeMoreMenu();
},
// 显示使用说明
showInstructions() {
wx.showModal({
title: '使用说明',
content: '1. 描述您或牲畜的症状\n2. AI助手会分析并提供建议\n3. 可使用快捷症状选择\n4. 诊断结果仅供参考,请及时咨询专业兽医',
showCancel: false
});
this.closeMoreMenu();
}
});