feat: support batch publish/unpublish posts (#6123)

#### What type of PR is this?

/area ui
/kind feature
/milestone 2.17.x

#### What this PR does / why we need it:

支持批量发布/取消发布文章。

<img width="475" alt="image" src="https://github.com/halo-dev/halo/assets/21301288/5b79123b-5917-4b5e-9eaa-41c0cf5c8cdb">

#### Which issue(s) this PR fixes:

Fixes https://github.com/halo-dev/halo/issues/6085

#### Does this PR introduce a user-facing change?

```release-note
支持批量发布/取消发布文章。
```
pull/6147/head
Ryan Wang 2024-06-26 11:38:48 +08:00 committed by GitHub
parent 8302c21bb6
commit c0d38a99ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 74 additions and 3 deletions

View File

@ -280,9 +280,52 @@ const handleDeleteInBatch = async () => {
});
};
watch(selectedPostNames, (newValue) => {
checkedAll.value = newValue.length === posts.value?.length;
});
const handlePublishInBatch = async () => {
Dialog.info({
title: t("core.post.operations.publish_in_batch.title"),
description: t("core.post.operations.publish_in_batch.description"),
confirmText: t("core.common.buttons.confirm"),
cancelText: t("core.common.buttons.cancel"),
onConfirm: async () => {
for (const i in selectedPostNames.value) {
const name = selectedPostNames.value[i];
await consoleApiClient.content.post.publishPost({ name });
}
await refetch();
selectedPostNames.value = [];
Toast.success(t("core.common.toast.publish_success"));
},
});
};
const handleCancelPublishInBatch = async () => {
Dialog.warning({
title: t("core.post.operations.cancel_publish_in_batch.title"),
description: t("core.post.operations.cancel_publish_in_batch.description"),
confirmText: t("core.common.buttons.confirm"),
cancelText: t("core.common.buttons.cancel"),
onConfirm: async () => {
for (const i in selectedPostNames.value) {
const name = selectedPostNames.value[i];
await consoleApiClient.content.post.unpublishPost({ name });
}
await refetch();
selectedPostNames.value = [];
Toast.success(t("core.common.toast.cancel_publish_success"));
},
});
};
watch(
() => selectedPostNames.value,
(newValue) => {
checkedAll.value = newValue.length === posts.value?.length;
}
);
</script>
<template>
<PostSettingModal
@ -349,6 +392,12 @@ watch(selectedPostNames, (newValue) => {
<div class="flex w-full flex-1 items-center sm:w-auto">
<SearchInput v-if="!selectedPostNames.length" v-model="keyword" />
<VSpace v-else>
<VButton @click="handlePublishInBatch">
{{ $t("core.common.buttons.publish") }}
</VButton>
<VButton @click="handleCancelPublishInBatch">
{{ $t("core.common.buttons.cancel_publish") }}
</VButton>
<VButton type="danger" @click="handleDeleteInBatch">
{{ $t("core.common.buttons.delete") }}
</VButton>

View File

@ -193,6 +193,16 @@ core:
description: >-
This operation will move the posts to the recycle bin, and it can be
restored from the recycle bin later.
publish_in_batch:
title: Publish posts
description: >-
Batch publish posts, the selected posts will be set to published
status
cancel_publish_in_batch:
title: Cancel publish posts
description: >-
Batch cancel publish posts, the selected posts will be set to
unpublished status
filters:
status:
items:

View File

@ -185,6 +185,12 @@ core:
delete_in_batch:
title: 删除所选文章
description: 该操作会将文章放入回收站,后续可以从回收站恢复。
publish_in_batch:
title: 发布文章
description: 批量发布文章,所选文章会被设置为发布状态
cancel_publish_in_batch:
title: 取消发布文章
description: 批量取消发布文章,所选文章会被设置为未发布状态
filters:
status:
items:

View File

@ -185,6 +185,12 @@ core:
delete_in_batch:
title: 刪除所選文章
description: 該操作會將文章放入回收站,後續可以從回收站恢復。
publish_in_batch:
title: 發布文章
description: 批量發佈文章,所選文章會被設置為發佈狀態
cancel_publish_in_batch:
title: 取消發佈文章
description: 批量取消發佈文章,所選文章會被設置為未發布狀態
filters:
status:
items: