perf: add more operation feedback prompt (#785)

#### What type of PR is this?

/kind improvement

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

为部分关键操作添加反馈提示。

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

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

#### Special notes for your reviewer:

测试方式:

1. 测试 Console 端所有页面的操作。
2. 观察是否有反馈。

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

```release-note
完善 Console 端的部分操作反馈提示
```
pull/790/head
Ryan Wang 2022-12-20 19:04:29 +08:00 committed by GitHub
parent 2c3147a5a2
commit ca4749432e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 208 additions and 65 deletions

View File

@ -9,6 +9,7 @@ import cloneDeep from "lodash.clonedeep";
import merge from "lodash.merge"; import merge from "lodash.merge";
import type { ConfigMap, Setting, SettingForm } from "@halo-dev/api-client"; import type { ConfigMap, Setting, SettingForm } from "@halo-dev/api-client";
import type { FormKitSchemaCondition, FormKitSchemaNode } from "@formkit/core"; import type { FormKitSchemaCondition, FormKitSchemaNode } from "@formkit/core";
import { Toast } from "@halo-dev/components";
const initialConfigMap: ConfigMap = { const initialConfigMap: ConfigMap = {
apiVersion: "v1alpha1", apiVersion: "v1alpha1",
@ -150,6 +151,8 @@ export function useSettingForm(
}); });
configMapName.value = data.metadata.name; configMapName.value = data.metadata.name;
} }
Toast.success("保存成功");
} catch (e) { } catch (e) {
console.error("Failed to save configMap", e); console.error("Failed to save configMap", e);
} finally { } finally {

View File

@ -20,6 +20,7 @@ import {
VEntity, VEntity,
VEntityField, VEntityField,
VLoading, VLoading,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import LazyImage from "@/components/image/LazyImage.vue"; import LazyImage from "@/components/image/LazyImage.vue";
import UserDropdownSelector from "@/components/dropdown-selector/UserDropdownSelector.vue"; import UserDropdownSelector from "@/components/dropdown-selector/UserDropdownSelector.vue";
@ -175,6 +176,8 @@ const handleMove = async (group: Group) => {
await Promise.all(promises); await Promise.all(promises);
selectedAttachments.value.clear(); selectedAttachments.value.clear();
Toast.success("移动成功");
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} finally { } finally {

View File

@ -1,5 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import { VButton, VModal, VSpace } from "@halo-dev/components"; import { Toast, VButton, VModal, VSpace } from "@halo-dev/components";
import SubmitButton from "@/components/button/SubmitButton.vue"; import SubmitButton from "@/components/button/SubmitButton.vue";
import type { Group } from "@halo-dev/api-client"; import type { Group } from "@halo-dev/api-client";
import { computed, ref, watch } from "vue"; import { computed, ref, watch } from "vue";
@ -64,6 +64,8 @@ const handleSave = async () => {
} }
); );
} }
Toast.success("保存成功");
onVisibleChange(false); onVisibleChange(false);
} catch (e) { } catch (e) {
console.error("Failed to save attachment group", e); console.error("Failed to save attachment group", e);

View File

@ -9,6 +9,7 @@ import {
VEntity, VEntity,
VEntityField, VEntityField,
VStatusDot, VStatusDot,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import AttachmentPolicyEditingModal from "./AttachmentPolicyEditingModal.vue"; import AttachmentPolicyEditingModal from "./AttachmentPolicyEditingModal.vue";
import { ref, watch } from "vue"; import { ref, watch } from "vue";
@ -93,6 +94,8 @@ const handleDelete = async (policy: Policy) => {
await apiClient.extension.storage.policy.deletestorageHaloRunV1alpha1Policy( await apiClient.extension.storage.policy.deletestorageHaloRunV1alpha1Policy(
{ name: policy.metadata.name } { name: policy.metadata.name }
); );
Toast.success("删除成功");
handleFetchPolicies(); handleFetchPolicies();
}, },
}); });

View File

