diff --git a/src/formkit/theme.ts b/src/formkit/theme.ts index a2b46e236..d609b94dd 100644 --- a/src/formkit/theme.ts +++ b/src/formkit/theme.ts @@ -25,11 +25,11 @@ const buttonClassification = { const theme: Record> = { global: { - outer: "formkit-disabled:opacity-50 py-3", + outer: "formkit-disabled:opacity-50", help: "text-xs text-gray-500", messages: "list-none p-0 mt-1 mb-0", message: "text-red-500 mb-1 text-xs", - form: "flex flex-col divide-y divide-gray-100", + form: "flex flex-col divide-y divide-gray-100 space-y-3", }, button: buttonClassification, color: { diff --git a/src/modules/system/plugins/PluginList.vue b/src/modules/system/plugins/PluginList.vue index 501585d87..a3324863c 100644 --- a/src/modules/system/plugins/PluginList.vue +++ b/src/modules/system/plugins/PluginList.vue @@ -4,6 +4,7 @@ import { IconArrowDown, IconPlug, IconSettings, + useDialog, VButton, VCard, VPageHeader, @@ -11,15 +12,25 @@ import { VSwitch, VTag, } from "@halo-dev/components"; -import { onMounted, ref } from "vue"; +import { onMounted, ref, watch } from "vue"; import { useRouter } from "vue-router"; import type { Plugin } from "@/types/extension"; import { axiosInstance } from "@halo-dev/admin-shared"; +import cloneDeep from "lodash.clonedeep"; -const checkAll = ref(false); -const plugins = ref([]); +const checkedAll = ref(false); +const plugins = ref([] as Plugin[]); +const selectedPlugins = ref([]); const router = useRouter(); +const dialog = useDialog(); + +watch( + () => selectedPlugins.value, + (newValue) => { + checkedAll.value = newValue.length === plugins.value?.length; + } +); const handleRouteToDetail = (plugin: Plugin) => { router.push({ @@ -28,9 +39,9 @@ const handleRouteToDetail = (plugin: Plugin) => { }); }; -function isStarted(plugin: Plugin) { +const isStarted = (plugin: Plugin) => { return plugin.status?.phase === "STARTED" && plugin.spec.enabled; -} +}; const handleFetchPlugins = async () => { try { @@ -43,20 +54,67 @@ const handleFetchPlugins = async () => { } }; -const handleChangePluginStatus = async (plugin: Plugin) => { - try { - plugin.spec.enabled = !plugin.spec.enabled; - await axiosInstance.put( - `/apis/plugin.halo.run/v1alpha1/plugins/${plugin.metadata.name}`, - plugin - ); - } catch (e) { - console.error(e); - } finally { - window.location.reload(); +const handleChangeStatus = (plugin: Plugin) => { + const pluginToUpdate = cloneDeep(plugin); + + dialog.info({ + title: `确定要${plugin.spec.enabled ? "停止" : "启动"}该插件吗?`, + onConfirm: async () => { + try { + pluginToUpdate.spec.enabled = !pluginToUpdate.spec.enabled; + await axiosInstance.put( + `/apis/plugin.halo.run/v1alpha1/plugins/${plugin.metadata.name}`, + pluginToUpdate + ); + } catch (e) { + console.error(e); + } finally { + window.location.reload(); + } + }, + }); +}; + +const handleCheckedAllChange = () => { + if (checkedAll.value) { + selectedPlugins.value = plugins.value.map((plugin) => plugin.metadata.name); + } else { + selectedPlugins.value.length = 0; } }; +const handleChangeStatusInBatch = (enable: boolean) => { + const pluginsToUpdate = plugins.value.filter( + (plugin) => + selectedPlugins.value.includes(plugin.metadata.name) && + plugin.spec.enabled !== enable + ); + + if (pluginsToUpdate.length === 0) { + alert("没有需要更新的插件"); + return; + } + + dialog.warning({ + title: `确定要${enable ? "启动" : "停止"}所选插件吗?`, + onConfirm: async () => { + try { + for (const plugin of pluginsToUpdate) { + plugin.spec.enabled = enable; + await axiosInstance.put( + `/apis/plugin.halo.run/v1alpha1/plugins/${plugin.metadata.name}`, + plugin + ); + } + } catch (e) { + console.error(e); + } finally { + window.location.reload(); + } + }, + }); +}; + onMounted(handleFetchPlugins);