Skip to main content
Glama
PostDetail.vue8.16 kB
<!-- views/PostDetail.vue - 帖子详情页组件 --> <template> <div class="post-detail"> <!-- 加载状态 --> <div v-if="loading" class="loading-container"> <el-skeleton :rows="10" animated /> </div> <!-- 帖子内容 --> <template v-else-if="post"> <el-card class="post-card"> <!-- 帖子头部 --> <div class="post-header"> <h1 class="post-title">{{ post.title }}</h1> <div class="post-meta"> <div class="post-author"> <el-avatar :size="32" :src="post.author.avatar || ''"> {{ post.author.username.charAt(0).toUpperCase() }} </el-avatar> <span class="author-name">{{ post.author.username }}</span> </div> <div class="post-info"> <span class="post-category">{{ getCategoryName(post.categoryId) }}</span> <span class="post-time">{{ formatDate(post.createTime) }}</span> <span class="post-views"> <el-icon><View /></el-icon> {{ post.viewCount || 0 }} </span> </div> </div> </div> <!-- 帖子内容 --> <div class="post-content"> {{ post.content }} </div> <!-- 帖子操作 --> <div class="post-actions"> <el-button type="primary" plain size="small" @click="handleLike"> <el-icon><Star /></el-icon> 点赞 ({{ post.likeCount || 0 }}) </el-button> <!-- 仅帖子作者可见的操作 --> <div v-if="isPostAuthor" class="author-actions"> <el-button type="primary" plain size="small" @click="handleEdit"> <el-icon><Edit /></el-icon> 编辑 </el-button> <el-button type="danger" plain size="small" @click="handleDelete"> <el-icon><Delete /></el-icon> 删除 </el-button> </div> </div> </el-card> <!-- 评论区 --> <el-card class="comment-card"> <template #header> <div class="card-header"> <span>评论 ({{ post.comments?.length || 0 }})</span> </div> </template> <!-- 评论列表 --> <div class="comment-list"> <div v-if="post.comments && post.comments.length > 0"> <div v-for="comment in post.comments" :key="comment.id" class="comment-item"> <div class="comment-avatar"> <el-avatar :size="32" :src="comment.author.avatar || ''"> {{ comment.author.username.charAt(0).toUpperCase() }} </el-avatar> </div> <div class="comment-content"> <div class="comment-header"> <span class="comment-author">{{ comment.author.username }}</span> <span class="comment-time">{{ formatDate(comment.createTime) }}</span> </div> <div class="comment-text">{{ comment.content }}</div> </div> </div> </div> <el-empty v-else description="暂无评论" /> </div> <!-- 发表评论 --> <div class="comment-form"> <el-input v-model="commentContent" type="textarea" :rows="3" placeholder="发表你的评论..." :disabled="!isAuthenticated" /> <div class="form-actions"> <el-button type="primary" @click="submitComment" :disabled="!isAuthenticated || !commentContent.trim()" > 发表评论 </el-button> </div> <div v-if="!isAuthenticated" class="login-tip"> 请 <router-link to="/login">登录</router-link> 后发表评论 </div> </div> </el-card> </template> <!-- 帖子不存在 --> <el-result v-else icon="error" title="帖子不存在" subtitle="该帖子可能已被删除或您没有权限查看"> <template #extra> <el-button type="primary" @click="$router.push('/')">返回首页</el-button> </template> </el-result> <!-- 删除确认对话框 --> <el-dialog v-model="deleteDialogVisible" title="删除帖子" width="30%" > <span>确定要删除这篇帖子吗?此操作不可恢复。</span> <template #footer> <span class="dialog-footer"> <el-button @click="deleteDialogVisible = false">取消</el-button> <el-button type="danger" @click="confirmDelete">确定删除</el-button> </span> </template> </el-dialog> </div> </template> <script> import { ref, computed, onMounted } from 'vue' import { useStore } from 'vuex' import { useRoute, useRouter } from 'vue-router' import { View, Star, Edit, Delete } from '@element-plus/icons-vue' import { ElMessage, ElMessageBox } from 'element-plus' export default { name: 'PostDetail', components: { View, Star, Edit, Delete }, setup() { const store = useStore() const route = useRoute() const router = useRouter() // 状态 const loading = ref(true) const commentContent = ref('') const deleteDialogVisible = ref(false) // 从store获取数据 const post = computed(() => store.getters.getCurrentPost) const categories = computed(() => store.getters.getCategories) const isAuthenticated = computed(() => store.getters.isAuthenticated) const currentUser = computed(() => store.getters.currentUser) // 判断当前用户是否是帖子作者 const isPostAuthor = computed(() => { if (!isAuthenticated.value || !post.value || !currentUser.value) return false return post.value.author.id === currentUser.value.id }) // 获取帖子详情 const fetchPostDetail = async () => { loading.value = true try { const postId = route.params.id await store.dispatch('fetchPostById', postId) } catch (error) { ElMessage.error('获取帖子详情失败') console.error('获取帖子详情失败:', error) } finally { loading.value = false } } // 获取分类名称 const getCategoryName = (categoryId) => { const category = categories.value.find(c => c.id === categoryId) return category ? category.name : '未分类' } // 格式化日期 const formatDate = (dateString) => { if (!dateString) return '' const date = new Date(dateString) const now = new Date() const diff = now - date // 一分钟内 if (diff < 60 * 1000) { return '刚刚' } // 一小时内 if (diff < 60 * 60 * 1000) { return `${Math.floor(diff / (60 * 1000))}分钟前` } // 一天内 if (diff < 24 * 60 * 60 * 1000) { return `${Math.floor(diff / (60 * 60 * 1000))}小时前` } // 一周内 if (diff < 7 * 24 * 60 * 60 * 1000) { return `${Math.floor(diff / (24 * 60 * 60 * 1000))}天前` } // 其他 return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}` } // 点赞帖子 const handleLike = () => { if (!isAuthenticated.value) { ElMessage.warning('请先登录') router.push('/login') return } ElMessage.success('点赞成功') // 这里应该调用API进行点赞操作 // 实际项目中需要实现后端API } // 编辑帖子 const handleEdit = () => { if (!isPostAuthor.value) { ElMessage.warning('只有作者才能编辑帖子') return } router.push(`/edit-post/${post.value.id}`) } // 删除帖子 const handleDelete = () => { if (!isPostAuthor.value) { ElMessage.warning('只有作者才能删除帖子') return } deleteDialogVisible.value = true } // 确认删除

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TonyCui35/Forum_Web'

If you have feedback or need assistance with the MCP directory API, please join our Discord server