@ -1,5 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import { VButton, VModal, VSpace } from "@halo-dev/components"; import { Toast, VButton, VModal, VSpace } from "@halo-dev/components";
import SubmitButton from "@/components/button/SubmitButton.vue"; import SubmitButton from "@/components/button/SubmitButton.vue";
import type { Policy, PolicyTemplate } from "@halo-dev/api-client"; import type { Policy, PolicyTemplate } from "@halo-dev/api-client";
import cloneDeep from "lodash.clonedeep"; import cloneDeep from "lodash.clonedeep";
@ -128,6 +128,7 @@ const handleSave = async () => {
); );
} }
Toast.success("保存成功");
onVisibleChange(false); onVisibleChange(false);
} catch (e) { } catch (e) {
console.error("Failed to save attachment policy", e); console.error("Failed to save attachment policy", e);

View File

@ -5,6 +5,7 @@ import {
VCard, VCard,
IconDeleteBin, IconDeleteBin,
Dialog, Dialog,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import type { AttachmentLike } from "@halo-dev/console-shared"; import type { AttachmentLike } from "@halo-dev/console-shared";
@ -104,6 +105,8 @@ const handleDelete = async (attachment: Attachment) => {
); );
attachments.value.delete(attachment); attachments.value.delete(attachment);
selectedAttachments.value.delete(attachment); selectedAttachments.value.delete(attachment);
Toast.success("删除成功");
} catch (e) { } catch (e) {
console.error("Failed to delete attachment", e); console.error("Failed to delete attachment", e);
} }

View File

