|
@@ -7,14 +7,19 @@
|
|
|
<el-button style="float: right" type="primary" size="small" @click="$router.push('/article-edit')">+ 新建文章</el-button>
|
|
<el-button style="float: right" type="primary" size="small" @click="$router.push('/article-edit')">+ 新建文章</el-button>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
+ <!-- 状态标签栏 -->
|
|
|
|
|
+ <div class="status-tabs">
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ v-for="tab in statusTabs"
|
|
|
|
|
+ :key="tab.value"
|
|
|
|
|
+ :type="filters.status === tab.value ? 'primary' : 'default'"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ @click="filters.status = tab.value; loadList()"
|
|
|
|
|
+ >{{ tab.label }}</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<!-- 搜索筛选栏 -->
|
|
<!-- 搜索筛选栏 -->
|
|
|
<div class="filter-bar">
|
|
<div class="filter-bar">
|
|
|
- <el-select v-model="filters.status" placeholder="状态" clearable @change="loadList" style="width: 130px;">
|
|
|
|
|
- <el-option label="全部" value="" />
|
|
|
|
|
- <el-option label="草稿" value="draft" />
|
|
|
|
|
- <el-option label="已发布" value="published" />
|
|
|
|
|
- <el-option label="已归档" value="archived" />
|
|
|
|
|
- </el-select>
|
|
|
|
|
<el-select v-model="filters.categoryId" placeholder="分类" clearable @change="loadList" style="width: 150px;">
|
|
<el-select v-model="filters.categoryId" placeholder="分类" clearable @change="loadList" style="width: 150px;">
|
|
|
<el-option label="全部分类" value="" />
|
|
<el-option label="全部分类" value="" />
|
|
|
<el-option v-for="cat in categories" :key="cat.id" :label="cat.name" :value="cat.id" />
|
|
<el-option v-for="cat in categories" :key="cat.id" :label="cat.name" :value="cat.id" />
|
|
@@ -92,18 +97,21 @@
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
<el-table-column prop="author" label="作者" width="100" />
|
|
<el-table-column prop="author" label="作者" width="100" />
|
|
|
- <el-table-column label="状态" width="90">
|
|
|
|
|
|
|
+ <el-table-column label="状态" width="100">
|
|
|
<template slot-scope="{ row }">
|
|
<template slot-scope="{ row }">
|
|
|
- <el-tag v-if="row.status === 'published'" size="small" type="success">已发布</el-tag>
|
|
|
|
|
- <el-tag v-else-if="row.status === 'draft'" size="small" type="info">草稿</el-tag>
|
|
|
|
|
- <el-tag v-else size="small" type="warning">已归档</el-tag>
|
|
|
|
|
|
|
+ <el-tag v-if="row.status === 'draft' && row.auditStatus === 'pending'" size="small" type="warning">待审核</el-tag>
|
|
|
|
|
+ <el-tag v-else-if="row.status === 'draft'" size="small" type="info">草稿箱</el-tag>
|
|
|
|
|
+ <el-tag v-else-if="row.status === 'rejected'" size="small" type="danger">已驳回</el-tag>
|
|
|
|
|
+ <el-tag v-else-if="row.status === 'published'" size="small" type="success">发布中</el-tag>
|
|
|
|
|
+ <el-tag v-else-if="row.status === 'withdrawn'" size="small">已撤回</el-tag>
|
|
|
|
|
+ <el-tag v-else size="small" type="info">{{ row.status }}</el-tag>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
<el-table-column label="审核状态" width="120">
|
|
<el-table-column label="审核状态" width="120">
|
|
|
<template slot-scope="{ row }">
|
|
<template slot-scope="{ row }">
|
|
|
<el-tag v-if="row.auditStatus === 'approved'" size="small" type="success">已通过</el-tag>
|
|
<el-tag v-if="row.auditStatus === 'approved'" size="small" type="success">已通过</el-tag>
|
|
|
<el-tag v-else-if="row.auditStatus === 'pending'" size="small" type="warning">待审核</el-tag>
|
|
<el-tag v-else-if="row.auditStatus === 'pending'" size="small" type="warning">待审核</el-tag>
|
|
|
- <el-tag v-else-if="row.auditStatus === 'rejected'" size="small" type="danger">已驳回</el-tag>
|
|
|
|
|
|
|
+ <el-tag v-else-if="row.auditStatus === 'rejected'" size="small" type="danger" :title="row.auditReason || ''">已驳回</el-tag>
|
|
|
<span v-else>-</span>
|
|
<span v-else>-</span>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
@@ -113,27 +121,47 @@
|
|
|
{{ row.publishedAt || '-' }}
|
|
{{ row.publishedAt || '-' }}
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
- <el-table-column label="操作" width="400" fixed="right">
|
|
|
|
|
|
|
+ <el-table-column label="操作" width="420" fixed="right">
|
|
|
<template slot-scope="{ row }">
|
|
<template slot-scope="{ row }">
|
|
|
- <!-- 草稿且从未发布过:可编辑 -->
|
|
|
|
|
- <el-button v-if="row.status === 'draft' && !row.publishedAt" size="mini" type="primary" plain @click="$router.push('/article-edit?id=' + row.id)">编辑</el-button>
|
|
|
|
|
- <!-- 已发布或曾发布过的草稿:只能查看 -->
|
|
|
|
|
- <el-button v-else-if="row.status === 'draft'" size="mini" type="info" plain @click="$router.push('/article-edit?id=' + row.id + '&readonly=1')">查看</el-button>
|
|
|
|
|
- <el-button size="mini" type="default" @click="handleCopy(row)">复制</el-button>
|
|
|
|
|
- <!-- 审核中:审核通过/驳回 -->
|
|
|
|
|
- <el-button v-if="row.auditStatus === 'pending'" size="mini" type="success" @click="handleAudit(row, 'approved')">通过</el-button>
|
|
|
|
|
- <el-button v-if="row.auditStatus === 'pending'" size="mini" type="danger" @click="showRejectDialog(row)">驳回</el-button>
|
|
|
|
|
- <el-button v-if="row.status === 'draft'" size="mini" type="success" @click="handlePublish(row)">发布</el-button>
|
|
|
|
|
- <el-button v-if="row.status === 'published'" size="mini" type="warning" @click="handleUnpublish(row)">下架</el-button>
|
|
|
|
|
- <el-button
|
|
|
|
|
- size="mini"
|
|
|
|
|
- :type="row.isFeatured === 1 || row.isFeatured === true ? 'warning' : 'default'"
|
|
|
|
|
- :plain="!(row.isFeatured === 1 || row.isFeatured === true)"
|
|
|
|
|
- @click="handleToggleFeatured(row)"
|
|
|
|
|
- >
|
|
|
|
|
- {{ row.isFeatured === 1 || row.isFeatured === true ? '取消精选' : '精选' }}
|
|
|
|
|
- </el-button>
|
|
|
|
|
- <el-button size="mini" type="danger" @click="handleDelete(row)">删除</el-button>
|
|
|
|
|
|
|
+ <!-- 草稿箱:可编辑 -->
|
|
|
|
|
+ <template v-if="row.status === 'draft' && !row.auditStatus">
|
|
|
|
|
+ <el-button size="mini" type="primary" plain @click="$router.push('/article-edit?id=' + row.id)">编辑</el-button>
|
|
|
|
|
+ <el-button size="mini" type="success" @click="handleSubmitReview(row)">提交审核</el-button>
|
|
|
|
|
+ <el-button size="mini" type="warning" plain @click="handlePublishDirect(row)">直接发布</el-button>
|
|
|
|
|
+ <el-button size="mini" @click="handleCopy(row)">复制</el-button>
|
|
|
|
|
+ <el-button size="mini" type="danger" @click="handleDelete(row)">删除</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <!-- 待审核:审核操作 -->
|
|
|
|
|
+ <template v-else-if="row.status === 'draft' && row.auditStatus === 'pending'">
|
|
|
|
|
+ <el-button size="mini" type="info" plain @click="$router.push('/article-edit?id=' + row.id + '&readonly=1')">查看</el-button>
|
|
|
|
|
+ <el-button size="mini" type="success" @click="handleAudit(row, 'approved')">通过</el-button>
|
|
|
|
|
+ <el-button size="mini" type="danger" @click="showRejectDialog(row)">驳回</el-button>
|
|
|
|
|
+ <el-button size="mini" @click="handleCopy(row)">复制</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <!-- 已驳回:查看 + 重新编辑 -->
|
|
|
|
|
+ <template v-else-if="row.status === 'rejected'">
|
|
|
|
|
+ <el-button size="mini" type="info" plain @click="$router.push('/article-edit?id=' + row.id + '&readonly=1')">查看</el-button>
|
|
|
|
|
+ <el-button size="mini" type="primary" @click="handleReDraft(row)">重新编辑</el-button>
|
|
|
|
|
+ <el-button size="mini" @click="handleCopy(row)">复制</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <!-- 发布中:查看 + 下架 + 精选 -->
|
|
|
|
|
+ <template v-else-if="row.status === 'published'">
|
|
|
|
|
+ <el-button size="mini" type="info" plain @click="$router.push('/article-edit?id=' + row.id + '&readonly=1')">查看</el-button>
|
|
|
|
|
+ <el-button size="mini" type="warning" @click="handleWithdraw(row)">下架</el-button>
|
|
|
|
|
+ <el-button size="mini" :type="row.isFeatured === 1 || row.isFeatured === true ? 'warning' : 'default'" :plain="!(row.isFeatured === 1 || row.isFeatured === true)" @click="handleToggleFeatured(row)">{{ row.isFeatured === 1 || row.isFeatured === true ? '取消精选' : '精选' }}</el-button>
|
|
|
|
|
+ <el-button size="mini" @click="handleCopy(row)">复制</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <!-- 已撤回:查看 + 重新发布 -->
|
|
|
|
|
+ <template v-else-if="row.status === 'withdrawn'">
|
|
|
|
|
+ <el-button size="mini" type="info" plain @click="$router.push('/article-edit?id=' + row.id + '&readonly=1')">查看</el-button>
|
|
|
|
|
+ <el-button size="mini" type="success" @click="handlePublishDirect(row)">重新发布</el-button>
|
|
|
|
|
+ <el-button size="mini" @click="handleCopy(row)">复制</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <!-- 其他 -->
|
|
|
|
|
+ <template v-else>
|
|
|
|
|
+ <el-button size="mini" type="info" plain @click="$router.push('/article-edit?id=' + row.id + '&readonly=1')">查看</el-button>
|
|
|
|
|
+ <el-button size="mini" @click="handleCopy(row)">复制</el-button>
|
|
|
|
|
+ </template>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
</el-table>
|
|
</el-table>
|
|
@@ -175,7 +203,10 @@ import {
|
|
|
adminArticleCategoriesList,
|
|
adminArticleCategoriesList,
|
|
|
adminArticleAudit,
|
|
adminArticleAudit,
|
|
|
adminArticleDetail,
|
|
adminArticleDetail,
|
|
|
- adminArticleCreate
|
|
|
|
|
|
|
+ adminArticleCreate,
|
|
|
|
|
+ adminArticleSubmitReview,
|
|
|
|
|
+ adminArticleWithdraw,
|
|
|
|
|
+ adminArticleReDraft
|
|
|
} from '@/api/article.js'
|
|
} from '@/api/article.js'
|
|
|
import { getTagList } from '@/api/dimension.js'
|
|
import { getTagList } from '@/api/dimension.js'
|
|
|
|
|
|
|
@@ -188,6 +219,14 @@ export default {
|
|
|
total: 0,
|
|
total: 0,
|
|
|
page: 1,
|
|
page: 1,
|
|
|
size: 20,
|
|
size: 20,
|
|
|
|
|
+ statusTabs: [
|
|
|
|
|
+ { value: '', label: '全部' },
|
|
|
|
|
+ { value: 'draft', label: '草稿箱' },
|
|
|
|
|
+ { value: 'pending', label: '待审核' },
|
|
|
|
|
+ { value: 'rejected', label: '已驳回' },
|
|
|
|
|
+ { value: 'published', label: '发布中' },
|
|
|
|
|
+ { value: 'withdrawn', label: '已撤回' }
|
|
|
|
|
+ ],
|
|
|
filters: {
|
|
filters: {
|
|
|
status: '',
|
|
status: '',
|
|
|
categoryId: '',
|
|
categoryId: '',
|
|
@@ -259,7 +298,7 @@ export default {
|
|
|
onPageChange() {
|
|
onPageChange() {
|
|
|
this.loadList()
|
|
this.loadList()
|
|
|
},
|
|
},
|
|
|
- async handlePublish(row) {
|
|
|
|
|
|
|
+ async handlePublishDirect(row) {
|
|
|
try {
|
|
try {
|
|
|
await adminArticlePublish({ id: row.id, status: 'published' })
|
|
await adminArticlePublish({ id: row.id, status: 'published' })
|
|
|
this.$message.success('文章已发布')
|
|
this.$message.success('文章已发布')
|
|
@@ -268,15 +307,33 @@ export default {
|
|
|
this.$message.error(e.message || '发布失败')
|
|
this.$message.error(e.message || '发布失败')
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
- async handleUnpublish(row) {
|
|
|
|
|
|
|
+ async handleSubmitReview(row) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await adminArticleSubmitReview({ id: row.id })
|
|
|
|
|
+ this.$message.success('已提交审核')
|
|
|
|
|
+ this.loadList()
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ this.$message.error(e.message || '提交审核失败')
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ async handleWithdraw(row) {
|
|
|
try {
|
|
try {
|
|
|
- await adminArticlePublish({ id: row.id, status: 'draft' })
|
|
|
|
|
|
|
+ await adminArticleWithdraw({ id: row.id })
|
|
|
this.$message.success('文章已下架')
|
|
this.$message.success('文章已下架')
|
|
|
this.loadList()
|
|
this.loadList()
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
this.$message.error(e.message || '下架失败')
|
|
this.$message.error(e.message || '下架失败')
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
+ async handleReDraft(row) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await adminArticleReDraft({ id: row.id })
|
|
|
|
|
+ this.$message.success('已保存到草稿箱')
|
|
|
|
|
+ this.loadList()
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ this.$message.error(e.message || '操作失败')
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
async handleToggleFeatured(row) {
|
|
async handleToggleFeatured(row) {
|
|
|
try {
|
|
try {
|
|
|
const newVal = row.isFeatured === 1 || row.isFeatured === true ? 0 : 1
|
|
const newVal = row.isFeatured === 1 || row.isFeatured === true ? 0 : 1
|
|
@@ -387,4 +444,11 @@ export default {
|
|
|
gap: 10px;
|
|
gap: 10px;
|
|
|
flex-wrap: wrap;
|
|
flex-wrap: wrap;
|
|
|
}
|
|
}
|
|
|
|
|
+.status-tabs {
|
|
|
|
|
+ margin-bottom: 18px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 6px;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|