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