@ -9,7 +9,7 @@ import type { Ref } from "vue";
import { ref, watch } from "vue"; import { ref, watch } from "vue";
import type { AttachmentLike } from "@halo-dev/console-shared"; import type { AttachmentLike } from "@halo-dev/console-shared";
import { apiClient } from "@/utils/api-client"; import { apiClient } from "@/utils/api-client";
import { Dialog } from "@halo-dev/components"; import { Dialog, Toast } from "@halo-dev/components";
import type { Content, Editor } from "@halo-dev/richtext-editor"; import type { Content, Editor } from "@halo-dev/richtext-editor";
import { onBeforeRouteLeave } from "vue-router"; import { onBeforeRouteLeave } from "vue-router";
@ -180,6 +180,8 @@ export function useAttachmentControl(filterOptions?: {
selectedAttachment.value = undefined; selectedAttachment.value = undefined;
} }
selectedAttachments.value.delete(attachment); selectedAttachments.value.delete(attachment);
Toast.success("删除成功");
} catch (e) { } catch (e) {
console.error("Failed to delete attachment", e); console.error("Failed to delete attachment", e);
} finally { } finally {
@ -207,6 +209,8 @@ export function useAttachmentControl(filterOptions?: {
); );
await Promise.all(promises); await Promise.all(promises);
selectedAttachments.value.clear(); selectedAttachments.value.clear();
Toast.success("删除成功");
} catch (e) { } catch (e) {
console.error("Failed to delete attachments", e); console.error("Failed to delete attachments", e);
} finally { } finally {

View File

@ -11,6 +11,7 @@ import {
VEmpty, VEmpty,
Dialog, Dialog,
VLoading, VLoading,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import CommentListItem from "./components/CommentListItem.vue"; import CommentListItem from "./components/CommentListItem.vue";
import UserDropdownSelector from "@/components/dropdown-selector/UserDropdownSelector.vue"; import UserDropdownSelector from "@/components/dropdown-selector/UserDropdownSelector.vue";
@ -146,6 +147,8 @@ const handleDeleteInBatch = async () => {
}); });
await Promise.all(promises); await Promise.all(promises);
selectedCommentNames.value = []; selectedCommentNames.value = [];
Toast.success("删除成功");
} catch (e) { } catch (e) {
console.error("Failed to delete comments", e); console.error("Failed to delete comments", e);
} finally { } finally {
@ -181,6 +184,8 @@ const handleApproveInBatch = async () => {
}); });
await Promise.all(promises); await Promise.all(promises);
selectedCommentNames.value = []; selectedCommentNames.value = [];
Toast.success("操作成功");
} catch (e) { } catch (e) {
console.error("Failed to approve comments in batch", e); console.error("Failed to approve comments in batch", e);
} finally { } finally {

View File

@ -11,6 +11,7 @@ import {
IconAddCircle, IconAddCircle,
IconExternalLinkLine, IconExternalLinkLine,
VLoading, VLoading,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import ReplyCreationModal from "./ReplyCreationModal.vue"; import ReplyCreationModal from "./ReplyCreationModal.vue";
import type { import type {
@ -65,6 +66,8 @@ const handleDelete = async () => {
await apiClient.extension.comment.deletecontentHaloRunV1alpha1Comment({ await apiClient.extension.comment.deletecontentHaloRunV1alpha1Comment({
name: props.comment?.comment?.metadata.name as string, name: props.comment?.comment?.metadata.name as string,
}); });
Toast.success("删除成功");
} catch (error) { } catch (error) {
console.log("Failed to delete comment", error); console.log("Failed to delete comment", error);
} finally { } finally {
@ -93,6 +96,8 @@ const handleApproveReplyInBatch = async () => {
}); });
}); });
await Promise.all(promises); await Promise.all(promises);
Toast.success("操作成功");
} catch (e) { } catch (e) {
console.error("Failed to approve comment replies in batch", e); console.error("Failed to approve comment replies in batch", e);
} finally { } finally {
@ -112,6 +117,8 @@ const handleApprove = async () => {
name: commentToUpdate.metadata.name, name: commentToUpdate.metadata.name,
comment: commentToUpdate, comment: commentToUpdate,
}); });
Toast.success("操作成功");
} catch (error) { } catch (error) {
console.error("Failed to approve comment", error); console.error("Failed to approve comment", error);
} finally { } finally {

View File

@ -1,5 +1,11 @@
<script lang="ts" setup> <script lang="ts" setup>
import { VModal, VSpace, VButton, IconMotionLine } from "@halo-dev/components"; import {
VModal,
VSpace,
VButton,
IconMotionLine,
Toast,
} from "@halo-dev/components";
import SubmitButton from "@/components/button/SubmitButton.vue"; import SubmitButton from "@/components/button/SubmitButton.vue";
import type { import type {
ListedComment, ListedComment,
@ -100,6 +106,8 @@ const handleCreateReply = async () => {
replyRequest: formState.value, replyRequest: formState.value,
}); });
onVisibleChange(false); onVisibleChange(false);
Toast.success("回复成功");
} catch (error) { } catch (error) {
console.error("Failed to create comment reply", error); console.error("Failed to create comment reply", error);
} finally { } finally {

View File

@ -8,6 +8,7 @@ import {
Dialog, Dialog,
VStatusDot, VStatusDot,
IconReplyLine, IconReplyLine,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import type { ListedReply } from "@halo-dev/api-client"; import type { ListedReply } from "@halo-dev/api-client";
import { formatDatetime } from "@/utils/date"; import { formatDatetime } from "@/utils/date";
@ -53,6 +54,8 @@ const handleDelete = async () => {
await apiClient.extension.reply.deletecontentHaloRunV1alpha1Reply({ await apiClient.extension.reply.deletecontentHaloRunV1alpha1Reply({
name: props.reply?.reply.metadata.name as string, name: props.reply?.reply.metadata.name as string,
}); });
Toast.success("删除成功");
} catch (error) { } catch (error) {
console.log("Failed to delete comment reply", error); console.log("Failed to delete comment reply", error);
} finally { } finally {
@ -72,6 +75,8 @@ const handleApprove = async () => {
name: replyToUpdate.metadata.name, name: replyToUpdate.metadata.name,
reply: replyToUpdate, reply: replyToUpdate,
}); });
Toast.success("操作成功");
} catch (error) { } catch (error) {
console.error("Failed to approve comment reply", error); console.error("Failed to approve comment reply", error);
} finally { } finally {

View File

@ -15,6 +15,7 @@ import {
VPageHeader, VPageHeader,
VStatusDot, VStatusDot,
VLoading, VLoading,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import { onMounted, ref, watch } from "vue"; import { onMounted, ref, watch } from "vue";
import type { ListedSinglePageList, SinglePage } from "@halo-dev/api-client"; import type { ListedSinglePageList, SinglePage } from "@halo-dev/api-client";
@ -132,6 +133,8 @@ const handleDeletePermanently = async (singlePage: SinglePage) => {
} }
); );
await handleFetchSinglePages(); await handleFetchSinglePages();
Toast.success("删除成功");
}, },
}); });
}; };
@ -153,6 +156,8 @@ const handleDeletePermanentlyInBatch = async () => {
); );
await handleFetchSinglePages(); await handleFetchSinglePages();
selectedPageNames.value = []; selectedPageNames.value = [];
Toast.success("删除成功");
}, },
}); });
}; };
@ -171,6 +176,8 @@ const handleRecovery = async (singlePage: SinglePage) => {
} }
); );
await handleFetchSinglePages(); await handleFetchSinglePages();
Toast.success("恢复成功");
}, },
}); });
}; };
@ -201,6 +208,8 @@ const handleRecoveryInBatch = async () => {
); );
await handleFetchSinglePages(); await handleFetchSinglePages();
selectedPageNames.value = []; selectedPageNames.value = [];
Toast.success("恢复成功");
}, },
}); });
}; };

View File

