13 changed files with 1229 additions and 6 deletions
@ -0,0 +1,174 @@ |
|||||
|
const API = require('../../utils/api.js'); |
||||
|
|
||||
|
Page({ |
||||
|
data: { |
||||
|
content: '', |
||||
|
images: [], |
||||
|
selectedTopic: null, |
||||
|
showTopicModal: false, |
||||
|
hotTopics: [] |
||||
|
}, |
||||
|
|
||||
|
onLoad() { |
||||
|
this.loadHotTopics(); |
||||
|
}, |
||||
|
|
||||
|
loadHotTopics() { |
||||
|
API.getHotTopics().then(res => { |
||||
|
this.setData({ |
||||
|
hotTopics: res.data || [] |
||||
|
}); |
||||
|
}).catch(err => { |
||||
|
console.error('加载热门话题失败:', err); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
onContentChange(e) { |
||||
|
this.setData({ |
||||
|
content: e.detail.value |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
chooseImage() { |
||||
|
if (this.data.images.length >= 9) { |
||||
|
wx.showToast({ |
||||
|
title: '最多只能上传9张图片', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
wx.chooseImage({ |
||||
|
count: 9 - this.data.images.length, |
||||
|
sizeType: ['compressed'], |
||||
|
sourceType: ['album', 'camera'], |
||||
|
success: (res) => { |
||||
|
this.setData({ |
||||
|
images: [...this.data.images, ...res.tempFilePaths] |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
deleteImage(e) { |
||||
|
const index = e.currentTarget.dataset.index; |
||||
|
const images = this.data.images.filter((_, i) => i !== index); |
||||
|
this.setData({ |
||||
|
images |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
showTopicPicker() { |
||||
|
this.setData({ |
||||
|
showTopicModal: true |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
hideTopicPicker() { |
||||
|
this.setData({ |
||||
|
showTopicModal: false |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
selectTopic(e) { |
||||
|
const topic = e.currentTarget.dataset.topic; |
||||
|
this.setData({ |
||||
|
selectedTopic: topic, |
||||
|
showTopicModal: false |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
stopPropagation() { |
||||
|
// 阻止事件冒泡
|
||||
|
}, |
||||
|
|
||||
|
cancel() { |
||||
|
wx.navigateBack(); |
||||
|
}, |
||||
|
|
||||
|
submit() { |
||||
|
if (!this.data.content.trim()) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
wx.showLoading({ |
||||
|
title: '发布中...' |
||||
|
}); |
||||
|
|
||||
|
// 先上传图片,获取永久 URL
|
||||
|
this.uploadImages(this.data.images) |
||||
|
.then(uploadedImages => { |
||||
|
const postData = { |
||||
|
content: this.data.content, |
||||
|
images: uploadedImages, |
||||
|
topic: this.data.selectedTopic |
||||
|
}; |
||||
|
|
||||
|
return API.createPost(postData); |
||||
|
}) |
||||
|
.then(res => { |
||||
|
wx.hideLoading(); |
||||
|
wx.showToast({ |
||||
|
title: '发布成功', |
||||
|
icon: 'success' |
||||
|
}); |
||||
|
setTimeout(() => { |
||||
|
wx.navigateBack(); |
||||
|
}, 1000); |
||||
|
}) |
||||
|
.catch(err => { |
||||
|
wx.hideLoading(); |
||||
|
wx.showToast({ |
||||
|
title: '发布失败,请重试', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
console.error('发布动态失败:', err); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 上传图片获取永久 URL
|
||||
|
uploadImages(tempImagePaths) { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
if (!tempImagePaths || tempImagePaths.length === 0) { |
||||
|
resolve([]); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
const uploadedImages = []; |
||||
|
let uploadedCount = 0; |
||||
|
|
||||
|
tempImagePaths.forEach((tempPath, index) => { |
||||
|
wx.uploadFile({ |
||||
|
url: API.BASE_URL + '/api/eggbar/upload', |
||||
|
filePath: tempPath, |
||||
|
name: 'image', |
||||
|
formData: { |
||||
|
index: index, |
||||
|
total: tempImagePaths.length |
||||
|
}, |
||||
|
success: (res) => { |
||||
|
if (res.statusCode === 200) { |
||||
|
try { |
||||
|
const data = JSON.parse(res.data); |
||||
|
if (data.success && data.imageUrl) { |
||||
|
uploadedImages.push(data.imageUrl); |
||||
|
} |
||||
|
} catch (e) { |
||||
|
console.error('解析上传响应失败:', e); |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
fail: (err) => { |
||||
|
console.error('上传图片失败:', err); |
||||
|
}, |
||||
|
complete: () => { |
||||
|
uploadedCount++; |
||||
|
if (uploadedCount === tempImagePaths.length) { |
||||
|
resolve(uploadedImages); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
@ -0,0 +1,9 @@ |
|||||
|
{ |
||||
|
"usingComponents": {}, |
||||
|
"enablePullDownRefresh": false, |
||||
|
"backgroundTextStyle": "dark", |
||||
|
"backgroundColor": "#f8f8f8", |
||||
|
"navigationBarBackgroundColor": "#ffffff", |
||||
|
"navigationBarTitleText": "发布动态", |
||||
|
"navigationBarTextStyle": "black" |
||||
|
} |
||||
@ -0,0 +1,68 @@ |
|||||
|
<view> |
||||
|
<view class="header"> |
||||
|
<text class="title">发布动态</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="form"> |
||||
|
<view class="form-item"> |
||||
|
<textarea |
||||
|
class="textarea" |
||||
|
placeholder="分享你的想法..." |
||||
|
placeholder-class="placeholder" |
||||
|
value="{{content}}" |
||||
|
bindinput="onContentChange" |
||||
|
maxlength="500" |
||||
|
></textarea> |
||||
|
<text class="counter">{{content.length}}/500</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="form-item"> |
||||
|
<view class="label">添加图片</view> |
||||
|
<view class="image-uploader"> |
||||
|
<view class="upload-area" bindtap="chooseImage"> |
||||
|
<text class="upload-icon">+</text> |
||||
|
<text class="upload-text">选择图片</text> |
||||
|
</view> |
||||
|
<view class="image-list"> |
||||
|
<view class="image-item" wx:for="{{images}}" wx:key="index"> |
||||
|
<image class="image" src="{{item}}" mode="aspectFill"></image> |
||||
|
<view class="image-delete" bindtap="deleteImage" data-index="{{index}}"> |
||||
|
<text>×</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="form-item"> |
||||
|
<view class="label">选择话题</view> |
||||
|
<view class="topic-picker" bindtap="showTopicPicker"> |
||||
|
<text class="topic-text">{{selectedTopic ? '#' + selectedTopic : '选择话题'}}</text> |
||||
|
<text class="topic-arrow">▼</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="footer"> |
||||
|
<button class="cancel-btn" bindtap="cancel">取消</button> |
||||
|
<button class="submit-btn" bindtap="submit" disabled="{{!content.trim()}}"> |
||||
|
发布 |
||||
|
</button> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 话题选择器弹窗 --> |
||||
|
<view wx:if="{{showTopicModal}}" class="modal-overlay" bindtap="hideTopicPicker"> |
||||
|
<view class="modal-container" catchtap="stopPropagation"> |
||||
|
<view class="modal-header"> |
||||
|
<text class="modal-title">选择话题</text> |
||||
|
<text class="modal-close" bindtap="hideTopicPicker">×</text> |
||||
|
</view> |
||||
|
<view class="modal-content"> |
||||
|
<view class="topic-item" wx:for="{{hotTopics}}" wx:key="id" bindtap="selectTopic" data-topic="{{item.name}}"> |
||||
|
<text class="topic-name">#{{item.name}}</text> |
||||
|
<text class="topic-count">{{item.count}}人讨论</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
@ -0,0 +1,281 @@ |
|||||
|
page { |
||||
|
background-color: #f5f5f5; |
||||
|
height: 100vh; |
||||
|
} |
||||
|
|
||||
|
.container { |
||||
|
min-height: 100vh; |
||||
|
padding: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.header { |
||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
||||
|
border-radius: 20rpx; |
||||
|
padding: 30rpx; |
||||
|
margin-bottom: 20rpx; |
||||
|
box-shadow: 0 4rpx 20rpx rgba(102, 126, 234, 0.3); |
||||
|
} |
||||
|
|
||||
|
.title { |
||||
|
font-size: 36rpx; |
||||
|
font-weight: bold; |
||||
|
color: #ffffff; |
||||
|
} |
||||
|
|
||||
|
.form { |
||||
|
background: #ffffff; |
||||
|
border-radius: 20rpx; |
||||
|
padding: 30rpx; |
||||
|
margin-bottom: 20rpx; |
||||
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08); |
||||
|
} |
||||
|
|
||||
|
.form-item { |
||||
|
margin-bottom: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.label { |
||||
|
font-size: 28rpx; |
||||
|
font-weight: 600; |
||||
|
color: #333333; |
||||
|
margin-bottom: 15rpx; |
||||
|
} |
||||
|
|
||||
|
.textarea { |
||||
|
width: 100%; |
||||
|
min-height: 200rpx; |
||||
|
font-size: 28rpx; |
||||
|
color: #333333; |
||||
|
border: 2rpx solid #f0f0f0; |
||||
|
border-radius: 12rpx; |
||||
|
padding: 20rpx; |
||||
|
box-sizing: border-box; |
||||
|
resize: none; |
||||
|
line-height: 1.6; |
||||
|
} |
||||
|
|
||||
|
.placeholder { |
||||
|
color: #999999; |
||||
|
} |
||||
|
|
||||
|
.counter { |
||||
|
display: block; |
||||
|
text-align: right; |
||||
|
font-size: 24rpx; |
||||
|
color: #999999; |
||||
|
margin-top: 10rpx; |
||||
|
} |
||||
|
|
||||
|
.image-uploader { |
||||
|
margin-top: 10rpx; |
||||
|
} |
||||
|
|
||||
|
.upload-area { |
||||
|
width: 120rpx; |
||||
|
height: 120rpx; |
||||
|
border: 2rpx dashed #e0e0e0; |
||||
|
border-radius: 12rpx; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
background: #fafafa; |
||||
|
margin-bottom: 15rpx; |
||||
|
transition: all 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
.upload-area:active { |
||||
|
background: #f0f0f0; |
||||
|
transform: scale(0.98); |
||||
|
} |
||||
|
|
||||
|
.upload-icon { |
||||
|
font-size: 48rpx; |
||||
|
color: #999999; |
||||
|
margin-bottom: 10rpx; |
||||
|
} |
||||
|
|
||||
|
.upload-text { |
||||
|
font-size: 24rpx; |
||||
|
color: #999999; |
||||
|
} |
||||
|
|
||||
|
.image-list { |
||||
|
display: flex; |
||||
|
gap: 15rpx; |
||||
|
flex-wrap: wrap; |
||||
|
margin-top: 15rpx; |
||||
|
} |
||||
|
|
||||
|
.image-item { |
||||
|
position: relative; |
||||
|
width: 150rpx; |
||||
|
height: 150rpx; |
||||
|
border-radius: 12rpx; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.image { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
background: #f0f0f0; |
||||
|
} |
||||
|
|
||||
|
.image-delete { |
||||
|
position: absolute; |
||||
|
top: 5rpx; |
||||
|
right: 5rpx; |
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
background: rgba(0, 0, 0, 0.6); |
||||
|
border-radius: 50%; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
color: #ffffff; |
||||
|
font-size: 32rpx; |
||||
|
font-weight: bold; |
||||
|
transition: all 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
.image-delete:active { |
||||
|
background: rgba(0, 0, 0, 0.8); |
||||
|
transform: scale(0.9); |
||||
|
} |
||||
|
|
||||
|
.topic-picker { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
padding: 20rpx; |
||||
|
border: 2rpx solid #f0f0f0; |
||||
|
border-radius: 12rpx; |
||||
|
background: #fafafa; |
||||
|
transition: all 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
.topic-picker:active { |
||||
|
background: #f0f0f0; |
||||
|
} |
||||
|
|
||||
|
.topic-text { |
||||
|
font-size: 28rpx; |
||||
|
color: #333333; |
||||
|
} |
||||
|
|
||||
|
.topic-arrow { |
||||
|
font-size: 20rpx; |
||||
|
color: #999999; |
||||
|
} |
||||
|
|
||||
|
.footer { |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
display: flex; |
||||
|
padding: 20rpx; |
||||
|
background: #ffffff; |
||||
|
border-top: 1rpx solid #f0f0f0; |
||||
|
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05); |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
|
||||
|
.cancel-btn { |
||||
|
flex: 1; |
||||
|
height: 80rpx; |
||||
|
margin-right: 15rpx; |
||||
|
background: #f5f5f5; |
||||
|
color: #333333; |
||||
|
border: none; |
||||
|
border-radius: 40rpx; |
||||
|
font-size: 28rpx; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
|
||||
|
.submit-btn { |
||||
|
flex: 1; |
||||
|
height: 80rpx; |
||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
||||
|
color: #ffffff; |
||||
|
border: none; |
||||
|
border-radius: 40rpx; |
||||
|
font-size: 28rpx; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
|
||||
|
.submit-btn:disabled { |
||||
|
background: #e0e0e0; |
||||
|
color: #999999; |
||||
|
} |
||||
|
|
||||
|
.modal-overlay { |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
background: rgba(0, 0, 0, 0.5); |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
z-index: 9999; |
||||
|
} |
||||
|
|
||||
|
.modal-container { |
||||
|
width: 80%; |
||||
|
max-height: 70vh; |
||||
|
background: #ffffff; |
||||
|
border-radius: 20rpx; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.modal-header { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
padding: 20rpx; |
||||
|
border-bottom: 1rpx solid #f0f0f0; |
||||
|
} |
||||
|
|
||||
|
.modal-title { |
||||
|
font-size: 32rpx; |
||||
|
font-weight: bold; |
||||
|
color: #333333; |
||||
|
} |
||||
|
|
||||
|
.modal-close { |
||||
|
font-size: 36rpx; |
||||
|
color: #999999; |
||||
|
padding: 10rpx; |
||||
|
} |
||||
|
|
||||
|
.modal-content { |
||||
|
padding: 20rpx; |
||||
|
max-height: 50vh; |
||||
|
overflow-y: auto; |
||||
|
} |
||||
|
|
||||
|
.topic-item { |
||||
|
padding: 20rpx; |
||||
|
border-bottom: 1rpx solid #f0f0f0; |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
transition: all 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
.topic-item:active { |
||||
|
background: #f0f7ff; |
||||
|
} |
||||
|
|
||||
|
.topic-name { |
||||
|
font-size: 28rpx; |
||||
|
color: #333333; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
.topic-count { |
||||
|
font-size: 24rpx; |
||||
|
color: #999999; |
||||
|
} |
||||
@ -0,0 +1,148 @@ |
|||||
|
const API = require('../../utils/api.js'); |
||||
|
|
||||
|
Page({ |
||||
|
data: { |
||||
|
hotTopics: [], |
||||
|
posts: [], |
||||
|
loading: false, |
||||
|
hasMore: true, |
||||
|
page: 1, |
||||
|
pageSize: 10 |
||||
|
}, |
||||
|
|
||||
|
onLoad() { |
||||
|
this.loadHotTopics(); |
||||
|
this.loadPosts(); |
||||
|
}, |
||||
|
|
||||
|
onShow() { |
||||
|
this.setData({ |
||||
|
page: 1, |
||||
|
hasMore: true, |
||||
|
posts: [] |
||||
|
}); |
||||
|
this.loadPosts(); |
||||
|
}, |
||||
|
|
||||
|
onReachBottom() { |
||||
|
if (this.data.hasMore && !this.data.loading) { |
||||
|
this.loadPosts(); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
onPullDownRefresh() { |
||||
|
this.setData({ |
||||
|
page: 1, |
||||
|
hasMore: true, |
||||
|
posts: [] |
||||
|
}); |
||||
|
this.loadHotTopics(); |
||||
|
this.loadPosts(); |
||||
|
wx.stopPullDownRefresh(); |
||||
|
}, |
||||
|
|
||||
|
loadHotTopics() { |
||||
|
API.getHotTopics().then(res => { |
||||
|
this.setData({ |
||||
|
hotTopics: res.data || [] |
||||
|
}); |
||||
|
}).catch(err => { |
||||
|
console.error('加载热门话题失败:', err); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
loadPosts() { |
||||
|
if (this.data.loading) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
this.setData({ |
||||
|
loading: true |
||||
|
}); |
||||
|
|
||||
|
API.getPosts({ |
||||
|
page: this.data.page, |
||||
|
pageSize: this.data.pageSize |
||||
|
}).then(res => { |
||||
|
const newPosts = res.data || []; |
||||
|
this.setData({ |
||||
|
posts: this.data.page === 1 ? newPosts : [...this.data.posts, ...newPosts], |
||||
|
loading: false, |
||||
|
hasMore: newPosts.length >= this.data.pageSize, |
||||
|
page: this.data.page + 1 |
||||
|
}); |
||||
|
}).catch(err => { |
||||
|
console.error('加载动态失败:', err); |
||||
|
this.setData({ |
||||
|
loading: false |
||||
|
}); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
viewTopic(e) { |
||||
|
const topic = e.currentTarget.dataset.topic; |
||||
|
wx.navigateTo({ |
||||
|
url: `/pages/eggbar/topic-detail?id=${topic.id}` |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
viewPost(e) { |
||||
|
const post = e.currentTarget.dataset.post; |
||||
|
wx.navigateTo({ |
||||
|
url: `/pages/eggbar/post-detail?id=${post.id}` |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
likePost(e) { |
||||
|
const postId = e.currentTarget.dataset.id; |
||||
|
const posts = this.data.posts.map(post => { |
||||
|
if (post.id === postId) { |
||||
|
return { |
||||
|
...post, |
||||
|
liked: !post.liked, |
||||
|
likes: post.liked ? post.likes - 1 : post.likes + 1 |
||||
|
}; |
||||
|
} |
||||
|
return post; |
||||
|
}); |
||||
|
|
||||
|
this.setData({ posts }); |
||||
|
|
||||
|
API.likePost(postId).then(res => { |
||||
|
console.log('点赞成功'); |
||||
|
}).catch(err => { |
||||
|
console.error('点赞失败:', err); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
commentPost(e) { |
||||
|
const postId = e.currentTarget.dataset.id; |
||||
|
wx.navigateTo({ |
||||
|
url: `/pages/eggbar/post-detail?id=${postId}&focusComment=true` |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
sharePost(e) { |
||||
|
const postId = e.currentTarget.dataset.id; |
||||
|
wx.showShareMenu({ |
||||
|
withShareTicket: true, |
||||
|
success: () => { |
||||
|
console.log('分享成功'); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
createPost() { |
||||
|
wx.navigateTo({ |
||||
|
url: '/pages/eggbar/create-post' |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
onShareAppMessage() { |
||||
|
return { |
||||
|
title: '蛋吧 - 鸡蛋行业交流社区', |
||||
|
path: '/pages/eggbar/eggbar', |
||||
|
imageUrl: '/images/eggbar-share.jpg' |
||||
|
}; |
||||
|
} |
||||
|
}); |
||||
@ -0,0 +1,12 @@ |
|||||
|
{ |
||||
|
"usingComponents": { |
||||
|
"navigation-bar": "/components/navigation-bar/navigation-bar" |
||||
|
}, |
||||
|
"enablePullDownRefresh": false, |
||||
|
"backgroundTextStyle": "dark", |
||||
|
"backgroundColor": "#f8f8f8", |
||||
|
"navigationBarBackgroundColor": "#ffffff", |
||||
|
"navigationBarTitleText": "蛋吧", |
||||
|
"navigationBarTextStyle": "black", |
||||
|
"navigationStyle": "custom" |
||||
|
} |
||||
@ -0,0 +1,79 @@ |
|||||
|
<view> |
||||
|
|
||||
|
|
||||
|
<view class="content"> |
||||
|
<view class="header"> |
||||
|
<text class="title">蛋吧</text> |
||||
|
<text class="subtitle">欢迎来到蛋吧社区</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="section"> |
||||
|
<view class="section-title"> |
||||
|
<text class="title-text">热门话题</text> |
||||
|
</view> |
||||
|
<view class="topic-list"> |
||||
|
<view class="topic-item" wx:for="{{hotTopics}}" wx:key="id" bindtap="viewTopic" data-topic="{{item}}"> |
||||
|
<view class="topic-rank">{{index + 1}}</view> |
||||
|
<view class="topic-info"> |
||||
|
<text class="topic-name">{{item.name}}</text> |
||||
|
<text class="topic-count">{{item.count}}人讨论</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="section"> |
||||
|
<view class="section-title"> |
||||
|
<text class="title-text">最新动态</text> |
||||
|
</view> |
||||
|
<view class="post-list"> |
||||
|
<view class="post-item" wx:for="{{posts}}" wx:key="id" bindtap="viewPost" data-post="{{item}}"> |
||||
|
<view class="post-header"> |
||||
|
<image class="post-avatar" src="{{item.avatar}}" mode="aspectFill"></image> |
||||
|
<view class="post-user"> |
||||
|
<text class="post-username">{{item.username}}</text> |
||||
|
<text class="post-time">{{item.time}}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="post-content"> |
||||
|
<text class="post-text">{{item.content}}</text> |
||||
|
<view class="post-images" wx:if="{{item.images && item.images.length > 0}}"> |
||||
|
<image class="post-image" wx:for="{{item.images}}" wx:for-item="img" wx:key="index" src="{{img}}" mode="aspectFill"></image> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="post-footer"> |
||||
|
<view class="post-action" bindtap="likePost" data-id="{{item.id}}" catchtap="true"> |
||||
|
<text class="action-icon">{{item.liked ? '❤️' : '🤍'}}</text> |
||||
|
<text class="action-text">{{item.likes}}</text> |
||||
|
</view> |
||||
|
<view class="post-action" bindtap="commentPost" data-id="{{item.id}}" catchtap="true"> |
||||
|
<text class="action-icon">💬</text> |
||||
|
<text class="action-text">{{item.comments}}</text> |
||||
|
</view> |
||||
|
<view class="post-action" bindtap="sharePost" data-id="{{item.id}}" catchtap="true"> |
||||
|
<text class="action-icon">📤</text> |
||||
|
<text class="action-text">分享</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="loading" wx:if="{{loading}}"> |
||||
|
<text>加载中...</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="no-more" wx:if="{{!hasMore && posts.length > 0}}"> |
||||
|
<text>没有更多内容了</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="empty" wx:if="{{posts.length === 0 && !loading}}"> |
||||
|
<text class="empty-icon">📭</text> |
||||
|
<text class="empty-text">暂无动态</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="fab-button" bindtap="createPost"> |
||||
|
<text class="fab-icon">✏️</text> |
||||
|
</view> |
||||
|
</view> |
||||
@ -0,0 +1,270 @@ |
|||||
|
page { |
||||
|
background-color: #f5f5f5; |
||||
|
height: 100vh; |
||||
|
} |
||||
|
|
||||
|
.container { |
||||
|
min-height: 100vh; |
||||
|
padding-bottom: 120rpx; |
||||
|
} |
||||
|
|
||||
|
.content { |
||||
|
padding: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.header { |
||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
||||
|
border-radius: 20rpx; |
||||
|
padding: 40rpx 30rpx; |
||||
|
margin-bottom: 20rpx; |
||||
|
box-shadow: 0 4rpx 20rpx rgba(102, 126, 234, 0.3); |
||||
|
} |
||||
|
|
||||
|
.title { |
||||
|
display: block; |
||||
|
font-size: 48rpx; |
||||
|
font-weight: bold; |
||||
|
color: #ffffff; |
||||
|
margin-bottom: 10rpx; |
||||
|
} |
||||
|
|
||||
|
.subtitle { |
||||
|
display: block; |
||||
|
font-size: 28rpx; |
||||
|
color: rgba(255, 255, 255, 0.9); |
||||
|
} |
||||
|
|
||||
|
.section { |
||||
|
background: #ffffff; |
||||
|
border-radius: 20rpx; |
||||
|
padding: 30rpx; |
||||
|
margin-bottom: 20rpx; |
||||
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08); |
||||
|
} |
||||
|
|
||||
|
.section-title { |
||||
|
margin-bottom: 20rpx; |
||||
|
padding-bottom: 15rpx; |
||||
|
border-bottom: 2rpx solid #f0f0f0; |
||||
|
} |
||||
|
|
||||
|
.title-text { |
||||
|
font-size: 32rpx; |
||||
|
font-weight: bold; |
||||
|
color: #333333; |
||||
|
} |
||||
|
|
||||
|
.topic-list { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
gap: 15rpx; |
||||
|
} |
||||
|
|
||||
|
.topic-item { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
padding: 20rpx; |
||||
|
background: #f8f9fa; |
||||
|
border-radius: 12rpx; |
||||
|
transition: all 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
.topic-item:active { |
||||
|
transform: scale(0.98); |
||||
|
background: #e9ecef; |
||||
|
} |
||||
|
|
||||
|
.topic-rank { |
||||
|
width: 50rpx; |
||||
|
height: 50rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
||||
|
border-radius: 50%; |
||||
|
font-size: 24rpx; |
||||
|
font-weight: bold; |
||||
|
color: #ffffff; |
||||
|
margin-right: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.topic-info { |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
gap: 5rpx; |
||||
|
} |
||||
|
|
||||
|
.topic-name { |
||||
|
font-size: 28rpx; |
||||
|
font-weight: 600; |
||||
|
color: #333333; |
||||
|
} |
||||
|
|
||||
|
.topic-count { |
||||
|
font-size: 24rpx; |
||||
|
color: #999999; |
||||
|
} |
||||
|
|
||||
|
.post-list { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
gap: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.post-item { |
||||
|
background: #ffffff; |
||||
|
border-radius: 16rpx; |
||||
|
padding: 25rpx; |
||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06); |
||||
|
transition: all 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
.post-item:active { |
||||
|
transform: translateY(-2rpx); |
||||
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
|
||||
|
.post-header { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin-bottom: 15rpx; |
||||
|
} |
||||
|
|
||||
|
.post-avatar { |
||||
|
width: 80rpx; |
||||
|
height: 80rpx; |
||||
|
border-radius: 50%; |
||||
|
margin-right: 15rpx; |
||||
|
background: #f0f0f0; |
||||
|
} |
||||
|
|
||||
|
.post-user { |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
gap: 5rpx; |
||||
|
} |
||||
|
|
||||
|
.post-username { |
||||
|
font-size: 28rpx; |
||||
|
font-weight: 600; |
||||
|
color: #333333; |
||||
|
} |
||||
|
|
||||
|
.post-time { |
||||
|
font-size: 24rpx; |
||||
|
color: #999999; |
||||
|
} |
||||
|
|
||||
|
.post-content { |
||||
|
margin-bottom: 15rpx; |
||||
|
} |
||||
|
|
||||
|
.post-text { |
||||
|
display: block; |
||||
|
font-size: 28rpx; |
||||
|
color: #333333; |
||||
|
line-height: 1.6; |
||||
|
margin-bottom: 15rpx; |
||||
|
} |
||||
|
|
||||
|
.post-images { |
||||
|
display: flex; |
||||
|
gap: 10rpx; |
||||
|
flex-wrap: wrap; |
||||
|
} |
||||
|
|
||||
|
.post-image { |
||||
|
width: 200rpx; |
||||
|
height: 200rpx; |
||||
|
border-radius: 12rpx; |
||||
|
background: #f0f0f0; |
||||
|
} |
||||
|
|
||||
|
.post-footer { |
||||
|
display: flex; |
||||
|
justify-content: space-around; |
||||
|
padding-top: 15rpx; |
||||
|
border-top: 1rpx solid #f0f0f0; |
||||
|
} |
||||
|
|
||||
|
.post-action { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 8rpx; |
||||
|
padding: 10rpx 20rpx; |
||||
|
border-radius: 20rpx; |
||||
|
transition: all 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
.post-action:active { |
||||
|
background: #f5f5f5; |
||||
|
} |
||||
|
|
||||
|
.action-icon { |
||||
|
font-size: 32rpx; |
||||
|
} |
||||
|
|
||||
|
.action-text { |
||||
|
font-size: 24rpx; |
||||
|
color: #666666; |
||||
|
} |
||||
|
|
||||
|
.loading { |
||||
|
text-align: center; |
||||
|
padding: 40rpx; |
||||
|
color: #999999; |
||||
|
font-size: 28rpx; |
||||
|
} |
||||
|
|
||||
|
.no-more { |
||||
|
text-align: center; |
||||
|
padding: 40rpx; |
||||
|
color: #999999; |
||||
|
font-size: 28rpx; |
||||
|
} |
||||
|
|
||||
|
.empty { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
padding: 100rpx 20rpx; |
||||
|
} |
||||
|
|
||||
|
.empty-icon { |
||||
|
font-size: 120rpx; |
||||
|
margin-bottom: 20rpx; |
||||
|
opacity: 0.5; |
||||
|
} |
||||
|
|
||||
|
.empty-text { |
||||
|
font-size: 28rpx; |
||||
|
color: #999999; |
||||
|
} |
||||
|
|
||||
|
.fab-button { |
||||
|
position: fixed; |
||||
|
right: 30rpx; |
||||
|
bottom: 150rpx; |
||||
|
width: 120rpx; |
||||
|
height: 120rpx; |
||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
||||
|
border-radius: 50%; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
box-shadow: 0 6rpx 20rpx rgba(102, 126, 234, 0.4); |
||||
|
z-index: 1000; |
||||
|
transition: all 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
.fab-button:active { |
||||
|
transform: scale(0.95); |
||||
|
box-shadow: 0 4rpx 15rpx rgba(102, 126, 234, 0.3); |
||||
|
} |
||||
|
|
||||
|
.fab-icon { |
||||
|
font-size: 48rpx; |
||||
|
} |
||||
Loading…
Reference in new issue