mirror of https://github.com/halo-dev/halo-admin
perf: improve theme detail and settings page
parent
6c71424421
commit
2da147b3bf
|
@ -1,6 +1,6 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
// core libs
|
// core libs
|
||||||
import { computed, inject, ref } from "vue";
|
import { inject } from "vue";
|
||||||
import { RouterLink } from "vue-router";
|
import { RouterLink } from "vue-router";
|
||||||
|
|
||||||
// components
|
// components
|
||||||
|
@ -10,37 +10,30 @@ import { VAlert, VSpace, VTag } from "@halo-dev/components";
|
||||||
import type { ComputedRef, Ref } from "vue";
|
import type { ComputedRef, Ref } from "vue";
|
||||||
import type { Theme } from "@halo-dev/api-client";
|
import type { Theme } from "@halo-dev/api-client";
|
||||||
|
|
||||||
const selectedTheme = inject<Ref<Theme>>(
|
const selectedTheme = inject<Ref<Theme | undefined>>("selectedTheme");
|
||||||
"selectedTheme",
|
const isActivated = inject<ComputedRef<boolean>>("isActivated");
|
||||||
ref<Theme>({} as Theme)
|
|
||||||
);
|
|
||||||
const isActivated = inject<ComputedRef<boolean>>(
|
|
||||||
"isActivated",
|
|
||||||
computed(() => false)
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="bg-white px-4 py-4 sm:px-6">
|
<div class="bg-white px-4 py-4 sm:px-6">
|
||||||
<div class="flex flex-row gap-3">
|
<div class="flex flex-row gap-3">
|
||||||
<div v-if="selectedTheme.spec?.logo">
|
<div
|
||||||
<div
|
class="h-12 w-12 overflow-hidden rounded border bg-white hover:shadow-sm"
|
||||||
class="h-12 w-12 overflow-hidden rounded border bg-white hover:shadow-sm"
|
>
|
||||||
>
|
<img
|
||||||
<img
|
:key="selectedTheme?.metadata.name"
|
||||||
:alt="selectedTheme.spec?.displayName"
|
:alt="selectedTheme?.spec.displayName"
|
||||||
:src="selectedTheme.spec?.logo"
|
:src="selectedTheme?.spec.logo"
|
||||||
class="h-full w-full"
|
class="h-full w-full"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 class="text-lg font-medium leading-6 text-gray-900">
|
<h3 class="text-lg font-medium leading-6 text-gray-900">
|
||||||
{{ selectedTheme.spec?.displayName }}
|
{{ selectedTheme?.spec.displayName }}
|
||||||
</h3>
|
</h3>
|
||||||
<p class="mt-1 flex max-w-2xl items-center gap-2">
|
<p class="mt-1 flex max-w-2xl items-center gap-2">
|
||||||
<span class="text-sm text-gray-500">
|
<span class="text-sm text-gray-500">
|
||||||
{{ selectedTheme.spec?.version }}
|
{{ selectedTheme?.spec.version }}
|
||||||
</span>
|
</span>
|
||||||
<VTag>
|
<VTag>
|
||||||
{{ isActivated ? "当前启用" : "未启用" }}
|
{{ isActivated ? "当前启用" : "未启用" }}
|
||||||
|
@ -56,7 +49,7 @@ const isActivated = inject<ComputedRef<boolean>>(
|
||||||
>
|
>
|
||||||
<dt class="text-sm font-medium text-gray-900">ID</dt>
|
<dt class="text-sm font-medium text-gray-900">ID</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
||||||
{{ selectedTheme.metadata?.name }}
|
{{ selectedTheme?.metadata.name }}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -64,7 +57,7 @@ const isActivated = inject<ComputedRef<boolean>>(
|
||||||
>
|
>
|
||||||
<dt class="text-sm font-medium text-gray-900">作者</dt>
|
<dt class="text-sm font-medium text-gray-900">作者</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
||||||
{{ selectedTheme.spec?.author?.name }}
|
{{ selectedTheme?.spec.author.name }}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -72,8 +65,8 @@ const isActivated = inject<ComputedRef<boolean>>(
|
||||||
>
|
>
|
||||||
<dt class="text-sm font-medium text-gray-900">网站</dt>
|
<dt class="text-sm font-medium text-gray-900">网站</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
||||||
<a :href="selectedTheme.spec?.website" target="_blank">
|
<a :href="selectedTheme?.spec.website" target="_blank">
|
||||||
{{ selectedTheme.spec?.website }}
|
{{ selectedTheme?.spec.website }}
|
||||||
</a>
|
</a>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
@ -82,8 +75,8 @@ const isActivated = inject<ComputedRef<boolean>>(
|
||||||
>
|
>
|
||||||
<dt class="text-sm font-medium text-gray-900">源码仓库</dt>
|
<dt class="text-sm font-medium text-gray-900">源码仓库</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
||||||
<a :href="selectedTheme.spec?.repo" target="_blank">
|
<a :href="selectedTheme?.spec.repo" target="_blank">
|
||||||
{{ selectedTheme.spec?.repo }}
|
{{ selectedTheme?.spec.repo }}
|
||||||
</a>
|
</a>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
@ -92,7 +85,7 @@ const isActivated = inject<ComputedRef<boolean>>(
|
||||||
>
|
>
|
||||||
<dt class="text-sm font-medium text-gray-900">当前版本</dt>
|
<dt class="text-sm font-medium text-gray-900">当前版本</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
||||||
{{ selectedTheme.spec?.version }}
|
{{ selectedTheme?.spec.version }}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -100,7 +93,7 @@ const isActivated = inject<ComputedRef<boolean>>(
|
||||||
>
|
>
|
||||||
<dt class="text-sm font-medium text-gray-900">Halo 版本要求</dt>
|
<dt class="text-sm font-medium text-gray-900">Halo 版本要求</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
<dd class="mt-1 text-sm text-gray-900 sm:col-span-3 sm:mt-0">
|
||||||
{{ selectedTheme.spec?.require }}
|
{{ selectedTheme?.spec.require }}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -118,7 +111,7 @@ const isActivated = inject<ComputedRef<boolean>>(
|
||||||
<ul class="mt-2 space-y-2">
|
<ul class="mt-2 space-y-2">
|
||||||
<li>
|
<li>
|
||||||
<div
|
<div
|
||||||
class="inline-flex w-96 cursor-pointer flex-row flex-col gap-y-3 rounded border p-5 hover:border-primary"
|
class="inline-flex w-96 cursor-pointer flex-col gap-y-3 rounded border p-5 hover:border-primary"
|
||||||
>
|
>
|
||||||
<RouterLink
|
<RouterLink
|
||||||
:to="{
|
:to="{
|
||||||
|
@ -138,7 +131,7 @@ const isActivated = inject<ComputedRef<boolean>>(
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<div
|
<div
|
||||||
class="inline-flex w-96 cursor-pointer flex-row flex-col gap-y-3 rounded border p-5 hover:border-primary"
|
class="inline-flex w-96 cursor-pointer flex-col gap-y-3 rounded border p-5 hover:border-primary"
|
||||||
>
|
>
|
||||||
<span class="font-medium hover:text-blue-400">
|
<span class="font-medium hover:text-blue-400">
|
||||||
run.halo.plugins.photos
|
run.halo.plugins.photos
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
// core libs
|
// core libs
|
||||||
import { computed, inject, onMounted, ref } from "vue";
|
import { computed, inject, watch } from "vue";
|
||||||
|
|
||||||
// components
|
// components
|
||||||
import { VButton } from "@halo-dev/components";
|
import { VButton } from "@halo-dev/components";
|
||||||
|
@ -11,12 +11,15 @@ import type { Theme } from "@halo-dev/api-client";
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
import { useSettingForm } from "@halo-dev/admin-shared";
|
import { useSettingForm } from "@halo-dev/admin-shared";
|
||||||
|
import { useRouteParams } from "@vueuse/router";
|
||||||
|
|
||||||
const selectedTheme = inject<Ref<Theme>>("selectedTheme", ref({} as Theme));
|
const group = useRouteParams<string>("group");
|
||||||
const group = inject<Ref<string | undefined>>("activeTab");
|
|
||||||
|
const selectedTheme = inject<Ref<Theme | undefined>>("selectedTheme");
|
||||||
|
|
||||||
|
const settingName = computed(() => selectedTheme?.value?.spec.settingName);
|
||||||
|
const configMapName = computed(() => selectedTheme?.value?.spec.configMapName);
|
||||||
|
|
||||||
const settingName = computed(() => selectedTheme.value.spec?.settingName);
|
|
||||||
const configMapName = computed(() => selectedTheme.value.spec?.configMapName);
|
|
||||||
const {
|
const {
|
||||||
settings,
|
settings,
|
||||||
configMapFormData,
|
configMapFormData,
|
||||||
|
@ -34,10 +37,16 @@ const formSchema = computed(() => {
|
||||||
?.formSchema;
|
?.formSchema;
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
await handleFetchSettings();
|
||||||
handleFetchSettings();
|
await handleFetchConfigMap();
|
||||||
handleFetchConfigMap();
|
|
||||||
});
|
watch(
|
||||||
|
() => selectedTheme?.value,
|
||||||
|
() => {
|
||||||
|
handleFetchSettings();
|
||||||
|
handleFetchConfigMap();
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="bg-white p-4 sm:px-6">
|
<div class="bg-white p-4 sm:px-6">
|
||||||
|
|
|
@ -64,7 +64,7 @@ onMounted(() => {
|
||||||
<div class="flex h-screen">
|
<div class="flex h-screen">
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<div
|
<div
|
||||||
class="grid h-16 grid-cols-2 items-center bg-white py-2 px-4 drop-shadow-sm sm:grid-cols-3"
|
class="grid h-14 grid-cols-2 items-center bg-white px-4 drop-shadow-sm sm:grid-cols-3"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<h2 class="truncate text-xl font-bold text-gray-800">
|
<h2 class="truncate text-xl font-bold text-gray-800">
|
||||||
|
@ -80,7 +80,7 @@ onMounted(() => {
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-end">
|
<div class="flex justify-end">
|
||||||
<VSpace>
|
<VSpace>
|
||||||
<VButton type="default" @click="settingVisible = true">
|
<VButton size="sm" type="default" @click="settingVisible = true">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<IconSettings class="h-full w-full" />
|
<IconSettings class="h-full w-full" />
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -11,11 +11,11 @@ import {
|
||||||
VTag,
|
VTag,
|
||||||
} from "@halo-dev/components";
|
} from "@halo-dev/components";
|
||||||
import ThemeInstallModal from "./ThemeInstallModal.vue";
|
import ThemeInstallModal from "./ThemeInstallModal.vue";
|
||||||
import { onMounted, ref } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import type { Theme } from "@halo-dev/api-client";
|
import type { Theme } from "@halo-dev/api-client";
|
||||||
import { apiClient } from "@halo-dev/admin-shared";
|
import { apiClient } from "@halo-dev/admin-shared";
|
||||||
|
|
||||||
withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
selectedTheme: Theme | null;
|
selectedTheme: Theme | null;
|
||||||
|
@ -32,6 +32,7 @@ const emit = defineEmits<{
|
||||||
(event: "update:visible", visible: boolean): void;
|
(event: "update:visible", visible: boolean): void;
|
||||||
(event: "close"): void;
|
(event: "close"): void;
|
||||||
(event: "update:selectedTheme", theme: Theme | null): void;
|
(event: "update:selectedTheme", theme: Theme | null): void;
|
||||||
|
(event: "select", theme: Theme | null): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const themes = ref<Theme[]>([]);
|
const themes = ref<Theme[]>([]);
|
||||||
|
@ -71,7 +72,7 @@ const handleUninstall = async (theme: Theme) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleVisibleChange = (visible: boolean) => {
|
const onVisibleChange = (visible: boolean) => {
|
||||||
emit("update:visible", visible);
|
emit("update:visible", visible);
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
emit("close");
|
emit("close");
|
||||||
|
@ -80,10 +81,18 @@ const handleVisibleChange = (visible: boolean) => {
|
||||||
|
|
||||||
const handleSelectTheme = (theme: Theme) => {
|
const handleSelectTheme = (theme: Theme) => {
|
||||||
emit("update:selectedTheme", theme);
|
emit("update:selectedTheme", theme);
|
||||||
handleVisibleChange(false);
|
emit("select", theme);
|
||||||
|
onVisibleChange(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(handleFetchThemes);
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(visible) => {
|
||||||
|
if (visible) {
|
||||||
|
handleFetchThemes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
handleFetchThemes,
|
handleFetchThemes,
|
||||||
|
@ -95,7 +104,7 @@ defineExpose({
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
:width="888"
|
:width="888"
|
||||||
title="已安装的主题"
|
title="已安装的主题"
|
||||||
@update:visible="handleVisibleChange"
|
@update:visible="onVisibleChange"
|
||||||
>
|
>
|
||||||
<VEmpty
|
<VEmpty
|
||||||
v-if="!themes.length && !loading"
|
v-if="!themes.length && !loading"
|
||||||
|
@ -212,7 +221,7 @@ defineExpose({
|
||||||
<VButton type="secondary" @click="themeInstall = true">
|
<VButton type="secondary" @click="themeInstall = true">
|
||||||
安装主题
|
安装主题
|
||||||
</VButton>
|
</VButton>
|
||||||
<VButton @click="handleVisibleChange(false)">关闭</VButton>
|
<VButton @click="onVisibleChange(false)">关闭</VButton>
|
||||||
</VSpace>
|
</VSpace>
|
||||||
</template>
|
</template>
|
||||||
</VModal>
|
</VModal>
|
||||||
|
|
|
@ -6,17 +6,19 @@ import { useDialog } from "@halo-dev/components";
|
||||||
|
|
||||||
interface useThemeLifeCycleReturn {
|
interface useThemeLifeCycleReturn {
|
||||||
loading: Ref<boolean>;
|
loading: Ref<boolean>;
|
||||||
activatedTheme: Ref<Theme>;
|
activatedTheme: Ref<Theme | undefined>;
|
||||||
isActivated: ComputedRef<boolean>;
|
isActivated: ComputedRef<boolean>;
|
||||||
handleActiveTheme: () => void;
|
handleActiveTheme: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useThemeLifeCycle(theme: Ref<Theme>): useThemeLifeCycleReturn {
|
export function useThemeLifeCycle(
|
||||||
const activatedTheme = ref<Theme>({} as Theme);
|
theme: Ref<Theme | undefined>
|
||||||
|
): useThemeLifeCycleReturn {
|
||||||
|
const activatedTheme = ref<Theme | undefined>();
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
const isActivated = computed(() => {
|
const isActivated = computed(() => {
|
||||||
return activatedTheme.value?.metadata?.name === theme.value?.metadata?.name;
|
return activatedTheme.value?.metadata.name === theme.value?.metadata.name;
|
||||||
});
|
});
|
||||||
|
|
||||||
const dialog = useDialog();
|
const dialog = useDialog();
|
||||||
|
@ -54,7 +56,7 @@ export function useThemeLifeCycle(theme: Ref<Theme>): useThemeLifeCycleReturn {
|
||||||
const handleActiveTheme = async () => {
|
const handleActiveTheme = async () => {
|
||||||
dialog.info({
|
dialog.info({
|
||||||
title: "是否确认启用当前主题",
|
title: "是否确认启用当前主题",
|
||||||
description: theme.value.spec.displayName,
|
description: theme.value?.spec.displayName,
|
||||||
onConfirm: async () => {
|
onConfirm: async () => {
|
||||||
try {
|
try {
|
||||||
const { data: systemConfigMap } =
|
const { data: systemConfigMap } =
|
||||||
|
@ -66,7 +68,7 @@ export function useThemeLifeCycle(theme: Ref<Theme>): useThemeLifeCycleReturn {
|
||||||
const themeConfigToUpdate = JSON.parse(
|
const themeConfigToUpdate = JSON.parse(
|
||||||
systemConfigMap.data?.theme || "{}"
|
systemConfigMap.data?.theme || "{}"
|
||||||
);
|
);
|
||||||
themeConfigToUpdate.active = theme.value?.metadata?.name;
|
themeConfigToUpdate.active = theme.value?.metadata.name;
|
||||||
systemConfigMap.data["theme"] = JSON.stringify(themeConfigToUpdate);
|
systemConfigMap.data["theme"] = JSON.stringify(themeConfigToUpdate);
|
||||||
|
|
||||||
await apiClient.extension.configMap.updatev1alpha1ConfigMap({
|
await apiClient.extension.configMap.updatev1alpha1ConfigMap({
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
// core libs
|
// core libs
|
||||||
import type { ComputedRef, Ref } from "vue";
|
import { nextTick, type ComputedRef, type Ref } from "vue";
|
||||||
import { computed, provide, ref, watch, watchEffect } from "vue";
|
import { computed, provide, ref, watch } from "vue";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
|
|
||||||
// libs
|
// libs
|
||||||
|
@ -48,25 +48,23 @@ const initialTabs: ThemeTab[] = [
|
||||||
];
|
];
|
||||||
|
|
||||||
const tabs = ref<ThemeTab[]>(cloneDeep(initialTabs));
|
const tabs = ref<ThemeTab[]>(cloneDeep(initialTabs));
|
||||||
const selectedTheme = ref<Theme>({} as Theme);
|
const selectedTheme = ref<Theme | undefined>();
|
||||||
const themesModal = ref(false);
|
const themesModal = ref(false);
|
||||||
const activeTab = ref("");
|
const activeTab = ref("");
|
||||||
|
|
||||||
const { loading, isActivated, activatedTheme, handleActiveTheme } =
|
const { loading, isActivated, activatedTheme, handleActiveTheme } =
|
||||||
useThemeLifeCycle(selectedTheme);
|
useThemeLifeCycle(selectedTheme);
|
||||||
|
|
||||||
const settingName = computed(() => selectedTheme.value.spec?.settingName);
|
const settingName = computed(() => selectedTheme.value?.spec.settingName);
|
||||||
const configMapName = computed(() => selectedTheme.value.spec?.configMapName);
|
const configMapName = computed(() => selectedTheme.value?.spec.configMapName);
|
||||||
|
|
||||||
const { settings, handleFetchSettings } = useSettingForm(
|
const { settings, handleFetchSettings } = useSettingForm(
|
||||||
settingName,
|
settingName,
|
||||||
configMapName
|
configMapName
|
||||||
);
|
);
|
||||||
|
|
||||||
provide<Ref<Theme>>("activatedTheme", activatedTheme);
|
provide<Ref<Theme | undefined>>("selectedTheme", selectedTheme);
|
||||||
provide<Ref<Theme>>("selectedTheme", selectedTheme);
|
|
||||||
provide<ComputedRef<boolean>>("isActivated", isActivated);
|
provide<ComputedRef<boolean>>("isActivated", isActivated);
|
||||||
provide<Ref<string | undefined>>("activeTab", activeTab);
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -74,42 +72,49 @@ const router = useRouter();
|
||||||
const handleTabChange = (id: string) => {
|
const handleTabChange = (id: string) => {
|
||||||
const tab = tabs.value.find((item) => item.id === id);
|
const tab = tabs.value.find((item) => item.id === id);
|
||||||
if (tab) {
|
if (tab) {
|
||||||
|
activeTab.value = tab.id;
|
||||||
router.push(tab.route);
|
router.push(tab.route);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
watchEffect(async () => {
|
watch(
|
||||||
if (selectedTheme.value) {
|
() => selectedTheme.value,
|
||||||
// reset tabs
|
async () => {
|
||||||
tabs.value = cloneDeep(initialTabs);
|
if (selectedTheme.value) {
|
||||||
await handleFetchSettings();
|
// reset tabs
|
||||||
|
tabs.value = cloneDeep(initialTabs);
|
||||||
|
await handleFetchSettings();
|
||||||
|
|
||||||
if (settings.value && settings.value.spec) {
|
if (settings.value && settings.value.spec) {
|
||||||
tabs.value = [
|
tabs.value = [
|
||||||
...tabs.value,
|
...tabs.value,
|
||||||
...settings.value.spec.map((item: FormKitSettingSpec) => {
|
...settings.value.spec.map((item: FormKitSettingSpec) => {
|
||||||
return {
|
return {
|
||||||
id: item.group,
|
id: item.group,
|
||||||
label: item.label || "",
|
label: item.label || "",
|
||||||
route: {
|
route: {
|
||||||
name: "ThemeSetting",
|
name: "ThemeSetting",
|
||||||
params: {
|
params: {
|
||||||
group: item.group,
|
group: item.group,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
};
|
||||||
};
|
}),
|
||||||
}),
|
] as ThemeTab[];
|
||||||
] as ThemeTab[];
|
}
|
||||||
onTabChange(route.name as string);
|
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
handleTriggerTabChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
const onTabChange = (routeName: string) => {
|
const handleTriggerTabChange = () => {
|
||||||
if (routeName === "ThemeSetting") {
|
if (route.name === "ThemeSetting") {
|
||||||
const tab = tabs.value.find((tab) => {
|
const tab = tabs.value.find((tab) => {
|
||||||
return (
|
return (
|
||||||
tab.route.name === routeName &&
|
tab.route.name === route.name &&
|
||||||
tab.route.params?.group === route.params.group
|
tab.route.params?.group === route.params.group
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -117,7 +122,7 @@ const onTabChange = (routeName: string) => {
|
||||||
activeTab.value = tab.id;
|
activeTab.value = tab.id;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
router.push({ name: "ThemeDetail" });
|
handleTabChange(tabs.value[0].id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,12 +130,9 @@ const onTabChange = (routeName: string) => {
|
||||||
activeTab.value = tab ? tab.id : tabs.value[0].id;
|
activeTab.value = tab ? tab.id : tabs.value[0].id;
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
watch([() => route.name, () => route.params], async () => {
|
||||||
() => route.name,
|
handleTriggerTabChange();
|
||||||
async (newRouteName) => {
|
});
|
||||||
onTabChange(newRouteName as string);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<BasicLayout>
|
<BasicLayout>
|
||||||
|
@ -139,7 +141,7 @@ watch(
|
||||||
v-model:selected-theme="selectedTheme"
|
v-model:selected-theme="selectedTheme"
|
||||||
v-model:visible="themesModal"
|
v-model:visible="themesModal"
|
||||||
/>
|
/>
|
||||||
<VPageHeader :title="selectedTheme.spec?.displayName">
|
<VPageHeader :title="selectedTheme?.spec.displayName">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<IconPalette class="mr-2 self-center" />
|
<IconPalette class="mr-2 self-center" />
|
||||||
</template>
|
</template>
|
||||||
|
@ -171,11 +173,7 @@ watch(
|
||||||
|
|
||||||
<div class="m-0 md:m-4">
|
<div class="m-0 md:m-4">
|
||||||
<VEmpty
|
<VEmpty
|
||||||
v-if="
|
v-if="!selectedTheme && !loading"
|
||||||
!selectedTheme.metadata?.name &&
|
|
||||||
!activatedTheme.metadata?.name &&
|
|
||||||
!loading
|
|
||||||
"
|
|
||||||
message="当前没有已激活或者选择的主题,你可以切换主题或者安装新主题"
|
message="当前没有已激活或者选择的主题,你可以切换主题或者安装新主题"
|
||||||
title="当前没有已激活或已选择的主题"
|
title="当前没有已激活或已选择的主题"
|
||||||
>
|
>
|
||||||
|
@ -205,7 +203,18 @@ watch(
|
||||||
</template>
|
</template>
|
||||||
</VCard>
|
</VCard>
|
||||||
<div>
|
<div>
|
||||||
<RouterView :key="activeTab" />
|
<RouterView :key="activeTab" v-slot="{ Component }">
|
||||||
|
<template v-if="Component">
|
||||||
|
<Suspense>
|
||||||
|
<component :is="Component"></component>
|
||||||
|
<template #fallback>
|
||||||
|
<div class="flex h-32 w-full justify-center bg-white">
|
||||||
|
<span class="text-sm text-gray-600">加载中...</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Suspense>
|
||||||
|
</template>
|
||||||
|
</RouterView>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -76,7 +76,7 @@ const { isStarted, changeStatus, uninstall } = usePluginLifeCycle(plugin);
|
||||||
</div>
|
</div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div
|
<div
|
||||||
class="inline-flex flex-col flex-col-reverse items-end gap-4 sm:flex-row sm:items-center sm:gap-6"
|
class="inline-flex flex-col items-end gap-4 sm:flex-row sm:items-center sm:gap-6"
|
||||||
>
|
>
|
||||||
<FloatingTooltip
|
<FloatingTooltip
|
||||||
v-if="plugin?.status?.phase === 'FAILED'"
|
v-if="plugin?.status?.phase === 'FAILED'"
|
||||||
|
|
Loading…
Reference in New Issue