refactor: post list component code optimization (halo-dev/console#445)

Signed-off-by: Ryan Wang <i@ryanc.cc>
pull/3445/head
Ryan Wang 2022-02-21 13:59:10 +08:00 committed by GitHub
parent f33dfed835
commit 2f775241b7
2 changed files with 216 additions and 200 deletions

View File

@ -95,3 +95,30 @@ export const attachmentTypes = {
text: 'MinIO' text: 'MinIO'
} }
} }
export const postStatuses = {
PUBLISHED: {
value: 'PUBLISHED',
color: 'green',
status: 'success',
text: '已发布'
},
DRAFT: {
value: 'DRAFT',
color: 'yellow',
status: 'warning',
text: '草稿'
},
RECYCLE: {
value: 'RECYCLE',
color: 'red',
status: 'error',
text: '回收站'
},
INTIMATE: {
value: 'INTIMATE',
color: 'blue',
status: 'success',
text: '私密'
}
}

View File

@ -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(postStatus)" :key="status" :value="status"> <a-select-option v-for="status in Object.keys(postStatuses)" :key="status" :value="status">
{{ postStatus[status].text }} {{ postStatuses[status].text }}
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
@ -51,32 +51,34 @@
<a-button icon="plus" type="primary">写文章</a-button> <a-button icon="plus" type="primary">写文章</a-button>
</router-link> </router-link>
<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="['DRAFT', 'RECYCLE'].includes(list.params.status)" <a-menu-item
key="1" v-if="['DRAFT', 'RECYCLE'].includes(list.params.status)"
@click="handleEditStatusMore(postStatus.PUBLISHED.value)" key="1"
> @click="handleEditStatusMore(postStatuses.PUBLISHED.value)"
发布 >
</a-menu-item> 发布
<a-menu-item </a-menu-item>
v-if="['PUBLISHED', 'DRAFT', 'INTIMATE'].includes(list.params.status)" <a-menu-item
key="2" v-if="['PUBLISHED', 'DRAFT', 'INTIMATE'].includes(list.params.status)"
@click="handleEditStatusMore(postStatus.RECYCLE.value)" key="2"
> @click="handleEditStatusMore(postStatuses.RECYCLE.value)"
移到回收站 >
</a-menu-item> 移到回收站
<a-menu-item </a-menu-item>
v-if="['RECYCLE', 'PUBLISHED', 'INTIMATE'].includes(list.params.status)" <a-menu-item
key="3" v-if="['RECYCLE', 'PUBLISHED', 'INTIMATE'].includes(list.params.status)"
@click="handleEditStatusMore(postStatus.DRAFT.value)" key="3"
> @click="handleEditStatusMore(postStatuses.DRAFT.value)"
草稿 >
</a-menu-item> 草稿
<a-menu-item v-if="['RECYCLE', 'DRAFT'].includes(list.params.status)" key="4" @click="handleDeleteMore"> </a-menu-item>
永久删除 <a-menu-item v-if="['RECYCLE', 'DRAFT'].includes(list.params.status)" key="4" @click="handleDeleteMore">
</a-menu-item> 永久删除
</a-menu> </a-menu-item>
</a-menu>
</template>
<a-button class="ml-2"> <a-button class="ml-2">
批量操作 批量操作
<a-icon type="down" /> <a-icon type="down" />
@ -87,138 +89,153 @@
<!-- Mobile --> <!-- Mobile -->
<a-list <a-list
v-if="isMobile()" v-if="isMobile()"
:dataSource="formattedPosts" :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">
<span> <template #actions>
<a-icon type="eye" />
{{ item.visits }}
</span>
<span @click="handleShowPostComments(item)">
<a-icon type="message" />
{{ item.commentCount }}
</span>
<a-dropdown :trigger="['click']" placement="topLeft">
<span> <span>
<a-icon type="bars" /> <a-icon type="eye" />
{{ item.visits }}
</span> </span>
<a-menu slot="overlay"> <span @click="handleShowPostComments(item)">
<a-menu-item <a-icon type="message" />
v-if="['PUBLISHED', 'DRAFT', 'INTIMATE'].includes(item.status)" {{ item.commentCount }}
@click="handleEditClick(item)" </span>
> <a-dropdown :trigger="['click']" placement="topLeft">
编辑 <span>
</a-menu-item> <a-icon type="bars" />
<a-menu-item v-else-if="item.status === 'RECYCLE'"> </span>
<a-popconfirm
:title="'你确定要发布【' + item.title + '】文章?'" <template #overlay>
cancelText="取消" <a-menu>
okText="确定" <a-menu-item
@confirm="handleEditStatusClick(item.id, 'PUBLISHED')" v-if="['PUBLISHED', 'DRAFT', 'INTIMATE'].includes(item.status)"
> @click="handleEditClick(item)"
还原 >
</a-popconfirm> 编辑
</a-menu-item> </a-menu-item>
<a-menu-item v-if="['PUBLISHED', 'DRAFT', 'INTIMATE'].includes(item.status)"> <a-menu-item v-else-if="item.status === 'RECYCLE'">
<a-popconfirm <a-popconfirm
:title="'你确定要将【' + item.title + '】文章移到回收站?'" :title="'你确定要发布【' + item.title + '】文章?'"
cancelText="取消" cancelText="取消"
okText="确定" okText="确定"
@confirm="handleEditStatusClick(item.id, 'RECYCLE')" @confirm="handleEditStatusClick(item.id, 'PUBLISHED')"
> >
回收站 还原
</a-popconfirm> </a-popconfirm>
</a-menu-item> </a-menu-item>
<a-menu-item v-else-if="item.status === 'RECYCLE'"> <a-menu-item v-if="['PUBLISHED', 'DRAFT', 'INTIMATE'].includes(item.status)">
<a-popconfirm <a-popconfirm
:title="'你确定要永久删除【' + item.title + '】文章?'" :title="'你确定要将【' + item.title + '】文章移到回收站?'"
cancelText="取消" cancelText="取消"
okText="确定" okText="确定"
@confirm="handleDeleteClick(item.id)" @confirm="handleEditStatusClick(item.id, 'RECYCLE')"
> >
删除 回收站
</a-popconfirm> </a-popconfirm>
</a-menu-item> </a-menu-item>
<a-menu-item @click="handleShowPostSettings(item)"></a-menu-item> <a-menu-item v-else-if="item.status === 'RECYCLE'">
</a-menu> <a-popconfirm
</a-dropdown> :title="'你确定要永久删除【' + item.title + '】文章?'"
</template> cancelText="取消"
<template slot="extra"> okText="确定"
<span> @confirm="handleDeleteClick(item.id)"
<a-badge :status="item.statusProperty.status" :text="item.statusProperty.text" /> >
</span> 删除
</template> </a-popconfirm>
<a-list-item-meta> </a-menu-item>
<template slot="description"> <a-menu-item @click="handleShowPostSettings(item)"></a-menu-item>
{{ item.createTime | moment }} </a-menu>
</template>
</a-dropdown>
</template> </template>
<template #title> <template #extra>
<div <a-badge :status="postStatuses[item.status].status" :text="item.status | statusText" />
style=" </template>
max-width: 300px; <a-list-item-meta>
display: block; <template #description>
white-space: nowrap; {{ item.createTime | moment }}
overflow: hidden; </template>
text-overflow: ellipsis; <template #title>
" <div
> style="
<a-icon max-width: 300px;
v-if="item.topPriority !== 0" display: block;
style="margin-right: 3px" white-space: nowrap;
theme="twoTone" overflow: hidden;
twoToneColor="red" text-overflow: ellipsis;
type="pushpin" "
/>
<a-tooltip
v-if="['PUBLISHED', 'INTIMATE'].includes(item.status)"
:title="'点击访问【' + item.title + '】'"
placement="top"
> >
<a :href="item.fullPath" class="no-underline" target="_blank"> <a-icon
{{ item.title }} v-if="item.topPriority !== 0"
</a> style="margin-right: 3px"
</a-tooltip> theme="twoTone"
<a-tooltip twoToneColor="red"
v-else-if="item.status === 'DRAFT'" type="pushpin"
:title="'点击预览【' + item.title + '】'" />
placement="top" <a-tooltip v-if="item.inProgress" placement="top" title="当前有内容已保存,但还未发布。">
> <a-icon
<a-button class="!p-0" type="link" @click="handlePreview(item.id)"> class="cursor-pointer"
style="margin-right: 3px"
theme="twoTone"
twoToneColor="#52c41a"
type="info-circle"
/>
</a-tooltip>
<a-tooltip
v-if="['PUBLISHED', 'INTIMATE'].includes(item.status)"
:title="'点击访问【' + item.title + '】'"
placement="top"
>
<a :href="item.fullPath" class="no-underline" target="_blank">
{{ item.title }}
</a>
</a-tooltip>
<a-tooltip
v-else-if="item.status === 'DRAFT'"
:title="'点击预览【' + item.title + '】'"
placement="top"
>
<a class="no-underline" href="javascript:void(0);" @click="handlePreview(item.id)">
{{ item.title }}
</a>
</a-tooltip>
<a-button v-else class="!p-0" disabled type="link">
{{ item.title }} {{ item.title }}
</a-button> </a-button>
</a-tooltip> </div>
<a-button v-else class="!p-0" disabled type="link"> </template>
{{ item.title }} </a-list-item-meta>
</a-button>
</div> <div v-if="item.summary" class="mb-3 block">
</template> <span> {{ item.summary }}... </span>
</a-list-item-meta> </div>
<span> {{ item.summary }}... </span>
<br /> <div class="block">
<br /> <a-tag
<a-tag v-for="(category, categoryIndex) in item.categories"
v-for="(category, categoryIndex) in item.categories" :key="'category_' + categoryIndex"
:key="'category_' + categoryIndex" color="blue"
color="blue" style="margin-bottom: 8px"
style="margin-bottom: 8px" @click="handleSelectCategory(category)"
@click="handleSelectCategory(category)" >{{ category.name }}
>{{ category.name }} </a-tag>
</a-tag> </div>
<br /> <post-tag v-for="(tag, tagIndex) in item.tags" :key="tagIndex" :tag="tag" style="margin-bottom: 8px" />
<post-tag v-for="(tag, tagIndex) in item.tags" :key="tagIndex" :tag="tag" style="margin-bottom: 8px" /> </a-list-item>
</a-list-item> </template>
</a-list> </a-list>
<!-- Desktop --> <!-- Desktop -->
<a-table <a-table
v-else v-else
:columns="columns" :columns="columns"
:dataSource="formattedPosts" :dataSource="list.data"
:loading="list.loading" :loading="list.loading"
:pagination="false" :pagination="false"
:rowKey="post => post.id" :rowKey="post => post.id"
@ -264,13 +281,14 @@
{{ text }} {{ text }}
</a-button> </a-button>
</template> </template>
<span slot="status" slot-scope="statusProperty">
<a-badge :status="statusProperty.status" :text="statusProperty.text" />
</span>
<span slot="categories" slot-scope="categoriesOfPost"> <template #status="status">
<a-badge :status="postStatuses[status].status" :text="status | statusText" />
</template>
<template #categories="categories">
<a-tag <a-tag
v-for="(category, index) in categoriesOfPost" v-for="(category, index) in categories"
:key="index" :key="index"
color="blue" color="blue"
style="margin-bottom: 8px; cursor: pointer" style="margin-bottom: 8px; cursor: pointer"
@ -278,52 +296,50 @@
> >
{{ category.name }} {{ category.name }}
</a-tag> </a-tag>
</span> </template>
<template #tags="tags"> <template #tags="tags">
<post-tag v-for="(tag, index) in tags" :key="index" :tag="tag" style="margin-bottom: 8px" /> <post-tag v-for="(tag, index) in tags" :key="index" :tag="tag" style="margin-bottom: 8px" />
</template> </template>
<span <template #commentCount="text, record">
slot="commentCount"
slot-scope="text, record"
style="cursor: pointer"
@click="handleShowPostComments(record)"
>
<a-badge <a-badge
:count="record.commentCount" :count="record.commentCount"
:numberStyle="{ backgroundColor: '#f38181' }" :numberStyle="{ backgroundColor: '#f38181' }"
:overflowCount="999" :overflowCount="999"
:showZero="true" :showZero="true"
class="cursor-pointer"
@click="handleShowPostComments(record)"
/> />
</span> </template>
<span slot="visits" slot-scope="visits"> <template #visits="visits">
<a-badge <a-badge
:count="visits" :count="visits"
:numberStyle="{ backgroundColor: '#00e0ff' }" :numberStyle="{ backgroundColor: '#00e0ff' }"
:overflowCount="9999" :overflowCount="9999"
:showZero="true" :showZero="true"
class="cursor-pointer"
/> />
</span> </template>
<span slot="createTime" slot-scope="createTime"> <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, post"> <template #action="text, post">
<a-button <a-button
v-if="['PUBLISHED', 'DRAFT', 'INTIMATE'].includes(post.status)" v-if="['PUBLISHED', 'DRAFT', 'INTIMATE'].includes(post.status)"
class="!p-0" class="!p-0"
type="link" type="link"
@click="handleEditClick(post)" @click="handleEditClick(post)"
>编辑</a-button >编辑
> </a-button>
<a-popconfirm <a-popconfirm
v-else-if="post.status === 'RECYCLE'" v-else-if="post.status === 'RECYCLE'"
:title="'你确定要发布【' + post.title + '】文章?'" :title="'你确定要发布【' + post.title + '】文章?'"
@ -359,7 +375,7 @@
<a-divider type="vertical" /> <a-divider type="vertical" />
<a-button class="!p-0" type="link" @click="handleShowPostSettings(post)"></a-button> <a-button class="!p-0" type="link" @click="handleShowPostSettings(post)"></a-button>
</span> </template>
</a-table> </a-table>
<div class="page-wrapper"> <div class="page-wrapper">
<a-pagination <a-pagination
@ -407,6 +423,7 @@ import { PageView } from '@/layouts'
import PostSettingModal from './components/PostSettingModal.vue' import PostSettingModal from './components/PostSettingModal.vue'
import TargetCommentDrawer from '../comment/components/TargetCommentDrawer' import TargetCommentDrawer from '../comment/components/TargetCommentDrawer'
import apiClient from '@/utils/api-client' import apiClient from '@/utils/api-client'
import { postStatuses } from '@/core/constant'
const columns = [ const columns = [
{ {
@ -418,8 +435,7 @@ const columns = [
}, },
{ {
title: '状态', title: '状态',
className: 'status', dataIndex: 'status',
dataIndex: 'statusProperty',
width: '100px', width: '100px',
scopedSlots: { customRender: 'status' } scopedSlots: { customRender: 'status' }
}, },
@ -457,32 +473,6 @@ const columns = [
scopedSlots: { customRender: 'action' } scopedSlots: { customRender: 'action' }
} }
] ]
const postStatus = {
PUBLISHED: {
value: 'PUBLISHED',
color: 'green',
status: 'success',
text: '已发布'
},
DRAFT: {
value: 'DRAFT',
color: 'yellow',
status: 'warning',
text: '草稿'
},
RECYCLE: {
value: 'RECYCLE',
color: 'red',
status: 'error',
text: '回收站'
},
INTIMATE: {
value: 'INTIMATE',
color: 'blue',
status: 'success',
text: '私密'
}
}
export default { export default {
name: 'PostList', name: 'PostList',
components: { components: {
@ -493,8 +483,8 @@ export default {
mixins: [mixin, mixinDevice], mixins: [mixin, mixinDevice],
data() { data() {
return { return {
postStatus,
columns, columns,
postStatuses,
list: { list: {
data: [], data: [],
loading: false, loading: false,
@ -523,12 +513,6 @@ export default {
} }
}, },
computed: { computed: {
formattedPosts() {
return this.list.data.map(post => {
post.statusProperty = this.postStatus[post.status]
return post
})
},
pagination() { pagination() {
return { return {
page: this.list.params.page + 1, page: this.list.params.page + 1,
@ -799,6 +783,11 @@ export default {
this.postSettingLoading = false this.postSettingLoading = false
} }
} }
},
filters: {
statusText(type) {
return type ? postStatuses[type].text : ''
}
} }
} }
</script> </script>