@zuopngfei d80105ab13 www
2025-11-13 14:08:22 +08:00

576 lines
16 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const request = require('../../api/request.js');
const uploadFile = require('../../api/upload.js');
Page({
data: {
messages: [],
inputText: '',
scrollToId: '',
userAvatar: '/static/user.png',
serviceAvatar: '/static/contact.png',
showGetUser: false,
userInfo: {},
appid: '',
page: 1,
page_size: 100,
openid: '',
total: 0,
isAtBottom: true,
loadingMore: false,
// 新消息提醒
showNewMessageTip: false, // 是否显示新消息提醒
newMessageCount: 0, // 新消息数量
lastMessageId: '', // 最后一条消息的ID用于检测新消息
// 欢迎消息标记
hasWelcomeMessageSent: false, // 是否已发送欢迎消息
// 订阅消息
template_id: '',
},
onLoad(options) {
const accountInfo = wx.getAccountInfoSync();
this.setData({
appid: accountInfo.miniProgram.appId,
});
if (wx.getStorageSync('user_info')) {
this.setData({
showGetUser: false,
userInfo: wx.getStorageSync('user_info'),
userAvatar: wx.getStorageSync('user_info').user_avatar || '/static/user.png',
});
this.getMessages().then(() => {
this.sendWelcomeMessage();
});
this.startPolling();
} else {
this.silentLogin();
}
this.getTemplateId();
},
// onShow() {
// this.getMessages()
// },
getTemplateId() {
const accountInfo = wx.getAccountInfoSync();
request('wechat/template', 'post', {
app_id: accountInfo.miniProgram.appId
}).then((res) => {
this.setData({
template_id: res.template_id
});
});
},
dingyue() {
return new Promise((resolve, reject) => {
wx.requestSubscribeMessage({
tmplIds: [this.data.template_id],
success: (res) => {
resolve(res);
},
fail: (err) => {
reject(err);
}
});
});
},
getMessages() {
const userInfo = wx.getStorageSync('user_info');
const that = this;
return request('app/messages', 'get', {
app_id: that.data.appid,
user_id: userInfo.openid,
page: that.data.page,
page_size: that.data.page_size,
}).then(res => {
const list = that.processMessages(res.list);
const sortedList = that.sortMessagesByID(list);
const updateData = {
messages: sortedList,
total: res.total
};
that.setData(updateData);
if (that.data.isAtBottom && sortedList.length > 0) {
const lastMessageId = sortedList[sortedList.length - 1].id;
console.log('用户在底部准备自动滚动到消息ID:', lastMessageId);
setTimeout(() => {
that.setData({
scrollToId: lastMessageId
});
console.log('已设置scrollToId:', lastMessageId);
}, 50);
} else {
console.log('用户不在底部或无消息保持当前位置。isAtBottom:', that.data.isAtBottom, '消息数量:', sortedList.length);
}
return res;
});
},
loadMoreAtTop() {
if (this.data.loadingMore) return;
const already = this.data.messages.length || 0;
if (already >= this.data.total) return;
const nextPage = this.data.page + 1;
this.setData({ loadingMore: true });
const userInfo = wx.getStorageSync('user_info');
const that = this;
const prevTopId = this.data.messages[0] ? this.data.messages[0].id : null;
request('app/messages', 'get', {
app_id: this.data.appid,
user_id: userInfo.openid,
page: nextPage,
page_size: this.data.page_size,
}).then(res => {
const newList = that.processMessages(res.list);
const combined = newList.concat(that.data.messages);
const sortedCombined = that.sortMessagesByID(combined);
that.setData({
messages: sortedCombined,
page: nextPage,
total: res.total,
}, () => {
if (prevTopId) {
that.setData({ scrollToId: prevTopId });
}
that.setData({ loadingMore: false });
});
}).catch(() => {
that.setData({ loadingMore: false });
});
},
processMessages(messageList) {
const processedMessages = messageList.map((item, index) => {
if (item.id && !item.id.toString().startsWith('m') && !item.id.toString().startsWith('u')) {
item.id = 'm' + item.id;
} else if (item.create_time) {
item.id = 'm' + new Date(item.create_time).getTime();
} else if (!item.id) {
item.id = 'm' + (Date.now() + index);
}
if (typeof item.content === 'string') {
try {
item.content = {
message: JSON.parse(item.content).message || JSON.parse(item.content).messages
}
} catch (e) {
console.warn('消息内容解析失败:', item.content);
item.content = { message: item.content };
}
}
return item;
});
this.checkNewMessages(processedMessages);
return processedMessages;
},
checkNewMessages(newMessages) {
if (newMessages.length === 0) return;
const currentMessages = this.data.messages;
const currentLastMessageId = this.data.lastMessageId;
const sortedNewMessages = this.sortMessagesByID(newMessages);
const latestNewMessage = sortedNewMessages[sortedNewMessages.length - 1];
if (!this.data.isAtBottom && currentMessages.length > 0) {
const currentMessageIds = new Set(currentMessages.map(msg => msg.id));
const realNewMessages = sortedNewMessages.filter(msg => !currentMessageIds.has(msg.id));
if (realNewMessages.length > 0) {
const currentCount = this.data.newMessageCount || 0;
this.setData({
showNewMessageTip: true,
newMessageCount: currentCount + realNewMessages.length
});
}
}
if (latestNewMessage) {
this.setData({
lastMessageId: latestNewMessage.id
});
}
},
sortMessagesByID(messages) {
return messages.sort((a, b) => {
const getNumericId = (id) => {
if (id.startsWith('u')) {
return parseInt(id.replace('u', '')) || 0;
} else if (id.startsWith('m')) {
const numId = parseInt(id.replace('m', '')) || 0;
if (numId < 1000000000000) {
return numId + 1000000000;
}
return numId;
}
return 0;
};
const idA = getNumericId(a.id);
const idB = getNumericId(b.id);
return idA - idB;
});
},
silentLogin() {
const that = this;
const accountInfo = wx.getAccountInfoSync();
wx.login({
success: function (res) {
request('wechat/miniprogram/login', 'post', {
"app_id": accountInfo.miniProgram.appId,
"js_code": res.code
}).then(resp => {
wx.setStorageSync('user_info', resp);
that.setData({
showGetUser: false,
userInfo: resp,
userAvatar: resp.user_avatar || '/static/user.png',
});
request('app/user/create', 'post', {
"app_id": accountInfo.miniProgram.appId,
"user_avatar": resp.user_avatar || '/static/user.png',
"user_id": resp.openid,
"user_name": resp.user_name || '微信用户'
}).then(resp => {
that.getMessages().then(() => {
that.sendWelcomeMessage();
});
that.startPolling();
});
}).catch(err => {
console.error('静默登录失败:', err);
that.setData({
showGetUser: true
});
});
},
fail: function (err) {
console.error('wx.login失败:', err);
}
});
},
startPolling() {
if (this.poller) return;
this.getMessages();
this.poller = setInterval(() => {
this.getMessages();
}, 1000);
},
stopPolling() {
if (this.poller) {
clearInterval(this.poller);
this.poller = null;
}
},
onScroll(e) {
const scrollTop = e.detail.scrollTop || 0;
const last = this._lastScrollTop || 0;
if (scrollTop < last) {
if (this.data.isAtBottom) {
console.log('用户向上滚动设置isAtBottom为false');
this.setData({ isAtBottom: false });
}
}
if (scrollTop <= 2) {
if (!this.data.loadingMore && this.data.messages.length < this.data.total) {
this.loadMoreAtTop();
}
}
this._lastScrollTop = scrollTop;
},
onScrollToLower() {
console.log('用户滚动到底部当前isAtBottom状态:', this.data.isAtBottom);
if (!this.data.isAtBottom) {
this.setData({
isAtBottom: true,
showNewMessageTip: false,
newMessageCount: 0
});
console.log('已设置isAtBottom为true');
this.startPolling();
const lastId = this.data.messages[this.data.messages.length - 1] ? this.data.messages[this.data.messages.length - 1].id : '';
if (lastId) {
this.setData({ scrollToId: lastId });
console.log('设置scrollToId到最新消息:', lastId);
}
} else {
if (this.data.showNewMessageTip) {
this.setData({
showNewMessageTip: false,
newMessageCount: 0
});
console.log('隐藏新消息提醒');
}
}
},
onReady() {
const now = new Date();
const timeStr = this.formatTime(now);
this.setData({
messages: [],
scrollToId: 'm1'
});
},
onInput(e) {
this.setData({
inputText: e.detail.value
});
},
sendWelcomeMessage() {
if (!this.data.userInfo || !this.data.userInfo.openid) {
console.log('用户信息不存在,无法发送欢迎消息');
return;
}
const welcomeKey = `welcome_sent_${this.data.userInfo.openid}`;
const hasWelcomeSent = wx.getStorageSync(welcomeKey);
if (hasWelcomeSent) {
console.log('该用户的欢迎消息已发送过,跳过');
this.setData({ hasWelcomeMessageSent: true });
return;
}
const welcomeText = '你好,我有需求';
const now = new Date();
const id = 'welcome_' + Date.now();
const msg = {
id,
content: {
message: welcomeText
},
"msg_type": 1,
receiver_id: '',
send_time: "刚刚",
sender_id: this.data.userInfo.openid,
sender_name: this.data.userInfo.user_name
};
// 添加新消息并重新排序
const newMessages = this.data.messages.concat(msg);
const sortedMessages = this.sortMessagesByID(newMessages);
this.setData({
messages: sortedMessages,
hasWelcomeMessageSent: true
});
const accountInfo = wx.getAccountInfoSync();
const userInfo = wx.getStorageSync('user_info');
console.log('发送欢迎消息:', welcomeText);
// 发送到服务器
request('app/send_message', 'POST', {
"app_id": accountInfo.miniProgram.appId,
"content": JSON.stringify({
message: welcomeText
}),
"from_user_id": userInfo.openid,
"from_user_name": userInfo.user_name,
"msg_type": 1
}).then(() => {
console.log('欢迎消息发送成功');
wx.setStorageSync(welcomeKey, true);
}).catch(err => {
console.error('欢迎消息发送失败:', err);
});
setTimeout(() => {
const latestMessage = sortedMessages[sortedMessages.length - 1];
this.setData({
scrollToId: latestMessage ? latestMessage.id : id
});
}, 50);
},
async sendText() {
const text = this.data.inputText && this.data.inputText.trim();
if (!text) return;
const now = new Date();
const id = 'u' + Date.now();
const msg = {
id,
content: {
message: text
},
"msg_type": 1,
receiver_id: '',
send_time: "刚刚",
sender_id: this.data.userInfo.openid,
sender_name: this.data.userInfo.user_name
};
const newMessages = this.data.messages.concat(msg);
const sortedMessages = this.sortMessagesByID(newMessages);
this.setData({
messages: sortedMessages,
inputText: ''
});
const accountInfo = wx.getAccountInfoSync();
const userInfo = wx.getStorageSync('user_info')
request('app/send_message', 'POST', {
"app_id": accountInfo.miniProgram.appId,
"content": JSON.stringify({
message: text
}),
"from_user_id": userInfo.openid,
"from_user_name": userInfo.user_name,
"msg_type": 1
})
setTimeout(() => {
const latestMessage = sortedMessages[sortedMessages.length - 1];
this.setData({
scrollToId: latestMessage ? latestMessage.id : id
});
}, 50);
},
async chooseImage() {
const that = this;
wx.chooseImage({
count: 1,
mediaType: ['image'],
sizeType: ['compressed', 'original'],
sourceType: ['album', 'camera'],
success(res) {
const tempFilePaths = res.tempFilePaths;
console.log('选择的图片路径:', res);
if (tempFilePaths && tempFilePaths.length) {
const userInfo = wx.getStorageSync('user_info')
const id = 'u' + Date.now();
const msg = {
id,
msg_type: '2',
receiver_id: '',
content: {
message: tempFilePaths[0]
},
sender_id: userInfo.openid,
sender_name: userInfo.user_name,
receiver_id: '',
send_time: "刚刚",
};
const list = that.data.messages
list.push(msg);
that.setData({
messages: list
});
setTimeout(() => {
that.setData({
scrollToId: id
});
}, 50);
uploadFile(tempFilePaths[0]).then((res) => {
const accountInfo = wx.getAccountInfoSync();
request('app/send_message', 'POST', {
"app_id": accountInfo.miniProgram.appId,
"content": JSON.stringify({
message: res
}),
"from_user_id": userInfo.openid,
"from_user_name": userInfo.user_name,
"msg_type": 2
}).catch((err) => {
wx.showToast({
title: '图片发送失败',
icon: 'none'
});
});
}).catch((err) => {
wx.showToast({
title: '图片发送失败',
icon: 'none'
});
});
}
}
});
},
formatTime(date) {
const y = date.getFullYear();
const m = (date.getMonth() + 1).toString().padStart(2, '0');
const d = date.getDate().toString().padStart(2, '0');
const h = date.getHours().toString().padStart(2, '0');
const min = date.getMinutes().toString().padStart(2, '0');
return `${y}${m}${d}${h}:${min}`;
},
previewImage(e) {
const src = e.currentTarget.dataset.src;
if (!src) return;
wx.previewImage({
urls: [src],
current: src
});
},
onShow() {
if (wx.getStorageSync('user_info')) {
this.getMessages();
this.startPolling();
}
},
onHide() {
this.stopPolling();
},
onUnload() {
this.stopPolling();
},
onPullDownRefresh() {
if (wx.getStorageSync('user_info')) {
this.getMessages().then(() => {
wx.stopPullDownRefresh();
}).catch(() => {
wx.stopPullDownRefresh();
});
} else {
wx.stopPullDownRefresh();
}
},
scrollToBottom() {
const messages = this.data.messages;
if (messages.length > 0) {
const sortedMessages = this.sortMessagesByID(messages);
const latestMessage = sortedMessages[sortedMessages.length - 1];
this.setData({
scrollToId: latestMessage.id,
showNewMessageTip: false,
newMessageCount: 0,
isAtBottom: true
});
setTimeout(() => {
this.setData({
scrollToId: ''
});
}, 100);
}
},
onReachBottom() { },
onShareAppMessage() { },
handleSubscribe() {
this.dingyue()
}
});