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,142 @@
<script setup lang="ts">
import { companies, regionOptions, routeOptions, serviceOptions } from '~/data/mock'
// USelect 的候选项不允许 value 为空字符串(Reka UI 会直接抛错导致页面水合失败),
// 因此「全部」使用 'all' 作为哨兵值,筛选时再转换为「不限制」。
const ANY = 'all'
const route = useRoute()
const keyword = ref(typeof route.query.q === 'string' ? route.query.q : '')
const region = ref<string>(ANY)
const routeFilter = ref<string>(ANY)
const serviceFilter = ref<string>(ANY)
const verifiedOnly = ref(false)
// 平台主导航的搜索框会带 q 跳转;目录页内再次搜索时组件复用,需同步 query
watch(() => route.query.q, (q) => {
if (typeof q === 'string') {
keyword.value = q
}
})
const toItems = (options: string[], label: string) => [
{ label: `全部${label}`, value: ANY },
...options.map(o => ({ label: o, value: o }))
]
const filtered = computed(() => {
const kw = keyword.value.trim().toLowerCase()
return companies.filter((c) => {
if (verifiedOnly.value && !c.verified) return false
if (region.value !== ANY && c.region !== region.value) return false
if (routeFilter.value !== ANY && !c.routes.includes(routeFilter.value)) return false
if (serviceFilter.value !== ANY && !c.services.includes(serviceFilter.value)) return false
if (kw && !(`${c.name}${c.slogan}${c.description}${c.city}`.toLowerCase().includes(kw))) return false
return true
})
})
function resetFilters() {
keyword.value = ''
region.value = ANY
routeFilter.value = ANY
serviceFilter.value = ANY
verifiedOnly.value = false
}
useSeoMeta({
title: '企业目录 - 链通物流',
description: '按航线、服务类型与地区筛选物流企业:海运整箱、拼箱、空运、铁路联运、报关报检、仓储与跨境电商物流服务商目录。'
})
</script>
<template>
<UPage>
<UPageHeader
headline="企业目录"
title="查找物流服务商"
description="按航线、服务类型、地区筛选,或直接搜索企业名称与主营关键词。"
/>
<UPageBody>
<UContainer>
<!-- 筛选器 -->
<div class="flex flex-col lg:flex-row gap-3 lg:items-center mb-6">
<UInput
v-model="keyword"
icon="i-lucide-search"
placeholder="搜索企业名称、主营关键词…"
class="flex-1"
size="lg"
/>
<div class="flex flex-wrap gap-3 items-center">
<USelect
v-model="region"
:items="toItems(regionOptions, '地区')"
icon="i-lucide-map-pin"
class="w-32"
/>
<USelect
v-model="routeFilter"
:items="toItems(routeOptions, '航线')"
icon="i-lucide-globe"
class="w-36"
/>
<USelect
v-model="serviceFilter"
:items="toItems(serviceOptions, '服务')"
icon="i-lucide-ship"
class="w-40"
/>
<UCheckbox
v-model="verifiedOnly"
label="仅认证企业"
icon="i-lucide-badge-check"
/>
</div>
</div>
<!-- 结果统计 -->
<p class="text-sm text-muted mb-4">
共找到 <span class="font-semibold text-default">{{ filtered.length }}</span> 家企业
</p>
<!-- 企业列表 -->
<div
v-if="filtered.length"
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"
>
<CompanyCard
v-for="company in filtered"
:key="company.slug"
:company="company"
/>
</div>
<div
v-else
class="flex flex-col items-center gap-3 py-20 text-center"
>
<UIcon
name="i-lucide-search-x"
class="size-10 text-dimmed"
/>
<p class="text-toned">
没有符合条件的企业,试试放宽筛选条件
</p>
<UButton
label="重置筛选"
color="neutral"
variant="outline"
icon="i-lucide-rotate-ccw"
@click="resetFilters"
/>
</div>
<div class="h-12" />
</UContainer>
</UPageBody>
</UPage>
</template>