@ -20,6 +20,7 @@ import {
VEntity, VEntity,
VEntityField, VEntityField,
VLoading, VLoading,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import SinglePageSettingModal from "./components/SinglePageSettingModal.vue"; import SinglePageSettingModal from "./components/SinglePageSettingModal.vue";
import UserDropdownSelector from "@/components/dropdown-selector/UserDropdownSelector.vue"; import UserDropdownSelector from "@/components/dropdown-selector/UserDropdownSelector.vue";
@ -229,6 +230,8 @@ const handleDelete = async (singlePage: SinglePage) => {
} }
); );
await handleFetchSinglePages(); await handleFetchSinglePages();
Toast.success("删除成功");
}, },
}); });
}; };
@ -260,6 +263,8 @@ const handleDeleteInBatch = async () => {
); );
await handleFetchSinglePages(); await handleFetchSinglePages();
selectedPageNames.value = []; selectedPageNames.value = [];
Toast.success("删除成功");
}, },
}); });
}; };

View File

@ -1,5 +1,12 @@
<script lang="ts" setup> <script lang="ts" setup>
import { VButton, VModal, VSpace, VTabItem, VTabs } from "@halo-dev/components"; import {
Toast,
VButton,
VModal,
VSpace,
VTabItem,
VTabs,
} from "@halo-dev/components";
import { computed, ref, watchEffect } from "vue"; import { computed, ref, watchEffect } from "vue";
import type { SinglePage } from "@halo-dev/api-client"; import type { SinglePage } from "@halo-dev/api-client";
import cloneDeep from "lodash.clonedeep"; import cloneDeep from "lodash.clonedeep";
@ -105,6 +112,8 @@ const handleSave = async () => {
emit("saved", data); emit("saved", data);
onVisibleChange(false); onVisibleChange(false);
Toast.success("保存成功");
} catch (error) { } catch (error) {
console.error("Failed to save single page", error); console.error("Failed to save single page", error);
} finally { } finally {
@ -150,6 +159,8 @@ const handleSwitchPublish = async (publish: boolean) => {
} }
onVisibleChange(false); onVisibleChange(false);
Toast.success(`${publish ? "发布" : "取消发布"}成功`);
} catch (error) { } catch (error) {
console.error("Failed to publish single page", error); console.error("Failed to publish single page", error);
} finally { } finally {

View File

@ -15,6 +15,7 @@ import {
VEntity, VEntity,
VEntityField, VEntityField,
VLoading, VLoading,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import PostTag from "./tags/components/PostTag.vue"; import PostTag from "./tags/components/PostTag.vue";
import { onMounted, ref, watch } from "vue"; import { onMounted, ref, watch } from "vue";
@ -124,6 +125,8 @@ const handleDeletePermanently = async (post: Post) => {
name: post.metadata.name, name: post.metadata.name,
}); });
await handleFetchPosts(); await handleFetchPosts();
Toast.success("删除成功");
}, },
}); });
}; };
@ -143,6 +146,8 @@ const handleDeletePermanentlyInBatch = async () => {
); );
await handleFetchPosts(); await handleFetchPosts();
selectedPostNames.value = []; selectedPostNames.value = [];
Toast.success("删除成功");
}, },
}); });
}; };
@ -159,6 +164,8 @@ const handleRecovery = async (post: Post) => {
post: postToUpdate, post: postToUpdate,
}); });
await handleFetchPosts(); await handleFetchPosts();
Toast.success("恢复成功");
}, },
}); });
}; };
@ -187,6 +194,8 @@ const handleRecoveryInBatch = async () => {
); );
await handleFetchPosts(); await handleFetchPosts();
selectedPostNames.value = []; selectedPostNames.value = [];
Toast.success("恢复成功");
}, },
}); });
}; };

View File

@ -22,6 +22,7 @@ import {
VEntity, VEntity,
VEntityField, VEntityField,
VLoading, VLoading,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import UserDropdownSelector from "@/components/dropdown-selector/UserDropdownSelector.vue"; import UserDropdownSelector from "@/components/dropdown-selector/UserDropdownSelector.vue";
import CategoryDropdownSelector from "@/components/dropdown-selector/CategoryDropdownSelector.vue"; import CategoryDropdownSelector from "@/components/dropdown-selector/CategoryDropdownSelector.vue";
@ -256,6 +257,8 @@ const handleDelete = async (post: Post) => {
name: post.metadata.name, name: post.metadata.name,
}); });
await handleFetchPosts(); await handleFetchPosts();
Toast.success("删除成功");
}, },
}); });
}; };
@ -285,6 +288,8 @@ const handleDeleteInBatch = async () => {
); );
await handleFetchPosts(); await handleFetchPosts();
selectedPostNames.value = []; selectedPostNames.value = [];
Toast.success("删除成功");
}, },
}); });
}; };

View File

