与牧同行-小程序用户端
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.
 

346 lines
10 KiB

Page({
data: {
posts: [],
loading: false,
loadingMore: false,
refreshing: false,
hasMore: true,
page: 1,
pageSize: 10,
currentFilter: 'all',
searchKeyword: '',
currentUser: '当前用户'
},
onLoad: function() {
this.loadPosts();
// 监听页面显示,用于刷新数据
wx.onAppShow(() => {
this.refreshData();
});
},
onShow: function() {
this.refreshData();
},
// 加载帖子列表
loadPosts: function(reset = false) {
if (reset) {
this.setData({
page: 1,
hasMore: true,
posts: [],
loading: true
});
} else if (this.data.loadingMore) {
return;
}
const params = {
page: this.data.page,
pageSize: this.data.pageSize,
filter: this.data.currentFilter,
search: this.data.searchKeyword
};
this.setData({
loading: reset || this.data.page === 1,
loadingMore: !reset && this.data.page > 1
});
// 模拟API请求
setTimeout(() => {
const mockPosts = this.generateMockPosts(params);
if (reset) {
this.setData({
posts: mockPosts,
loading: false,
hasMore: mockPosts.length === params.pageSize
});
} else {
this.setData({
posts: [...this.data.posts, ...mockPosts],
loading: false,
loadingMore: false,
hasMore: mockPosts.length === params.pageSize
});
}
if (this.data.refreshing) {
wx.stopPullDownRefresh();
this.setData({ refreshing: false });
}
}, 800);
},
// 生成模拟数据
generateMockPosts: function(params) {
const posts = [];
const currentUser = this.data.currentUser;
const baseId = (params.page - 1) * params.pageSize;
for (let i = 0; i < params.pageSize; i++) {
const id = baseId + i + 1;
const solved = i % 4 === 0;
const hot = i % 3 === 0 && i % 2 === 0;
const isMine = i % 5 === 0;
// 根据筛选条件过滤
if (params.filter === 'solved' && !solved) continue;
if (params.filter === 'unsolved' && solved) continue;
if (params.filter === 'mine' && !isMine) continue;
const tags = this.getRandomTags();
const post = {
id: id,
title: this.getRandomTitle(id),
summary: this.getRandomSummary(id),
username: isMine ? currentUser : this.getRandomUsername(),
avatar: 'https://img.yzcdn.cn/vant/cat.jpeg',
time: this.getRandomTime(),
likeCount: Math.floor(Math.random() * 50),
replyCount: Math.floor(Math.random() * 30),
viewCount: Math.floor(Math.random() * 300),
solved: solved,
hot: hot,
tags: tags,
lastReply: Math.random() > 0.3 ? {
username: this.getRandomUsername(),
time: this.getRandomTime('short')
} : null
};
// 搜索过滤
if (params.search) {
const keyword = params.search.toLowerCase();
const titleMatch = post.title.toLowerCase().includes(keyword);
const summaryMatch = post.summary.toLowerCase().includes(keyword);
const tagMatch = post.tags.some(tag => tag.toLowerCase().includes(keyword));
if (!titleMatch && !summaryMatch && !tagMatch) {
continue;
}
}
posts.push(post);
}
// 热门排序
if (params.filter === 'hot') {
posts.sort((a, b) => {
const aScore = a.likeCount * 2 + a.replyCount * 3 + a.viewCount;
const bScore = b.likeCount * 2 + b.replyCount * 3 + b.viewCount;
return bScore - aScore;
});
}
return posts;
},
// 随机生成标题
getRandomTitle: function(id) {
const titles = [
'微信小程序如何实现图片上传和预览功能?',
'uni-app开发中如何处理不同平台的兼容性问题?',
'JavaScript闭包的使用场景有哪些?',
'Vue3组合式API和选项式API该如何选择?',
'React Hooks在项目中的最佳实践',
'Node.js高并发场景下的性能优化方案',
'TypeScript在大型项目中的类型设计经验分享',
'微信小程序云开发数据库查询性能优化',
'前端工程化建设:从零搭建Webpack配置',
'移动端H5页面适配的最佳方案是什么?',
'如何优雅地处理前端错误监控和上报?',
'微前端架构在实际项目中的应用经验',
'Webpack5 Module Federation实战分享',
'前端代码质量保证:ESLint + Prettier + Husky',
'跨端开发框架选型:Flutter vs React Native vs uni-app'
];
return titles[id % titles.length] || titles[0];
},
// 随机生成摘要
getRandomSummary: function(id) {
const summaries = [
'我正在开发一个微信小程序,需要实现图片上传功能,并且能够在上传前预览图片。请问有什么好的实现方案吗?上传的图片大小限制和格式有什么建议?',
'最近在做一个uni-app项目,需要同时兼容微信小程序和H5,遇到了一些样式和API兼容性问题,大家有什么好的解决方案吗?',
'在实际项目中经常使用闭包,但对其原理和应用场景理解还不够深入,想请教一下大家在项目中都是如何使用闭包的?',
'公司新项目准备使用Vue3,对于组合式API和选项式API的选择有些纠结,大家有什么建议吗?各自的使用场景是什么?',
'React Hooks确实很方便,但在大型项目中如何合理组织Hooks,避免过度使用导致代码难以维护?',
'我们的Node.js服务在高并发场景下性能表现不佳,有哪些常见的性能优化方案可以参考?',
'项目准备从JavaScript迁移到TypeScript,在类型设计方面有什么经验可以分享吗?如何设计合理的泛型和接口?'
];
return summaries[id % summaries.length] || summaries[0];
},
// 随机生成用户名
getRandomUsername: function() {
const usernames = [
'前端工程师', '技术爱好者', '小程序开发', '全栈程序员',
'架构师老王', '代码艺术家', '算法工程师', '产品经理',
'UI设计师', '测试工程师', '运维小哥', '数据分析师'
];
return usernames[Math.floor(Math.random() * usernames.length)];
},
// 随机生成时间
getRandomTime: function(type = 'normal') {
const times = type === 'short'
? ['5分钟前', '10分钟前', '半小时前', '1小时前']
: ['2小时前', '5小时前', '昨天', '2天前', '3天前', '一周前'];
return times[Math.floor(Math.random() * times.length)];
},
// 随机生成标签
getRandomTags: function() {
const allTags = [
'微信小程序', '前端开发', 'JavaScript', 'Vue.js', 'React',
'Node.js', 'TypeScript', 'uni-app', '性能优化', '工程化',
'移动端', 'H5', 'CSS', 'Webpack', 'Git'
];
const count = Math.floor(Math.random() * 3) + 1;
const tags = [];
const usedIndices = new Set();
for (let i = 0; i < count; i++) {
let index;
do {
index = Math.floor(Math.random() * allTags.length);
} while (usedIndices.has(index));
usedIndices.add(index);
tags.push(allTags[index]);
}
return tags;
},
// 下拉刷新
onRefresh: function() {
this.setData({ refreshing: true });
this.loadPosts(true);
},
// 滚动到底部加载更多
loadMore: function() {
if (!this.data.hasMore || this.data.loadingMore) return;
this.setData({
page: this.data.page + 1
}, () => {
this.loadPosts();
});
},
// 筛选切换
changeFilter: function(e) {
const filterType = e.currentTarget.dataset.type;
if (this.data.currentFilter === filterType) return;
this.setData({
currentFilter: filterType,
searchKeyword: '' // 切换筛选时清空搜索
}, () => {
this.loadPosts(true);
});
},
// 搜索输入
onSearchInput: function(e) {
this.setData({ searchKeyword: e.detail.value });
// 防抖搜索
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
if (e.detail.value.trim()) {
this.loadPosts(true);
}
}, 300);
},
// 搜索确认
onSearchConfirm: function(e) {
const keyword = e.detail.value.trim();
if (keyword) {
this.setData({ searchKeyword: keyword });
this.loadPosts(true);
}
},
// 清空搜索
clearSearch: function() {
this.setData({
searchKeyword: '',
currentFilter: 'all'
}, () => {
this.loadPosts(true);
});
},
// 跳转到详情页
goToDetail: function(e) {
const postId = e.currentTarget.dataset.id;
wx.navigateTo({
url: `/pages/forum/detail/detail?id=${postId}`,
success: () => {
// 记录浏览历史
this.recordViewHistory(postId);
}
});
},
// 创建新帖子
createPost: function() {
wx.navigateTo({
url: '/pages/forum/create/create'
});
},
// 记录浏览历史
recordViewHistory: function(postId) {
try {
const history = wx.getStorageSync('forumViewHistory') || [];
const index = history.findIndex(item => item.id === postId);
if (index !== -1) {
history.splice(index, 1);
}
history.unshift({
id: postId,
timestamp: Date.now()
});
// 只保留最近50条记录
if (history.length > 50) {
history.pop();
}
wx.setStorageSync('forumViewHistory', history);
} catch (error) {
console.error('记录浏览历史失败:', error);
}
},
// 刷新数据
refreshData: function() {
// 这里可以检查是否有新数据需要刷新
// 例如:从详情页返回时刷新点赞状态等
},
onPullDownRefresh: function() {
this.onRefresh();
},
onReachBottom: function() {
this.loadMore();
},
onPageScroll: function(e) {
// 可以在这里处理页面滚动时的效果
}
});