mirror of https://github.com/halo-dev/halo-admin
refactor: comment list component code optimization (#464)
Signed-off-by: Ryan Wang <i@ryanc.cc>pull/470/head
parent
8c071ae6a5
commit
5f790386ce
|
@ -166,3 +166,24 @@ export const sheetStatuses = {
|
||||||
text: '回收站'
|
text: '回收站'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const commentStatuses = {
|
||||||
|
PUBLISHED: {
|
||||||
|
value: 'PUBLISHED',
|
||||||
|
color: 'green',
|
||||||
|
status: 'success',
|
||||||
|
text: '已发布'
|
||||||
|
},
|
||||||
|
AUDITING: {
|
||||||
|
value: 'AUDITING',
|
||||||
|
color: 'yellow',
|
||||||
|
status: 'warning',
|
||||||
|
text: '待审核'
|
||||||
|
},
|
||||||
|
RECYCLE: {
|
||||||
|
value: 'RECYCLE',
|
||||||
|
color: 'red',
|
||||||
|
status: 'error',
|
||||||
|
text: '回收站'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
<div class="card-container">
|
<div class="card-container">
|
||||||
<a-tabs type="card">
|
<a-tabs type="card">
|
||||||
<a-tab-pane key="1" tab="文章">
|
<a-tab-pane key="1" tab="文章">
|
||||||
<comment-tab type="posts"></comment-tab>
|
<comment-tab target="post"></comment-tab>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="2" tab="页面">
|
<a-tab-pane key="2" tab="页面">
|
||||||
<comment-tab type="sheets"></comment-tab>
|
<comment-tab target="sheet"></comment-tab>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
<a-col :md="6" :sm="24">
|
<a-col :md="6" :sm="24">
|
||||||
<a-form-item label="评论状态:">
|
<a-form-item label="评论状态:">
|
||||||
<a-select v-model="list.params.status" allowClear placeholder="请选择评论状态" @change="handleQuery()">
|
<a-select v-model="list.params.status" allowClear placeholder="请选择评论状态" @change="handleQuery()">
|
||||||
<a-select-option v-for="status in Object.keys(commentStatus)" :key="status" :value="status">
|
<a-select-option v-for="status in Object.keys(commentStatuses)" :key="status" :value="status">
|
||||||
{{ commentStatus[status].text }}
|
{{ commentStatuses[status].text }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
@ -33,131 +33,151 @@
|
||||||
|
|
||||||
<div class="table-operator">
|
<div class="table-operator">
|
||||||
<a-dropdown v-show="list.params.status != null && list.params.status !== '' && !isMobile()">
|
<a-dropdown v-show="list.params.status != null && list.params.status !== '' && !isMobile()">
|
||||||
<a-menu slot="overlay">
|
<template #overlay>
|
||||||
<a-menu-item
|
<a-menu>
|
||||||
v-if="list.params.status === 'AUDITING'"
|
<a-menu-item
|
||||||
key="1"
|
v-if="list.params.status === commentStatuses.AUDITING.value"
|
||||||
@click="handleEditStatusMore(commentStatus.PUBLISHED.value)"
|
key="1"
|
||||||
>
|
@click="handleChangeStatusInBatch(commentStatuses.PUBLISHED.value)"
|
||||||
通过
|
>
|
||||||
</a-menu-item>
|
通过
|
||||||
<a-menu-item
|
</a-menu-item>
|
||||||
v-if="list.params.status === 'PUBLISHED' || list.params.status === 'AUDITING'"
|
<a-menu-item
|
||||||
key="2"
|
v-if="[commentStatuses.PUBLISHED.value, commentStatuses.AUDITING.value].includes(list.params.status)"
|
||||||
@click="handleEditStatusMore(commentStatus.RECYCLE.value)"
|
key="2"
|
||||||
>
|
@click="handleChangeStatusInBatch(commentStatuses.RECYCLE.value)"
|
||||||
移到回收站
|
>
|
||||||
</a-menu-item>
|
移到回收站
|
||||||
<a-menu-item v-if="list.params.status === 'RECYCLE'" key="3" @click="handleDeleteMore">
|
</a-menu-item>
|
||||||
永久删除
|
<a-menu-item
|
||||||
</a-menu-item>
|
v-if="list.params.status === commentStatuses.RECYCLE.value"
|
||||||
</a-menu>
|
key="3"
|
||||||
|
@click="handleDeleteInBatch"
|
||||||
|
>
|
||||||
|
永久删除
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</template>
|
||||||
<a-button>
|
<a-button>
|
||||||
批量操作
|
批量操作
|
||||||
<a-icon type="down" />
|
<a-icon type="down" />
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<!-- Mobile -->
|
<!-- Mobile -->
|
||||||
<a-list
|
<a-list
|
||||||
v-if="isMobile()"
|
v-if="isMobile()"
|
||||||
:dataSource="formattedComments"
|
:dataSource="list.data"
|
||||||
:loading="list.loading"
|
:loading="list.loading"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
itemLayout="vertical"
|
itemLayout="vertical"
|
||||||
size="large"
|
size="large"
|
||||||
>
|
>
|
||||||
<a-list-item :key="index" slot="renderItem" slot-scope="item, index">
|
<template #renderItem="item, index">
|
||||||
<template slot="actions">
|
<a-list-item :key="index">
|
||||||
<a-dropdown :trigger="['click']" placement="topLeft">
|
<template #actions>
|
||||||
<span>
|
<a-dropdown :trigger="['click']" placement="topLeft">
|
||||||
<a-icon type="bars" />
|
<span>
|
||||||
</span>
|
<a-icon type="bars" />
|
||||||
<a-menu slot="overlay">
|
</span>
|
||||||
<a-menu-item v-if="item.status === 'AUDITING'" @click="handleEditStatusClick(item.id, 'PUBLISHED')">
|
<template #overlay>
|
||||||
通过
|
<a-menu>
|
||||||
</a-menu-item>
|
<a-menu-item
|
||||||
<a-menu-item v-if="item.status === 'AUDITING'" @click="handleReplyAndPassClick(item)">
|
v-if="item.status === commentStatuses.AUDITING.value"
|
||||||
通过并回复
|
@click="handleChangeStatus(item.id, commentStatuses.PUBLISHED.value)"
|
||||||
</a-menu-item>
|
>
|
||||||
<a-menu-item v-else-if="item.status === 'PUBLISHED'" @click="handleReplyClick(item)">
|
通过
|
||||||
回复
|
</a-menu-item>
|
||||||
</a-menu-item>
|
<a-menu-item
|
||||||
<a-menu-item v-else-if="item.status === 'RECYCLE'">
|
v-if="item.status === commentStatuses.AUDITING.value"
|
||||||
<a-popconfirm
|
@click="handlePublishAndReply(item)"
|
||||||
:title="'你确定要还原该评论?'"
|
>
|
||||||
cancelText="取消"
|
通过并回复
|
||||||
okText="确定"
|
</a-menu-item>
|
||||||
@confirm="handleEditStatusClick(item.id, 'PUBLISHED')"
|
<a-menu-item
|
||||||
>
|
v-else-if="item.status === commentStatuses.PUBLISHED.value"
|
||||||
还原
|
@click="handleOpenReplyModal(item)"
|
||||||
</a-popconfirm>
|
>
|
||||||
</a-menu-item>
|
回复
|
||||||
<a-menu-item v-if="item.status === 'PUBLISHED' || item.status === 'AUDITING'">
|
</a-menu-item>
|
||||||
<a-popconfirm
|
<a-menu-item v-else-if="item.status === commentStatuses.RECYCLE.value">
|
||||||
:title="'你确定要将该评论移到回收站?'"
|
<a-popconfirm
|
||||||
cancelText="取消"
|
:title="'你确定要还原该评论?'"
|
||||||
okText="确定"
|
cancelText="取消"
|
||||||
@confirm="handleEditStatusClick(item.id, 'RECYCLE')"
|
okText="确定"
|
||||||
>
|
@confirm="handleChangeStatus(item.id, commentStatuses.PUBLISHED.value)"
|
||||||
回收站
|
>
|
||||||
</a-popconfirm>
|
还原
|
||||||
</a-menu-item>
|
</a-popconfirm>
|
||||||
<a-menu-item v-else-if="item.status === 'RECYCLE'">
|
</a-menu-item>
|
||||||
<a-popconfirm
|
<a-menu-item
|
||||||
:title="'你确定要永久删除该评论?'"
|
v-if="[commentStatuses.PUBLISHED.value, commentStatuses.AUDITING.value].includes(item.status)"
|
||||||
cancelText="取消"
|
>
|
||||||
okText="确定"
|
<a-popconfirm
|
||||||
@confirm="handleDeleteClick(item.id)"
|
:title="'你确定要将该评论移到回收站?'"
|
||||||
>
|
cancelText="取消"
|
||||||
删除
|
okText="确定"
|
||||||
</a-popconfirm>
|
@confirm="handleChangeStatus(item.id, commentStatuses.RECYCLE.value)"
|
||||||
</a-menu-item>
|
>
|
||||||
</a-menu>
|
回收站
|
||||||
</a-dropdown>
|
</a-popconfirm>
|
||||||
</template>
|
</a-menu-item>
|
||||||
<template slot="extra">
|
<a-menu-item v-else-if="item.status === commentStatuses.RECYCLE.value">
|
||||||
<span>
|
<a-popconfirm
|
||||||
<a-badge :status="item.statusProperty.status" :text="item.statusProperty.text" />
|
:title="'你确定要永久删除该评论?'"
|
||||||
</span>
|
cancelText="取消"
|
||||||
</template>
|
okText="确定"
|
||||||
<a-list-item-meta>
|
@confirm="handleDelete(item.id)"
|
||||||
<template slot="description">
|
>
|
||||||
发表在
|
删除
|
||||||
<a v-if="type === 'posts'" :href="item.post.fullPath" target="_blank">《{{ item.post.title }}》</a>
|
</a-popconfirm>
|
||||||
<a v-if="type === 'sheets'" :href="item.sheet.fullPath" target="_blank">《{{ item.sheet.title }}》</a>
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</template>
|
||||||
|
</a-dropdown>
|
||||||
</template>
|
</template>
|
||||||
<a-avatar slot="avatar" :src="item.avatar" size="large" />
|
<template #extra>
|
||||||
<span
|
<a-badge :status="commentStatuses[item.status].status" :text="item.status | statusText" />
|
||||||
v-if="item.authorUrl"
|
</template>
|
||||||
slot="title"
|
<a-list-item-meta>
|
||||||
style="max-width: 300px; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis"
|
<template #description>
|
||||||
>
|
发表在
|
||||||
<a-icon v-if="item.isAdmin" style="margin-right: 3px" type="user" />
|
<a v-if="targetName === 'posts'" :href="item.post.fullPath" target="_blank"
|
||||||
<a :href="item.authorUrl" target="_blank">{{ item.author }}</a>
|
>《{{ item.post.title }}》</a
|
||||||
<small style="color: rgba(0, 0, 0, 0.45)">{{ item.createTime | timeAgo }}</small>
|
>
|
||||||
</span>
|
<a v-if="targetName === 'sheets'" :href="item.sheet.fullPath" target="_blank"
|
||||||
<span
|
>《{{ item.sheet.title }}》</a
|
||||||
v-else
|
>
|
||||||
slot="title"
|
</template>
|
||||||
style="max-width: 300px; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis"
|
|
||||||
>
|
<template #avatar>
|
||||||
<a-icon v-if="item.isAdmin" style="margin-right: 3px" type="user" /> {{ item.author }} <small
|
<a-avatar :src="item.avatar" size="large" />
|
||||||
style="color: rgba(0, 0, 0, 0.45)"
|
</template>
|
||||||
>
|
|
||||||
{{ item.createTime | timeAgo }}
|
<template #title>
|
||||||
</small>
|
<div class="truncate">
|
||||||
</span>
|
<a-icon v-if="item.isAdmin" class="mr-2" type="user" />
|
||||||
</a-list-item-meta>
|
|
||||||
<p v-html="item.content"></p>
|
<a v-if="item.authorUrl" :href="item.authorUrl" class="mr-1" target="_blank">{{ item.author }}</a>
|
||||||
</a-list-item>
|
<span v-else class="mr-1">{{ item.author }}</span>
|
||||||
|
|
||||||
|
<small style="color: rgba(0, 0, 0, 0.45)">
|
||||||
|
{{ item.createTime | timeAgo }}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-list-item-meta>
|
||||||
|
<p v-html="$options.filters.markdownRender(item.content)"></p>
|
||||||
|
</a-list-item>
|
||||||
|
</template>
|
||||||
</a-list>
|
</a-list>
|
||||||
<!-- Desktop -->
|
<!-- Desktop -->
|
||||||
<a-table
|
<a-table
|
||||||
v-else
|
v-else
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:dataSource="formattedComments"
|
:dataSource="list.data"
|
||||||
:loading="list.loading"
|
:loading="list.loading"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
:rowKey="comment => comment.id"
|
:rowKey="comment => comment.id"
|
||||||
|
@ -168,53 +188,70 @@
|
||||||
}"
|
}"
|
||||||
scrollToFirstRowOnChange
|
scrollToFirstRowOnChange
|
||||||
>
|
>
|
||||||
<template slot="author" slot-scope="text, record">
|
<template #author="text, record">
|
||||||
<a-icon v-if="record.isAdmin" style="margin-right: 3px" type="user" />
|
<a-icon v-if="record.isAdmin" class="mr-2" type="user" />
|
||||||
<a v-if="record.authorUrl" :href="record.authorUrl" target="_blank">{{ text }}</a>
|
<a v-if="record.authorUrl" :href="record.authorUrl" target="_blank">{{ text }}</a>
|
||||||
<span v-else>{{ text }}</span>
|
<span v-else>{{ text }}</span>
|
||||||
</template>
|
</template>
|
||||||
<p slot="content" slot-scope="content" class="comment-content-wrapper" v-html="content"></p>
|
|
||||||
<span slot="status" slot-scope="statusProperty">
|
<template #content="content">
|
||||||
<a-badge :status="statusProperty.status" :text="statusProperty.text" />
|
<p class="comment-content-wrapper" v-html="$options.filters.markdownRender(content)"></p>
|
||||||
</span>
|
</template>
|
||||||
<a v-if="type === 'posts'" slot="post" slot-scope="post" :href="post.fullPath" target="_blank">
|
|
||||||
{{ post.title }}
|
<template #status="status">
|
||||||
</a>
|
<a-badge :status="commentStatuses[status].status" :text="status | statusText" />
|
||||||
<a v-if="type === 'sheets'" slot="sheet" slot-scope="sheet" :href="sheet.fullPath" target="_blank">
|
</template>
|
||||||
{{ sheet.title }}
|
|
||||||
</a>
|
<template v-if="targetName === 'posts'" #post="post">
|
||||||
<span slot="createTime" slot-scope="createTime">
|
<a :href="post.fullPath" target="_blank">
|
||||||
|
{{ post.title }}
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-if="targetName === 'sheets'" #sheet="sheet">
|
||||||
|
<a :href="sheet.fullPath" target="_blank">
|
||||||
|
{{ sheet.title }}
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #createTime="createTime">
|
||||||
<a-tooltip placement="top">
|
<a-tooltip placement="top">
|
||||||
<template slot="title">
|
<template #title>
|
||||||
{{ createTime | moment }}
|
{{ createTime | moment }}
|
||||||
</template>
|
</template>
|
||||||
{{ createTime | timeAgo }}
|
{{ createTime | timeAgo }}
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</span>
|
</template>
|
||||||
<span slot="action" slot-scope="text, record">
|
|
||||||
<a-dropdown v-if="record.status === 'AUDITING'" :trigger="['click']">
|
<template #action="text, record">
|
||||||
|
<a-dropdown v-if="record.status === commentStatuses.AUDITING.value" :trigger="['click']">
|
||||||
<a-button class="!p-0" type="link">通过</a-button>
|
<a-button class="!p-0" type="link">通过</a-button>
|
||||||
<a-menu slot="overlay">
|
|
||||||
<a-menu-item key="1" @click="handleEditStatusClick(record.id, 'PUBLISHED')"> 通过 </a-menu-item>
|
<template #overlay>
|
||||||
<a-menu-item key="2" @click="handleReplyAndPassClick(record)"> 通过并回复 </a-menu-item>
|
<a-menu>
|
||||||
</a-menu>
|
<a-menu-item key="1" @click="handleChangeStatus(record.id, commentStatuses.PUBLISHED.value)">
|
||||||
|
通过
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item key="2" @click="handlePublishAndReply(record)"> 通过并回复</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</template>
|
||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
|
|
||||||
<a-button
|
<a-button
|
||||||
v-else-if="record.status === 'PUBLISHED'"
|
v-else-if="record.status === commentStatuses.PUBLISHED.value"
|
||||||
class="!p-0"
|
class="!p-0"
|
||||||
type="link"
|
type="link"
|
||||||
@click="handleReplyClick(record)"
|
@click="handleOpenReplyModal(record)"
|
||||||
>
|
>
|
||||||
回复
|
回复
|
||||||
</a-button>
|
</a-button>
|
||||||
|
|
||||||
<a-popconfirm
|
<a-popconfirm
|
||||||
v-else-if="record.status === 'RECYCLE'"
|
v-else-if="record.status === commentStatuses.RECYCLE.value"
|
||||||
:title="'你确定要还原该评论?'"
|
:title="'你确定要还原该评论?'"
|
||||||
cancelText="取消"
|
cancelText="取消"
|
||||||
okText="确定"
|
okText="确定"
|
||||||
@confirm="handleEditStatusClick(record.id, 'PUBLISHED')"
|
@confirm="handleChangeStatus(record.id, commentStatuses.PUBLISHED.value)"
|
||||||
>
|
>
|
||||||
<a-button class="!p-0" type="link">还原</a-button>
|
<a-button class="!p-0" type="link">还原</a-button>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
|
@ -222,25 +259,25 @@
|
||||||
<a-divider type="vertical" />
|
<a-divider type="vertical" />
|
||||||
|
|
||||||
<a-popconfirm
|
<a-popconfirm
|
||||||
v-if="record.status === 'PUBLISHED' || record.status === 'AUDITING'"
|
v-if="[commentStatuses.PUBLISHED.value, commentStatuses.AUDITING.value].includes(record.status)"
|
||||||
:title="'你确定要将该评论移到回收站?'"
|
:title="'你确定要将该评论移到回收站?'"
|
||||||
cancelText="取消"
|
cancelText="取消"
|
||||||
okText="确定"
|
okText="确定"
|
||||||
@confirm="handleEditStatusClick(record.id, 'RECYCLE')"
|
@confirm="handleChangeStatus(record.id, commentStatuses.RECYCLE.value)"
|
||||||
>
|
>
|
||||||
<a-button class="!p-0" type="link">回收站</a-button>
|
<a-button class="!p-0" type="link">回收站</a-button>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
|
|
||||||
<a-popconfirm
|
<a-popconfirm
|
||||||
v-else-if="record.status === 'RECYCLE'"
|
v-else-if="record.status === commentStatuses.RECYCLE.value"
|
||||||
:title="'你确定要永久删除该评论?'"
|
:title="'你确定要永久删除该评论?'"
|
||||||
cancelText="取消"
|
cancelText="取消"
|
||||||
okText="确定"
|
okText="确定"
|
||||||
@confirm="handleDeleteClick(record.id)"
|
@confirm="handleDelete(record.id)"
|
||||||
>
|
>
|
||||||
<a-button class="!p-0" type="link">删除</a-button>
|
<a-button class="!p-0" type="link">删除</a-button>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</span>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<div class="page-wrapper">
|
<div class="page-wrapper">
|
||||||
<a-pagination
|
<a-pagination
|
||||||
|
@ -258,37 +295,22 @@
|
||||||
</div>
|
</div>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
|
||||||
<a-modal
|
<CommentReplyModal
|
||||||
v-if="selectedComment"
|
:comment="selectedComment"
|
||||||
v-model="replyCommentVisible"
|
:target="target"
|
||||||
:title="'回复给:' + selectedComment.author"
|
:target-id="targetId"
|
||||||
destroyOnClose
|
:visible.sync="replyModalVisible"
|
||||||
@close="onReplyClose"
|
@succeed="onReplyModalClose"
|
||||||
>
|
/>
|
||||||
<template slot="footer">
|
|
||||||
<ReactiveButton
|
|
||||||
:errored="replyErrored"
|
|
||||||
:loading="replying"
|
|
||||||
erroredText="回复失败"
|
|
||||||
loadedText="回复成功"
|
|
||||||
text="回复"
|
|
||||||
type="primary"
|
|
||||||
@callback="handleRepliedCallback"
|
|
||||||
@click="handleCreateClick"
|
|
||||||
></ReactiveButton>
|
|
||||||
</template>
|
|
||||||
<a-form-model ref="replyCommentForm" :model="replyComment" :rules="replyCommentRules" layout="vertical">
|
|
||||||
<a-form-model-item prop="content">
|
|
||||||
<a-input ref="contentInput" v-model="replyComment.content" :autoSize="{ minRows: 8 }" type="textarea" />
|
|
||||||
</a-form-model-item>
|
|
||||||
</a-form-model>
|
|
||||||
</a-modal>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
// components
|
||||||
|
import CommentReplyModal from '@/components/Comment/CommentReplyModal'
|
||||||
|
|
||||||
import { mixin, mixinDevice } from '@/mixins/mixin.js'
|
import { mixin, mixinDevice } from '@/mixins/mixin.js'
|
||||||
import { marked } from 'marked'
|
|
||||||
import apiClient from '@/utils/api-client'
|
import apiClient from '@/utils/api-client'
|
||||||
|
import { commentStatuses } from '@/core/constant'
|
||||||
|
|
||||||
const postColumns = [
|
const postColumns = [
|
||||||
{
|
{
|
||||||
|
@ -305,8 +327,7 @@ const postColumns = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: '状态',
|
||||||
className: 'status',
|
dataIndex: 'status',
|
||||||
dataIndex: 'statusProperty',
|
|
||||||
width: '100px',
|
width: '100px',
|
||||||
scopedSlots: { customRender: 'status' }
|
scopedSlots: { customRender: 'status' }
|
||||||
},
|
},
|
||||||
|
@ -345,8 +366,7 @@ const sheetColumns = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: '状态',
|
||||||
className: 'status',
|
dataIndex: 'status',
|
||||||
dataIndex: 'statusProperty',
|
|
||||||
width: '100px',
|
width: '100px',
|
||||||
scopedSlots: { customRender: 'status' }
|
scopedSlots: { customRender: 'status' }
|
||||||
},
|
},
|
||||||
|
@ -371,43 +391,23 @@ const sheetColumns = [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const commentStatus = {
|
|
||||||
PUBLISHED: {
|
|
||||||
value: 'PUBLISHED',
|
|
||||||
color: 'green',
|
|
||||||
status: 'success',
|
|
||||||
text: '已发布'
|
|
||||||
},
|
|
||||||
AUDITING: {
|
|
||||||
value: 'AUDITING',
|
|
||||||
color: 'yellow',
|
|
||||||
status: 'warning',
|
|
||||||
text: '待审核'
|
|
||||||
},
|
|
||||||
RECYCLE: {
|
|
||||||
value: 'RECYCLE',
|
|
||||||
color: 'red',
|
|
||||||
status: 'error',
|
|
||||||
text: '回收站'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CommentTab',
|
name: 'CommentTab',
|
||||||
|
components: { CommentReplyModal },
|
||||||
mixins: [mixin, mixinDevice],
|
mixins: [mixin, mixinDevice],
|
||||||
props: {
|
props: {
|
||||||
type: {
|
target: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
default: 'posts',
|
default: 'post',
|
||||||
validator: function (value) {
|
validator: function (value) {
|
||||||
return ['posts', 'sheets', 'journals'].indexOf(value) !== -1
|
return ['post', 'sheet', 'journal'].indexOf(value) !== -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
commentStatus,
|
commentStatuses,
|
||||||
replyCommentVisible: false,
|
|
||||||
|
|
||||||
list: {
|
list: {
|
||||||
data: [],
|
data: [],
|
||||||
|
@ -422,28 +422,17 @@ export default {
|
||||||
status: null
|
status: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
selectedRowKeys: [],
|
selectedRowKeys: [],
|
||||||
selectedRows: [],
|
selectedRows: [],
|
||||||
selectedComment: {},
|
selectedComment: {},
|
||||||
replyComment: {},
|
replyModalVisible: false
|
||||||
replyCommentRules: {
|
|
||||||
content: [{ required: true, message: '* 内容不能为空', trigger: ['change'] }]
|
|
||||||
},
|
|
||||||
replying: false,
|
|
||||||
replyErrored: false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.handleListComments()
|
this.handleListComments()
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
formattedComments() {
|
|
||||||
return this.list.data.map(comment => {
|
|
||||||
comment.statusProperty = this.commentStatus[comment.status]
|
|
||||||
comment.content = marked.parse(comment.content)
|
|
||||||
return comment
|
|
||||||
})
|
|
||||||
},
|
|
||||||
pagination() {
|
pagination() {
|
||||||
return {
|
return {
|
||||||
page: this.list.params.page + 1,
|
page: this.list.params.page + 1,
|
||||||
|
@ -452,7 +441,22 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
columns() {
|
columns() {
|
||||||
return this.type === 'posts' ? postColumns : sheetColumns
|
return this.targetName === 'posts' ? postColumns : sheetColumns
|
||||||
|
},
|
||||||
|
targetName() {
|
||||||
|
return `${this.target}s`
|
||||||
|
},
|
||||||
|
targetId() {
|
||||||
|
if (Object.keys(this.selectedComment).length === 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if (this.targetName === 'posts') {
|
||||||
|
return this.selectedComment.post.id
|
||||||
|
}
|
||||||
|
if (this.targetName === 'sheets') {
|
||||||
|
return this.selectedComment.sheet.id
|
||||||
|
}
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -460,7 +464,7 @@ export default {
|
||||||
try {
|
try {
|
||||||
this.list.loading = true
|
this.list.loading = true
|
||||||
|
|
||||||
const response = await apiClient.comment.list(this.type, this.list.params)
|
const response = await apiClient.comment.list(this.targetName, this.list.params)
|
||||||
|
|
||||||
this.list.data = response.data.content
|
this.list.data = response.data.content
|
||||||
this.list.total = response.data.total
|
this.list.total = response.data.total
|
||||||
|
@ -472,74 +476,76 @@ export default {
|
||||||
this.list.loading = false
|
this.list.loading = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleQuery() {
|
handleQuery() {
|
||||||
this.handleClearRowKeys()
|
this.handleClearRowKeys()
|
||||||
this.handlePageChange(1)
|
this.handlePageChange(1)
|
||||||
},
|
},
|
||||||
handleEditStatusClick(commentId, status) {
|
|
||||||
apiClient.comment
|
async handleChangeStatus(commentId, status) {
|
||||||
.updateStatusById(this.type, commentId, status)
|
try {
|
||||||
.then(() => {
|
await apiClient.comment.updateStatusById(this.targetName, commentId, status)
|
||||||
this.$message.success('操作成功!')
|
this.$message.success('操作成功!')
|
||||||
})
|
} catch (e) {
|
||||||
.finally(() => {
|
this.$log.error('Failed to change comment status', e)
|
||||||
this.handleListComments()
|
} finally {
|
||||||
})
|
await this.handleListComments()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
handleDeleteClick(commentId) {
|
|
||||||
apiClient.comment
|
async handleChangeStatusInBatch(status) {
|
||||||
.delete(this.type, commentId)
|
if (!this.selectedRowKeys.length) {
|
||||||
.then(() => {
|
this.$message.info('请至少选择一项!')
|
||||||
this.$message.success('删除成功!')
|
return
|
||||||
})
|
}
|
||||||
.finally(() => {
|
|
||||||
this.handleListComments()
|
try {
|
||||||
})
|
this.$log.debug(`commentIds: ${this.selectedRowKeys}, status: ${status}`)
|
||||||
|
await apiClient.comment.updateStatusInBatch(this.targetName, this.selectedRowKeys, status)
|
||||||
|
this.selectedRowKeys = []
|
||||||
|
} catch (e) {
|
||||||
|
this.$log.error('Failed to change comment status in batch', e)
|
||||||
|
} finally {
|
||||||
|
await this.handleListComments()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
handleReplyAndPassClick(comment) {
|
|
||||||
this.handleReplyClick(comment)
|
async handleDelete(commentId) {
|
||||||
this.handleEditStatusClick(comment.id, 'PUBLISHED')
|
try {
|
||||||
|
await apiClient.comment.delete(this.targetName, commentId)
|
||||||
|
this.$message.success('删除成功!')
|
||||||
|
} catch (e) {
|
||||||
|
this.$log.error('Failed to delete comment', e)
|
||||||
|
} finally {
|
||||||
|
await this.handleListComments()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
handleReplyClick(comment) {
|
|
||||||
|
async handleDeleteInBatch() {
|
||||||
|
if (!this.selectedRowKeys.length) {
|
||||||
|
this.$message.info('请至少选择一项!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.$log.debug(`delete: ${this.selectedRowKeys}`)
|
||||||
|
await apiClient.comment.deleteInBatch(this.targetName, this.selectedRowKeys)
|
||||||
|
this.selectedRowKeys = []
|
||||||
|
} catch (e) {
|
||||||
|
this.$log.error('Failed to delete comments in batch', e)
|
||||||
|
} finally {
|
||||||
|
await this.handleListComments()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async handlePublishAndReply(comment) {
|
||||||
|
await this.handleChangeStatus(comment.id, this.commentStatuses.PUBLISHED.value)
|
||||||
|
this.handleOpenReplyModal(comment)
|
||||||
|
},
|
||||||
|
|
||||||
|
handleOpenReplyModal(comment) {
|
||||||
this.selectedComment = comment
|
this.selectedComment = comment
|
||||||
this.replyCommentVisible = true
|
this.replyModalVisible = true
|
||||||
this.replyComment.parentId = comment.id
|
|
||||||
if (this.type === 'posts') {
|
|
||||||
this.replyComment.postId = comment.post.id
|
|
||||||
} else {
|
|
||||||
this.replyComment.postId = comment.sheet.id
|
|
||||||
}
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs.contentInput.focus()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
handleCreateClick() {
|
|
||||||
const _this = this
|
|
||||||
_this.$refs.replyCommentForm.validate(valid => {
|
|
||||||
if (valid) {
|
|
||||||
_this.replying = true
|
|
||||||
apiClient.comment
|
|
||||||
.create(_this.type, _this.replyComment)
|
|
||||||
.catch(() => {
|
|
||||||
_this.replyErrored = true
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
_this.replying = false
|
|
||||||
}, 400)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
handleRepliedCallback() {
|
|
||||||
if (this.replyErrored) {
|
|
||||||
this.replyErrored = false
|
|
||||||
} else {
|
|
||||||
this.replyComment = {}
|
|
||||||
this.selectedComment = {}
|
|
||||||
this.replyCommentVisible = false
|
|
||||||
this.handleListComments()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -566,48 +572,22 @@ export default {
|
||||||
this.handleClearRowKeys()
|
this.handleClearRowKeys()
|
||||||
this.handlePageChange(1)
|
this.handlePageChange(1)
|
||||||
},
|
},
|
||||||
handleEditStatusMore(status) {
|
|
||||||
if (this.selectedRowKeys.length <= 0) {
|
|
||||||
this.$message.info('请至少选择一项!')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
apiClient.comment
|
|
||||||
.updateStatusInBatch(this.type, this.selectedRowKeys, status)
|
|
||||||
.then(() => {
|
|
||||||
this.$log.debug(`commentIds: ${this.selectedRowKeys}, status: ${status}`)
|
|
||||||
this.selectedRowKeys = []
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.handleListComments()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
handleDeleteMore() {
|
|
||||||
if (this.selectedRowKeys.length <= 0) {
|
|
||||||
this.$message.info('请至少选择一项!')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
apiClient.comment
|
|
||||||
.deleteInBatch(this.type, this.selectedRowKeys)
|
|
||||||
.then(() => {
|
|
||||||
this.$log.debug(`delete: ${this.selectedRowKeys}`)
|
|
||||||
this.selectedRowKeys = []
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.handleListComments()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
handleClearRowKeys() {
|
handleClearRowKeys() {
|
||||||
this.selectedRowKeys = []
|
this.selectedRowKeys = []
|
||||||
},
|
},
|
||||||
onReplyClose() {
|
|
||||||
this.replyComment = {}
|
onReplyModalClose() {
|
||||||
this.selectedComment = {}
|
this.selectedComment = {}
|
||||||
this.replyCommentVisible = false
|
this.replyModalVisible = false
|
||||||
|
this.handleListComments()
|
||||||
},
|
},
|
||||||
|
|
||||||
onSelectionChange(selectedRowKeys) {
|
onSelectionChange(selectedRowKeys) {
|
||||||
this.selectedRowKeys = selectedRowKeys
|
this.selectedRowKeys = selectedRowKeys
|
||||||
this.$log.debug(`SelectedRowKeys: ${selectedRowKeys}`)
|
this.$log.debug(`SelectedRowKeys: ${selectedRowKeys}`)
|
||||||
},
|
},
|
||||||
|
|
||||||
getCheckboxProps(comment) {
|
getCheckboxProps(comment) {
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
|
@ -616,6 +596,11 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
statusText(type) {
|
||||||
|
return type ? commentStatuses[type].text : ''
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue