<template>
<div class="forum-post">
<el-card>
<!-- 搜索栏 -->
<el-form :inline="true" :model="searchForm" class="search-form">
<el-form-item label="标题">
<el-input v-model="searchForm.title" placeholder="请输入标题" clearable></el-input>
</el-form-item>
<el-form-item label="分类">
<el-select v-model="searchForm.categoryId" placeholder="请选择分类" clearable>
<el-option v-for="category in categories" :key="category.id" :label="category.name" :value="category.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="状态">
<el-select v-model="searchForm.status" placeholder="请选择状态" clearable>
<el-option label="上架" :value="0"></el-option>
<el-option label="下架" :value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleSearch">搜索</el-button>
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
<!-- 表格 -->
<el-table :data="tableData" border stripe>
<el-table-column prop="id" label="ID" width="80"></el-table-column>
<el-table-column prop="title" label="标题" min-width="200"></el-table-column>
<el-table-column prop="categoryName" label="分类" width="120"></el-table-column>
<el-table-column prop="username" label="发布用户" width="120"></el-table-column>
<el-table-column label="状态" width="100">
<template slot-scope="scope">
<el-tag v-if="scope.row.status === 0" type="success">上架</el-tag>
<el-tag v-else type="warning">下架</el-tag>
</template>
</el-table-column>
<el-table-column label="创建时间" width="180">
<template slot-scope="scope">{{ scope.row.createTime | formatDate }}</template>
</el-table-column>
<el-table-column label="操作" width="280" fixed="right">
<template slot-scope="scope">
<el-button type="info" size="small" icon="el-icon-view" @click="handleView(scope.row)">查看</el-button>
<el-button v-if="scope.row.status === 0" type="warning" size="small" icon="el-icon-bottom" @click="handleUnpublish(scope.row.id)">下架</el-button>
<el-button v-else type="success" size="small" icon="el-icon-top" @click="handlePublish(scope.row.id)">上架</el-button>
<el-button type="danger" size="small" icon="el-icon-delete" @click="handleDelete(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pagination.pageNum"
:page-sizes="[10, 20, 50, 100]"
:page-size="pagination.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total"
style="margin-top: 20px; text-align: right;">
</el-pagination>
</el-card>
<!-- 查看对话框 -->
<el-dialog title="帖子详情" :visible.sync="viewDialogVisible" width="800px">
<div class="post-detail">
<h2>{{ viewData.title }}</h2>
<div class="post-meta">
<span>分类:{{ viewData.categoryName }}</span>
<span>发布用户:{{ viewData.username }}</span>
<span>发布时间:{{ viewData.createTime | formatDate }}</span>
<el-tag v-if="viewData.status === 0" type="success" size="small">上架</el-tag>
<el-tag v-else type="warning" size="small">下架</el-tag>
</div>
<el-divider></el-divider>
<div class="post-content">{{ viewData.content }}</div>
<el-divider></el-divider>
<div class="comment-section">
<h3>评论列表 ({{ commentCount }}条)</h3>
<div v-if="comments.length > 0" class="comment-list">
<admin-comment-item v-for="comment in comments" :key="comment.id" :comment="comment"></admin-comment-item>
</div>
<el-empty v-else description="暂无评论" :image-size="80"></el-empty>
</div>
</div>
<div slot="footer">
<el-button @click="viewDialogVisible = false">关闭</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import AdminCommentItem from '@/components/AdminCommentItem.vue'
export default {
name: 'ForumPost',
components: { AdminCommentItem },
data() {
return {
searchForm: { title: '', categoryId: null, status: null },
categories: [],
tableData: [],
pagination: { pageNum: 1, pageSize: 10, total: 0 },
viewDialogVisible: false,
viewData: {},
comments: [],
commentCount: 0
}
},
mounted() {
this.loadCategories()
this.loadData()
},
methods: {
loadCategories() {
this.$request.get('/forum/category/list').then(res => {
this.categories = res.data || []
})
},
loadData() {
const params = {
pageNum: this.pagination.pageNum,
pageSize: this.pagination.pageSize,
...this.searchForm
}
this.$request.get('/forum/post/adminPage', { params }).then(res => {
this.tableData = res.data.records
this.pagination.total = res.data.total
})
},
handleSearch() {
this.pagination.pageNum = 1
this.loadData()
},
handleReset() {
this.searchForm = { title: '', categoryId: null, status: null }
this.handleSearch()
},
handleSizeChange(val) {
this.pagination.pageSize = val
this.loadData()
},
handleCurrentChange(val) {
this.pagination.pageNum = val
this.loadData()
},
handleView(row) {
this.viewData = { ...row }
this.viewDialogVisible = true
// 加载评论(保持树形结构)
this.$request.get(`/forum/comment/list/${row.id}`).then(res => {
this.comments = res.data || []
this.commentCount = this.countComments(this.comments)
})
},
countComments(comments) {
let count = 0
const countAll = (list) => {
list.forEach(comment => {
count++
if (comment.children && comment.children.length > 0) {
countAll(comment.children)
}
})
}
countAll(comments)
return count
},
handlePublish(id) {
this.$request.put(`/forum/post/publish/${id}`).then(() => {
this.$message.success('上架成功')
this.loadData()
})
},
handleUnpublish(id) {
this.$request.put(`/forum/post/unpublish/${id}`).then(() => {
this.$message.success('下架成功')
this.loadData()
})
},
handleDelete(id) {
this.$confirm('确定要删除该帖子吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$request.delete(`/forum/post/delete/${id}`).then(() => {
this.$message.success('删除成功')
this.loadData()
})
}).catch(() => {})
}
}
}
</script>
<style scoped>
.search-form { margin-bottom: 20px; }
.post-detail h2 { text-align: center; color: #333; margin-bottom: 20px; }
.post-meta { display: flex; justify-content: space-around; color: #999; font-size: 14px; flex-wrap: wrap; gap: 10px; }
.post-content { line-height: 1.8; color: #666; white-space: pre-wrap; min-height: 100px; }
.comment-section { margin-top: 20px; background: #fafafa; padding: 20px; border-radius: 8px; }
.comment-section h3 { font-size: 18px; color: #303133; margin-bottom: 20px; font-weight: 600; padding-bottom: 10px; border-bottom: 2px solid #409EFF; }
.comment-list { max-height: 500px; overflow-y: auto; padding: 10px 0; }
.comment-list::-webkit-scrollbar { width: 6px; }
.comment-list::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 3px; }
.comment-list::-webkit-scrollbar-thumb { background: #c0c4cc; border-radius: 3px; }
.comment-list::-webkit-scrollbar-thumb:hover { background: #909399; }
</style>