refactor(frontend): move detail view state initialization to server plugin

Remove top-level await from useAsyncData in detail views
Remove manual state initialization blocks in components
Introduce 03-detail-seo.server.ts to handle SEO and state
This commit is contained in:
2026-05-06 17:40:44 +08:00
parent 4dc73d42cb
commit 5ef1f4ecc9
5 changed files with 80 additions and 25 deletions

View File

@@ -34,7 +34,7 @@ const detailTabs = computed<TabOption[]>(() => [
{ value: 'history', label: t('history.editHistory') }
]);
const { data: initialHabitat } = await useAsyncData<HabitatDetail | null>(
const { data: initialHabitat } = useAsyncData<HabitatDetail | null>(
`habitat-detail:${activeHabitatRouteId() ?? 'none'}:${locale.value}`,
async () => {
const routeId = activeHabitatRouteId();
@@ -52,11 +52,6 @@ const { data: initialHabitat } = await useAsyncData<HabitatDetail | null>(
);
const initialHabitatLoaded = ref(false);
if (initialHabitat.value) {
habitat.value = initialHabitat.value;
initialHabitatLoaded.value = true;
}
const habitatSeo = computed(() =>
habitat.value && route.meta.editorModal !== true
? resolveSeo({

View File

@@ -73,7 +73,7 @@ const possibleTagEvidenceSections = computed(() => [
{ key: 'neutral', title: t('pages.pokemon.tradingNeutral'), rows: item.value?.possibleTags?.evidence.neutral ?? [] }
]);
const { data: initialItem } = await useAsyncData<ItemDetail | null>(
const { data: initialItem } = useAsyncData<ItemDetail | null>(
`item-detail:${String(route.name)}:${activeItemRouteId() ?? 'none'}:${locale.value}`,
async () => {
const routeId = activeItemRouteId();
@@ -92,11 +92,6 @@ const { data: initialItem } = await useAsyncData<ItemDetail | null>(
);
const initialItemLoaded = ref(false);
if (initialItem.value) {
item.value = initialItem.value;
initialItemLoaded.value = true;
}
const itemSeo = computed(() =>
item.value && route.meta.editorModal !== true
? resolveSeo({

View File

@@ -41,7 +41,7 @@ const weathers = ['晴天', '阴天', '雨天'];
const relatedPokemonLimit = 6;
const pokemonDetailRouteNames = new Set(['pokemon-detail', 'pokemon-edit']);
const { data: initialPokemon } = await useAsyncData<PokemonDetail | null>(
const { data: initialPokemon } = useAsyncData<PokemonDetail | null>(
`pokemon-detail:${activePokemonRouteId() ?? 'none'}:${locale.value}`,
async () => {
const routeId = activePokemonRouteId();
@@ -59,12 +59,6 @@ const { data: initialPokemon } = await useAsyncData<PokemonDetail | null>(
);
const initialPokemonLoaded = ref(false);
if (initialPokemon.value) {
pokemon.value = initialPokemon.value;
relatedHabitatTab.value = habitatTabValue(initialPokemon.value.environment.id);
initialPokemonLoaded.value = true;
}
const pokemonSeo = computed(() =>
pokemon.value && route.meta.editorModal !== true
? resolveSeo({

View File

@@ -42,7 +42,7 @@ const recipeSubtitle = computed(() => {
return categoryName ?? t('pages.recipes.detailSubtitle');
});
const { data: initialRecipe } = await useAsyncData<RecipeDetail | null>(
const { data: initialRecipe } = useAsyncData<RecipeDetail | null>(
`recipe-detail:${String(route.params.id)}:${locale.value}`,
async () => {
try {
@@ -55,11 +55,6 @@ const { data: initialRecipe } = await useAsyncData<RecipeDetail | null>(
);
const initialRecipeLoaded = ref(false);
if (initialRecipe.value) {
recipe.value = initialRecipe.value;
initialRecipeLoaded.value = true;
}
const recipeSeo = computed(() =>
recipe.value && route.meta.editorModal !== true
? resolveSeo({