Compare commits

..

3 Commits

Author SHA1 Message Date
300266d32c refactor: 将各个界面的notfound提示提取为单独的组件NotFoundResult
All checks were successful
deploy to server / build-and-deploy (push) Successful in 2m56s
2025-10-28 16:32:00 +08:00
c6e0ea2a47 refactor: 将各个页面的面包屑导航提取为单独组件AppBreadcrumb 2025-10-28 16:16:57 +08:00
dc90e1045b refactor: 调整components目录
- 将components根据作用范围/可复用性进行分类
2025-10-28 16:01:34 +08:00
28 changed files with 168 additions and 186 deletions

View File

@ -0,0 +1,21 @@
<template>
<el-breadcrumb separator="/">
<el-breadcrumb-item
v-for="(item, index) in items"
:key="index"
class="text-md opacity-50"
>
<NuxtLink v-if="item.to" :to="item.to">{{ item.label }}</NuxtLink>
<span v-else>{{ item.label }}</span>
</el-breadcrumb-item>
</el-breadcrumb>
</template>
<script setup lang="ts">
defineProps({
items: {
type: Array as () => Array<{ label: string; to?: string }>,
required: true,
},
});
</script>

View File

@ -0,0 +1,33 @@
<template>
<el-result icon="warning" :title="title" :sub-title="subTitle">
<template #extra>
<el-button type="primary" @click="onBack">
{{ backText || $t('back') }}
</el-button>
</template>
</el-result>
</template>
<script setup lang="ts">
defineProps({
title: {
type: String,
required: true,
},
subTitle: {
type: String,
required: false,
default: '',
},
backText: {
type: String,
required: false,
default: '',
},
onBack: {
type: Function as () => unknown,
required: false,
default: undefined,
},
});
</script>

View File

@ -1,17 +1,10 @@
<template> <template>
<main p="x4 y10" text="center teal-700 dark:gray-200"> <main p="x4 y10" text="center teal-700 dark:gray-200">
<div text4xl> <not-found-result
<div i-ep-warning inline-block /> :title="$t('page-not-found')"
</div> :sub-title="$t('page-not-found-desc')"
<div>{{ $t('not-found') }}</div> :back-text="$t('back-to-home')"
<div> :on-back="() => $router.push($localePath('/'))"
<button text-sm btn m="3 t8" @click="router.back()"> />
{{ $t('back') }}
</button>
</div>
</main> </main>
</template> </template>
<script setup lang="ts">
const router = useRouter();
</script>

View File

@ -1,18 +1,7 @@
<template> <template>
<div class="page-container"> <div class="page-container">
<div v-if="!pending"> <div v-if="!pending">
<el-breadcrumb class="breadcrumb" separator="/"> <app-breadcrumb class="breadcrumb" :items="breadcrumbItems" />
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/')">
{{ $t('navigation.home') }}
</NuxtLink>
</el-breadcrumb-item>
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/about')">
{{ $t('navigation.about-us') }}
</NuxtLink>
</el-breadcrumb-item>
</el-breadcrumb>
<div class="content"> <div class="content">
<markdown-renderer :content="content.content || ''" /> <markdown-renderer :content="content.content || ''" />
@ -38,6 +27,11 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const localePath = useLocalePath();
const breadcrumbItems = [
{ label: $t('navigation.home'), to: localePath('/') },
{ label: $t('navigation.about-us') },
];
const { data, pending, error } = await useCompanyProfile(); const { data, pending, error } = await useCompanyProfile();
const content = computed(() => toCompanyProfileView(data.value)); const content = computed(() => toCompanyProfileView(data.value));

View File

@ -2,18 +2,7 @@
<div class="page-container"> <div class="page-container">
<div class="page-header"> <div class="page-header">
<h1 class="page-title">文件下载</h1> <h1 class="page-title">文件下载</h1>
<el-breadcrumb class="breadcrumb"> <app-breadcrumb class="breadcrumb" :items="breadcrumbItems" />
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/')">{{
$t('navigation.home')
}}</NuxtLink>
</el-breadcrumb-item>
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/products')">{{
$t('navigation.downloads')
}}</NuxtLink>
</el-breadcrumb-item>
</el-breadcrumb>
</div> </div>
<div v-if="!pending" class="page-content"> <div v-if="!pending" class="page-content">
<el-card shadow="hover" class="p-4"> <el-card shadow="hover" class="p-4">
@ -60,6 +49,12 @@
<script setup lang="ts"> <script setup lang="ts">
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const localePath = useLocalePath();
const breadcrumbItems = [
{ label: $t('navigation.home'), to: localePath('/') },
{ label: $t('navigation.downloads'), to: localePath('/downloads') },
];
// 获取路由参数 // 获取路由参数
const id = computed(() => route.params.id as string); const id = computed(() => route.params.id as string);

