2b69686795
- 新增404页面,优化未找到页面体验,避免被搜索引擎索引 - 增加文件代理接口,隐藏真实文件服务器地址,支持文件请求代理 - 实现/article、/case、/product及/page动态路由兼容列表与详情展示 - 添加动态CMS页面兼容入口处理旧式路径,统一路由与SEO设置 - 新增模板1、模板7、模板2、模板3关于我们页面,实现多模板支持 - 模板增强支持CMS单页内容加载及SEO信息动态设置 - 配置环境变量及Git忽略文件规则辅助开发和构建环境管理
160 lines
7.1 KiB
Vue
160 lines
7.1 KiB
Vue
<template>
|
||
<footer class="bg-[var(--t10-footer-bg)] text-[var(--t10-footer-text)]">
|
||
<div class="t10-container py-12 lg:py-16">
|
||
<!-- 上排:Logo 联系信息 + 链接列 -->
|
||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-10 lg:gap-8">
|
||
<!-- 公司信息 -->
|
||
<div class="lg:col-span-2">
|
||
<SiteBrand
|
||
link-class="inline-flex items-center gap-2 mb-5"
|
||
:logo="siteLogo"
|
||
:icon="siteIcon"
|
||
:name="siteName"
|
||
logo-class="h-[44px] w-auto max-w-[220px] object-contain brightness-0 invert"
|
||
icon-class="h-8 w-auto object-contain brightness-0 invert"
|
||
name-class="text-xl font-bold text-white truncate max-w-[220px]"
|
||
>
|
||
<template #fallback-icon>
|
||
<span class="text-xl font-bold text-white">C-MVP</span>
|
||
</template>
|
||
</SiteBrand>
|
||
<ul class="space-y-3 text-sm">
|
||
<li v-if="phone" class="flex items-start gap-3">
|
||
<svg class="w-4 h-4 mt-0.5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||
</svg>
|
||
<a :href="`tel:${phone}`" class="hover:text-white transition-colors">{{ phone }}</a>
|
||
</li>
|
||
<li v-if="email" class="flex items-start gap-3">
|
||
<svg class="w-4 h-4 mt-0.5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
|
||
</svg>
|
||
<a :href="`mailto:${email}`" class="hover:text-white transition-colors break-all">{{ email }}</a>
|
||
</li>
|
||
<li v-if="siteUrl" class="flex items-start gap-3">
|
||
<svg class="w-4 h-4 mt-0.5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" />
|
||
</svg>
|
||
<a :href="siteUrl" target="_blank" rel="noopener" class="hover:text-white transition-colors break-all">{{ siteUrl }}</a>
|
||
</li>
|
||
<li v-if="address" class="flex items-start gap-3">
|
||
<svg class="w-4 h-4 mt-0.5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
|
||
</svg>
|
||
<span>{{ address }}</span>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<!-- 链接列 -->
|
||
<div v-for="col in linkColumns" :key="col.title">
|
||
<h3 class="text-white font-semibold mb-5">{{ col.title }}</h3>
|
||
<ul class="space-y-2.5 text-sm">
|
||
<li v-for="link in col.links" :key="link.navigationId || link.path">
|
||
<NuxtLink
|
||
:to="getNavLink(link)"
|
||
:target="link.target === '_blank' ? '_blank' : undefined"
|
||
class="hover:text-white transition-colors"
|
||
>
|
||
{{ link.title }}
|
||
</NuxtLink>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 分隔线 -->
|
||
<div class="mt-12 pt-8 border-t border-white/15">
|
||
<div class="flex flex-col md:flex-row items-center justify-between gap-4 text-xs text-center md:text-left">
|
||
<span>{{ copyright || `Copyright © ${new Date().getFullYear()} ${siteName || ''} 版权所有` }}</span>
|
||
<div class="flex flex-wrap items-center justify-center gap-x-4 gap-y-2">
|
||
<a
|
||
v-if="icpNo"
|
||
href="https://beian.miit.gov.cn"
|
||
target="_blank"
|
||
rel="nofollow"
|
||
class="hover:text-white transition-colors"
|
||
>{{ icpNo }}</a>
|
||
<a
|
||
v-if="siteInfo?.policeNo"
|
||
:href="policeUrl"
|
||
target="_blank"
|
||
rel="nofollow"
|
||
class="hover:text-white transition-colors"
|
||
>{{ siteInfo.policeNo }}</a>
|
||
<a
|
||
rel="nofollow"
|
||
href="https://site.websoft.top"
|
||
target="_blank"
|
||
class="hover:text-white transition-colors"
|
||
>Powered by 云·企业官网</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
/**
|
||
* 模板 10 - Footer 组件(创芯存储科技蓝风格)
|
||
* 科技蓝底 + 公司信息 + 四列链接 + 备案版权
|
||
*/
|
||
import type { CmsNavigation } from '~/types'
|
||
|
||
const {
|
||
siteInfo, siteName, siteLogo, siteIcon,
|
||
phone, email, address, copyright, icpNo,
|
||
navigations, allNavigations, fetchSiteInfo
|
||
} = useSite()
|
||
|
||
await fetchSiteInfo()
|
||
|
||
const siteUrl = computed(() => {
|
||
const url = siteInfo.value?.domain || ''
|
||
if (!url) return ''
|
||
return url.startsWith('http') ? url : `https://${url}`
|
||
})
|
||
|
||
const policeUrl = computed(() => {
|
||
const no = String(siteInfo.value?.policeNo || '')
|
||
const code = no.replace(/\D/g, '')
|
||
return code
|
||
? `https://beian.mps.gov.cn/#/query/webSearch?code=${code}`
|
||
: 'https://beian.mps.gov.cn/'
|
||
})
|
||
|
||
/** 按模型或标题智能分组链接 */
|
||
const linkColumns = computed(() => {
|
||
const navs = navigations.value || []
|
||
const all = allNavigations.value || []
|
||
const cols: { title: string, links: CmsNavigation[] }[] = []
|
||
|
||
const findByModel = (model: string) => all.filter((n) => n.model === model && (n.parentId || 0) === 0).slice(0, 6)
|
||
const findByKeyword = (...keywords: string[]) => {
|
||
return navs.filter((n) => keywords.some((k) => n.title.includes(k))).slice(0, 6)
|
||
}
|
||
|
||
const products = findByModel('product')
|
||
if (products.length) cols.push({ title: products[0]?.title || '产品中心', links: products[0]?.children?.slice(0, 6) || [products[0]].filter(Boolean) })
|
||
|
||
const cases = findByModel('case')
|
||
if (cases.length) cols.push({ title: cases[0]?.title || '行业解决方案', links: cases[0]?.children?.slice(0, 6) || [cases[0]].filter(Boolean) })
|
||
|
||
const aboutLinks = findByKeyword('关于', '资讯', '联系', '加入')
|
||
if (aboutLinks.length) cols.push({ title: '关于我们', links: aboutLinks })
|
||
|
||
const partnerLinks = findByKeyword('合作', '伙伴', '服务')
|
||
if (partnerLinks.length) cols.push({ title: '合作伙伴', links: partnerLinks })
|
||
|
||
// 兜底:用底部导航补足列数
|
||
if (cols.length < 3) {
|
||
const bottom = (navs || []).filter((n) => n.model !== 'index').slice(0, 6)
|
||
if (bottom.length) cols.push({ title: '快速链接', links: bottom })
|
||
}
|
||
|
||
return cols
|
||
})
|
||
</script>
|