@ -4,7 +4,7 @@ import { computed, ref, watch } from "vue";
import { apiClient } from "@/utils/api-client"; import { apiClient } from "@/utils/api-client";
// components // components
import { VButton, VModal, VSpace } from "@halo-dev/components"; import { Toast, VButton, VModal, VSpace } from "@halo-dev/components";
import SubmitButton from "@/components/button/SubmitButton.vue"; import SubmitButton from "@/components/button/SubmitButton.vue";
// types // types
@ -76,6 +76,8 @@ const handleSaveCategory = async () => {
}); });
} }
onVisibleChange(false); onVisibleChange(false);
Toast.success("保存成功");
} catch (e) { } catch (e) {
console.error("Failed to create category", e); console.error("Failed to create category", e);
} finally { } finally {

View File

@ -4,7 +4,7 @@ import { onUnmounted, type Ref } from "vue";
import { onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
import type { CategoryTree } from "@/modules/contents/posts/categories/utils"; import type { CategoryTree } from "@/modules/contents/posts/categories/utils";
import { buildCategoriesTree } from "@/modules/contents/posts/categories/utils"; import { buildCategoriesTree } from "@/modules/contents/posts/categories/utils";
import { Dialog } from "@halo-dev/components"; import { Dialog, Toast } from "@halo-dev/components";
import { onBeforeRouteLeave } from "vue-router"; import { onBeforeRouteLeave } from "vue-router";
interface usePostCategoryReturn { interface usePostCategoryReturn {
@ -76,6 +76,8 @@ export function usePostCategory(options?: {
name: category.metadata.name, name: category.metadata.name,
} }
); );
Toast.success("删除成功");
} catch (e) { } catch (e) {
console.error("Failed to delete tag", e); console.error("Failed to delete tag", e);
} finally { } finally {

View File

@ -1,5 +1,12 @@
<script lang="ts" setup> <script lang="ts" setup>
import { VButton, VModal, VSpace, VTabItem, VTabs } from "@halo-dev/components"; import {
Toast,
VButton,
VModal,
VSpace,
VTabItem,
VTabs,
} from "@halo-dev/components";
import { computed, ref, watchEffect } from "vue"; import { computed, ref, watchEffect } from "vue";
import type { Post } from "@halo-dev/api-client"; import type { Post } from "@halo-dev/api-client";
import cloneDeep from "lodash.clonedeep"; import cloneDeep from "lodash.clonedeep";
@ -101,6 +108,8 @@ const handleSave = async () => {
emit("saved", data); emit("saved", data);
handleVisibleChange(false); handleVisibleChange(false);
Toast.success("保存成功");
} catch (e) { } catch (e) {
console.error("Failed to save post", e); console.error("Failed to save post", e);
} finally { } finally {
@ -126,6 +135,8 @@ const handlePublish = async () => {
emit("published", data); emit("published", data);
handleVisibleChange(false); handleVisibleChange(false);
Toast.success("发布成功");
} catch (e) { } catch (e) {
console.error("Failed to publish post", e); console.error("Failed to publish post", e);
} finally { } finally {
@ -142,6 +153,8 @@ const handleUnpublish = async () => {
}); });
handleVisibleChange(false); handleVisibleChange(false);
Toast.success("取消发布成功");
} catch (e) { } catch (e) {
console.error("Failed to publish post", e); console.error("Failed to publish post", e);
} finally { } finally {

View File

@ -7,6 +7,7 @@ import { apiClient } from "@/utils/api-client";
import { import {
IconArrowLeft, IconArrowLeft,
IconArrowRight, IconArrowRight,
Toast,
VButton, VButton,
VModal, VModal,
VSpace, VSpace,
@ -79,6 +80,8 @@ const handleSaveTag = async () => {
}); });
} }
onVisibleChange(false); onVisibleChange(false);
Toast.success("保存成功");
} catch (e) { } catch (e) {
console.error("Failed to create tag", e); console.error("Failed to create tag", e);
} finally { } finally {

View File

@ -2,7 +2,7 @@ import { apiClient } from "@/utils/api-client";
import type { Tag } from "@halo-dev/api-client"; import type { Tag } from "@halo-dev/api-client";
import { onUnmounted, type Ref } from "vue"; import { onUnmounted, type Ref } from "vue";
import { onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
import { Dialog } from "@halo-dev/components"; import { Dialog, Toast } from "@halo-dev/components";
import { onBeforeRouteLeave } from "vue-router"; import { onBeforeRouteLeave } from "vue-router";
interface usePostTagReturn { interface usePostTagReturn {
@ -70,6 +70,8 @@ export function usePostTag(options?: {
await apiClient.extension.tag.deletecontentHaloRunV1alpha1Tag({ await apiClient.extension.tag.deletecontentHaloRunV1alpha1Tag({
name: tag.metadata.name, name: tag.metadata.name,
}); });
Toast.success("删除成功");
} catch (e) { } catch (e) {
console.error("Failed to delete tag", e); console.error("Failed to delete tag", e);
} finally { } finally {

View File

@ -9,6 +9,7 @@ import {
VPageHeader, VPageHeader,
VSpace, VSpace,
VLoading, VLoading,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import MenuItemEditingModal from "./components/MenuItemEditingModal.vue"; import MenuItemEditingModal from "./components/MenuItemEditingModal.vue";
import MenuItemListItem from "./components/MenuItemListItem.vue"; import MenuItemListItem from "./components/MenuItemListItem.vue";
@ -173,6 +174,8 @@ const handleDelete = async (menuItem: MenuTreeItem) => {
} }
await handleFetchMenuItems(); await handleFetchMenuItems();
Toast.success("删除成功");
}, },
}); });
}; };

