refactor: rendering conditions for plugin installation components (#5577)

#### What type of PR is this?

/area ui
/kind improvement
/milestone 2.14.x

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

优化插件安装弹框组件的渲染时机,改为在未打开时不进行渲染,可以避免一些不必要的请求,尤其是在安装了应用市场插件之后。

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

Fixes #5573 

#### Special notes for your reviewer:

测试插件安装和升级功能是否正常即可。

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

```release-note
优化插件安装弹框组件的渲染时机,避免不必要的请求。
```
pull/5602/head
Ryan Wang 2024-03-26 18:48:07 +08:00 committed by GitHub
parent b660eb6d3e
commit 78b60a0a29
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 56 additions and 62 deletions

View File

@ -1,42 +1,34 @@
<script lang="ts" setup> <script lang="ts" setup>
import { import {
Dialog,
IconAddCircle, IconAddCircle,
IconPlug, IconPlug,
IconRefreshLine, IconRefreshLine,
VButton, VButton,
VCard, VCard,
VEmpty,
VPageHeader,
VSpace,
VLoading,
Dialog,
VDropdown, VDropdown,
VDropdownItem, VDropdownItem,
VEmpty,
VLoading,
VPageHeader,
VSpace,
} from "@halo-dev/components"; } from "@halo-dev/components";
import PluginListItem from "./components/PluginListItem.vue"; import PluginListItem from "./components/PluginListItem.vue";
import PluginInstallationModal from "./components/PluginInstallationModal.vue"; import PluginInstallationModal from "./components/PluginInstallationModal.vue";
import { computed, ref, onMounted } from "vue"; import type { Ref } from "vue";
import { computed, onMounted, provide, ref, watch } from "vue";
import { apiClient } from "@/utils/api-client"; import { apiClient } from "@/utils/api-client";
import { usePermission } from "@/utils/permission"; import { usePermission } from "@/utils/permission";
import { useQuery } from "@tanstack/vue-query"; import { useQuery } from "@tanstack/vue-query";
import type { Plugin } from "@halo-dev/api-client"; import type { Plugin } from "@halo-dev/api-client";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useRouteQuery } from "@vueuse/router"; import { useRouteQuery } from "@vueuse/router";
import { watch } from "vue";
import { provide } from "vue";
import type { Ref } from "vue";
import { usePluginBatchOperations } from "./composables/use-plugin"; import { usePluginBatchOperations } from "./composables/use-plugin";
const { t } = useI18n(); const { t } = useI18n();
const { currentUserHasPermission } = usePermission(); const { currentUserHasPermission } = usePermission();
const pluginInstallationModal = ref(false); const pluginInstallationModalVisible = ref(false);
const pluginToUpgrade = ref<Plugin>();
function handleOpenUploadModal(plugin?: Plugin) {
pluginToUpgrade.value = plugin;
pluginInstallationModal.value = true;
}
const keyword = ref(""); const keyword = ref("");
@ -120,7 +112,7 @@ onMounted(() => {
confirmText: t("core.common.buttons.download"), confirmText: t("core.common.buttons.download"),
cancelText: t("core.common.buttons.cancel"), cancelText: t("core.common.buttons.cancel"),
onConfirm() { onConfirm() {
handleOpenUploadModal(); pluginInstallationModalVisible.value = true;
}, },
onCancel() { onCancel() {
routeRemoteDownloadUrl.value = null; routeRemoteDownloadUrl.value = null;
@ -131,9 +123,11 @@ onMounted(() => {
</script> </script>
<template> <template>
<PluginInstallationModal <PluginInstallationModal
v-if="currentUserHasPermission(['system:plugins:manage'])" v-if="
v-model:visible="pluginInstallationModal" pluginInstallationModalVisible &&
:plugin-to-upgrade="pluginToUpgrade" currentUserHasPermission(['system:plugins:manage'])
"
@close="pluginInstallationModalVisible = false"
/> />
<VPageHeader :title="$t('core.plugin.title')"> <VPageHeader :title="$t('core.plugin.title')">
@ -144,7 +138,7 @@ onMounted(() => {
<VButton <VButton
v-permission="['system:plugins:manage']" v-permission="['system:plugins:manage']"
type="secondary" type="secondary"
@click="handleOpenUploadModal()" @click="pluginInstallationModalVisible = true"
> >
<template #icon> <template #icon>
<IconAddCircle class="h-full w-full" /> <IconAddCircle class="h-full w-full" />
@ -276,7 +270,7 @@ onMounted(() => {
<VButton <VButton
v-permission="['system:plugins:manage']" v-permission="['system:plugins:manage']"
type="secondary" type="secondary"
@click="handleOpenUploadModal" @click="pluginInstallationModalVisible = true"
> >
<template #icon> <template #icon>
<IconAddCircle class="h-full w-full" /> <IconAddCircle class="h-full w-full" />
@ -297,7 +291,6 @@ onMounted(() => {
<PluginListItem <PluginListItem
:plugin="plugin" :plugin="plugin"
:is-selected="selectedNames.includes(plugin.metadata.name)" :is-selected="selectedNames.includes(plugin.metadata.name)"
@open-upgrade-modal="handleOpenUploadModal"
/> />
</li> </li>
</ul> </ul>

View File

@ -1,21 +1,25 @@
<script lang="ts" setup> <script lang="ts" setup>
import { VModal, VButton, VTabbar } from "@halo-dev/components"; import { VButton, VModal, VTabbar } from "@halo-dev/components";
import type { Plugin } from "@halo-dev/api-client"; import type { Plugin } from "@halo-dev/api-client";
import { computed, ref, watch } from "vue"; import {
computed,
markRaw,
nextTick,
onMounted,
provide,
type Ref,
ref,
toRefs,
} from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useRouteQuery } from "@vueuse/router"; import { useRouteQuery } from "@vueuse/router";
import { provide } from "vue";
import { toRefs } from "vue";
import type { Ref } from "vue";
import LocalUpload from "./installation-tabs/LocalUpload.vue"; import LocalUpload from "./installation-tabs/LocalUpload.vue";
import RemoteDownload from "./installation-tabs/RemoteDownload.vue"; import RemoteDownload from "./installation-tabs/RemoteDownload.vue";
import { markRaw } from "vue";
import type { import type {
PluginInstallationTab, PluginInstallationTab,
PluginModule, PluginModule,
} from "@halo-dev/console-shared"; } from "@halo-dev/console-shared";
import { usePluginModuleStore } from "@/stores/plugin"; import { usePluginModuleStore } from "@/stores/plugin";
import { onMounted } from "vue";
import { usePermission } from "@/utils/permission"; import { usePermission } from "@/utils/permission";
const { t } = useI18n(); const { t } = useI18n();
@ -23,23 +27,22 @@ const { currentUserHasPermission } = usePermission();
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
visible: boolean;
pluginToUpgrade?: Plugin; pluginToUpgrade?: Plugin;
}>(), }>(),
{ {
visible: false,
pluginToUpgrade: undefined, pluginToUpgrade: undefined,
} }
); );
const emit = defineEmits<{ const emit = defineEmits<{
(event: "update:visible", visible: boolean): void;
(event: "close"): void; (event: "close"): void;
}>(); }>();
const { pluginToUpgrade } = toRefs(props); const { pluginToUpgrade } = toRefs(props);
provide<Ref<Plugin | undefined>>("pluginToUpgrade", pluginToUpgrade); provide<Ref<Plugin | undefined>>("pluginToUpgrade", pluginToUpgrade);
const modal = ref();
const tabs = ref<PluginInstallationTab[]>([ const tabs = ref<PluginInstallationTab[]>([
{ {
id: "local", id: "local",
@ -65,26 +68,18 @@ const modalTitle = computed(() => {
: t("core.plugin.upload_modal.titles.install"); : t("core.plugin.upload_modal.titles.install");
}); });
const handleVisibleChange = (visible: boolean) => {
emit("update:visible", visible);
if (!visible) {
emit("close");
}
};
// handle remote download url from route // handle remote download url from route
const routeRemoteDownloadUrl = useRouteQuery<string | null>( const routeRemoteDownloadUrl = useRouteQuery<string | null>(
"remote-download-url" "remote-download-url"
); );
watch( onMounted(() => {
() => props.visible, if (routeRemoteDownloadUrl.value) {
(visible) => { nextTick(() => {
if (visible && routeRemoteDownloadUrl.value) {
activeTabId.value = "remote"; activeTabId.value = "remote";
} });
} }
); });
const { pluginModules } = usePluginModuleStore(); const { pluginModules } = usePluginModuleStore();
onMounted(() => { onMounted(() => {
@ -114,12 +109,12 @@ onMounted(() => {
</script> </script>
<template> <template>
<VModal <VModal
:visible="visible" ref="modal"
:title="modalTitle" :title="modalTitle"
:centered="true" :centered="true"
:width="920" :width="920"
height="calc(100vh - 20px)" height="calc(100vh - 20px)"
@update:visible="handleVisibleChange" @close="emit('close')"
> >
<VTabbar <VTabbar
v-model:active-id="activeTabId" v-model:active-id="activeTabId"
@ -136,12 +131,12 @@ onMounted(() => {
:is="tab.component" :is="tab.component"
v-bind="tab.props" v-bind="tab.props"
v-if="tab.id === activeTabId" v-if="tab.id === activeTabId"
@close-modal="handleVisibleChange(false)" @close-modal="modal.close()"
/> />
</template> </template>
</div> </div>
<template #footer> <template #footer>
<VButton @click="handleVisibleChange(false)"> <VButton @click="modal.close()">
{{ $t("core.common.buttons.close") }} {{ $t("core.common.buttons.close") }}
</VButton> </VButton>
</template> </template>

View File

@ -1,21 +1,20 @@
<script lang="ts" setup> <script lang="ts" setup>
import { import {
VEntity,
VEntityField,
Dialog, Dialog,
Toast, Toast,
VDropdownItem,
VDropdownDivider, VDropdownDivider,
VDropdownItem,
VEntity,
VEntityField,
} from "@halo-dev/components"; } from "@halo-dev/components";
import { inject, toRefs, markRaw } from "vue"; import type { Ref } from "vue";
import { computed, inject, markRaw, ref, toRefs } from "vue";
import { usePluginLifeCycle } from "../composables/use-plugin"; import { usePluginLifeCycle } from "../composables/use-plugin";
import type { Plugin } from "@halo-dev/api-client"; import type { Plugin } from "@halo-dev/api-client";
import { formatDatetime } from "@/utils/date"; import { formatDatetime } from "@/utils/date";
import { usePermission } from "@/utils/permission"; import { usePermission } from "@/utils/permission";
import { apiClient } from "@/utils/api-client"; import { apiClient } from "@/utils/api-client";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import type { Ref } from "vue";
import { ref } from "vue";
import { useEntityFieldItemExtensionPoint } from "@console/composables/use-entity-extension-points"; import { useEntityFieldItemExtensionPoint } from "@console/composables/use-entity-extension-points";
import { useOperationItemExtensionPoint } from "@console/composables/use-operation-extension-points"; import { useOperationItemExtensionPoint } from "@console/composables/use-operation-extension-points";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
@ -25,8 +24,8 @@ import LogoField from "./entity-fields/LogoField.vue";
import StatusDotField from "@/components/entity-fields/StatusDotField.vue"; import StatusDotField from "@/components/entity-fields/StatusDotField.vue";
import AuthorField from "./entity-fields/AuthorField.vue"; import AuthorField from "./entity-fields/AuthorField.vue";
import SwitchField from "./entity-fields/SwitchField.vue"; import SwitchField from "./entity-fields/SwitchField.vue";
import { computed } from "vue";
import type { EntityFieldItem, OperationItem } from "@halo-dev/console-shared"; import type { EntityFieldItem, OperationItem } from "@halo-dev/console-shared";
import PluginInstallationModal from "@console/modules/system/plugins/components/PluginInstallationModal.vue";
const { currentUserHasPermission } = usePermission(); const { currentUserHasPermission } = usePermission();
const { t } = useI18n(); const { t } = useI18n();
@ -40,16 +39,14 @@ const props = withDefaults(
{ isSelected: false } { isSelected: false }
); );
const emit = defineEmits<{
(event: "open-upgrade-modal", plugin?: Plugin): void;
}>();
const { plugin } = toRefs(props); const { plugin } = toRefs(props);
const selectedNames = inject<Ref<string[]>>("selectedNames", ref([])); const selectedNames = inject<Ref<string[]>>("selectedNames", ref([]));
const { getFailedMessage, uninstall } = usePluginLifeCycle(plugin); const { getFailedMessage, uninstall } = usePluginLifeCycle(plugin);
const pluginUpgradeModalVisible = ref(false);
const handleResetSettingConfig = async () => { const handleResetSettingConfig = async () => {
Dialog.warning({ Dialog.warning({
title: t("core.plugin.operations.reset.title"), title: t("core.plugin.operations.reset.title"),
@ -97,7 +94,7 @@ const { operationItems } = useOperationItemExtensionPoint<Plugin>(
label: t("core.common.buttons.upgrade"), label: t("core.common.buttons.upgrade"),
permissions: [], permissions: [],
action: () => { action: () => {
emit("open-upgrade-modal", props.plugin); pluginUpgradeModalVisible.value = true;
}, },
}, },
{ {
@ -257,4 +254,13 @@ const { startFields, endFields } = useEntityFieldItemExtensionPoint<Plugin>(
<EntityDropdownItems :dropdown-items="operationItems" :item="plugin" /> <EntityDropdownItems :dropdown-items="operationItems" :item="plugin" />
</template> </template>
</VEntity> </VEntity>
<PluginInstallationModal
v-if="
pluginUpgradeModalVisible &&
currentUserHasPermission(['system:plugins:manage'])
"
:plugin-to-upgrade="plugin"
@close="pluginUpgradeModalVisible = false"
/>
</template> </template>