| | |
| | | <!-- 系统logo --> |
| | | <template> |
| | | <div class="flex-cc"> |
| | | <img :style="logoStyle" src="@imgs/common/logo.webp" alt="logo" class="w-full h-full" /> |
| | | <div class="flex-cc" :style="wrapperStyle"> |
| | | <img :style="logoStyle" :src="logoSrc" alt="logo" class="w-full h-full object-contain" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import defaultLogo from '@imgs/common/logo.webp' |
| | | import { fetchPublicProjectLogoConfig } from '@/api/system-manage' |
| | | |
| | | const PROJECT_LOGO_UPDATED_EVENT = 'project-logo-updated' |
| | | let cachedLogoSrc = '' |
| | | let logoRequest = null |
| | | |
| | | defineOptions({ name: 'ArtLogo' }) |
| | | const props = defineProps({ |
| | | size: { required: false, default: 36 } |
| | | size: { required: false, default: 36 }, |
| | | fill: { type: Boolean, default: false } |
| | | }) |
| | | const logoStyle = computed(() => ({ width: `${props.size}px` })) |
| | | const logoSrc = ref(cachedLogoSrc || defaultLogo) |
| | | const wrapperStyle = computed(() => (props.fill ? { width: '100%', height: '100%' } : {})) |
| | | const logoStyle = computed(() => { |
| | | if (props.fill) { |
| | | return { width: '100%', height: '100%' } |
| | | } |
| | | return { width: resolveLogoSize(props.size) } |
| | | }) |
| | | |
| | | function resolveLogoSize(size) { |
| | | if (typeof size === 'number') return `${size}px` |
| | | const normalizedSize = String(size || '').trim() |
| | | if (!normalizedSize) return '36px' |
| | | return /^\d+(\.\d+)?$/.test(normalizedSize) ? `${normalizedSize}px` : normalizedSize |
| | | } |
| | | |
| | | function normalizeLogoSrc(value) { |
| | | const normalized = String(value || '').trim() |
| | | return normalized || defaultLogo |
| | | } |
| | | |
| | | async function loadProjectLogo(force = false) { |
| | | if (cachedLogoSrc && !force) { |
| | | logoSrc.value = cachedLogoSrc |
| | | return |
| | | } |
| | | |
| | | if (!logoRequest || force) { |
| | | logoRequest = fetchPublicProjectLogoConfig() |
| | | .then((response) => normalizeLogoSrc(response?.val)) |
| | | .catch(() => defaultLogo) |
| | | .then((resolvedLogo) => { |
| | | cachedLogoSrc = resolvedLogo |
| | | return resolvedLogo |
| | | }) |
| | | } |
| | | |
| | | logoSrc.value = await logoRequest |
| | | } |
| | | |
| | | function handleProjectLogoUpdated(event) { |
| | | const nextLogoSrc = normalizeLogoSrc(event?.detail?.url) |
| | | cachedLogoSrc = nextLogoSrc |
| | | logoRequest = Promise.resolve(nextLogoSrc) |
| | | logoSrc.value = nextLogoSrc |
| | | } |
| | | |
| | | onMounted(() => { |
| | | loadProjectLogo() |
| | | window.addEventListener(PROJECT_LOGO_UPDATED_EVENT, handleProjectLogoUpdated) |
| | | }) |
| | | |
| | | onBeforeUnmount(() => { |
| | | window.removeEventListener(PROJECT_LOGO_UPDATED_EVENT, handleProjectLogoUpdated) |
| | | }) |
| | | </script> |