View File

@ -1,5 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import { VButton, VModal, VSpace } from "@halo-dev/components"; import { Toast, VButton, VModal, VSpace } from "@halo-dev/components";
import SubmitButton from "@/components/button/SubmitButton.vue"; import SubmitButton from "@/components/button/SubmitButton.vue";
import type { Menu } from "@halo-dev/api-client"; import type { Menu } from "@halo-dev/api-client";
import { computed, ref, watch } from "vue"; import { computed, ref, watch } from "vue";
@ -60,6 +60,8 @@ const handleCreateMenu = async () => {
emit("created", data); emit("created", data);
} }
onVisibleChange(false); onVisibleChange(false);
Toast.success("保存成功");
} catch (e) { } catch (e) {
console.error("Failed to create menu", e); console.error("Failed to create menu", e);
} finally { } finally {

View File

@ -1,5 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import { VButton, VModal, VSpace } from "@halo-dev/components"; import { Toast, VButton, VModal, VSpace } from "@halo-dev/components";
import SubmitButton from "@/components/button/SubmitButton.vue"; import SubmitButton from "@/components/button/SubmitButton.vue";
import { computed, ref, watch } from "vue"; import { computed, ref, watch } from "vue";
import type { Menu, MenuItem, Ref } from "@halo-dev/api-client"; import type { Menu, MenuItem, Ref } from "@halo-dev/api-client";
@ -105,6 +105,8 @@ const handleSaveMenuItem = async () => {
onVisibleChange(false); onVisibleChange(false);
emit("saved", data); emit("saved", data);
} }
Toast.success("保存成功");
} catch (e) { } catch (e) {
console.error("Failed to create menu item", e); console.error("Failed to create menu item", e);
} finally { } finally {

View File

@ -10,6 +10,7 @@ import {
VEntityField, VEntityField,
VTag, VTag,
VLoading, VLoading,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import MenuEditingModal from "./MenuEditingModal.vue"; import MenuEditingModal from "./MenuEditingModal.vue";
import { onMounted, onUnmounted, ref } from "vue"; import { onMounted, onUnmounted, ref } from "vue";
@ -113,6 +114,8 @@ const handleDeleteMenu = async (menu: Menu) => {
); );
await Promise.all(deleteItemsPromises); await Promise.all(deleteItemsPromises);
Toast.success("删除成功");
} catch (e) { } catch (e) {
console.error("Failed to delete menu", e); console.error("Failed to delete menu", e);
} finally { } finally {
@ -181,6 +184,8 @@ const handleSetPrimaryMenu = async (menu: Menu) => {
}); });
} }
await handleFetchPrimaryMenuName(); await handleFetchPrimaryMenuName();
Toast.success("设置成功");
}; };
onMounted(handleFetchPrimaryMenuName); onMounted(handleFetchPrimaryMenuName);

View File

