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.
534 lines
13 KiB
534 lines
13 KiB
// 专家端聊天页面 - 纯模拟数据,无真实接口
|
|
Page({
|
|
data: {
|
|
// 专家信息
|
|
expertInfo: {
|
|
id: 'expert_001',
|
|
name: '张医生',
|
|
avatar: '/pages/images/tx.png'
|
|
},
|
|
expertAvatar: '/pages/images/tx.png',
|
|
|
|
// 对话信息
|
|
conversation: {
|
|
userId: 'user_001',
|
|
userName: '李华',
|
|
userAvatar: '/pages/images/tx.png'
|
|
},
|
|
|
|
// 在线状态
|
|
onlineStatus: true,
|
|
|
|
// 消息列表
|
|
messageList: [],
|
|
scrollTop: 0,
|
|
scrollAnimate: true,
|
|
|
|
// 输入相关
|
|
inputValue: '',
|
|
inputFocus: false,
|
|
|
|
// 多媒体面板
|
|
showMediaSheet: false,
|
|
|
|
|
|
// 页面状态
|
|
loadingMore: false,
|
|
hasMore: true,
|
|
page: 1,
|
|
|
|
// 模拟数据
|
|
mockMessages: [
|
|
{
|
|
id: 'msg_1',
|
|
isMe: false,
|
|
type: 'text',
|
|
content: '医生您好,我想咨询一下皮肤问题',
|
|
timestamp: Date.now() - 3600000,
|
|
status: 'success',
|
|
avatar: '/pages/images/tx.png'
|
|
},
|
|
{
|
|
id: 'msg_2',
|
|
isMe: true,
|
|
type: 'text',
|
|
content: '您好,请描述一下您的具体症状',
|
|
timestamp: Date.now() - 3500000,
|
|
status: 'success',
|
|
avatar: '/pages/images/tx.png'
|
|
},
|
|
{
|
|
id: 'msg_3',
|
|
isMe: false,
|
|
type: 'text',
|
|
content: '脸上起了很多小红点,有点痒',
|
|
timestamp: Date.now() - 3400000,
|
|
status: 'success',
|
|
avatar: '/pages/images/tx.png'
|
|
},
|
|
{
|
|
id: 'msg_4',
|
|
isMe: false,
|
|
type: 'image',
|
|
content: 'https://picsum.photos/200/200?random=1',
|
|
timestamp: Date.now() - 3300000,
|
|
status: 'success',
|
|
avatar: '/pages/images/tx.png'
|
|
},
|
|
{
|
|
id: 'msg_5',
|
|
isMe: true,
|
|
type: 'text',
|
|
content: '看起来像是过敏反应,最近有接触什么新的东西吗?',
|
|
timestamp: Date.now() - 3200000,
|
|
status: 'success',
|
|
avatar: '/pages/images/tx.png'
|
|
}
|
|
],
|
|
|
|
// 定时器
|
|
typingTimer: null,
|
|
mockUserTimer: null
|
|
},
|
|
|
|
onLoad: function(options) {
|
|
console.log('专家端聊天页面加载', options);
|
|
|
|
// 获取传递的参数
|
|
if (options.userId) {
|
|
this.setData({
|
|
'conversation.userId': options.userId,
|
|
'conversation.userName': options.userName || '用户'
|
|
});
|
|
}
|
|
|
|
// 加载模拟消息
|
|
this.loadMockMessages();
|
|
|
|
// 模拟用户在线状态变化
|
|
this.simulateOnlineStatus();
|
|
|
|
// 模拟用户发送消息
|
|
this.startMockUserTyping();
|
|
},
|
|
|
|
onShow: function() {
|
|
// 滚动到底部
|
|
setTimeout(() => {
|
|
this.scrollToBottom(false);
|
|
}, 200);
|
|
},
|
|
|
|
onUnload: function() {
|
|
// 清理定时器
|
|
if (this.data.mockUserTimer) {
|
|
clearInterval(this.data.mockUserTimer);
|
|
}
|
|
if (this.data.typingTimer) {
|
|
clearTimeout(this.data.typingTimer);
|
|
}
|
|
},
|
|
|
|
// 返回上一页
|
|
goBack: function() {
|
|
wx.navigateBack({
|
|
delta: 1
|
|
});
|
|
},
|
|
|
|
|
|
|
|
// 加载模拟消息
|
|
loadMockMessages: function() {
|
|
// 处理消息时间显示
|
|
const messages = this.processMessageTimes(this.data.mockMessages);
|
|
|
|
this.setData({
|
|
messageList: messages,
|
|
hasMore: false
|
|
});
|
|
},
|
|
|
|
// 加载更多消息(模拟)
|
|
loadMoreMessages: function() {
|
|
if (this.data.loadingMore || !this.data.hasMore) return;
|
|
|
|
this.setData({ loadingMore: true });
|
|
|
|
// 模拟网络延迟
|
|
setTimeout(() => {
|
|
// 模拟更早的消息
|
|
const olderMessages = [
|
|
{
|
|
id: 'old_' + Date.now(),
|
|
isMe: false,
|
|
type: 'text',
|
|
content: '之前也出现过类似情况',
|
|
timestamp: Date.now() - 86400000,
|
|
status: 'success',
|
|
avatar: '/pages/images/tx.png'
|
|
},
|
|
{
|
|
id: 'old_' + (Date.now() + 1),
|
|
isMe: true,
|
|
type: 'text',
|
|
content: '那当时是怎么处理的呢?',
|
|
timestamp: Date.now() - 86000000,
|
|
status: 'success',
|
|
avatar: '/pages/images/tx.png'
|
|
}
|
|
];
|
|
|
|
const processedOld = this.processMessageTimes(olderMessages);
|
|
const newList = [...processedOld, ...this.data.messageList];
|
|
|
|
this.setData({
|
|
messageList: newList,
|
|
loadingMore: false,
|
|
hasMore: false // 模拟没有更多了
|
|
});
|
|
|
|
// 调整滚动位置
|
|
setTimeout(() => {
|
|
this.setData({
|
|
scrollAnimate: false,
|
|
scrollTop: 300
|
|
}, () => {
|
|
setTimeout(() => {
|
|
this.setData({ scrollAnimate: true });
|
|
}, 100);
|
|
});
|
|
}, 50);
|
|
}, 800);
|
|
},
|
|
|
|
// 模拟用户在线状态变化
|
|
simulateOnlineStatus: function() {
|
|
setInterval(() => {
|
|
// 随机改变在线状态(模拟)
|
|
const random = Math.random();
|
|
this.setData({
|
|
onlineStatus: random > 0.3 // 70%时间在线
|
|
});
|
|
}, 30000);
|
|
},
|
|
|
|
// 模拟用户正在输入并发送消息
|
|
startMockUserTyping: function() {
|
|
// 每45-90秒模拟用户发送一条消息
|
|
const timer = setInterval(() => {
|
|
// 只有在线时才发送
|
|
if (this.data.onlineStatus) {
|
|
this.simulateUserMessage();
|
|
}
|
|
}, Math.random() * 45000 + 45000); // 45-90秒
|
|
|
|
this.setData({ mockUserTimer: timer });
|
|
},
|
|
|
|
// 模拟用户发送消息
|
|
simulateUserMessage: function() {
|
|
const messages = [
|
|
'好的,我明白了',
|
|
'谢谢医生!',
|
|
'需要用什么药吗?',
|
|
'大概多久能好?',
|
|
'有没有什么需要注意的?',
|
|
'好的,我试试看',
|
|
'明白了,非常感谢!'
|
|
];
|
|
|
|
const randomMsg = messages[Math.floor(Math.random() * messages.length)];
|
|
|
|
const newMsg = {
|
|
id: 'user_' + Date.now() + Math.random(),
|
|
isMe: false,
|
|
type: 'text',
|
|
content: randomMsg,
|
|
timestamp: Date.now(),
|
|
status: 'success',
|
|
avatar: this.data.conversation.userAvatar || '/pages/images/tx.png'
|
|
};
|
|
|
|
this.addMessageToList(newMsg);
|
|
|
|
// 震动提示(可选)
|
|
wx.vibrateShort({ type: 'light' });
|
|
},
|
|
|
|
// 发送文本消息
|
|
sendTextMessage: function() {
|
|
const content = this.data.inputValue.trim();
|
|
if (!content) return;
|
|
|
|
const messageId = 'msg_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
|
|
|
|
// 创建本地消息
|
|
const newMessage = {
|
|
id: messageId,
|
|
isMe: true,
|
|
type: 'text',
|
|
content: content,
|
|
timestamp: Date.now(),
|
|
status: 'sending',
|
|
avatar: this.data.expertAvatar
|
|
};
|
|
|
|
// 添加到列表
|
|
this.addMessageToList(newMessage);
|
|
|
|
// 清空输入框
|
|
this.setData({ inputValue: '' });
|
|
|
|
// 模拟发送延迟
|
|
setTimeout(() => {
|
|
this.updateMessageStatus(messageId, 'success');
|
|
}, 500);
|
|
},
|
|
|
|
// 添加消息到列表
|
|
addMessageToList: function(message) {
|
|
const { messageList } = this.data;
|
|
|
|
// 新消息添加到末尾
|
|
messageList.push(message);
|
|
|
|
// 重新处理时间显示
|
|
const processedMessages = this.processMessageTimes(messageList);
|
|
|
|
this.setData({
|
|
messageList: processedMessages
|
|
}, () => {
|
|
this.scrollToBottom(true);
|
|
});
|
|
},
|
|
|
|
// 更新消息状态
|
|
updateMessageStatus: function(messageId, status) {
|
|
const { messageList } = this.data;
|
|
const index = messageList.findIndex(msg => msg.id === messageId);
|
|
|
|
if (index !== -1) {
|
|
messageList[index].status = status;
|
|
this.setData({ messageList });
|
|
}
|
|
},
|
|
|
|
// 重试发送
|
|
retrySend: function(e) {
|
|
const messageId = e.currentTarget.dataset.id;
|
|
const { messageList } = this.data;
|
|
const msg = messageList.find(m => m.id === messageId);
|
|
|
|
if (msg) {
|
|
msg.status = 'sending';
|
|
this.setData({ messageList });
|
|
|
|
setTimeout(() => {
|
|
msg.status = 'success';
|
|
this.setData({ messageList });
|
|
}, 500);
|
|
}
|
|
},
|
|
|
|
// 处理消息时间显示
|
|
processMessageTimes: function(messages) {
|
|
if (!messages || messages.length === 0) return [];
|
|
|
|
const timeInterval = 5; // 5分钟间隔显示时间
|
|
|
|
return messages.map((msg, index) => {
|
|
const showTime = index === 0 ||
|
|
(msg.timestamp - messages[index - 1].timestamp) > timeInterval * 60 * 1000;
|
|
|
|
return {
|
|
...msg,
|
|
showTime
|
|
};
|
|
});
|
|
},
|
|
|
|
// 格式化时间
|
|
formatTime: function(timestamp) {
|
|
if (!timestamp) return '';
|
|
|
|
const date = new Date(Number(timestamp));
|
|
const hours = date.getHours().toString().padStart(2, '0');
|
|
const minutes = date.getMinutes().toString().padStart(2, '0');
|
|
return `${hours}:${minutes}`;
|
|
},
|
|
|
|
// 格式化文件大小
|
|
formatFileSize: function(bytes) {
|
|
if (!bytes || bytes === 0) return '0B';
|
|
|
|
const units = ['B', 'KB', 'MB', 'GB'];
|
|
let size = bytes;
|
|
let unitIndex = 0;
|
|
|
|
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
size /= 1024;
|
|
unitIndex++;
|
|
}
|
|
|
|
return size.toFixed(1) + units[unitIndex];
|
|
},
|
|
|
|
// 输入处理
|
|
onInput: function(e) {
|
|
this.setData({ inputValue: e.detail.value });
|
|
},
|
|
|
|
// 输入框获得焦点
|
|
onInputFocus: function() {
|
|
this.setData({ inputFocus: true }, () => {
|
|
setTimeout(() => {
|
|
this.scrollToBottom(true);
|
|
}, 200);
|
|
});
|
|
},
|
|
|
|
// 输入框失去焦点
|
|
onInputBlur: function() {
|
|
this.setData({ inputFocus: false });
|
|
},
|
|
|
|
// 清除输入
|
|
clearInput: function() {
|
|
this.setData({
|
|
inputValue: '',
|
|
inputFocus: true
|
|
});
|
|
},
|
|
|
|
// 滚动事件
|
|
onScroll: function(e) {
|
|
const scrollTop = e.detail.scrollTop;
|
|
this.setData({ lastScrollTop: scrollTop });
|
|
|
|
// 滚动到顶部加载更多
|
|
if (scrollTop <= 30 && !this.data.loadingMore && this.data.hasMore) {
|
|
this.loadMoreMessages();
|
|
}
|
|
},
|
|
|
|
// 滚动到底部
|
|
scrollToBottom: function(animate = true) {
|
|
this.setData({
|
|
scrollAnimate: animate
|
|
}, () => {
|
|
setTimeout(() => {
|
|
this.setData({ scrollTop: 999999 });
|
|
}, 50);
|
|
});
|
|
},
|
|
|
|
// 显示多媒体选择面板
|
|
showMediaActionSheet: function() {
|
|
this.setData({
|
|
showMediaSheet: true,
|
|
inputFocus: false
|
|
});
|
|
},
|
|
|
|
// 隐藏多媒体选择面板
|
|
hideMediaActionSheet: function() {
|
|
this.setData({ showMediaSheet: false });
|
|
},
|
|
|
|
// 选择图片(模拟)
|
|
chooseImage: function() {
|
|
this.hideMediaActionSheet();
|
|
|
|
// 模拟选择图片
|
|
const mockImages = [
|
|
'https://picsum.photos/200/200?random=2',
|
|
'https://picsum.photos/200/200?random=3',
|
|
'https://picsum.photos/200/200?random=4'
|
|
];
|
|
|
|
const randomImage = mockImages[Math.floor(Math.random() * mockImages.length)];
|
|
|
|
const messageId = 'img_' + Date.now();
|
|
|
|
const newMessage = {
|
|
id: messageId,
|
|
isMe: true,
|
|
type: 'image',
|
|
content: randomImage,
|
|
timestamp: Date.now(),
|
|
status: 'uploading',
|
|
progress: 0,
|
|
avatar: this.data.expertAvatar
|
|
};
|
|
|
|
this.addMessageToList(newMessage);
|
|
|
|
// 模拟上传进度
|
|
let progress = 0;
|
|
const interval = setInterval(() => {
|
|
progress += 20;
|
|
|
|
if (progress >= 100) {
|
|
clearInterval(interval);
|
|
this.updateMessageStatus(messageId, 'success');
|
|
} else {
|
|
const msgIndex = this.data.messageList.findIndex(m => m.id === messageId);
|
|
if (msgIndex !== -1) {
|
|
this.data.messageList[msgIndex].progress = progress;
|
|
this.setData({ messageList: this.data.messageList });
|
|
}
|
|
}
|
|
}, 200);
|
|
},
|
|
|
|
// 选择视频(模拟)
|
|
chooseVideo: function() {
|
|
this.hideMediaActionSheet();
|
|
|
|
const messageId = 'video_' + Date.now();
|
|
|
|
const newMessage = {
|
|
id: messageId,
|
|
isMe: true,
|
|
type: 'video',
|
|
content: 'https://example.com/video.mp4',
|
|
thumb: 'https://picsum.photos/200/200?random=5',
|
|
timestamp: Date.now(),
|
|
status: 'uploading',
|
|
progress: 0,
|
|
avatar: this.data.expertAvatar
|
|
};
|
|
|
|
this.addMessageToList(newMessage);
|
|
|
|
// 模拟上传进度
|
|
let progress = 0;
|
|
const interval = setInterval(() => {
|
|
progress += 25;
|
|
|
|
if (progress >= 100) {
|
|
clearInterval(interval);
|
|
this.updateMessageStatus(messageId, 'success');
|
|
} else {
|
|
const msgIndex = this.data.messageList.findIndex(m => m.id === messageId);
|
|
if (msgIndex !== -1) {
|
|
this.data.messageList[msgIndex].progress = progress;
|
|
this.setData({ messageList: this.data.messageList });
|
|
}
|
|
}
|
|
}, 300);
|
|
},
|
|
|
|
// 预览图片
|
|
previewImage: function(e) {
|
|
const url = e.currentTarget.dataset.url;
|
|
wx.previewImage({
|
|
current: url,
|
|
urls: [url]
|
|
});
|
|
},
|
|
|
|
// 阻止事件冒泡
|
|
stopPropagation: function() {}
|
|
});
|