113 lines
4.5 KiB
Vue
113 lines
4.5 KiB
Vue
<script setup lang="ts">
|
||
const { t } = useI18n();
|
||
const siteStore = useSiteStore();
|
||
const { footer, social, site } = storeToRefs(siteStore);
|
||
|
||
const currentYear = new Date().getFullYear();
|
||
|
||
// 社交链接图标(系统内置,admin 只填链接/二维码)
|
||
const socialIcons: Record<string, string> = {
|
||
wechat: '💬',
|
||
weibo: '🌐',
|
||
bilibili: '📺',
|
||
youtube: '▶️',
|
||
facebook: '📘',
|
||
instagram: '📷'
|
||
};
|
||
|
||
// 仅显示已填写链接或二维码的社交入口
|
||
const visibleSocial = computed(() =>
|
||
(social.value || []).filter((s) => s.url || s.qrcode_url)
|
||
);
|
||
|
||
// 悬浮显示微信二维码
|
||
const wechatHover = ref(false);
|
||
</script>
|
||
|
||
<template>
|
||
<footer class="border-t border-gray-100 bg-gray-50 dark:bg-dark-900 dark:border-dark-700">
|
||
<div class="section-container py-48px">
|
||
<div class="flex flex-col md:flex-row md:items-start md:justify-between gap-32px">
|
||
<!-- 品牌与联系信息 -->
|
||
<div class="flex flex-col gap-12px">
|
||
<p class="text-lg font-bold text-gray-900 dark:text-white">
|
||
{{ site?.site_title || t('app.name') }}
|
||
</p>
|
||
<p v-if="footer?.company_name" class="text-sm text-gray-600 dark:text-gray-300">
|
||
{{ footer.company_name }}
|
||
</p>
|
||
<p v-if="footer?.company_address" class="text-sm text-gray-500 dark:text-gray-400">
|
||
{{ footer.company_address }}
|
||
</p>
|
||
<div class="flex flex-wrap items-center gap-16px text-sm text-gray-500 dark:text-gray-400">
|
||
<a v-if="footer?.contact_phone" :href="`tel:${footer.contact_phone}`" class="hover:text-primary transition-colors">
|
||
{{ footer.contact_phone }}
|
||
</a>
|
||
<a v-if="footer?.contact_email" :href="`mailto:${footer.contact_email}`" class="text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-300 transition-colors">
|
||
{{ footer.contact_email }}
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 社交媒体 -->
|
||
<div v-if="visibleSocial.length" class="flex items-center gap-16px">
|
||
<template v-for="item in visibleSocial" :key="item.platform">
|
||
<!-- 微信:悬浮显示二维码 -->
|
||
<div
|
||
v-if="item.platform === 'wechat' && item.qrcode_url"
|
||
class="relative"
|
||
@mouseenter="wechatHover = true"
|
||
@mouseleave="wechatHover = false"
|
||
>
|
||
<span class="w-40px h-40px flex-center rounded-full bg-white border border-gray-200 text-lg cursor-pointer hover:border-primary transition-colors dark:bg-dark-800 dark:border-dark-600">
|
||
{{ socialIcons[item.platform] || '🔗' }}
|
||
</span>
|
||
<transition name="qr">
|
||
<img
|
||
v-if="wechatHover"
|
||
:src="item.qrcode_url"
|
||
alt="WeChat QR"
|
||
class="absolute bottom-48px right-0 w-140px h-140px object-contain rounded-8px shadow-xl border border-gray-100 bg-white"
|
||
/>
|
||
</transition>
|
||
</div>
|
||
|
||
<!-- 其他平台:外链 -->
|
||
<a
|
||
v-else-if="item.url"
|
||
:href="item.url"
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
class="w-40px h-40px flex-center rounded-full bg-white border border-gray-200 text-lg hover:border-primary transition-colors dark:bg-dark-800 dark:border-dark-600"
|
||
>
|
||
{{ socialIcons[item.platform] || '🔗' }}
|
||
</a>
|
||
</template>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 版权与备案 -->
|
||
<div class="mt-32px pt-24px border-t border-gray-200 dark:border-dark-700 flex flex-col md:flex-row md:items-center md:justify-between gap-8px">
|
||
<p class="text-xs text-gray-400 dark:text-gray-500">
|
||
{{ footer?.copyright_text || t('footer.copyright', { year: currentYear }) }}
|
||
</p>
|
||
<div class="flex flex-wrap items-center gap-16px text-xs text-gray-400 dark:text-gray-500">
|
||
<a v-if="footer?.icp_number" href="https://beian.miit.gov.cn" target="_blank" rel="noopener noreferrer" class="text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-300 transition-colors">{{ footer.icp_number }}</a>
|
||
<span v-if="footer?.police_number">{{ footer.police_number }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.qr-enter-active,
|
||
.qr-leave-active {
|
||
transition: opacity 0.18s ease;
|
||
}
|
||
.qr-enter-from,
|
||
.qr-leave-to {
|
||
opacity: 0;
|
||
}
|
||
</style>
|