From 9bb0f42a1aae964c282ededa8dbc8fdc77f689ac Mon Sep 17 00:00:00 2001 From: ZhaoYang <565837861@qq.com> Date: Fri, 30 Jan 2026 18:06:43 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9C=A8=E7=BA=BF=E9=97=AE=E7=AD=94=E5=88=97?= =?UTF-8?q?=E8=A1=A8=EF=BC=8C=E8=AF=A6=E6=83=85=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.json | 3 +- pages/home/home.js | 9 +- pages/home/home.wxml | 9 +- pages/home/home.wxss | 12 - pagesB/images/hf.png | Bin 0 -> 3872 bytes pagesB/pages/forumlist/forumlist.js | 346 +++++++++++ pagesB/pages/forumlist/forumlist.json | 3 + pagesB/pages/forumlist/forumlist.wxml | 202 +++++++ pagesB/pages/forumlist/forumlist.wxss | 442 ++++++++++++++ pagesB/pages/onlineAsk/onlineAsk.js | 556 ++++++++++------- pagesB/pages/onlineAsk/onlineAsk.wxml | 252 ++++---- pagesB/pages/onlineAsk/onlineAsk.wxss | 828 ++++++++++++++------------ 12 files changed, 1931 insertions(+), 731 deletions(-) create mode 100644 pagesB/images/hf.png create mode 100644 pagesB/pages/forumlist/forumlist.js create mode 100644 pagesB/pages/forumlist/forumlist.json create mode 100644 pagesB/pages/forumlist/forumlist.wxml create mode 100644 pagesB/pages/forumlist/forumlist.wxss diff --git a/app.json b/app.json index 3f7600a..b7785a1 100644 --- a/app.json +++ b/app.json @@ -30,7 +30,8 @@ "pages/onlineAsk/onlineAsk", "pages/administrativeDivision/administrativeDivision", "pages/wzDetails/wzDetails", - "pages/spDetails/spDetails" + "pages/spDetails/spDetails", + "pages/forumlist/forumlist" ], "independent": true } diff --git a/pages/home/home.js b/pages/home/home.js index 0419896..a94f96a 100644 --- a/pages/home/home.js +++ b/pages/home/home.js @@ -107,7 +107,14 @@ Page({ }) }, - // 用户提问 + //问答列表 + bindwdlist(){ + wx.navigateTo({ + url: '/pagesB/pages/forumlist/forumlist', + }) + }, + + // 问答详情 bindTw() { wx.navigateTo({ url: '/pagesB/pages/onlineAsk/onlineAsk', diff --git a/pages/home/home.wxml b/pages/home/home.wxml index 78e6c5a..db1c59c 100644 --- a/pages/home/home.wxml +++ b/pages/home/home.wxml @@ -106,11 +106,11 @@ - + - + - 用户提问 + 在线问答 看看其他养殖户遇到的问题 @@ -120,10 +120,9 @@ - + - 【羊】 发烧、流鼻涕、越来越瘦是什么原因?应该怎么治疗? diff --git a/pages/home/home.wxss b/pages/home/home.wxss index c98782c..4c9549c 100644 --- a/pages/home/home.wxss +++ b/pages/home/home.wxss @@ -489,17 +489,6 @@ gap: 12rpx; } -.tag-icon { - font-size: 28rpx; - font-weight: bold; - color: #60C0B9; - background: rgba(96, 192, 185, 0.1); - padding: 6rpx 16rpx; - border-radius: 12rpx; - flex-shrink: 0; - line-height: 1.4; -} - .tag-text { font-size: 30rpx; color: #333; @@ -512,7 +501,6 @@ } - /* 用户信息 */ .question-info { display: flex; diff --git a/pagesB/images/hf.png b/pagesB/images/hf.png new file mode 100644 index 0000000000000000000000000000000000000000..02b5a9f839412c7e026e1cf0f4e71b86faaf3ef1 GIT binary patch literal 3872 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 literal 0 HcmV?d00001 diff --git a/pagesB/pages/forumlist/forumlist.js b/pagesB/pages/forumlist/forumlist.js new file mode 100644 index 0000000..2084876 --- /dev/null +++ b/pagesB/pages/forumlist/forumlist.js @@ -0,0 +1,346 @@ +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) { + // 可以在这里处理页面滚动时的效果 + } +}); \ No newline at end of file diff --git a/pagesB/pages/forumlist/forumlist.json b/pagesB/pages/forumlist/forumlist.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/pagesB/pages/forumlist/forumlist.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/pagesB/pages/forumlist/forumlist.wxml b/pagesB/pages/forumlist/forumlist.wxml new file mode 100644 index 0000000..e6b826c --- /dev/null +++ b/pagesB/pages/forumlist/forumlist.wxml @@ -0,0 +1,202 @@ + + + + + 问答论坛 + + + + + + + + + 全部 + + + 待解决 + + + 已解决 + + + 热门 + + + 我的帖子 + + + + + + + + + + + + × + + + + + + + + + + + + 没有找到"{{searchKeyword}}"相关的问题 + + + 暂无帖子,快来发布第一个问题吧! + + + + + + + + + + + + + + {{item.likeCount}} + 点赞 + + + {{item.replyCount}} + 回答 + + + {{item.viewCount}} + 浏览 + + + + + + + + + {{item.title}} + + 已解决 + + + 热门 + + + + + {{item.summary}} + + + + + + + 最后回复: + {{item.lastReply.username}} + · + {{item.lastReply.time}} + + + + + + + + + + + 上拉加载更多 + + + + 加载中... + + + + + + 没有更多了 + + + + + + + + + + + + + 加载中... + + + + + + + + + + \ No newline at end of file diff --git a/pagesB/pages/forumlist/forumlist.wxss b/pagesB/pages/forumlist/forumlist.wxss new file mode 100644 index 0000000..9612025 --- /dev/null +++ b/pagesB/pages/forumlist/forumlist.wxss @@ -0,0 +1,442 @@ +.forum-list-page { + min-height: 100vh; + background-color: #f8f8f8; + position: relative; + } + + /* 顶部栏 */ + .header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 60rpx 30rpx 20rpx; + background-color: #fff; + position: sticky; + top: 0; + z-index: 100; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + } + + .title { + font-size: 40rpx; + font-weight: bold; + color: #333; + } + + .add-btn { + background-color: #07c160; + color: white; + font-size: 28rpx; + padding: 12rpx 30rpx; + line-height: normal; + border-radius: 40rpx; + margin: 0; + } + + /* 筛选栏 */ + .filter-bar { + background-color: #fff; + padding: 20rpx 30rpx; + border-bottom: 1rpx solid #f0f0f0; + position: sticky; + top: 120rpx; + z-index: 99; + } + + .filter-scroll { + white-space: nowrap; + height: 60rpx; + } + + .filter-list { + display: inline-flex; + gap: 30rpx; + } + + .filter-item { + padding: 0 20rpx; + height: 60rpx; + line-height: 60rpx; + font-size: 28rpx; + color: #666; + border-radius: 30rpx; + transition: all 0.3s; + } + + .filter-item.active { + background-color: rgba(7, 193, 96, 0.1); + color: #07c160; + font-weight: 500; + } + + /* 搜索框 */ + .search-container { + padding: 20rpx 30rpx; + background-color: #fff; + position: sticky; + top: 200rpx; + z-index: 98; + } + + .search-input-wrapper { + display: flex; + align-items: center; + background-color: #f8f8f8; + border-radius: 40rpx; + padding: 0 30rpx; + height: 80rpx; + } + + .search-icon { + width: 36rpx; + height: 36rpx; + margin-right: 20rpx; + opacity: 0.5; + } + + .search-input { + flex: 1; + font-size: 28rpx; + height: 80rpx; + line-height: 80rpx; + } + + .search-clear { + width: 40rpx; + height: 40rpx; + line-height: 40rpx; + text-align: center; + font-size: 36rpx; + color: #999; + border-radius: 50%; + background-color: #e0e0e0; + } + + /* 帖子列表容器 */ + .post-list-container { + height: calc(100vh - 300rpx); + padding: 20rpx 0; + } + + /* 空状态 */ + .empty-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 120rpx 30rpx; + text-align: center; + } + + .empty-image { + width: 300rpx; + height: 300rpx; + margin-bottom: 40rpx; + opacity: 0.6; + } + + .empty-text { + font-size: 30rpx; + color: #999; + margin-bottom: 40rpx; + } + + .empty-btn { + background-color: #07c160; + color: white; + font-size: 28rpx; + padding: 20rpx 50rpx; + line-height: normal; + border-radius: 40rpx; + margin: 0; + } + + /* 帖子列表 */ + .post-list { + padding: 0 30rpx; + } + + .post-item { + display: flex; + background-color: white; + border-radius: 16rpx; + padding: 30rpx; + margin-bottom: 20rpx; + box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); + transition: transform 0.3s, box-shadow 0.3s; + } + + .post-item:active { + transform: translateY(-2rpx); + box-shadow: 0 6rpx 30rpx rgba(0, 0, 0, 0.1); + } + + /* 左侧状态栏 */ + .post-status-side { + display: flex; + flex-direction: column; + align-items: center; + margin-right: 30rpx; + min-width: 120rpx; + } + + .vote-count, + .reply-count, + .view-count { + display: flex; + flex-direction: column; + align-items: center; + margin-bottom: 20rpx; + } + + .vote-count .vote-number, + .reply-count .reply-number, + .view-count .view-number { + font-size: 28rpx; + font-weight: bold; + color: #333; + margin-bottom: 4rpx; + } + + .vote-count .vote-label, + .reply-count .reply-label, + .view-count .view-label { + font-size: 22rpx; + color: #999; + } + + /* 右侧内容区 */ + .post-content-main { + flex: 1; + min-width: 0; + } + + /* 帖子标题和状态 */ + .post-header { + display: flex; + align-items: center; + margin-bottom: 16rpx; + flex-wrap: wrap; + gap: 12rpx; + } + + .post-title { + font-size: 32rpx; + font-weight: bold; + color: #333; + line-height: 1.4; + flex: 1; + min-width: 0; + word-break: break-all; + } + + .status-badge { + flex-shrink: 0; + } + + .solved-badge { + background-color: #07c160; + color: white; + font-size: 22rpx; + padding: 4rpx 12rpx; + border-radius: 20rpx; + } + + .hot-badge { + background-color: #ff6b6b; + color: white; + font-size: 22rpx; + padding: 4rpx 12rpx; + border-radius: 20rpx; + } + + /* 帖子内容摘要 */ + .post-summary { + font-size: 28rpx; + color: #666; + line-height: 1.5; + margin-bottom: 20rpx; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + text-overflow: ellipsis; + } + + /* 帖子元信息 */ + .post-meta { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 15rpx; + flex-wrap: wrap; + gap: 15rpx; + } + + .user-info { + display: flex; + align-items: center; + font-size: 24rpx; + color: #999; + } + + .user-avatar { + width: 40rpx; + height: 40rpx; + border-radius: 50%; + margin-right: 10rpx; + } + + .username { + margin-right: 8rpx; + } + + .separator { + margin: 0 8rpx; + } + + .post-time { + color: #999; + } + + /* 标签 */ + .post-tags { + display: flex; + align-items: center; + gap: 10rpx; + } + + .tag { + font-size: 22rpx; + color: #07c160; + background-color: rgba(7, 193, 96, 0.1); + padding: 4rpx 12rpx; + border-radius: 20rpx; + flex-shrink: 0; + } + + .more-tags { + font-size: 22rpx; + color: #999; + margin-left: 4rpx; + } + + /* 最后回复信息 */ + .last-reply { + font-size: 24rpx; + color: #999; + padding-top: 15rpx; + border-top: 1rpx solid #f0f0f0; + } + + .last-reply-label { + color: #666; + } + + .last-reply-user { + color: #07c160; + margin: 0 5rpx; + } + + /* 加载更多 */ + .load-more { + padding: 40rpx 0; + text-align: center; + color: #999; + font-size: 28rpx; + } + + .loading-text { + color: #999; + } + + .loading-more { + display: flex; + flex-direction: column; + align-items: center; + color: #999; + } + + .loading-more .loading-icon { + width: 50rpx; + height: 50rpx; + margin-bottom: 10rpx; + } + + /* 没有更多了 */ + .no-more { + padding: 40rpx 0; + text-align: center; + color: #999; + font-size: 26rpx; + } + + /* 底部占位 */ + .bottom-placeholder { + height: 100rpx; + } + + /* 加载提示 */ + .loading { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 100rpx 0; + color: #999; + font-size: 28rpx; + } + + .loading-icon { + width: 60rpx; + height: 60rpx; + margin-bottom: 20rpx; + animation: rotate 1s linear infinite; + } + + @keyframes rotate { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } + } + + /* 浮动按钮 */ + .fab-container { + position: fixed; + bottom: 60rpx; + right: 40rpx; + z-index: 1000; + } + + .fab { + width: 100rpx; + height: 100rpx; + background-color: #07c160; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 8rpx 30rpx rgba(7, 193, 96, 0.3); + transition: transform 0.3s, box-shadow 0.3s; + } + + .fab:active { + transform: scale(0.95); + box-shadow: 0 4rpx 20rpx rgba(7, 193, 96, 0.2); + } + + .fab-icon { + width: 44rpx; + height: 44rpx; + } + + /* 移除按钮边框 */ + button::after { + border: none; + } + + /* 滚动条样式 */ + ::-webkit-scrollbar { + width: 0; + height: 0; + color: transparent; + } \ No newline at end of file diff --git a/pagesB/pages/onlineAsk/onlineAsk.js b/pagesB/pages/onlineAsk/onlineAsk.js index 9551624..7e6306b 100644 --- a/pagesB/pages/onlineAsk/onlineAsk.js +++ b/pagesB/pages/onlineAsk/onlineAsk.js @@ -1,305 +1,407 @@ -// pages/forum/forum.js Page({ data: { - // 帖子列表数据 - posts: [], - // 是否显示发帖弹窗 - showPostModal: false, - // 发帖标题 - postTitle: '', - // 发帖内容 - postContent: '', - // 标签输入 - tagInput: '', - // 已选标签 - selectedTags: [], - // 当前回复的帖子索引 - activeReplyIndex: -1, - // 回复内容 + post: null, replyContent: '', - // 加载状态 + replyTarget: { + type: '', + username: '', + replyId: '', + replyIndex: null, + commentId: '', + commentIndex: null + }, + replyPlaceholder: '输入您的回复...', + isInputFocused: false, + inputTransformY: '0', + isSubmitting: false, + showPreview: false, + previewImages: [], + previewIndex: 0, loading: false, + scrollToId: '', + currentUser: '当前用户', + keyboardHeight: 0 }, - onLoad: function() { - // 页面加载时获取帖子数据 - this.loadPosts(); - }, - - onPullDownRefresh: function() { - // 下拉刷新 - this.loadPosts(); - wx.stopPullDownRefresh(); + onLoad: function(options) { + const postId = options.id || '1'; + this.loadPostDetail(postId); + + // 监听键盘高度变化 + wx.onKeyboardHeightChange(res => { + if (res.height > 0) { + this.setData({ keyboardHeight: res.height }); + } + }); }, - // 加载帖子数据 - loadPosts: function() { + // 加载帖子详情 + loadPostDetail: function(postId) { this.setData({ loading: true }); - // 模拟网络请求 + // 模拟API请求 setTimeout(() => { - // 模拟数据 - const mockPosts = [ - { - id: 1, - username: '技术爱好者', - avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', - time: '2小时前', - title: '微信小程序如何实现图片上传和预览功能?', - content: '我正在开发一个微信小程序,需要实现图片上传功能,并且能够在上传前预览图片。请问有什么好的实现方案吗?上传的图片大小限制和格式有什么建议?', - tags: ['微信小程序', '图片上传', '前端开发'], - likeCount: 12, - replyCount: 5, - viewCount: 156, - liked: false, - solved: false, - showAllReplies: false, - replies: [ - { - username: '前端开发工程师', - avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', - time: '1小时前', - content: '可以使用wx.chooseImage选择图片,然后使用wx.uploadFile上传到服务器。预览功能可以使用wx.previewImage实现。' - }, - { - username: '小程序开发者', - avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', - time: '45分钟前', - content: '建议将图片大小限制在2MB以内,支持JPG、PNG格式。可以使用云开发存储功能简化上传流程。' - } - ] - }, - { - id: 2, - username: '产品经理小王', - avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', - time: '昨天 14:30', - title: '如何设计一个用户友好的注册流程?', - content: '我们正在设计一个新产品的注册流程,希望既保证安全性又尽量简化步骤。大家有什么好的设计建议或参考案例吗?', - tags: ['产品设计', '用户体验', '注册流程'], - likeCount: 8, - replyCount: 3, - viewCount: 89, - liked: true, - solved: true, - showAllReplies: false, - replies: [ - { - username: 'UX设计师', - avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', - time: '昨天 16:45', - content: '建议采用手机号验证码注册,配合第三方登录选项。关键是将必填信息减到最少,其他信息可以后续引导补充。' - } - ] - }, - { - id: 3, - username: '后端开发', - avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', - time: '3天前', - title: 'RESTful API设计的最佳实践有哪些?', - content: '我正在设计一组RESTful API,想了解一些最佳实践,比如URL命名规范、状态码使用、版本控制等方面有什么推荐的做法?', - tags: ['后端开发', 'API设计', 'RESTful'], - likeCount: 15, - replyCount: 7, - viewCount: 234, - liked: false, - solved: false, - showAllReplies: false, - replies: [ - { - username: '架构师', - avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', - time: '2天前', - content: '建议使用名词复数形式作为资源端点,合理使用HTTP状态码,API版本可以通过URL路径或请求头来管理。' - }, - { - username: '全栈工程师', - avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', - time: '1天前', - content: '不要忘记实现合适的错误处理机制,返回清晰的错误信息。同时考虑API限流和身份验证机制。' - }, - { - username: '资深开发者', - avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', - time: '1天前', - content: '推荐使用Swagger或OpenAPI规范来文档化你的API,这对前后端协作非常有帮助。' - } - ] - } - ]; + const mockPost = { + id: 1, + username: '技术爱好者', + avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', + time: '2小时前', + title: '微信小程序如何实现图片上传和预览功能?', + content: '我正在开发一个微信小程序,需要实现图片上传功能,并且能够在上传前预览图片。请问有什么好的实现方案吗?上传的图片大小限制和格式有什么建议?', + images: [ + 'https://img.yzcdn.cn/vant/cat.jpeg', + 'https://img.yzcdn.cn/vant/cat.jpeg' + ], + tags: ['微信小程序', '图片上传', '前端开发'], + likeCount: 12, + replyCount: 5, + viewCount: 156, + liked: false, + solved: false, + replies: [ + { + replyId: 'r1_1', + username: '前端开发工程师', + avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', + time: '1小时前', + content: '可以使用wx.chooseImage选择图片,然后使用wx.uploadFile上传到服务器。预览功能可以使用wx.previewImage实现。', + likeCount: 3, + liked: false, + comments: [ + { + commentId: 'c1_1', + username: '学习者', + avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', + toUsername: '前端开发工程师', + time: '30分钟前', + content: '感谢分享,请问有具体的代码示例吗?' + } + ] + }, + { + replyId: 'r1_2', + username: '小程序开发者', + avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', + time: '45分钟前', + content: '建议将图片大小限制在2MB以内,支持JPG、PNG格式。可以使用云开发存储功能简化上传流程。', + likeCount: 2, + liked: true, + comments: [] + } + ] + }; this.setData({ - posts: mockPosts, + post: mockPost, loading: false }); - }, 800); + }, 500); }, - // 显示发帖弹窗 - showPostModal: function() { + + + + + // 滚动监听 + onScroll: function(e) { + // 可以在这里实现滚动相关逻辑 + }, + + // 输入框获取焦点 + onInputFocus: function(e) { this.setData({ - showPostModal: true + isInputFocused: true, + inputTransformY: `-${e.detail.height}px` }); }, - // 隐藏发帖弹窗 - hidePostModal: function() { + // 输入框失去焦点 + onInputBlur: function() { this.setData({ - showPostModal: false, - postTitle: '', - postContent: '', - selectedTags: [], - tagInput: '' + isInputFocused: false, + inputTransformY: '0' }); }, - // 防止弹窗内点击事件冒泡 - preventTap: function() { - // 阻止事件冒泡 + // 回复输入 + onReplyInput: function(e) { + this.setData({ + replyContent: e.detail.value + }); }, - // 发帖标题输入 - onPostTitleInput: function(e) { + // 聚焦到输入框 + focusReplyInput: function() { this.setData({ - postTitle: e.detail.value + replyTarget: { + type: 'post', + username: this.data.post.username + }, + replyPlaceholder: `回复 ${this.data.post.username}...`, + replyContent: '', + isInputFocused: true }); }, - // 发帖内容输入 - onPostContentInput: function(e) { + // 回复用户 + replyToUser: function(e) { + const { type, index, replyIndex, commentIndex, username } = e.currentTarget.dataset; + + const replyTarget = { + type: type, + username: username + }; + + if (type === 'reply') { + replyTarget.replyIndex = parseInt(index); + replyTarget.replyId = this.data.post.replies[index].replyId; + } else if (type === 'comment') { + replyTarget.replyIndex = parseInt(replyIndex); + replyTarget.commentIndex = parseInt(commentIndex); + replyTarget.commentId = this.data.post.replies[replyIndex].comments[commentIndex].commentId; + replyTarget.replyId = this.data.post.replies[replyIndex].replyId; + } + this.setData({ - postContent: e.detail.value + replyTarget: replyTarget, + replyPlaceholder: `回复 @${username}...`, + replyContent: '', + isInputFocused: true }); + + // 滚动到输入框位置 + setTimeout(() => { + this.setData({ + scrollToId: type === 'reply' ? `reply-${replyTarget.replyId}` : '' + }); + }, 100); }, + // 清除回复目标 + clearReplyTarget: function() { + this.setData({ + replyTarget: { + type: '', + username: '', + replyId: '', + replyIndex: null, + commentId: '', + commentIndex: null + }, + replyPlaceholder: '输入您的回复...', + replyContent: '' + }); + }, - - - // 提交帖子 - submitPost: function() { - const { postTitle, postContent, selectedTags } = this.data; + // 提交回复 + submitReply: function() { + const { replyContent, replyTarget, post } = this.data; + const content = replyContent.trim(); - if (!postTitle.trim()) { - wx.showToast({ - title: '请输入标题', - icon: 'none' - }); + if (!content) { + wx.showToast({ title: '请输入内容', icon: 'none' }); return; } - if (!postContent.trim()) { - wx.showToast({ - title: '请输入内容', - icon: 'none' - }); + if (content.length > 500) { + wx.showToast({ title: '回复内容不能超过500字', icon: 'none' }); return; } - // 创建新帖子 - const newPost = { - id: Date.now(), - username: '当前用户', + this.setData({ isSubmitting: true }); + + // 模拟网络请求 + setTimeout(() => { + if (replyTarget.type === 'post') { + // 回复帖子 + this.replyToPost(content); + } else if (replyTarget.type === 'reply') { + // 回复评论 + this.replyToComment(content, replyTarget); + } else if (replyTarget.type === 'comment') { + // 回复评论的回复 + this.replyToCommentReply(content, replyTarget); + } else { + // 普通回复(直接回复帖子) + this.replyToPost(content); + } + + this.setData({ isSubmitting: false }); + }, 500); + }, + + // 回复帖子 + replyToPost: function(content) { + const post = this.data.post; + const replyId = `r${post.id}_${Date.now()}`; + + const newReply = { + replyId: replyId, + username: this.data.currentUser, avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', time: '刚刚', - title: postTitle, - content: postContent, - tags: selectedTags, + content: content, likeCount: 0, - replyCount: 0, - viewCount: 0, liked: false, - solved: false, - showAllReplies: false, - replies: [] + comments: [] }; - // 添加到帖子列表顶部 - const posts = this.data.posts; - posts.unshift(newPost); + post.replies.push(newReply); + post.replyCount += 1; this.setData({ - posts: posts, - showPostModal: false, - postTitle: '', - postContent: '', - selectedTags: [], - tagInput: '' + post: post, + replyContent: '', + replyTarget: { + type: '', + username: '', + replyId: '', + replyIndex: null, + commentId: '', + commentIndex: null + }, + replyPlaceholder: '输入您的回复...', + isInputFocused: false }); - wx.showToast({ - title: '发布成功', - icon: 'success' + wx.showToast({ + title: '回复成功', + icon: 'success', + duration: 1500 }); + + // 滚动到最新回复 + setTimeout(() => { + this.setData({ + scrollToId: `reply-${replyId}` + }); + }, 800); }, - - - // 显示回复输入框 - showReplyInput: function(e) { - const index = e.currentTarget.dataset.index; + // 回复评论 + replyToComment: function(content, target) { + const post = this.data.post; + const replyIndex = target.replyIndex; + const reply = post.replies[replyIndex]; + const commentId = `c${reply.replyId}_${Date.now()}`; + + const newComment = { + commentId: commentId, + username: this.data.currentUser, + avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', + toUsername: target.username, + time: '刚刚', + content: content + }; + + if (!reply.comments) { + reply.comments = []; + } + reply.comments.push(newComment); + this.setData({ - activeReplyIndex: index, - replyContent: '' + post: post, + replyContent: '', + replyTarget: { + type: '', + username: '', + replyId: '', + replyIndex: null, + commentId: '', + commentIndex: null + }, + replyPlaceholder: '输入您的回复...', + isInputFocused: false }); - }, - - // 回复内容输入 - onReplyInput: function(e) { - this.setData({ - replyContent: e.detail.value + + wx.showToast({ + title: '回复成功', + icon: 'success', + duration: 1500 }); }, - // 提交回复 - submitReply: function(e) { - const index = e.currentTarget.dataset.index; - const replyContent = this.data.replyContent.trim(); - - if (!replyContent) { - wx.showToast({ - title: '请输入回复内容', - icon: 'none' - }); - return; - } - - const posts = this.data.posts; - const post = posts[index]; + // 回复评论的回复 + replyToCommentReply: function(content, target) { + const post = this.data.post; + const reply = post.replies[target.replyIndex]; + const originalComment = reply.comments[target.commentIndex]; + const commentId = `cc${originalComment.commentId}_${Date.now()}`; - // 创建新回复 - const newReply = { - username: '当前用户', + const newComment = { + commentId: commentId, + username: this.data.currentUser, avatar: 'https://img.yzcdn.cn/vant/cat.jpeg', + toUsername: target.username, time: '刚刚', - content: replyContent + content: content }; - post.replies.push(newReply); - post.replyCount += 1; + reply.comments.push(newComment); this.setData({ - posts: posts, - activeReplyIndex: -1, - replyContent: '' + post: post, + replyContent: '', + replyTarget: { + type: '', + username: '', + replyId: '', + replyIndex: null, + commentId: '', + commentIndex: null + }, + replyPlaceholder: '输入您的回复...', + isInputFocused: false }); - wx.showToast({ - title: '回复成功', - icon: 'success' + wx.showToast({ + title: '回复成功', + icon: 'success', + duration: 1500 }); }, - // 切换显示全部回复 - toggleReplies: function(e) { - const index = e.currentTarget.dataset.index; - const posts = this.data.posts; - const post = posts[index]; - - post.showAllReplies = !post.showAllReplies; + // 图片预览 + previewImage: function(e) { + const imgIndex = e.currentTarget.dataset.imgIndex; + const images = this.data.post.images; this.setData({ - posts: posts + showPreview: true, + previewImages: images, + previewIndex: imgIndex + }); + }, + + // 图片预览滑动 + onSwiperChange: function(e) { + this.setData({ + previewIndex: e.detail.current }); + }, + + // 隐藏预览 + hidePreview: function() { + this.setData({ showPreview: false }); + }, + + // 下拉刷新 + onPullDownRefresh: function() { + if (this.data.post) { + this.loadPostDetail(this.data.post.id); + } + wx.stopPullDownRefresh(); + }, + + // 页面上拉触底 + onReachBottom: function() { + // 这里可以实现加载更多回复的逻辑 + console.log('加载更多回复'); + }, + + // 页面卸载 + onUnload: function() { + // 移除键盘高度监听 + wx.offKeyboardHeightChange(); } }); \ No newline at end of file diff --git a/pagesB/pages/onlineAsk/onlineAsk.wxml b/pagesB/pages/onlineAsk/onlineAsk.wxml index 92ba451..3d4ff50 100644 --- a/pagesB/pages/onlineAsk/onlineAsk.wxml +++ b/pagesB/pages/onlineAsk/onlineAsk.wxml @@ -1,125 +1,167 @@ - - - - 问答论坛 - - - - - - - - - - - - - - - - 暂无帖子,快来发布第一个问题吧! - - - - - - - 发布新问题 - - - + + + + + + + 全部回复 + {{post.replyCount}}条 - -