From b79eccb6a20a9cc565ded01da47e84fef9b79fab Mon Sep 17 00:00:00 2001 From: Ryan Wang Date: Wed, 23 Nov 2022 12:59:28 +0800 Subject: [PATCH] perf: improve the list filter style and support clear all (#702) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #### What type of PR is this? /kind improvement /milestone 2.0 #### What this PR does / why we need it: 优化 Console 数据列表的筛选标签样式,以及支持清空所有筛选条件。 #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/2657 #### Screenshots: image #### Special notes for your reviewer: /cc @halo-dev/sig-halo-console 测试方式: 1. 测试文章、自定义页面、附件、插件、评论管理中的筛选功能。 #### Does this PR introduce a user-facing change? ```release-note 优化 Console 数据列表的筛选标签样式,以及支持清空所有筛选条件。 ``` --- src/components/filter/FilterCleanButton.vue | 15 ++ src/components/filter/FilterTag.vue | 25 +++ .../contents/attachments/AttachmentList.vue | 105 ++++++----- .../attachments/composables/use-attachment.ts | 9 +- src/modules/contents/comments/CommentList.vue | 119 +++++++----- .../comments/components/CommentListItem.vue | 6 - .../contents/pages/DeletedSinglePageList.vue | 35 +++- src/modules/contents/pages/SinglePageList.vue | 132 +++++++------ .../contents/posts/DeletedPostList.vue | 33 +++- src/modules/contents/posts/PostList.vue | 174 ++++++++++-------- src/modules/system/plugins/PluginList.vue | 91 ++++++--- 11 files changed, 483 insertions(+), 261 deletions(-) create mode 100644 src/components/filter/FilterCleanButton.vue create mode 100644 src/components/filter/FilterTag.vue diff --git a/src/components/filter/FilterCleanButton.vue b/src/components/filter/FilterCleanButton.vue new file mode 100644 index 00000000..b93b945c --- /dev/null +++ b/src/components/filter/FilterCleanButton.vue @@ -0,0 +1,15 @@ + + + diff --git a/src/components/filter/FilterTag.vue b/src/components/filter/FilterTag.vue new file mode 100644 index 00000000..433fa2e8 --- /dev/null +++ b/src/components/filter/FilterTag.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/modules/contents/attachments/AttachmentList.vue b/src/modules/contents/attachments/AttachmentList.vue index e5614fe8..9b2ad34d 100644 --- a/src/modules/contents/attachments/AttachmentList.vue +++ b/src/modules/contents/attachments/AttachmentList.vue @@ -15,7 +15,6 @@ import { VPagination, VSpace, VEmpty, - IconCloseCircle, IconFolder, VStatusDot, VEntity, @@ -40,6 +39,9 @@ import { isImage } from "@/utils/image"; import { useRouteQuery } from "@vueuse/router"; import { useFetchAttachmentGroup } from "./composables/use-attachment-group"; import { usePermission } from "@/utils/permission"; +import FilterTag from "@/components/filter/FilterTag.vue"; +import FilteCleanButton from "@/components/filter/FilterCleanButton.vue"; +import { getNode } from "@formkit/core"; const { currentUserHasPermission } = usePermission(); @@ -90,17 +92,47 @@ const selectedSortItemValue = computed(() => { function handleSelectPolicy(policy: Policy | undefined) { selectedPolicy.value = policy; - handleFetchAttachments(); + handleFetchAttachments(1); } function handleSelectUser(user: User | undefined) { selectedUser.value = user; - handleFetchAttachments(); + handleFetchAttachments(1); } function handleSortItemChange(sortItem?: SortItem) { selectedSortItem.value = sortItem; - handleFetchAttachments(); + handleFetchAttachments(1); +} + +function handleKeywordChange() { + const keywordNode = getNode("keywordInput"); + if (keywordNode) { + keyword.value = keywordNode._value as string; + } + handleFetchAttachments(1); +} + +function handleClearKeyword() { + keyword.value = ""; + handleFetchAttachments(1); +} + +const hasFilters = computed(() => { + return ( + selectedPolicy.value || + selectedUser.value || + selectedSortItem.value || + keyword.value + ); +}); + +function handleClearFilters() { + selectedPolicy.value = undefined; + selectedUser.value = undefined; + selectedSortItem.value = undefined; + keyword.value = ""; + handleFetchAttachments(1); } const { @@ -322,57 +354,44 @@ onMounted(() => { class="flex items-center gap-2" > -
+ 关键词:{{ keyword }} + + + - - 存储策略:{{ selectedPolicy?.spec.displayName }} - - -
+ 存储策略:{{ selectedPolicy?.spec.displayName }} + -
- - 上传者:{{ selectedUser?.spec.displayName }} - - -
+ 上传者:{{ selectedUser?.spec.displayName }} + -
- - 排序:{{ selectedSortItem.label }} - - -
+ 排序:{{ selectedSortItem.label }} + + + @@ -521,7 +540,7 @@ onMounted(() => {
; selectedAttachments: Ref>; checkedAll: Ref; - handleFetchAttachments: () => void; + handleFetchAttachments: (page?: number) => void; handlePaginationChange: ({ page, size, @@ -68,11 +68,16 @@ export function useAttachmentControl(filterOptions?: { const checkedAll = ref(false); const refreshInterval = ref(); - const handleFetchAttachments = async () => { + const handleFetchAttachments = async (page?: number) => { try { clearInterval(refreshInterval.value); loading.value = true; + + if (page) { + attachments.value.page = page; + } + const { data } = await apiClient.attachment.searchAttachments({ policy: policy?.value?.metadata.name, displayName: keyword?.value, diff --git a/src/modules/contents/comments/CommentList.vue b/src/modules/contents/comments/CommentList.vue index 56e7e51b..14d66a17 100644 --- a/src/modules/contents/comments/CommentList.vue +++ b/src/modules/contents/comments/CommentList.vue @@ -7,7 +7,6 @@ import { VPageHeader, VPagination, VSpace, - IconCloseCircle, IconRefreshLine, VEmpty, Dialog, @@ -19,9 +18,12 @@ import type { ListedCommentList, User, } from "@halo-dev/api-client"; -import { onMounted, ref, watch } from "vue"; +import { computed, onMounted, ref, watch } from "vue"; import { apiClient } from "@/utils/api-client"; import { onBeforeRouteLeave } from "vue-router"; +import FilterTag from "@/components/filter/FilterTag.vue"; +import FilterCleanButton from "@/components/filter/FilterCleanButton.vue"; +import { getNode } from "@formkit/core"; const comments = ref({ page: 1, @@ -41,11 +43,16 @@ const selectedCommentNames = ref([]); const keyword = ref(""); const refreshInterval = ref(); -const handleFetchComments = async () => { +const handleFetchComments = async (page?: number) => { try { clearInterval(refreshInterval.value); loading.value = true; + + if (page) { + comments.value.page = page; + } + const { data } = await apiClient.comment.listComments({ page: comments.value.page, size: comments.value.size, @@ -212,13 +219,16 @@ const SortFilterItems: { value: "CREATE_TIME", }, ]; + const selectedApprovedFilterItem = ref<{ label: string; value?: boolean }>( ApprovedFilterItems[0] ); + const selectedSortFilterItem = ref<{ label: string; value?: Sort; }>(SortFilterItems[0]); + const selectedUser = ref(); const handleApprovedFilterItemChange = (filterItem: { @@ -227,7 +237,7 @@ const handleApprovedFilterItemChange = (filterItem: { }) => { selectedApprovedFilterItem.value = filterItem; selectedCommentNames.value = []; - handlePaginationChange({ page: 1, size: 20 }); + handleFetchComments(1); }; const handleSortFilterItemChange = (filterItem: { @@ -236,12 +246,42 @@ const handleSortFilterItemChange = (filterItem: { }) => { selectedSortFilterItem.value = filterItem; selectedCommentNames.value = []; - handlePaginationChange({ page: 1, size: 20 }); + handleFetchComments(1); }; function handleSelectUser(user: User | undefined) { selectedUser.value = user; - handlePaginationChange({ page: 1, size: 20 }); + handleFetchComments(1); +} + +function handleKeywordChange() { + const keywordNode = getNode("keywordInput"); + if (keywordNode) { + keyword.value = keywordNode._value as string; + } + handleFetchComments(1); +} + +function handleClearKeyword() { + keyword.value = ""; + handleFetchComments(1); +} + +const hasFilters = computed(() => { + return ( + selectedApprovedFilterItem.value.value !== undefined || + selectedSortFilterItem.value.value !== "LAST_REPLY_TIME" || + selectedUser.value || + keyword.value + ); +}); + +function handleClearFilters() { + selectedApprovedFilterItem.value = ApprovedFilterItems[0]; + selectedSortFilterItem.value = SortFilterItems[0]; + selectedUser.value = undefined; + keyword.value = ""; + handleFetchComments(1); }