refactor: 移除注释并更新API基础URL
更新了多个文件中的API基础URL,并移除了冗余的注释和未使用的代码 清理了代码结构,提高了可读性
This commit is contained in:
parent
bb20e4ea87
commit
38c440bd23
@ -1,26 +1,8 @@
|
|||||||
const baseUrl = 'https://mini-chat.1024tool.vip/api/'
|
const baseUrl = 'https://dsjhd9s.tbmw.cn/api/'
|
||||||
/**
|
|
||||||
* 发送 HTTP 请求到后端接口
|
|
||||||
*
|
|
||||||
* 功能描述:
|
|
||||||
* - 封装 wx.request,统一设置 JSON 请求头与基础地址
|
|
||||||
* - 成功时返回后端 res.data(已由微信自动 JSON.parse)
|
|
||||||
* - 业务错误(res.data.code 存在)统一弹 Toast 并 reject
|
|
||||||
* - 网络错误或服务器异常走 fail 并直接 reject
|
|
||||||
*
|
|
||||||
* 参数说明:
|
|
||||||
* @param {string} url - 相对接口路径,例如 'app/send_message'
|
|
||||||
* @param {string} [method='GET'] - HTTP 方法,支持 'GET'、'POST' 等
|
|
||||||
* @param {Object} [data={}] - 请求参数对象,将作为请求体/查询参数发送
|
|
||||||
*
|
|
||||||
* 返回值:
|
|
||||||
* @returns {Promise<any>} - 成功时 resolve 为后端返回的数据对象,失败时 reject 错误信息
|
|
||||||
*/
|
|
||||||
function request(url, method = 'GET', data = {}) {
|
function request(url, method = 'GET', data = {}) {
|
||||||
|
|
||||||
const header = {
|
const header = {
|
||||||
'content-type': 'application/json',
|
'content-type': 'application/json'
|
||||||
// 有其他content-type需求加点逻辑判断处理即可
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -28,7 +10,7 @@ function request(url, method = 'GET', data = {}) {
|
|||||||
url: baseUrl + url,
|
url: baseUrl + url,
|
||||||
method,
|
method,
|
||||||
data,
|
data,
|
||||||
dataType: 'json', // 微信官方文档中介绍会对数据进行一次JSON.parse
|
dataType: 'json',
|
||||||
header,
|
header,
|
||||||
success(res) {
|
success(res) {
|
||||||
if (res.data.code) {
|
if (res.data.code) {
|
||||||
@ -49,12 +31,9 @@ function request(url, method = 'GET', data = {}) {
|
|||||||
},
|
},
|
||||||
fail(err) {
|
fail(err) {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
// 断网、服务器挂了都会fail回调,直接reject即可
|
|
||||||
reject(err);
|
reject(err);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出请求函数(CommonJS 导出,兼容微信小程序解析环境)
|
|
||||||
module.exports = request;
|
module.exports = request;
|
||||||
@ -9,12 +9,12 @@ function uploadFile(filePath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wx.uploadFile({
|
wx.uploadFile({
|
||||||
filePath: filePath, // 图片临时文件路径(由调用方传入)
|
filePath: filePath,
|
||||||
name: 'file', // 服务器接收文件的字段名,需与后端对应
|
name: 'file',
|
||||||
url: 'https://mini-chat.1024tool.vip/api/admin/upload/image', // 服务器接收图片的接口地址
|
url: 'https://dsjhd9s.tbmw.cn/api/admin/upload/image',
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
const data = JSON.parse(res.data);
|
const data = JSON.parse(res.data);
|
||||||
resolve('https://mini-chat.1024tool.vip/' + data.preview_image_url);
|
resolve('https://dsjhd9s.tbmw.cn/' + data.preview_image_url);
|
||||||
|
|
||||||
},
|
},
|
||||||
fail: (err) => {
|
fail: (err) => {
|
||||||
@ -25,7 +25,4 @@ function uploadFile(filePath) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 导出请求和服务地址(CommonJS 兼容)
|
|
||||||
module.exports = uploadFile;
|
module.exports = uploadFile;
|
||||||
@ -1,16 +1,11 @@
|
|||||||
// pages/contact/index.js
|
|
||||||
const request = require('../../api/request.js');
|
const request = require('../../api/request.js');
|
||||||
|
|
||||||
const uploadFile = require('../../api/upload.js');
|
const uploadFile = require('../../api/upload.js');
|
||||||
Page({
|
Page({
|
||||||
/**
|
|
||||||
* 页面的初始数据
|
|
||||||
*/
|
|
||||||
data: {
|
data: {
|
||||||
messages: [],
|
messages: [],
|
||||||
inputText: '',
|
inputText: '',
|
||||||
scrollToId: '',
|
scrollToId: '',
|
||||||
// 头像
|
|
||||||
userAvatar: '/static/user.png',
|
userAvatar: '/static/user.png',
|
||||||
serviceAvatar: '/static/contact.png',
|
serviceAvatar: '/static/contact.png',
|
||||||
showGetUser: false,
|
showGetUser: false,
|
||||||
@ -20,47 +15,32 @@ Page({
|
|||||||
page_size: 100,
|
page_size: 100,
|
||||||
openid: '',
|
openid: '',
|
||||||
total: 0,
|
total: 0,
|
||||||
// 滚动状态
|
|
||||||
isAtBottom: true,
|
isAtBottom: true,
|
||||||
// 加载状态
|
|
||||||
loadingMore: false,
|
loadingMore: false,
|
||||||
// 新消息提醒
|
showNewMessageTip: false,
|
||||||
showNewMessageTip: false, // 是否显示新消息提醒
|
newMessageCount: 0,
|
||||||
newMessageCount: 0, // 新消息数量
|
lastMessageId: '',
|
||||||
lastMessageId: '', // 最后一条消息的ID,用于检测新消息
|
hasWelcomeMessageSent: false,
|
||||||
// 欢迎消息标记
|
|
||||||
hasWelcomeMessageSent: false, // 是否已发送欢迎消息
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面加载
|
|
||||||
*/
|
|
||||||
onLoad(options) {
|
onLoad(options) {
|
||||||
const accountInfo = wx.getAccountInfoSync();
|
const accountInfo = wx.getAccountInfoSync();
|
||||||
this.setData({
|
this.setData({
|
||||||
appid: accountInfo.miniProgram.appId,
|
appid: accountInfo.miniProgram.appId,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 检查是否已有用户信息
|
|
||||||
if (wx.getStorageSync('user_info')) {
|
if (wx.getStorageSync('user_info')) {
|
||||||
this.setData({
|
this.setData({
|
||||||
showGetUser: false,
|
showGetUser: false,
|
||||||
userInfo: wx.getStorageSync('user_info'),
|
userInfo: wx.getStorageSync('user_info'),
|
||||||
});
|
});
|
||||||
this.getMessages().then(() => {
|
this.getMessages().then(() => {
|
||||||
// 在获取消息完成后发送欢迎消息
|
|
||||||
this.sendWelcomeMessage();
|
this.sendWelcomeMessage();
|
||||||
});
|
});
|
||||||
// start polling when page loads and user is present
|
|
||||||
this.startPolling();
|
this.startPolling();
|
||||||
} else {
|
} else {
|
||||||
// 直接进行静默登录,不显示授权弹窗
|
|
||||||
this.silentLogin();
|
this.silentLogin();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// onShow() {
|
|
||||||
// this.getMessages()
|
|
||||||
// },
|
|
||||||
|
|
||||||
getMessages() {
|
getMessages() {
|
||||||
const userInfo = wx.getStorageSync('user_info');
|
const userInfo = wx.getStorageSync('user_info');
|
||||||
@ -71,13 +51,10 @@ Page({
|
|||||||
page: that.data.page,
|
page: that.data.page,
|
||||||
page_size: that.data.page_size,
|
page_size: that.data.page_size,
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
// 处理消息列表,使用统一的消息处理函数
|
|
||||||
const list = that.processMessages(res.list);
|
const list = that.processMessages(res.list);
|
||||||
|
|
||||||
// 根据ID进行排序,确保ID最大的(最新的)消息在最后
|
|
||||||
const sortedList = that.sortMessagesByID(list);
|
const sortedList = that.sortMessagesByID(list);
|
||||||
|
|
||||||
// 智能滚动逻辑:用户在底部时自动滚动,在上方时保持位置
|
|
||||||
const updateData = {
|
const updateData = {
|
||||||
messages: sortedList,
|
messages: sortedList,
|
||||||
total: res.total
|
total: res.total
|
||||||
@ -85,7 +62,6 @@ Page({
|
|||||||
|
|
||||||
that.setData(updateData);
|
that.setData(updateData);
|
||||||
|
|
||||||
// 如果用户在底部,延迟设置滚动ID确保滚动生效
|
|
||||||
if (that.data.isAtBottom && sortedList.length > 0) {
|
if (that.data.isAtBottom && sortedList.length > 0) {
|
||||||
const lastMessageId = sortedList[sortedList.length - 1].id;
|
const lastMessageId = sortedList[sortedList.length - 1].id;
|
||||||
console.log('用户在底部,准备自动滚动到消息ID:', lastMessageId);
|
console.log('用户在底部,准备自动滚动到消息ID:', lastMessageId);
|
||||||
@ -99,25 +75,21 @@ Page({
|
|||||||
console.log('用户不在底部或无消息,保持当前位置。isAtBottom:', that.data.isAtBottom, '消息数量:', sortedList.length);
|
console.log('用户不在底部或无消息,保持当前位置。isAtBottom:', that.data.isAtBottom, '消息数量:', sortedList.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res; // 返回结果以支持链式调用
|
return res;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// Load older messages (previous pages) and prepend them to the top
|
|
||||||
loadMoreAtTop() {
|
loadMoreAtTop() {
|
||||||
if (this.data.loadingMore) return;
|
if (this.data.loadingMore) return;
|
||||||
// if we've loaded all messages, skip
|
|
||||||
const already = this.data.messages.length || 0;
|
const already = this.data.messages.length || 0;
|
||||||
if (already >= this.data.total) return;
|
if (already >= this.data.total) return;
|
||||||
|
|
||||||
// compute next page to fetch
|
|
||||||
const nextPage = this.data.page + 1;
|
const nextPage = this.data.page + 1;
|
||||||
this.setData({ loadingMore: true });
|
this.setData({ loadingMore: true });
|
||||||
|
|
||||||
const userInfo = wx.getStorageSync('user_info');
|
const userInfo = wx.getStorageSync('user_info');
|
||||||
const that = this;
|
const that = this;
|
||||||
|
|
||||||
// capture current top-most visible message id to preserve scroll position
|
|
||||||
const prevTopId = this.data.messages[0] ? this.data.messages[0].id : null;
|
const prevTopId = this.data.messages[0] ? this.data.messages[0].id : null;
|
||||||
|
|
||||||
request('app/messages', 'get', {
|
request('app/messages', 'get', {
|
||||||
@ -126,13 +98,10 @@ Page({
|
|||||||
page: nextPage,
|
page: nextPage,
|
||||||
page_size: this.data.page_size,
|
page_size: this.data.page_size,
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
// 处理新加载的消息,使用统一的消息处理函数
|
|
||||||
const newList = that.processMessages(res.list);
|
const newList = that.processMessages(res.list);
|
||||||
|
|
||||||
// 合并新消息和现有消息
|
|
||||||
const combined = newList.concat(that.data.messages);
|
const combined = newList.concat(that.data.messages);
|
||||||
|
|
||||||
// 根据ID进行排序,确保ID最大的(最新的)消息在最后
|
|
||||||
const sortedCombined = that.sortMessagesByID(combined);
|
const sortedCombined = that.sortMessagesByID(combined);
|
||||||
|
|
||||||
that.setData({
|
that.setData({
|
||||||
@ -140,9 +109,7 @@ Page({
|
|||||||
page: nextPage,
|
page: nextPage,
|
||||||
total: res.total,
|
total: res.total,
|
||||||
}, () => {
|
}, () => {
|
||||||
// after render, keep the previous top message in view
|
|
||||||
if (prevTopId) {
|
if (prevTopId) {
|
||||||
// scroll-into-view to the previous top id so viewport doesn't jump
|
|
||||||
that.setData({ scrollToId: prevTopId });
|
that.setData({ scrollToId: prevTopId });
|
||||||
}
|
}
|
||||||
that.setData({ loadingMore: false });
|
that.setData({ loadingMore: false });
|
||||||
@ -151,22 +118,16 @@ Page({
|
|||||||
that.setData({ loadingMore: false });
|
that.setData({ loadingMore: false });
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// 统一的消息处理函数
|
|
||||||
processMessages(messageList) {
|
processMessages(messageList) {
|
||||||
const processedMessages = messageList.map((item, index) => {
|
const processedMessages = messageList.map((item, index) => {
|
||||||
// 优先使用服务器返回的ID,如果没有则使用创建时间戳
|
|
||||||
if (item.id && !item.id.toString().startsWith('m') && !item.id.toString().startsWith('u')) {
|
if (item.id && !item.id.toString().startsWith('m') && !item.id.toString().startsWith('u')) {
|
||||||
item.id = 'm' + item.id;
|
item.id = 'm' + item.id;
|
||||||
} else if (item.create_time) {
|
} else if (item.create_time) {
|
||||||
// 使用创建时间的时间戳作为ID
|
|
||||||
item.id = 'm' + new Date(item.create_time).getTime();
|
item.id = 'm' + new Date(item.create_time).getTime();
|
||||||
} else if (!item.id) {
|
} else if (!item.id) {
|
||||||
// 兜底方案:使用当前时间戳 + 索引
|
|
||||||
item.id = 'm' + (Date.now() + index);
|
item.id = 'm' + (Date.now() + index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析消息内容
|
|
||||||
if (typeof item.content === 'string') {
|
if (typeof item.content === 'string') {
|
||||||
try {
|
try {
|
||||||
item.content = {
|
item.content = {
|
||||||
@ -181,13 +142,10 @@ Page({
|
|||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 检测新消息并显示提醒
|
|
||||||
this.checkNewMessages(processedMessages);
|
this.checkNewMessages(processedMessages);
|
||||||
|
|
||||||
return processedMessages;
|
return processedMessages;
|
||||||
},
|
},
|
||||||
|
|
||||||
// 检测新消息的函数
|
|
||||||
checkNewMessages(newMessages) {
|
checkNewMessages(newMessages) {
|
||||||
if (newMessages.length === 0) return;
|
if (newMessages.length === 0) return;
|
||||||
|
|
||||||
@ -195,15 +153,11 @@ Page({
|
|||||||
const currentLastMessageId = this.data.lastMessageId;
|
const currentLastMessageId = this.data.lastMessageId;
|
||||||
const sortedNewMessages = this.sortMessagesByID(newMessages);
|
const sortedNewMessages = this.sortMessagesByID(newMessages);
|
||||||
const latestNewMessage = sortedNewMessages[sortedNewMessages.length - 1];
|
const latestNewMessage = sortedNewMessages[sortedNewMessages.length - 1];
|
||||||
|
|
||||||
// 如果不在底部且有新消息
|
|
||||||
if (!this.data.isAtBottom && currentMessages.length > 0) {
|
if (!this.data.isAtBottom && currentMessages.length > 0) {
|
||||||
// 找出真正的新消息(在当前消息列表中不存在的消息)
|
|
||||||
const currentMessageIds = new Set(currentMessages.map(msg => msg.id));
|
const currentMessageIds = new Set(currentMessages.map(msg => msg.id));
|
||||||
const realNewMessages = sortedNewMessages.filter(msg => !currentMessageIds.has(msg.id));
|
const realNewMessages = sortedNewMessages.filter(msg => !currentMessageIds.has(msg.id));
|
||||||
|
|
||||||
if (realNewMessages.length > 0) {
|
if (realNewMessages.length > 0) {
|
||||||
// 累加新消息数量(而不是重置)
|
|
||||||
const currentCount = this.data.newMessageCount || 0;
|
const currentCount = this.data.newMessageCount || 0;
|
||||||
this.setData({
|
this.setData({
|
||||||
showNewMessageTip: true,
|
showNewMessageTip: true,
|
||||||
@ -211,31 +165,21 @@ Page({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新最后一条消息ID
|
|
||||||
if (latestNewMessage) {
|
if (latestNewMessage) {
|
||||||
this.setData({
|
this.setData({
|
||||||
lastMessageId: latestNewMessage.id
|
lastMessageId: latestNewMessage.id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 消息排序函数
|
|
||||||
sortMessagesByID(messages) {
|
sortMessagesByID(messages) {
|
||||||
return messages.sort((a, b) => {
|
return messages.sort((a, b) => {
|
||||||
// 提取ID的数字部分
|
|
||||||
const getNumericId = (id) => {
|
const getNumericId = (id) => {
|
||||||
if (id.startsWith('u')) {
|
if (id.startsWith('u')) {
|
||||||
// 用户消息:使用时间戳
|
|
||||||
return parseInt(id.replace('u', '')) || 0;
|
return parseInt(id.replace('u', '')) || 0;
|
||||||
} else if (id.startsWith('m')) {
|
} else if (id.startsWith('m')) {
|
||||||
// 服务器消息:如果是时间戳格式(长度>10),直接使用;否则转换为时间戳格式
|
|
||||||
const numId = parseInt(id.replace('m', '')) || 0;
|
const numId = parseInt(id.replace('m', '')) || 0;
|
||||||
// 如果是小数字(比如1,2,3),可能是服务器的序号ID,需要转换为可比较的时间戳
|
|
||||||
// 这里假设小于1000000000000(约2001年)的都是序号ID
|
|
||||||
if (numId < 1000000000000) {
|
if (numId < 1000000000000) {
|
||||||
// 将小的序号ID映射到一个较早的时间范围,确保它们排在用户消息之前
|
return numId + 1000000000;
|
||||||
return numId + 1000000000; // 加上一个基数,但仍然小于用户消息的时间戳
|
|
||||||
}
|
}
|
||||||
return numId;
|
return numId;
|
||||||
}
|
}
|
||||||
@ -247,8 +191,6 @@ Page({
|
|||||||
return idA - idB;
|
return idA - idB;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// 静默登录方法,只需要appid和js_code
|
|
||||||
silentLogin() {
|
silentLogin() {
|
||||||
const that = this;
|
const that = this;
|
||||||
const accountInfo = wx.getAccountInfoSync();
|
const accountInfo = wx.getAccountInfoSync();
|
||||||
@ -270,15 +212,12 @@ Page({
|
|||||||
"user_name": resp.user_name || '微信用户'
|
"user_name": resp.user_name || '微信用户'
|
||||||
}).then(resp => {
|
}).then(resp => {
|
||||||
that.getMessages().then(() => {
|
that.getMessages().then(() => {
|
||||||
// 在获取消息完成后发送欢迎消息
|
|
||||||
that.sendWelcomeMessage();
|
that.sendWelcomeMessage();
|
||||||
});
|
});
|
||||||
// start polling once user info exists
|
|
||||||
that.startPolling();
|
that.startPolling();
|
||||||
});
|
});
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error('静默登录失败:', err);
|
console.error('静默登录失败:', err);
|
||||||
// 如果静默登录失败,可以选择显示授权弹窗或其他处理
|
|
||||||
that.setData({
|
that.setData({
|
||||||
showGetUser: true
|
showGetUser: true
|
||||||
});
|
});
|
||||||
@ -289,54 +228,37 @@ Page({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// Start polling messages every 1 second. Ensures only one interval exists.
|
|
||||||
startPolling() {
|
startPolling() {
|
||||||
if (this.poller) return; // already polling
|
if (this.poller) return;
|
||||||
// immediate fetch then periodic
|
|
||||||
this.getMessages();
|
this.getMessages();
|
||||||
this.poller = setInterval(() => {
|
this.poller = setInterval(() => {
|
||||||
this.getMessages();
|
this.getMessages();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Stop polling and clear interval
|
|
||||||
stopPolling() {
|
stopPolling() {
|
||||||
if (this.poller) {
|
if (this.poller) {
|
||||||
clearInterval(this.poller);
|
clearInterval(this.poller);
|
||||||
this.poller = null;
|
this.poller = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Scroll handlers: stop polling when user scrolls up, resume when reach bottom
|
|
||||||
onScroll(e) {
|
onScroll(e) {
|
||||||
// e.detail.scrollTop increases when scrolling down. We want to detect upward scroll.
|
|
||||||
const scrollTop = e.detail.scrollTop || 0;
|
const scrollTop = e.detail.scrollTop || 0;
|
||||||
const last = this._lastScrollTop || 0;
|
const last = this._lastScrollTop || 0;
|
||||||
// If user scrolls up (new scrollTop < last), mark as not at bottom but keep polling
|
|
||||||
if (scrollTop < last) {
|
if (scrollTop < last) {
|
||||||
// user scrolled up
|
|
||||||
if (this.data.isAtBottom) {
|
if (this.data.isAtBottom) {
|
||||||
// only update state if we were previously at bottom, but keep polling active
|
|
||||||
console.log('用户向上滚动,设置isAtBottom为false');
|
console.log('用户向上滚动,设置isAtBottom为false');
|
||||||
this.setData({ isAtBottom: false });
|
this.setData({ isAtBottom: false });
|
||||||
// 注释掉停止轮询的逻辑,确保始终获取新消息
|
|
||||||
// this.stopPolling();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// detect reaching near top to load more
|
|
||||||
if (scrollTop <= 2) {
|
if (scrollTop <= 2) {
|
||||||
// if there are more messages to load and not already loading
|
|
||||||
if (!this.data.loadingMore && this.data.messages.length < this.data.total) {
|
if (!this.data.loadingMore && this.data.messages.length < this.data.total) {
|
||||||
this.loadMoreAtTop();
|
this.loadMoreAtTop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// update lastScrollTop for next event
|
|
||||||
this._lastScrollTop = scrollTop;
|
this._lastScrollTop = scrollTop;
|
||||||
},
|
},
|
||||||
|
|
||||||
onScrollToLower() {
|
onScrollToLower() {
|
||||||
// user scrolled to bottom (or very near). update state and ensure polling is active
|
|
||||||
console.log('用户滚动到底部,当前isAtBottom状态:', this.data.isAtBottom);
|
console.log('用户滚动到底部,当前isAtBottom状态:', this.data.isAtBottom);
|
||||||
if (!this.data.isAtBottom) {
|
if (!this.data.isAtBottom) {
|
||||||
this.setData({
|
this.setData({
|
||||||
@ -345,16 +267,13 @@ Page({
|
|||||||
newMessageCount: 0
|
newMessageCount: 0
|
||||||
});
|
});
|
||||||
console.log('已设置isAtBottom为true');
|
console.log('已设置isAtBottom为true');
|
||||||
// 确保轮询始终运行(即使之前已经在运行)
|
|
||||||
this.startPolling();
|
this.startPolling();
|
||||||
// also ensure we scroll to latest message next render
|
|
||||||
const lastId = this.data.messages[this.data.messages.length - 1] ? this.data.messages[this.data.messages.length - 1].id : '';
|
const lastId = this.data.messages[this.data.messages.length - 1] ? this.data.messages[this.data.messages.length - 1].id : '';
|
||||||
if (lastId) {
|
if (lastId) {
|
||||||
this.setData({ scrollToId: lastId });
|
this.setData({ scrollToId: lastId });
|
||||||
console.log('设置scrollToId到最新消息:', lastId);
|
console.log('设置scrollToId到最新消息:', lastId);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 即使已经在底部,也要隐藏新消息提醒
|
|
||||||
if (this.data.showNewMessageTip) {
|
if (this.data.showNewMessageTip) {
|
||||||
this.setData({
|
this.setData({
|
||||||
showNewMessageTip: false,
|
showNewMessageTip: false,
|
||||||
@ -364,11 +283,7 @@ Page({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
onReady() {
|
onReady() {
|
||||||
// 初始化欢迎消息,带时间分割线
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const timeStr = this.formatTime(now);
|
const timeStr = this.formatTime(now);
|
||||||
this.setData({
|
this.setData({
|
||||||
@ -382,16 +297,12 @@ Page({
|
|||||||
inputText: e.detail.value
|
inputText: e.detail.value
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// 发送欢迎消息
|
|
||||||
sendWelcomeMessage() {
|
sendWelcomeMessage() {
|
||||||
// 检查用户信息是否存在
|
|
||||||
if (!this.data.userInfo || !this.data.userInfo.openid) {
|
if (!this.data.userInfo || !this.data.userInfo.openid) {
|
||||||
console.log('用户信息不存在,无法发送欢迎消息');
|
console.log('用户信息不存在,无法发送欢迎消息');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用用户ID作为标记,检查是否已经发送过欢迎消息
|
|
||||||
const welcomeKey = `welcome_sent_${this.data.userInfo.openid}`;
|
const welcomeKey = `welcome_sent_${this.data.userInfo.openid}`;
|
||||||
const hasWelcomeSent = wx.getStorageSync(welcomeKey);
|
const hasWelcomeSent = wx.getStorageSync(welcomeKey);
|
||||||
|
|
||||||
@ -423,7 +334,7 @@ Page({
|
|||||||
|
|
||||||
this.setData({
|
this.setData({
|
||||||
messages: sortedMessages,
|
messages: sortedMessages,
|
||||||
hasWelcomeMessageSent: true // 标记已发送欢迎消息
|
hasWelcomeMessageSent: true
|
||||||
});
|
});
|
||||||
|
|
||||||
const accountInfo = wx.getAccountInfoSync();
|
const accountInfo = wx.getAccountInfoSync();
|
||||||
@ -442,16 +353,12 @@ Page({
|
|||||||
"msg_type": 1
|
"msg_type": 1
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
console.log('欢迎消息发送成功');
|
console.log('欢迎消息发送成功');
|
||||||
// 保存标记到本地存储,表示该用户已发送过欢迎消息
|
|
||||||
wx.setStorageSync(welcomeKey, true);
|
wx.setStorageSync(welcomeKey, true);
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error('欢迎消息发送失败:', err);
|
console.error('欢迎消息发送失败:', err);
|
||||||
// 如果发送失败,不保存标记,下次还可以重试
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 等待渲染,确保 scroll-into-view 生效
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// 滚动到最新的消息(排序后的最后一条)
|
|
||||||
const latestMessage = sortedMessages[sortedMessages.length - 1];
|
const latestMessage = sortedMessages[sortedMessages.length - 1];
|
||||||
this.setData({
|
this.setData({
|
||||||
scrollToId: latestMessage ? latestMessage.id : id
|
scrollToId: latestMessage ? latestMessage.id : id
|
||||||
@ -464,11 +371,6 @@ Page({
|
|||||||
if (!text) return;
|
if (!text) return;
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const id = 'u' + Date.now();
|
const id = 'u' + Date.now();
|
||||||
// const timeStr = this.formatTime(now);
|
|
||||||
// // 判断是否需要显示时间分割线
|
|
||||||
// let showTime = false;
|
|
||||||
// const lastMsg = this.data.messages.length ? this.data.messages[this.data.messages.length - 1] : null;
|
|
||||||
// if (!lastMsg || now - (lastMsg._ts || now) > 5 * 60 * 1000) showTime = true;
|
|
||||||
const msg = {
|
const msg = {
|
||||||
id,
|
id,
|
||||||
content: {
|
content: {
|
||||||
@ -481,7 +383,6 @@ Page({
|
|||||||
sender_name: this.data.userInfo.user_name
|
sender_name: this.data.userInfo.user_name
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加新消息并重新排序
|
|
||||||
const newMessages = this.data.messages.concat(msg);
|
const newMessages = this.data.messages.concat(msg);
|
||||||
const sortedMessages = this.sortMessagesByID(newMessages);
|
const sortedMessages = this.sortMessagesByID(newMessages);
|
||||||
|
|
||||||
@ -500,40 +401,19 @@ Page({
|
|||||||
"from_user_name": userInfo.user_name,
|
"from_user_name": userInfo.user_name,
|
||||||
"msg_type": 1
|
"msg_type": 1
|
||||||
})
|
})
|
||||||
// 等待渲染,确保 scroll-into-view 生效
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// 滚动到最新的消息(排序后的最后一条)
|
|
||||||
const latestMessage = sortedMessages[sortedMessages.length - 1];
|
const latestMessage = sortedMessages[sortedMessages.length - 1];
|
||||||
this.setData({
|
this.setData({
|
||||||
scrollToId: latestMessage ? latestMessage.id : id
|
scrollToId: latestMessage ? latestMessage.id : id
|
||||||
});
|
});
|
||||||
}, 50);
|
}, 50);
|
||||||
|
|
||||||
// 模拟客服回复(延迟)
|
|
||||||
// setTimeout(() => {
|
|
||||||
// const replyNow = new Date();
|
|
||||||
// const replyTimeStr = this.formatTime(replyNow);
|
|
||||||
// const reply = {
|
|
||||||
// id: 's' + Date.now(),
|
|
||||||
// from: 'service',
|
|
||||||
// type: 'text',
|
|
||||||
// content: '收到,客服正在处理中...',
|
|
||||||
// showTime: false,
|
|
||||||
// timeStr: replyTimeStr,
|
|
||||||
// _ts: replyNow
|
|
||||||
// };
|
|
||||||
// this.setData({
|
|
||||||
// messages: this.data.messages.concat(reply),
|
|
||||||
// scrollToId: reply.id
|
|
||||||
// });
|
|
||||||
// }, 800);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
chooseImage() {
|
chooseImage() {
|
||||||
const that = this;
|
const that = this;
|
||||||
wx.chooseImage({
|
wx.chooseImage({
|
||||||
count: 1, // 选择图片的数量
|
count: 1,
|
||||||
mediaType: ['image'], // 仅选择图片
|
mediaType: ['image'],
|
||||||
sizeType: ['compressed', 'original'],
|
sizeType: ['compressed', 'original'],
|
||||||
sourceType: ['album', 'camera'],
|
sourceType: ['album', 'camera'],
|
||||||
success(res) {
|
success(res) {
|
||||||
@ -541,12 +421,7 @@ Page({
|
|||||||
console.log('选择的图片路径:', res);
|
console.log('选择的图片路径:', res);
|
||||||
if (tempFilePaths && tempFilePaths.length) {
|
if (tempFilePaths && tempFilePaths.length) {
|
||||||
const userInfo = wx.getStorageSync('user_info')
|
const userInfo = wx.getStorageSync('user_info')
|
||||||
// const now = new Date();
|
|
||||||
const id = 'u' + Date.now();
|
const id = 'u' + Date.now();
|
||||||
// const timeStr = that.formatTime(now);
|
|
||||||
// let showTime = false;
|
|
||||||
// const lastMsg = that.data.messages.length ? that.data.messages[that.data.messages.length - 1] : null;
|
|
||||||
// if (!lastMsg || now - (lastMsg._ts || now) > 5 * 60 * 1000) showTime = true;
|
|
||||||
const msg = {
|
const msg = {
|
||||||
id,
|
id,
|
||||||
msg_type: '2',
|
msg_type: '2',
|
||||||
@ -593,45 +468,10 @@ Page({
|
|||||||
icon: 'none'
|
icon: 'none'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// wx.uploadFile({
|
|
||||||
// filePath: tempFilePaths[0], // 图片临时文件路径
|
|
||||||
// name: 'file', // 服务器接收文件的字段名,需与后端对应
|
|
||||||
// url: 'https://mini-chat.1024tool.vip/api/admin/upload/image', // 服务器接收图片的接口地址
|
|
||||||
// success: (res) => {
|
|
||||||
|
|
||||||
// },
|
|
||||||
// fail: (err) => {
|
|
||||||
// console.error('上传失败', err);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// 模拟客服返回图片确认
|
|
||||||
// setTimeout(() => {
|
|
||||||
// const replyNow = new Date();
|
|
||||||
// const replyTimeStr = that.formatTime(replyNow);
|
|
||||||
// const reply = {
|
|
||||||
// id: 's' + Date.now(),
|
|
||||||
// from: 'service',
|
|
||||||
// type: 'text',
|
|
||||||
// content: '已收到图片,感谢!',
|
|
||||||
// showTime: false,
|
|
||||||
// timeStr: replyTimeStr,
|
|
||||||
// _ts: replyNow
|
|
||||||
// };
|
|
||||||
// that.setData({
|
|
||||||
// messages: that.data.messages.concat(reply)
|
|
||||||
// });
|
|
||||||
// setTimeout(() => {
|
|
||||||
// that.setData({
|
|
||||||
// scrollToId: reply.id
|
|
||||||
// });
|
|
||||||
// }, 50);
|
|
||||||
// }, 1200);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 时间格式化
|
|
||||||
formatTime(date) {
|
formatTime(date) {
|
||||||
const y = date.getFullYear();
|
const y = date.getFullYear();
|
||||||
const m = (date.getMonth() + 1).toString().padStart(2, '0');
|
const m = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||||
@ -651,27 +491,20 @@ Page({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onShow() {
|
onShow() {
|
||||||
// resume polling when page becomes visible and get latest messages
|
|
||||||
if (wx.getStorageSync('user_info')) {
|
if (wx.getStorageSync('user_info')) {
|
||||||
// 立即请求最新消息
|
|
||||||
this.getMessages();
|
this.getMessages();
|
||||||
// 然后开始轮询
|
|
||||||
this.startPolling();
|
this.startPolling();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onHide() {
|
onHide() {
|
||||||
// stop polling when leaving page
|
|
||||||
this.stopPolling();
|
this.stopPolling();
|
||||||
},
|
},
|
||||||
onUnload() {
|
onUnload() {
|
||||||
// cleanup
|
|
||||||
this.stopPolling();
|
this.stopPolling();
|
||||||
},
|
},
|
||||||
onPullDownRefresh() {
|
onPullDownRefresh() {
|
||||||
// 下拉刷新时获取最新消息
|
|
||||||
if (wx.getStorageSync('user_info')) {
|
if (wx.getStorageSync('user_info')) {
|
||||||
this.getMessages().then(() => {
|
this.getMessages().then(() => {
|
||||||
// 停止下拉刷新动画
|
|
||||||
wx.stopPullDownRefresh();
|
wx.stopPullDownRefresh();
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
wx.stopPullDownRefresh();
|
wx.stopPullDownRefresh();
|
||||||
@ -680,8 +513,6 @@ Page({
|
|||||||
wx.stopPullDownRefresh();
|
wx.stopPullDownRefresh();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 点击新消息提醒,滚动到底部
|
|
||||||
scrollToBottom() {
|
scrollToBottom() {
|
||||||
const messages = this.data.messages;
|
const messages = this.data.messages;
|
||||||
if (messages.length > 0) {
|
if (messages.length > 0) {
|
||||||
@ -695,7 +526,6 @@ Page({
|
|||||||
isAtBottom: true
|
isAtBottom: true
|
||||||
});
|
});
|
||||||
|
|
||||||
// 延迟一下确保滚动完成
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.setData({
|
this.setData({
|
||||||
scrollToId: ''
|
scrollToId: ''
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
// 引入公共资源(原生小程序中需确保路径正确,若为工具类可直接 require,若为静态资源需用绝对路径)
|
|
||||||
const common_vendor = require("../../common/vendor.js");
|
const common_vendor = require("../../common/vendor.js");
|
||||||
const common_assets = require("../../common/assets.js");
|
const common_assets = require("../../common/assets.js");
|
||||||
const request = require('../../api/request.js');
|
const request = require('../../api/request.js');
|
||||||
|
|
||||||
// 定义舞蹈列表数据(原生小程序用普通数组存储,无需 ref 响应式包装)
|
|
||||||
const danceList = [
|
const danceList = [
|
||||||
{
|
{
|
||||||
id: 0,
|
id: 0,
|
||||||
@ -61,32 +59,23 @@ const danceList = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
// 原生小程序 Page 构造器(核心:数据、生命周期、方法)
|
|
||||||
Page({
|
Page({
|
||||||
// 1. 页面初始数据(对应 Vue 的 ref 数据,需用 this.data 访问,this.setData 更新)
|
|
||||||
data: {
|
data: {
|
||||||
currentDance: null, // 当前选中的舞蹈详情
|
currentDance: null,
|
||||||
danceIndex: 0, // 当前舞蹈在列表中的索引
|
danceIndex: 0,
|
||||||
wallpaperUrl: "", // 壁纸地址
|
wallpaperUrl: "",
|
||||||
appId: "", // 应用 ID
|
appId: "",
|
||||||
// 引入静态资源(原生小程序中需确保 assets 内的资源路径正确,此处与原代码保持一致)
|
|
||||||
commonAssets: common_assets
|
commonAssets: common_assets
|
||||||
},
|
},
|
||||||
|
|
||||||
// 2. 页面加载生命周期(对应原代码的 onLoad,接收页面参数 options)
|
|
||||||
onLoad(options) {
|
onLoad(options) {
|
||||||
// 日志打印(替换原框架的 log 方法,使用微信原生 console.log)
|
|
||||||
console.log("at pages/index/detail.js: onLoad", "接收到的参数:", options);
|
console.log("at pages/index/detail.js: onLoad", "接收到的参数:", options);
|
||||||
|
|
||||||
// 提取 app_id(逻辑与原代码一致,适配原生小程序 API)
|
|
||||||
try {
|
try {
|
||||||
if (options && options.app_id) {
|
if (options && options.app_id) {
|
||||||
this.setData({ appId: options.app_id }); // 原生用 setData 更新数据
|
this.setData({ appId: options.app_id });
|
||||||
} else {
|
} else {
|
||||||
// 原生小程序获取当前页面栈:getCurrentPages() 直接调用(无需通过 vendor)
|
|
||||||
const pages = getCurrentPages();
|
const pages = getCurrentPages();
|
||||||
if (pages && pages.length) {
|
if (pages && pages.length) {
|
||||||
const curPage = pages[pages.length - 1]; // 最后一个页面即当前页
|
const curPage = pages[pages.length - 1];
|
||||||
if (curPage && curPage.options && curPage.options.app_id) {
|
if (curPage && curPage.options && curPage.options.app_id) {
|
||||||
this.setData({ appId: curPage.options.app_id });
|
this.setData({ appId: curPage.options.app_id });
|
||||||
} else if (curPage && curPage.__route__) {
|
} else if (curPage && curPage.__route__) {
|
||||||
@ -109,38 +98,27 @@ Page({
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("提取 app_id 失败:", e);
|
console.error("提取 app_id 失败:", e);
|
||||||
}
|
}
|
||||||
|
if (options.url === "1") {
|
||||||
// 处理壁纸地址逻辑
|
|
||||||
if (options.url === "1") { // 原生小程序参数默认是字符串,需注意类型匹配
|
|
||||||
this.setData({ wallpaperUrl: options.url });
|
this.setData({ wallpaperUrl: options.url });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理舞蹈详情逻辑(根据 options.index 选择当前舞蹈)
|
|
||||||
if (options.index !== undefined) {
|
if (options.index !== undefined) {
|
||||||
const index = parseInt(options.index);
|
const index = parseInt(options.index);
|
||||||
this.setData({
|
this.setData({
|
||||||
danceIndex: index,
|
danceIndex: index,
|
||||||
currentDance: danceList[index] // 从预定义列表中获取对应舞蹈
|
currentDance: danceList[index]
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// 无索引时默认显示第一个舞蹈
|
|
||||||
this.setData({
|
this.setData({
|
||||||
currentDance: danceList[0]
|
currentDance: danceList[0]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 3. 其他可选生命周期(如需扩展,可在此添加,如 onShow、onReady 等)
|
|
||||||
onShow() {
|
onShow() {
|
||||||
// 页面显示时的逻辑(如重新获取数据等,根据需求添加)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 4. 自定义方法(如需添加交互逻辑,可在此定义,如切换舞蹈、跳转等)
|
|
||||||
// 示例:切换到下一个舞蹈
|
|
||||||
switchToNextDance() {
|
switchToNextDance() {
|
||||||
const { danceIndex } = this.data;
|
const { danceIndex } = this.data;
|
||||||
const nextIndex = (danceIndex + 1) % danceList.length; // 循环切换
|
const nextIndex = (danceIndex + 1) % danceList.length;
|
||||||
this.setData({
|
this.setData({
|
||||||
danceIndex: nextIndex,
|
danceIndex: nextIndex,
|
||||||
currentDance: danceList[nextIndex]
|
currentDance: danceList[nextIndex]
|
||||||
@ -151,7 +129,6 @@ Page({
|
|||||||
request('wechat/template', 'post', {
|
request('wechat/template', 'post', {
|
||||||
app_id: accountInfo.miniProgram.appId
|
app_id: accountInfo.miniProgram.appId
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
// return
|
|
||||||
wx.requestSubscribeMessage({
|
wx.requestSubscribeMessage({
|
||||||
tmplIds: [res.template_id],
|
tmplIds: [res.template_id],
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
@ -164,6 +141,5 @@ Page({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user