View File

@ -3,21 +3,7 @@
<div v-if="!pending"> <div v-if="!pending">
<div v-if="product"> <div v-if="product">
<!-- 面包屑导航 --> <!-- 面包屑导航 -->
<el-breadcrumb class="breadcrumb" separator="/"> <app-breadcrumb class="breadcrumb" :items="breadcrumbItems" />
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/')">{{
$t('navigation.home')
}}</NuxtLink>
</el-breadcrumb-item>
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/products')">{{
$t('navigation.products')
}}</NuxtLink>
</el-breadcrumb-item>
<el-breadcrumb-item class="text-md opactiy-50">{{
product.name
}}</el-breadcrumb-item>
</el-breadcrumb>
<!-- 产品详情内容 --> <!-- 产品详情内容 -->
<div class="product-header"> <div class="product-header">
@ -81,17 +67,12 @@
</div> </div>
<!-- 未找到产品 --> <!-- 未找到产品 -->
<div v-else class="not-found"> <div v-else class="not-found">
<el-result <not-found-result
icon="warning"
:title="$t('product-not-found')" :title="$t('product-not-found')"
:sub-title="$t('product-not-found-desc')" :sub-title="$t('product-not-found-desc')"
> :back-text="$t('back-to-products')"
<template #extra> :on-back="() => $router.push($localePath('/products'))"
<el-button type="primary" @click="$router.push('/products')"> />
{{ $t('back-to-products') }}
</el-button>
</template>
</el-result>
</div> </div>
</div> </div>
<div v-else class="loading"> <div v-else class="loading">
@ -107,6 +88,7 @@
<script setup lang="ts"> <script setup lang="ts">
const route = useRoute(); const route = useRoute();
const localePath = useLocalePath();
const { getImageUrl } = useDirectusImage(); const { getImageUrl } = useDirectusImage();
@ -115,17 +97,22 @@
const { data, pending, error } = await useProduct(id.value); const { data, pending, error } = await useProduct(id.value);
console.log('Raw Data: ', data.value);
const rawProduct = computed(() => data.value ?? null); const rawProduct = computed(() => data.value ?? null);
const product = computed(() => { const product = computed(() => {
if (rawProduct.value === null) {
return null;
}
return toProductView(rawProduct.value); return toProductView(rawProduct.value);
}); });
console.log('View Data: ', product.value);
const activeName = ref('details'); // 默认选中概览标签 const activeName = ref('details'); // 默认选中概览标签
const breadcrumbItems = computed(() => [
{ label: $t('navigation.home'), to: localePath('/') },
{ label: $t('navigation.products'), to: localePath('/products') },
{ label: product.value?.name || '' },
]);
watch(error, (value) => { watch(error, (value) => {
if (value) { if (value) {
console.error('数据获取失败: ', value); console.error('数据获取失败: ', value);

View File

@ -2,18 +2,7 @@
<div class="page-container"> <div class="page-container">
<div class="page-header"> <div class="page-header">
<h1 class="page-title">{{ $t('our-products') }}</h1> <h1 class="page-title">{{ $t('our-products') }}</h1>
<el-breadcrumb class="breadcrumb"> <app-breadcrumb class="breadcrumb" :items="breadcrumbItems" />
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/')">{{
$t('navigation.home')
}}</NuxtLink>
</el-breadcrumb-item>
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/products')">{{
$t('navigation.products')
}}</NuxtLink>
</el-breadcrumb-item>
</el-breadcrumb>
</div> </div>
<div v-if="!pending" class="page-content"> <div v-if="!pending" class="page-content">
<div class="products-container"> <div class="products-container">
@ -45,12 +34,18 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const localePath = useLocalePath();
const { getImageUrl } = useDirectusImage(); const { getImageUrl } = useDirectusImage();
const { data, pending, error } = useProductList(); const { data, pending, error } = useProductList();
const activeNames = ref<string[]>([]); const activeNames = ref<string[]>([]);
const breadcrumbItems = [
{ label: $t('navigation.home'), to: localePath('/') },
{ label: $t('navigation.products') },
];
const productsRaw = computed(() => data.value ?? []); const productsRaw = computed(() => data.value ?? []);
const products = computed(() => const products = computed(() =>
productsRaw.value.map((item) => toProductListView(item)) productsRaw.value.map((item) => toProductListView(item))

View File

@ -3,21 +3,7 @@
<div v-if="!pending"> <div v-if="!pending">
<div v-if="solution"> <div v-if="solution">
<div class="page-header"> <div class="page-header">
<el-breadcrumb class="breadcrumb" separator="/"> <app-breadcrumb class="breadcrumb" :items="breadcrumbItems" />
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/')">{{
$t('navigation.home')
}}</NuxtLink>
</el-breadcrumb-item>
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/solutions')">{{
$t('navigation.solutions')
}}</NuxtLink>
</el-breadcrumb-item>
<el-breadcrumb-item class="text-md opacity-50">{{
solution.title
}}</el-breadcrumb-item>
</el-breadcrumb>
</div> </div>
<div class="page-content"> <div class="page-content">
<div class="solution-info"> <div class="solution-info">
@ -36,17 +22,12 @@
</div> </div>
</div> </div>
<div v-else class="not-found"> <div v-else class="not-found">
<el-result <not-found-result
icon="warning"
:title="$t('solution-not-found')" :title="$t('solution-not-found')"
:sub-title="$t('solution-not-found-desc')" :sub-title="$t('solution-not-found-desc')"
> :back-text="$t('back-to-solutions')"
<template #extra> :on-back="() => $router.push($localePath('/solutions'))"
<el-button type="primary" @click="$router.push('/solutions')"> />
{{ $t('back-to-solutions') }}
</el-button>
</template>
</el-result>
</div> </div>
</div> </div>
<div v-else class="loading"> <div v-else class="loading">
@ -57,17 +38,25 @@
<script setup lang="ts"> <script setup lang="ts">
const route = useRoute(); const route = useRoute();
const localePath = useLocalePath();
// 获取路由参数(documentId) // 获取路由参数(documentId)
const id = computed(() => route.params.slug as string); const id = computed(() => route.params.slug as string);
const { data, pending, error } = await useSolution(id.value); const { data, pending, error } = await useSolution(id.value);
console.log('RawData: ', data.value); const solution = computed(() => {
const process = toSolutionView(data.value); if (!data.value) {
console.log('Processed Solution: ', process); return null;
}
return toSolutionView(data.value);
});
const solution = computed(() => toSolutionView(data.value)); const breadcrumbItems = computed(() => [
{ label: $t('navigation.home'), to: localePath('/') },
{ label: $t('navigation.solutions'), to: localePath('/solutions') },
{ label: solution.value ? solution.value.title : '' },
]);
watch(error, (value) => { watch(error, (value) => {
if (value) { if (value) {

View File

@ -2,18 +2,7 @@
<div class="page-container"> <div class="page-container">
<div class="page-header"> <div class="page-header">
<h1 class="page-title">{{ $t('learn-our-solutions') }}</h1> <h1 class="page-title">{{ $t('learn-our-solutions') }}</h1>
<el-breadcrumb class="breadcrumb"> <app-breadcrumb class="breadcrumb" :items="breadcrumbItems" />
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/')">{{
$t('navigation.home')
}}</NuxtLink>
</el-breadcrumb-item>
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/solutions')">{{
$t('navigation.solutions')
}}</NuxtLink>
</el-breadcrumb-item>
</el-breadcrumb>
</div> </div>
<div v-if="!pending" class="solutions-container"> <div v-if="!pending" class="solutions-container">
<el-tabs v-model="activeName" class="solutions-tabs"> <el-tabs v-model="activeName" class="solutions-tabs">
@ -55,8 +44,14 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const localePath = useLocalePath();
const { getImageUrl } = useDirectusImage(); const { getImageUrl } = useDirectusImage();
const breadcrumbItems = [
{ label: $t('navigation.home'), to: localePath('/') },
{ label: $t('navigation.solutions') },
];
const { data, pending, error } = await useSolutionList(); const { data, pending, error } = await useSolutionList();
const solutionsRaw = computed(() => data.value ?? []); const solutionsRaw = computed(() => data.value ?? []);
@ -66,8 +61,6 @@
const activeName = ref<string>('all'); const activeName = ref<string>('all');
console.log('Processed Data', solutions.value);
// 按类型分组 // 按类型分组
const groupedSolutions = computed(() => { const groupedSolutions = computed(() => {
const gourps: Record<string, SolutionListView[]> = {}; const gourps: Record<string, SolutionListView[]> = {};

View File

@ -3,23 +3,7 @@
<support-tabs model-value="contact-us" /> <support-tabs model-value="contact-us" />
<div class="page-header"> <div class="page-header">
<h1 class="page-title">{{ $t('navigation.contact-info') }}</h1> <h1 class="page-title">{{ $t('navigation.contact-info') }}</h1>
<el-breadcrumb class="breadcrumb" separator="/"> <app-breadcrumb class="breadcrumb" :items="breadcrumbItems" />
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/')">
{{ $t('navigation.home') }}
</NuxtLink>
</el-breadcrumb-item>
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/support')">
{{ $t('navigation.support') }}
</NuxtLink>
</el-breadcrumb-item>
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/support/contact-us')">
{{ $t('navigation.contact-info') }}
</NuxtLink>
</el-breadcrumb-item>
</el-breadcrumb>
</div> </div>
<div v-if="!pending" class="page-content"> <div v-if="!pending" class="page-content">
@ -32,6 +16,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const localePath = useLocalePath();
const breadcrumbItems = [
{ label: $t('navigation.home'), to: localePath('/') },
{ label: $t('navigation.support'), to: localePath('/support') },
{ label: $t('navigation.contact-info') },
];
const { data, pending, error } = await useContactInfo(); const { data, pending, error } = await useContactInfo();
const content = computed(() => toContactInfoView(data.value)); const content = computed(() => toContactInfoView(data.value));

View File

@ -7,23 +7,7 @@
<support-tabs model-value="documents" /> <support-tabs model-value="documents" />
<div class="page-header"> <div class="page-header">
<h1 class="page-title">{{ $t('navigation.documents') }}</h1> <h1 class="page-title">{{ $t('navigation.documents') }}</h1>
<el-breadcrumb class="breadcrumb" separator="/"> <app-breadcrumb class="breadcrumb" :items="breadcrumbItems" />
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/')">{{
$t('navigation.home')
}}</NuxtLink>
</el-breadcrumb-item>
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/support')">{{
$t('navigation.support')
}}</NuxtLink>
</el-breadcrumb-item>
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/support/documents')">{{
$t('navigation.documents')
}}</NuxtLink>
</el-breadcrumb-item>
</el-breadcrumb>
</div> </div>
<div class="document-category"> <div class="document-category">
<el-row :gutter="12"> <el-row :gutter="12">
@ -78,6 +62,13 @@
<script setup lang="ts"> <script setup lang="ts">
import { Search } from '@element-plus/icons-vue'; import { Search } from '@element-plus/icons-vue';
const localePath = useLocalePath();
const breadcrumbItems = [
{ label: $t('navigation.home'), to: localePath('/') },
{ label: $t('navigation.support'), to: localePath('/support') },
{ label: $t('navigation.documents') },
];
const { data, pending, error } = await useDocumentList(); const { data, pending, error } = await useDocumentList();
const documents = computed( const documents = computed(

View File

@ -7,23 +7,7 @@
<support-tabs model-value="faq" /> <support-tabs model-value="faq" />
<div class="page-header"> <div class="page-header">
<h1 class="page-title">{{ $t('navigation.faq') }}</h1> <h1 class="page-title">{{ $t('navigation.faq') }}</h1>
<el-breadcrumb class="breadcrumb" separator="/"> <app-breadcrumb class="breadcrumb" :items="breadcrumbItems" />
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/')">{{
$t('navigation.home')
}}</NuxtLink>
</el-breadcrumb-item>
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/support')">{{
$t('navigation.support')
}}</NuxtLink>
</el-breadcrumb-item>
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/support/faq')">{{
$t('navigation.faq')
}}</NuxtLink>
</el-breadcrumb-item>
</el-breadcrumb>
</div> </div>
<div class="question-category"> <div class="question-category">
@ -79,6 +63,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { Search } from '@element-plus/icons-vue'; import { Search } from '@element-plus/icons-vue';
const localePath = useLocalePath();
const breadcrumbItems = [
{ label: $t('navigation.home'), to: localePath('/') },
{ label: $t('navigation.support'), to: localePath('/support') },
{ label: $t('navigation.faq') },
];
const { data, pending, error } = await useQuestionList(); const { data, pending, error } = await useQuestionList();
const questions = computed( const questions = computed(

View File

@ -1,22 +1,11 @@
<template> <template>
<div class="page-container"> <div class="page-container">
<support-tabs /> <support-tabs />
<div class="page-content">
<div class="page-header"> <div class="page-header">
<h1 class="page-title">{{ $t('navigation.support') }}</h1> <h1 class="page-title">{{ $t('navigation.support') }}</h1>
<el-breadcrumb class="breadcrumb" separator="/"> <app-breadcrumb class="breadcrumb" :items="breadcrumbItems" />
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/')">{{
$t('navigation.home')
}}</NuxtLink>
</el-breadcrumb-item>
<el-breadcrumb-item class="text-md opacity-50">
<NuxtLink :to="$localePath('/support')">{{
$t('navigation.support')
}}</NuxtLink>
</el-breadcrumb-item>
</el-breadcrumb>
</div> </div>
<div class="page-content">
<section style="margin-bottom: 2rem"> <section style="margin-bottom: 2rem">
<p> <p>
金申机械制造有限公司致力于为客户提供优质的产品与服务针对纸管机分纸机纸吸管等产品我们提供全方位的售后服务确保客户能够安心地使用我们的产品 金申机械制造有限公司致力于为客户提供优质的产品与服务针对纸管机分纸机纸吸管等产品我们提供全方位的售后服务确保客户能够安心地使用我们的产品
@ -109,7 +98,13 @@
</div> </div>
</template> </template>
<script setup lang="ts"></script> <script setup lang="ts">
const localePath = useLocalePath();
const breadcrumbItems = [
{ label: $t('navigation.home'), to: localePath('/') },
{ label: $t('navigation.support') },
];
</script>
<style scoped> <style scoped>
.page-container { .page-container {
@ -119,6 +114,7 @@
.page-header { .page-header {
display: flex; display: flex;
padding: 2rem 2rem 0rem;
} }
.page-title { .page-title {

View File

@ -56,6 +56,9 @@
"solution-not-found": "Solution Not Found", "solution-not-found": "Solution Not Found",
"solution-not-found-desc": "Sorry, the solution you are lokking for does not exist or has been removed.", "solution-not-found-desc": "Sorry, the solution you are lokking for does not exist or has been removed.",
"back-to-solutions": "Back to Solutions", "back-to-solutions": "Back to Solutions",
"page-not-found": "Page Not Found",
"page-not-found-desc": "Sorry, the page you are looking for does not exist or has been removed.",
"back-to-home": "Back to Home",
"no-content-available": "No detailed information available", "no-content-available": "No detailed information available",
"loading": "Loading...", "loading": "Loading...",
"our-products": "Our Products", "our-products": "Our Products",

View File

@ -56,6 +56,9 @@
"solution-not-found": "解决方案未找到", "solution-not-found": "解决方案未找到",
"solution-not-found-desc": "抱歉,您访问的解决方案不存在或已被删除", "solution-not-found-desc": "抱歉,您访问的解决方案不存在或已被删除",
"back-to-solutions": "返回解决方案列表", "back-to-solutions": "返回解决方案列表",
"page-not-found": "页面未找到",
"page-not-found-desc": "抱歉,您访问的页面不存在或已被删除。",
"back-to-home": "返回首页",
"no-content-available": "暂无详细信息", "no-content-available": "暂无详细信息",
"loading": "加载中...", "loading": "加载中...",
"our-products": "我们的产品", "our-products": "我们的产品",

View File

@ -18,6 +18,13 @@ export default defineNuxtConfig({
}, },
}, },
components: [
{
path: '~/components',
pathPrefix: false,
},
],
runtimeConfig: { runtimeConfig: {
public: { public: {
meili: { meili: {