@ -13,6 +13,7 @@ import {
VButton, VButton,
Dialog, Dialog,
VAvatar, VAvatar,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import ThemeUploadModal from "./components/ThemeUploadModal.vue"; import ThemeUploadModal from "./components/ThemeUploadModal.vue";
@ -42,6 +43,8 @@ const handleReloadTheme = async () => {
name: selectedTheme.value.metadata.name as string, name: selectedTheme.value.metadata.name as string,
}); });
Toast.success("重载配置成功");
window.location.reload(); window.location.reload();
} catch (e) { } catch (e) {
console.error("Failed to reload theme setting", e); console.error("Failed to reload theme setting", e);

View File

@ -11,6 +11,7 @@ import {
VTabItem, VTabItem,
VTabs, VTabs,
VLoading, VLoading,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import LazyImage from "@/components/image/LazyImage.vue"; import LazyImage from "@/components/image/LazyImage.vue";
import ThemePreviewModal from "./preview/ThemePreviewModal.vue"; import ThemePreviewModal from "./preview/ThemePreviewModal.vue";
@ -108,6 +109,8 @@ const handleCreateTheme = async (theme: Theme) => {
apiClient.theme.reload({ name: data.metadata.name }); apiClient.theme.reload({ name: data.metadata.name });
activeTab.value = "installed"; activeTab.value = "installed";
Toast.success("安装成功");
} catch (error) { } catch (error) {
console.error("Failed to create theme", error); console.error("Failed to create theme", error);
} finally { } finally {

View File

@ -8,6 +8,7 @@ import {
VEntityField, VEntityField,
VStatusDot, VStatusDot,
Dialog, Dialog,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import LazyImage from "@/components/image/LazyImage.vue"; import LazyImage from "@/components/image/LazyImage.vue";
import type { Theme } from "@halo-dev/api-client"; import type { Theme } from "@halo-dev/api-client";
@ -43,8 +44,8 @@ const handleUninstall = async (theme: Theme, deleteExtensions?: boolean) => {
Dialog.warning({ Dialog.warning({
title: `${ title: `${
deleteExtensions deleteExtensions
? "确定要删除该主题以及对应的配置吗?" ? "确定要卸载该主题以及对应的配置吗?"
: "确定要删除该主题吗?" : "确定要卸载该主题吗?"
}`, }`,
description: "该操作不可恢复。", description: "该操作不可恢复。",
onConfirm: async () => { onConfirm: async () => {
@ -54,33 +55,33 @@ const handleUninstall = async (theme: Theme, deleteExtensions?: boolean) => {
}); });
// delete theme setting and configMap // delete theme setting and configMap
if (!deleteExtensions) { if (deleteExtensions) {
return; const { settingName, configMapName } = theme.spec;
if (settingName) {
await apiClient.extension.setting.deletev1alpha1Setting(
{
name: settingName,
},
{
mute: true,
}
);
}
if (configMapName) {
await apiClient.extension.configMap.deletev1alpha1ConfigMap(
{
name: configMapName,
},
{
mute: true,
}
);
}
} }
const { settingName, configMapName } = theme.spec; Toast.success("卸载成功");
if (settingName) {
await apiClient.extension.setting.deletev1alpha1Setting(
{
name: settingName,
},
{
mute: true,
}
);
}
if (configMapName) {
await apiClient.extension.configMap.deletev1alpha1ConfigMap(
{
name: configMapName,
},
{
mute: true,
}
);
}
} catch (e) { } catch (e) {
console.error("Failed to uninstall theme", e); console.error("Failed to uninstall theme", e);
} finally { } finally {

View File

@ -49,6 +49,8 @@ export function useThemeLifeCycle(
configMap: systemConfigMap, configMap: systemConfigMap,
}); });
} }
Toast.success("启用成功");
} catch (e) { } catch (e) {
console.error("Failed to active theme", e); console.error("Failed to active theme", e);
} finally { } finally {

View File

@ -3,7 +3,7 @@ import { computed } from "vue";
import type { Plugin } from "@halo-dev/api-client"; import type { Plugin } from "@halo-dev/api-client";
import cloneDeep from "lodash.clonedeep"; import cloneDeep from "lodash.clonedeep";
import { apiClient } from "@/utils/api-client"; import { apiClient } from "@/utils/api-client";
import { Dialog } from "@halo-dev/components"; import { Dialog, Toast } from "@halo-dev/components";
interface usePluginLifeCycleReturn { interface usePluginLifeCycleReturn {
isStarted: ComputedRef<boolean | undefined>; isStarted: ComputedRef<boolean | undefined>;
@ -34,6 +34,8 @@ export function usePluginLifeCycle(
name: pluginToUpdate.metadata.name, name: pluginToUpdate.metadata.name,
plugin: pluginToUpdate, plugin: pluginToUpdate,
}); });
Toast.success(`${pluginToUpdate.spec.enabled ? "启动" : "停止"}成功`);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} finally { } finally {
@ -79,33 +81,33 @@ export function usePluginLifeCycle(
}); });
// delete plugin setting and configMap // delete plugin setting and configMap
if (!deleteExtensions) { if (deleteExtensions) {
return; const { settingName, configMapName } = plugin.value.spec;
if (settingName) {
await apiClient.extension.setting.deletev1alpha1Setting(
{
name: settingName,
},
{
mute: true,
}
);
}
if (configMapName) {
await apiClient.extension.configMap.deletev1alpha1ConfigMap(
{
name: configMapName,
},
{
mute: true,
}
);
}
} }
const { settingName, configMapName } = plugin.value.spec; Toast.success("卸载成功");
if (settingName) {
await apiClient.extension.setting.deletev1alpha1Setting(
{
name: settingName,
},
{
mute: true,
}
);
}
if (configMapName) {
await apiClient.extension.configMap.deletev1alpha1ConfigMap(
{
name: configMapName,
},
{
mute: true,
}
);
}
} catch (e) { } catch (e) {
console.error("Failed to uninstall plugin", e); console.error("Failed to uninstall plugin", e);
} finally { } finally {

View File

@ -18,6 +18,7 @@ import {
VEntity, VEntity,
VEntityField, VEntityField,
VLoading, VLoading,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import RoleEditingModal from "./components/RoleEditingModal.vue"; import RoleEditingModal from "./components/RoleEditingModal.vue";
@ -132,6 +133,8 @@ const handleDelete = async (role: Role) => {
await apiClient.extension.role.deletev1alpha1Role({ await apiClient.extension.role.deletev1alpha1Role({
name: role.metadata.name, name: role.metadata.name,
}); });
Toast.success("删除成功");
} catch (e) { } catch (e) {
console.error("Failed to delete role", e); console.error("Failed to delete role", e);
} }

View File

@ -4,6 +4,7 @@ import { computed, onMounted, ref } from "vue";
import { roleLabels } from "@/constants/labels"; import { roleLabels } from "@/constants/labels";
import { rbacAnnotations } from "@/constants/annotations"; import { rbacAnnotations } from "@/constants/annotations";
import { apiClient } from "@/utils/api-client"; import { apiClient } from "@/utils/api-client";
import { Toast } from "@halo-dev/components";
interface RoleTemplateGroup { interface RoleTemplateGroup {
module: string | null | undefined; module: string | null | undefined;
@ -110,6 +111,8 @@ export function useRoleForm(): useRoleFormReturn {
formState.value = data; formState.value = data;
} }
Toast.success("保存成功");
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} finally { } finally {

View File

@ -16,6 +16,7 @@ import {
Dialog, Dialog,
VStatusDot, VStatusDot,
VLoading, VLoading,
Toast,
} from "@halo-dev/components"; } from "@halo-dev/components";
import UserEditingModal from "./components/UserEditingModal.vue"; import UserEditingModal from "./components/UserEditingModal.vue";
import UserPasswordChangeModal from "./components/UserPasswordChangeModal.vue"; import UserPasswordChangeModal from "./components/UserPasswordChangeModal.vue";
@ -110,6 +111,8 @@ const handleDelete = async (user: User) => {
await apiClient.extension.user.deletev1alpha1User({ await apiClient.extension.user.deletev1alpha1User({
name: user.metadata.name, name: user.metadata.name,
}); });
Toast.success("删除成功");
} catch (e) { } catch (e) {
console.error("Failed to delete user", e); console.error("Failed to delete user", e);
} finally { } finally {
@ -137,6 +140,7 @@ const handleDeleteInBatch = async () => {
); );
await handleFetchUsers(); await handleFetchUsers();
selectedUserNames.value.length = 0; selectedUserNames.value.length = 0;
Toast.success("删除成功");
}, },
}); });
}; };

