Files
sub2api/frontend/src/views/ModelPlazaView.vue
T
feeeei 720c405e35 feat: add model plaza with group-scoped pricing showcase
- public /model-plaza page (standalone + admin-embedded) listing groups
  with discounted effective prices alongside LiteLLM official reference
- faceted platform/group/rate filters: cross-dimension options gray out
  instead of disappearing, platform-tinted chips via accent color-mix
- paid-price columns highlighted with per-platform tint band
- OptionalJWT middleware so anonymous and signed-in users share one route
- admin settings: enable switch, require-auth switch, markdown description
2026-07-28 16:19:41 +08:00

49 lines
1.7 KiB
Vue

<template>
<!-- 后台内嵌形态:?embedded=1 且已登录,套完整后台布局 -->
<AppLayout v-if="isEmbedded">
<ModelPlazaContent :response="data" :loading="loading" :error="loadFailed" embedded />
</AppLayout>
<!-- 独立形态:自带导航条(logo/站名 + 登录/回后台) -->
<div v-else class="min-h-screen bg-gray-50 dark:bg-dark-950">
<PlazaNavBar />
<main class="mx-auto max-w-7xl px-4 py-6 sm:px-6 lg:px-8 lg:py-8">
<ModelPlazaContent :response="data" :loading="loading" :error="loadFailed" />
</main>
</div>
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useRoute } from 'vue-router'
import AppLayout from '@/components/layout/AppLayout.vue'
import PlazaNavBar from '@/components/modelPlaza/PlazaNavBar.vue'
import ModelPlazaContent from '@/components/modelPlaza/ModelPlazaContent.vue'
import { getModelPlaza, type ModelPlazaResponse } from '@/api/modelPlaza'
import { useAppStore } from '@/stores/app'
import { useAuthStore } from '@/stores/auth'
const route = useRoute()
const appStore = useAppStore()
const authStore = useAuthStore()
// embedded=1 但未登录(如转发的链接)自动降级为独立形态。
const isEmbedded = computed(() => route.query.embedded === '1' && authStore.isAuthenticated)
const data = ref<ModelPlazaResponse | null>(null)
const loading = ref(true)
const loadFailed = ref(false)
onMounted(async () => {
// 独立形态导航条需要站点名/Logo;有 __APP_CONFIG__ 注入时同步命中缓存。
void appStore.fetchPublicSettings()
try {
data.value = await getModelPlaza()
} catch {
loadFailed.value = true
} finally {
loading.value = false
}
})
</script>