|
|
|
|
@ -1,53 +1,81 @@
|
|
|
|
|
<template>
|
|
|
|
|
<!-- 主卡片容器,用于包裹整个评论管理页面内容 -->
|
|
|
|
|
<el-card class="main-card">
|
|
|
|
|
<!-- 页面标题,取自当前路由的名称 -->
|
|
|
|
|
<div class="title">{{ this.$route.name }}</div>
|
|
|
|
|
|
|
|
|
|
<!-- 评论状态筛选菜单 -->
|
|
|
|
|
<div class="review-menu">
|
|
|
|
|
<span>状态</span>
|
|
|
|
|
<!-- 全部评论筛选,点击时重置审核状态为null,添加激活样式 -->
|
|
|
|
|
<span @click="changeReview(null)" :class="isReview == null ? 'active-review' : 'review'"> 全部 </span>
|
|
|
|
|
<!-- 正常状态评论筛选,点击时设置审核状态为1,添加激活样式 -->
|
|
|
|
|
<span @click="changeReview(1)" :class="isReview == 1 ? 'active-review' : 'review'"> 正常 </span>
|
|
|
|
|
<!-- 审核中状态评论筛选,点击时设置审核状态为0,添加激活样式 -->
|
|
|
|
|
<span @click="changeReview(0)" :class="isReview == 0 ? 'active-review' : 'review'"> 审核中 </span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 操作按钮区域 -->
|
|
|
|
|
<div class="operation-container">
|
|
|
|
|
<!-- 批量删除按钮,当没有选中评论时禁用 -->
|
|
|
|
|
<el-button
|
|
|
|
|
type="danger"
|
|
|
|
|
size="small"
|
|
|
|
|
icon="el-icon-delete"
|
|
|
|
|
:disabled="commentIds.length == 0"
|
|
|
|
|
@click="remove = true">
|
|
|
|
|
type="danger"
|
|
|
|
|
size="small"
|
|
|
|
|
icon="el-icon-delete"
|
|
|
|
|
:disabled="commentIds.length == 0"
|
|
|
|
|
@click="remove = true">
|
|
|
|
|
批量删除
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
|
|
<!-- 批量通过按钮,当没有选中评论时禁用 -->
|
|
|
|
|
<el-button
|
|
|
|
|
type="success"
|
|
|
|
|
size="small"
|
|
|
|
|
icon="el-icon-success"
|
|
|
|
|
:disabled="commentIds.length == 0"
|
|
|
|
|
@click="updateCommentReview(null)">
|
|
|
|
|
type="success"
|
|
|
|
|
size="small"
|
|
|
|
|
icon="el-icon-success"
|
|
|
|
|
:disabled="commentIds.length == 0"
|
|
|
|
|
@click="updateCommentReview(null)">
|
|
|
|
|
批量通过
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
|
|
<!-- 右侧搜索区域 -->
|
|
|
|
|
<div style="margin-left: auto">
|
|
|
|
|
<!-- 评论来源筛选下拉框 -->
|
|
|
|
|
<el-select clearable v-model="type" placeholder="请选择来源" size="small" style="margin-right: 1rem">
|
|
|
|
|
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
|
|
</el-select>
|
|
|
|
|
|
|
|
|
|
<!-- 评论搜索输入框,支持回车搜索 -->
|
|
|
|
|
<el-input
|
|
|
|
|
v-model="keywords"
|
|
|
|
|
prefix-icon="el-icon-search"
|
|
|
|
|
size="small"
|
|
|
|
|
placeholder="请输入用户昵称"
|
|
|
|
|
style="width: 200px"
|
|
|
|
|
@keyup.enter.native="searchComments" />
|
|
|
|
|
v-model="keywords"
|
|
|
|
|
prefix-icon="el-icon-search"
|
|
|
|
|
size="small"
|
|
|
|
|
placeholder="请输入用户昵称"
|
|
|
|
|
style="width: 200px"
|
|
|
|
|
@keyup.enter.native="searchComments" />
|
|
|
|
|
|
|
|
|
|
<!-- 搜索按钮 -->
|
|
|
|
|
<el-button type="primary" size="small" icon="el-icon-search" style="margin-left: 1rem" @click="searchComments">
|
|
|
|
|
搜索
|
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 评论列表表格,加载时显示loading状态,支持选择功能 -->
|
|
|
|
|
<el-table border :data="comments" @selection-change="selectionChange" v-loading="loading">
|
|
|
|
|
<!-- 选择列 -->
|
|
|
|
|
<el-table-column type="selection" width="55" />
|
|
|
|
|
|
|
|
|
|
<!-- 头像列 -->
|
|
|
|
|
<el-table-column prop="avatar" label="头像" align="center" width="120">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<img :src="scope.row.avatar" width="40" height="40" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
<!-- 评论人列 -->
|
|
|
|
|
<el-table-column prop="nickname" label="评论人" align="center" width="120" />
|
|
|
|
|
|
|
|
|
|
<!-- 回复人列,若无回复人显示"无" -->
|
|
|
|
|
<el-table-column prop="replyNickname" label="回复人" align="center" width="120">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<span v-if="scope.row.replyNickname">
|
|
|
|
|
@ -56,6 +84,8 @@
|
|
|
|
|
<span v-else>无</span>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
<!-- 文章标题列,若无关联文章显示"无" -->
|
|
|
|
|
<el-table-column prop="articleTitle" label="文章标题" align="center">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<span v-if="scope.row.articleTitle">
|
|
|
|
|
@ -64,23 +94,31 @@
|
|
|
|
|
<span v-else>无</span>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
<!-- 评论内容列,使用v-html渲染富文本内容 -->
|
|
|
|
|
<el-table-column prop="commentContent" label="评论内容" align="center">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<span v-html="scope.row.commentContent" class="comment-content" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
<!-- 评论时间列,使用date过滤器格式化时间 -->
|
|
|
|
|
<el-table-column prop="createTime" label="评论时间" width="150" align="center">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<i class="el-icon-time" style="margin-right: 5px" />
|
|
|
|
|
{{ scope.row.createTime | date }}
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
<!-- 状态列,使用标签显示审核状态 -->
|
|
|
|
|
<el-table-column prop="isReview" label="状态" width="80" align="center">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<el-tag v-if="scope.row.isReview == 0" type="warning">审核中</el-tag>
|
|
|
|
|
<el-tag v-if="scope.row.isReview == 1" type="success">正常</el-tag>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
<!-- 来源列,使用标签显示评论来源类型 -->
|
|
|
|
|
<el-table-column label="来源" align="center" width="100">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<el-tag v-if="scope.row.type == 1">文章</el-tag>
|
|
|
|
|
@ -90,32 +128,41 @@
|
|
|
|
|
<el-tag v-if="scope.row.type == 5" type="warning">说说</el-tag>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
<!-- 操作列 -->
|
|
|
|
|
<el-table-column label="操作" width="160" align="center">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<!-- 通过按钮,仅对审核中状态的评论显示 -->
|
|
|
|
|
<el-button
|
|
|
|
|
v-if="scope.row.isReview == 0"
|
|
|
|
|
size="mini"
|
|
|
|
|
type="success"
|
|
|
|
|
slot="reference"
|
|
|
|
|
@click="updateCommentReview(scope.row.id)">
|
|
|
|
|
v-if="scope.row.isReview == 0"
|
|
|
|
|
size="mini"
|
|
|
|
|
type="success"
|
|
|
|
|
slot="reference"
|
|
|
|
|
@click="updateCommentReview(scope.row.id)">
|
|
|
|
|
通过
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
|
|
<!-- 删除确认弹窗触发器 -->
|
|
|
|
|
<el-popconfirm style="margin-left: 10px" title="确定删除吗?" @confirm="deleteComments(scope.row.id)">
|
|
|
|
|
<el-button size="mini" type="danger" slot="reference"> 删除 </el-button>
|
|
|
|
|
</el-popconfirm>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
</el-table>
|
|
|
|
|
|
|
|
|
|
<!-- 分页组件 -->
|
|
|
|
|
<el-pagination
|
|
|
|
|
class="pagination-container"
|
|
|
|
|
background
|
|
|
|
|
@size-change="sizeChange"
|
|
|
|
|
@current-change="currentChange"
|
|
|
|
|
:current-page="current"
|
|
|
|
|
:page-size="size"
|
|
|
|
|
:total="count"
|
|
|
|
|
:page-sizes="[10, 20]"
|
|
|
|
|
layout="total, sizes, prev, pager, next, jumper" />
|
|
|
|
|
class="pagination-container"
|
|
|
|
|
background
|
|
|
|
|
@size-change="sizeChange" <!-- 每页条数改变事件 -->
|
|
|
|
|
@current-change="currentChange" <!-- 当前页码改变事件 -->
|
|
|
|
|
:current-page="current" <!-- 当前页码 -->
|
|
|
|
|
:page-size="size" <!-- 每页条数 -->
|
|
|
|
|
:total="count" <!-- 总条数 -->
|
|
|
|
|
:page-sizes="[10, 20]" <!-- 可选每页条数 -->
|
|
|
|
|
layout="total, sizes, prev, pager, next, jumper" /> <!-- 分页布局 -->
|
|
|
|
|
|
|
|
|
|
<!-- 批量删除确认弹窗 -->
|
|
|
|
|
<el-dialog :visible.sync="remove" width="30%">
|
|
|
|
|
<div class="dialog-title-container" slot="title"><i class="el-icon-warning" style="color: #ff9900" />提示</div>
|
|
|
|
|
<div style="font-size: 1rem">是否彻底删除选中项?</div>
|
|
|
|
|
@ -129,15 +176,19 @@
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
export default {
|
|
|
|
|
// 页面创建时执行的钩子函数
|
|
|
|
|
created() {
|
|
|
|
|
// 从状态管理中获取评论页面的当前页码
|
|
|
|
|
this.current = this.$store.state.pageState.comment
|
|
|
|
|
// 加载评论列表数据
|
|
|
|
|
this.listComments()
|
|
|
|
|
},
|
|
|
|
|
// 数据定义
|
|
|
|
|
data: function () {
|
|
|
|
|
return {
|
|
|
|
|
loading: true,
|
|
|
|
|
remove: false,
|
|
|
|
|
options: [
|
|
|
|
|
loading: true, // 表格加载状态
|
|
|
|
|
remove: false, // 批量删除弹窗显示状态
|
|
|
|
|
options: [ // 评论来源下拉框选项
|
|
|
|
|
{
|
|
|
|
|
value: 1,
|
|
|
|
|
label: '文章'
|
|
|
|
|
@ -155,56 +206,68 @@ export default {
|
|
|
|
|
label: '友链'
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
comments: [],
|
|
|
|
|
commentIds: [],
|
|
|
|
|
type: null,
|
|
|
|
|
keywords: null,
|
|
|
|
|
isReview: null,
|
|
|
|
|
current: 1,
|
|
|
|
|
size: 10,
|
|
|
|
|
count: 0
|
|
|
|
|
comments: [], // 评论列表数据
|
|
|
|
|
commentIds: [], // 选中的评论ID列表
|
|
|
|
|
type: null, // 评论来源筛选条件
|
|
|
|
|
keywords: null, // 搜索关键词(用户昵称)
|
|
|
|
|
isReview: null, // 评论状态筛选条件(null:全部, 0:审核中, 1:正常)
|
|
|
|
|
current: 1, // 当前页码
|
|
|
|
|
size: 10, // 每页条数
|
|
|
|
|
count: 0 // 总条数
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
// 处理表格选择事件,收集选中的评论ID
|
|
|
|
|
selectionChange(comments) {
|
|
|
|
|
this.commentIds = []
|
|
|
|
|
comments.forEach((item) => {
|
|
|
|
|
this.commentIds.push(item.id)
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
// 搜索评论(重置页码为1)
|
|
|
|
|
searchComments() {
|
|
|
|
|
this.current = 1
|
|
|
|
|
this.listComments()
|
|
|
|
|
},
|
|
|
|
|
// 处理每页条数改变事件
|
|
|
|
|
sizeChange(size) {
|
|
|
|
|
this.size = size
|
|
|
|
|
this.listComments()
|
|
|
|
|
},
|
|
|
|
|
// 处理当前页码改变事件
|
|
|
|
|
currentChange(current) {
|
|
|
|
|
this.current = current
|
|
|
|
|
// 更新状态管理中的评论页面页码
|
|
|
|
|
this.$store.commit('updateCommentPageState', current)
|
|
|
|
|
this.listComments()
|
|
|
|
|
},
|
|
|
|
|
// 改变评论状态筛选条件
|
|
|
|
|
changeReview(review) {
|
|
|
|
|
this.current = 1
|
|
|
|
|
this.isReview = review
|
|
|
|
|
this.current = 1 // 重置页码为1
|
|
|
|
|
this.isReview = review // 更新筛选状态
|
|
|
|
|
},
|
|
|
|
|
// 更新评论审核状态(支持单个和批量通过)
|
|
|
|
|
updateCommentReview(id) {
|
|
|
|
|
let param = {}
|
|
|
|
|
// 单个通过时参数为单个ID,批量通过时为选中的ID列表
|
|
|
|
|
if (id != null) {
|
|
|
|
|
param.ids = [id]
|
|
|
|
|
} else {
|
|
|
|
|
param.ids = this.commentIds
|
|
|
|
|
}
|
|
|
|
|
param.isReview = 1
|
|
|
|
|
param.isReview = 1 // 设置审核状态为通过(1)
|
|
|
|
|
// 发送更新审核状态请求
|
|
|
|
|
this.axios.put('/api/admin/comments/review', param).then(({ data }) => {
|
|
|
|
|
if (data.flag) {
|
|
|
|
|
// 操作成功提示
|
|
|
|
|
this.$notify.success({
|
|
|
|
|
title: '成功',
|
|
|
|
|
message: data.message
|
|
|
|
|
})
|
|
|
|
|
// 重新加载评论列表
|
|
|
|
|
this.listComments()
|
|
|
|
|
} else {
|
|
|
|
|
// 操作失败提示
|
|
|
|
|
this.$notify.error({
|
|
|
|
|
title: '失败',
|
|
|
|
|
message: data.message
|
|
|
|
|
@ -212,67 +275,84 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
// 删除评论(支持单个删除和批量删除)
|
|
|
|
|
deleteComments(id) {
|
|
|
|
|
var param = {}
|
|
|
|
|
// 批量删除时参数为选中的ID列表,单个删除时为单个ID
|
|
|
|
|
if (id == null) {
|
|
|
|
|
param = { data: this.commentIds }
|
|
|
|
|
} else {
|
|
|
|
|
param = { data: [id] }
|
|
|
|
|
}
|
|
|
|
|
// 发送删除请求
|
|
|
|
|
this.axios.delete('/api/admin/comments', param).then(({ data }) => {
|
|
|
|
|
if (data.flag) {
|
|
|
|
|
// 删除成功提示
|
|
|
|
|
this.$notify.success({
|
|
|
|
|
title: '成功',
|
|
|
|
|
message: data.message
|
|
|
|
|
})
|
|
|
|
|
// 重新加载评论列表
|
|
|
|
|
this.listComments()
|
|
|
|
|
} else {
|
|
|
|
|
// 删除失败提示
|
|
|
|
|
this.$notify.error({
|
|
|
|
|
title: '失败',
|
|
|
|
|
message: data.message
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
// 关闭删除弹窗
|
|
|
|
|
this.remove = false
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
// 加载评论列表数据
|
|
|
|
|
listComments() {
|
|
|
|
|
this.axios
|
|
|
|
|
.get('/api/admin/comments', {
|
|
|
|
|
params: {
|
|
|
|
|
current: this.current,
|
|
|
|
|
size: this.size,
|
|
|
|
|
keywords: this.keywords,
|
|
|
|
|
type: this.type,
|
|
|
|
|
isReview: this.isReview
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.then(({ data }) => {
|
|
|
|
|
this.comments = data.data.records
|
|
|
|
|
this.count = data.data.count
|
|
|
|
|
this.loading = false
|
|
|
|
|
})
|
|
|
|
|
.get('/api/admin/comments', {
|
|
|
|
|
params: {
|
|
|
|
|
current: this.current, // 当前页码
|
|
|
|
|
size: this.size, // 每页条数
|
|
|
|
|
keywords: this.keywords, // 搜索关键词
|
|
|
|
|
type: this.type, // 来源类型
|
|
|
|
|
isReview: this.isReview // 审核状态
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.then(({ data }) => {
|
|
|
|
|
// 更新评论列表数据
|
|
|
|
|
this.comments = data.data.records
|
|
|
|
|
// 更新总条数
|
|
|
|
|
this.count = data.data.count
|
|
|
|
|
// 关闭加载状态
|
|
|
|
|
this.loading = false
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 监听器,监听筛选条件变化并重新加载数据
|
|
|
|
|
watch: {
|
|
|
|
|
// 监听审核状态变化
|
|
|
|
|
isReview() {
|
|
|
|
|
this.current = 1
|
|
|
|
|
this.listComments()
|
|
|
|
|
this.current = 1 // 重置页码为1
|
|
|
|
|
this.listComments() // 重新加载评论列表
|
|
|
|
|
},
|
|
|
|
|
// 监听来源类型变化
|
|
|
|
|
type() {
|
|
|
|
|
this.current = 1
|
|
|
|
|
this.listComments()
|
|
|
|
|
this.current = 1 // 重置页码为1
|
|
|
|
|
this.listComments() // 重新加载评论列表
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
/* 评论内容样式 */
|
|
|
|
|
.comment-content {
|
|
|
|
|
display: inline-block;
|
|
|
|
|
}
|
|
|
|
|
/* 操作按钮区域样式 */
|
|
|
|
|
.operation-container {
|
|
|
|
|
margin-top: 1.5rem;
|
|
|
|
|
}
|
|
|
|
|
/* 评论状态筛选菜单样式 */
|
|
|
|
|
.review-menu {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
margin-top: 40px;
|
|
|
|
|
@ -281,12 +361,14 @@ export default {
|
|
|
|
|
.review-menu span {
|
|
|
|
|
margin-right: 24px;
|
|
|
|
|
}
|
|
|
|
|
/* 未选中的筛选选项样式 */
|
|
|
|
|
.review {
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
/* 选中的筛选选项样式 */
|
|
|
|
|
.active-review {
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
color: #333;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
</style>
|