View File

@ -8,6 +8,7 @@ import type { User } from "@halo-dev/api-client";
import { import {
IconCodeBoxLine, IconCodeBoxLine,
IconEye, IconEye,
Toast,
VButton, VButton,
VCodemirror, VCodemirror,
VModal, VModal,
@ -123,6 +124,8 @@ const handleCreateUser = async () => {
} }
onVisibleChange(false); onVisibleChange(false);
Toast.success("保存成功");
} catch (e) { } catch (e) {
console.error("Failed to create or update user", e); console.error("Failed to create or update user", e);
} finally { } finally {

View File

@ -3,7 +3,7 @@ import IconLogo from "~icons/core/logo?width=5rem&height=2rem";
import { useSettingForm } from "@/composables/use-setting-form"; import { useSettingForm } from "@/composables/use-setting-form";
import { useSystemStatesStore } from "@/stores/system-states"; import { useSystemStatesStore } from "@/stores/system-states";
import { apiClient } from "@/utils/api-client"; import { apiClient } from "@/utils/api-client";
import { VButton } from "@halo-dev/components"; import { Toast, VButton } from "@halo-dev/components";
import { onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import category from "./setup-data/category.json"; import category from "./setup-data/category.json";
@ -100,6 +100,8 @@ const handleSubmit = async () => {
await systemStateStore.fetchSystemStates(); await systemStateStore.fetchSystemStates();
router.push({ name: "Dashboard" }); router.push({ name: "Dashboard" });
Toast.success("初始化成功");
} catch (error) { } catch (error) {
console.error("Failed to setup", error); console.error("Failed to setup", error);
} finally { } finally {