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() } });