20260831223203

This commit is contained in:
oneao committed 2026-08-31 22:32:03 +08:00
1 parent 4d46ce6c53
commit 3bbcafc5be
91 files changed
+20921 -584

No files matched your search

@@ -0,0 +1,43 @@
<script setup lang="ts">
import { getCompany } from '~/data/mock'
// 企业空间使用独立的 company 布局:顶部只有一根纯企业导航(到顶、不含公司信息),
// 公司身份信息下放到导航下方的内容 hero(CompanyIdentityHeader),满足“导航上方无特殊信息”。
definePageMeta({
layout: 'company'
})
const route = useRoute()
const company = getCompany(route.params.slug as string)
if (!company) {
throw createError({
statusCode: 404,
statusMessage: '企业不存在',
fatal: true
})
}
useSeoMeta({
title: `${company.name} - 链通物流`,
description: `${company.description}`,
ogTitle: company.name,
ogDescription: company.description
})
// 传给子页面(/company/[slug]/index、about、articles、services、contact)
provide('company', company)
</script>
<template>
<div v-if="company">
<!-- 顶部:纯企业导航(唯一一根栏,不含公司信息) -->
<CompanyPageTabs :company="company" />
<!-- 导航下方:企业 hero(公司信息放在内容区,不在导航栏) -->
<CompanyIdentityHeader :company="company" />
<NuxtPage />
</div>
</template>
@@ -0,0 +1,76 @@
<script setup lang="ts">
import type { Company } from '~/data/mock'
const company = inject<Company>('company')!
const qualifications = [
{ name: '营业执照', icon: 'i-lucide-file-check' },
{ name: 'NVOCC 无船承运人', icon: 'i-lucide-ship' },
{ name: '国际货运代理备案', icon: 'i-lucide-globe' },
{ name: '道路运输经营许可', icon: 'i-lucide-truck' }
]
useSeoMeta({
title: `关于我们 - ${company.name}`,
description: company.about[0]
})
</script>
<template>
<div>
<CompanyPageBanner :company="company" title="关于我们" />
<UContainer class="max-w-6xl py-10">
<!-- 公司介绍 -->
<div class="max-w-4xl">
<h2 class="text-xl font-bold text-highlighted mb-4">
公司介绍
</h2>
<div class="space-y-4 text-toned leading-loose">
<p v-for="(paragraph, i) in company.about" :key="i">
{{ paragraph }}
</p>
</div>
</div>
<!-- 基本信息 -->
<div class="grid grid-cols-2 md:grid-cols-4 gap-6 mt-12 py-8 border-y border-muted">
<div class="text-center">
<p class="text-2xl font-bold text-primary">{{ company.established }}</p>
<p class="text-sm text-muted mt-1">成立年份</p>
</div>
<div class="text-center">
<p class="text-2xl font-bold text-primary mt-1">{{ company.employees.split(' ')[0] }}</p>
<p class="text-sm text-muted mt-1">企业规模</p>
</div>
<div class="text-center">
<p class="text-2xl font-bold text-primary">{{ company.routes.length }}+</p>
<p class="text-sm text-muted mt-1">主营航线</p>
</div>
<div class="text-center">
<p class="text-2xl font-bold text-primary">{{ company.services.length }}+</p>
<p class="text-sm text-muted mt-1">服务类型</p>
</div>
</div>
<!-- 资质证书 -->
<div class="mt-12">
<h2 class="text-xl font-bold text-highlighted mb-6">
资质证书
</h2>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<div
v-for="qualification in qualifications"
:key="qualification.name"
class="flex items-center gap-3 rounded-lg bg-elevated ring ring-default p-4"
>
<div class="flex items-center justify-center size-10 rounded-lg bg-primary/10 shrink-0">
<UIcon :name="qualification.icon" class="size-5 text-primary" />
</div>
<span class="text-sm text-toned">{{ qualification.name }}</span>
</div>
</div>
</div>
</UContainer>
</div>
</template>
@@ -0,0 +1,41 @@
<script setup lang="ts">
import type { Company } from '~/data/mock'
import { getCompanyArticles } from '~/data/mock'
const company = inject<Company>('company')!
const articles = getCompanyArticles(company.slug)
useSeoMeta({
title: `${company.name} - 文章 - 链通物流`,
description: `${company.name} 发布的行业资讯、公司动态与案例分享。`
})
</script>
<template>
<UContainer class="max-w-6xl py-8">
<div
v-if="articles.length"
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"
>
<ArticleCard
v-for="article in articles"
:key="article.id"
:article="article"
/>
</div>
<div
v-else
class="flex flex-col items-center gap-2 py-20 text-center"
>
<UIcon
name="i-lucide-file-x"
class="size-10 text-dimmed"
/>
<p class="text-toned">
该企业暂未发布文章
</p>
</div>
</UContainer>
</template>
@@ -0,0 +1,85 @@
<script setup lang="ts">
import type { Company } from '~/data/mock'
const company = inject<Company>('company')!
const contacts = computed(() => [
{ icon: 'i-lucide-phone', label: '联系电话', value: company.contact.phone },
{ icon: 'i-lucide-mail', label: '电子邮箱', value: company.contact.email },
{ icon: 'i-lucide-map-pin', label: '办公地址', value: company.contact.address },
{ icon: 'i-lucide-clock', label: '工作时间', value: company.contact.hours }
])
useSeoMeta({
title: `${company.name} - 联系方式 - 链通物流`,
description: `联系${company.name}:电话 ${company.contact.phone},地址 ${company.contact.address}。`
})
</script>
<template>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- 联系信息 -->
<div class="lg:col-span-2 rounded-lg bg-elevated ring ring-default p-6">
<h2 class="font-semibold text-highlighted mb-5">
联系方式
</h2>
<div class="space-y-5">
<div
v-for="item in contacts"
:key="item.label"
class="flex items-start gap-3"
>
<div class="flex items-center justify-center size-9 rounded-lg bg-primary/10 shrink-0">
<UIcon
:name="item.icon"
class="size-4.5 text-primary"
/>
</div>
<div>
<p class="text-sm text-dimmed">
{{ item.label }}
</p>
<p class="text-default font-medium">
{{ item.value }}
</p>
</div>
</div>
</div>
</div>
<!-- 在线沟通(示例) -->
<div class="rounded-lg bg-elevated ring ring-default p-6 flex flex-col">
<h2 class="font-semibold text-highlighted mb-3">
在线沟通
</h2>
<p class="text-sm text-muted leading-relaxed">
登录后可通过站内私信与该企业直接沟通,咨询航线报价、服务方案与合作事宜。
</p>
<UBadge
color="warning"
variant="soft"
icon="i-lucide-clock"
class="mt-4 self-start"
>
示例阶段未开放
</UBadge>
<div class="flex flex-col gap-2 mt-auto pt-6">
<UButton
label="发私信"
icon="i-lucide-message-circle"
disabled
block
/>
<UButton
label="加入行业群聊"
icon="i-lucide-messages-square"
color="neutral"
variant="outline"
disabled
block
/>
</div>
</div>
</div>
</template>
@@ -0,0 +1,157 @@
<script setup lang="ts">
import type { Company } from '~/data/mock'
import { getCompanyArticles } from '~/data/mock'
const company = inject<Company>('company')!
const articles = getCompanyArticles(company.slug).slice(0, 4)
useSeoMeta({
title: `${company.name} - ${company.slogan} - 链通物流`,
description: company.description
})
</script>
<template>
<div>
<!-- 公司简介 -->
<UContainer class="max-w-6xl pt-10 pb-14">
<div class="grid grid-cols-1 lg:grid-cols-5 gap-8 items-center">
<div class="lg:col-span-3">
<p class="text-primary font-semibold tracking-wider mb-2">关于我们 / ABOUT US</p>
<h2 class="text-2xl font-bold text-highlighted mb-4">
{{ company.name }}
</h2>
<p class="text-toned leading-relaxed mb-6">
{{ company.about[0] }}
</p>
<div class="flex flex-wrap gap-8 text-sm">
<div class="flex items-center gap-2 text-muted">
<UIcon name="i-lucide-building-2" class="size-4 text-primary" />
成立于 {{ company.established }} 年
</div>
<div class="flex items-center gap-2 text-muted">
<UIcon name="i-lucide-users" class="size-4 text-primary" />
{{ company.employees }}
</div>
<div class="flex items-center gap-2 text-muted">
<UIcon name="i-lucide-map-pin" class="size-4 text-primary" />
{{ company.city }}
</div>
</div>
<UButton
:to="`/company/${company.slug}/about`"
label="了解更多"
trailing-icon="i-lucide-arrow-right"
variant="link"
class="px-0 mt-2"
/>
</div>
<!-- 服务类型统计卡 -->
<div class="lg:col-span-2 grid grid-cols-2 gap-4">
<div
v-for="service in company.services.slice(0, 4)"
:key="service"
class="rounded-lg bg-elevated ring ring-default p-5 text-center"
>
<p class="text-sm text-muted">{{ service }}</p>
<p class="text-xs text-dimmed mt-1">主营服务</p>
</div>
</div>
</div>
</UContainer>
<!-- 服务项目 -->
<div class="bg-muted/40 py-14">
<UContainer class="max-w-6xl">
<div class="text-center mb-10">
<p class="text-primary font-semibold tracking-wider mb-2">主营业务 / SERVICES</p>
<h2 class="text-2xl font-bold text-highlighted">
服务项目
</h2>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
<NuxtLink
v-for="service in company.servicesDetail"
:key="service.name"
:to="`/company/${company.slug}/services`"
class="group rounded-lg bg-elevated ring ring-default hover:ring-primary/50 p-6 transition-colors"
>
<div class="flex items-center justify-center size-11 rounded-lg bg-primary/10 mb-4">
<UIcon :name="company.strengths[0]?.icon ?? 'i-lucide-package'" class="size-5 text-primary" />
</div>
<h3 class="font-semibold text-default mb-2 group-hover:text-primary transition-colors">
{{ service.name }}
</h3>
<p class="text-sm text-muted line-clamp-3 leading-relaxed">
{{ service.description }}
</p>
</NuxtLink>
</div>
</UContainer>
</div>
<!-- 核心优势 -->
<UContainer class="max-w-6xl py-14">
<div class="text-center mb-10">
<p class="text-primary font-semibold tracking-wider mb-2">为什么选择我们 / WHY US</p>
<h2 class="text-2xl font-bold text-highlighted">
核心优势
</h2>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div
v-for="strength in company.strengths"
:key="strength.title"
class="text-center"
>
<div class="flex items-center justify-center size-14 rounded-full bg-primary/10 mx-auto mb-4">
<UIcon :name="strength.icon" class="size-6 text-primary" />
</div>
<h3 class="font-semibold text-default mb-2">
{{ strength.title }}
</h3>
<p class="text-sm text-muted leading-relaxed">
{{ strength.description }}
</p>
</div>
</div>
</UContainer>
<!-- 新闻资讯 -->
<div class="bg-muted/40 py-14">
<UContainer class="max-w-6xl">
<div class="flex items-center justify-between mb-8">
<div>
<p class="text-primary font-semibold tracking-wider mb-2">公司动态 / NEWS</p>
<h2 class="text-2xl font-bold text-highlighted">
新闻资讯
</h2>
</div>
<UButton
:to="`/company/${company.slug}/articles`"
label="更多文章"
trailing-icon="i-lucide-arrow-right"
color="neutral"
variant="outline"
size="sm"
/>
</div>
<div v-if="articles.length" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<ArticleCard
v-for="article in articles"
:key="article.id"
:article="article"
/>
</div>
<p v-else class="text-muted text-center py-8">
暂无新闻动态
</p>
</UContainer>
</div>
</div>
</template>
@@ -0,0 +1,65 @@
<script setup lang="ts">
import type { Company } from '~/data/mock'
const company = inject<Company>('company')!
useSeoMeta({
title: `${company.name} - 服务 - 链通物流`,
description: `${company.name} 的主营服务:${company.services.join('、')}。`
})
</script>
<template>
<UContainer class="max-w-6xl py-8">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div
v-for="service in company.servicesDetail"
:key="service.name"
class="rounded-lg bg-elevated ring ring-default p-6"
>
<div class="flex items-center justify-between mb-2">
<h3 class="font-semibold text-default">
{{ service.name }}
</h3>
<UBadge
color="primary"
variant="soft"
size="sm"
>
在营
</UBadge>
</div>
<p class="text-sm text-muted leading-relaxed">
{{ service.description }}
</p>
</div>
</div>
<!-- 覆盖航线 -->
<div class="rounded-lg bg-elevated ring ring-default p-6 mt-6">
<h2 class="font-semibold text-highlighted mb-4">
覆盖航线
</h2>
<div class="flex flex-wrap gap-2">
<UBadge
v-for="route in company.routes"
:key="route"
color="primary"
variant="soft"
size="lg"
>
{{ route }}
</UBadge>
</div>
<p class="text-sm text-muted mt-4">
需要该企业的航线报价或服务方案?
<NuxtLink
:to="`/company/${company.slug}/contact`"
class="text-primary hover:underline"
>
联系他们 →
</NuxtLink>
</p>
</div>
</UContainer>
</template>