本次提交主要进行了以下修改: 1. 在styles.css中调整了链接和代码块的样式,使用CSS变量提升可维护性。 2. 在faq.vue中优化了FAQ内容的渲染结构,增强了可读性。 3. 在index.vue和products/[id].vue中移除了多余的console.log语句,提升了代码整洁性。 这些改动旨在提升代码的可维护性和用户体验,同时减少不必要的调试信息。master
text-decoration-thickness: 1px; | text-decoration-thickness: 1px; | ||||
text-underline-offset: 2px; | text-underline-offset: 2px; | ||||
transition: color 0.2s; | transition: color 0.2s; | ||||
pointer-events: none; | |||||
color: var(--color-primary); | |||||
} | } | ||||
.prose a:hover { | .prose a:hover { | ||||
color: rgb(147 197 253); | color: rgb(147 197 253); | ||||
} | } | ||||
.prose h1 a, | |||||
.prose h2 a, | |||||
.prose h3 a, | |||||
.prose h4 a, | |||||
.prose h5 a, | |||||
.prose h6 a { | |||||
color: var(--color-text); | |||||
pointer-events: none; | |||||
} | |||||
.prose ul, | .prose ul, | ||||
.prose ol { | .prose ol { | ||||
margin: 1rem 0; | margin: 1rem 0; | ||||
} | } | ||||
.prose code { | .prose code { | ||||
background-color: rgb(39, 39, 42); | |||||
background-color: rgba(0, 0, 0, 0.5); | |||||
padding: 0.125rem 0.375rem; | padding: 0.125rem 0.375rem; | ||||
border-radius: 0.25rem; | border-radius: 0.25rem; | ||||
font-size: 0.875rem; | font-size: 0.875rem; | ||||
font-family: ui-monospace, monospace; | |||||
color: rgb(147 197 253); | |||||
color: var(--color-text); | |||||
} | } | ||||
.prose pre { | .prose pre { |
>{{ t("common.home") }}</nuxt-link | >{{ t("common.home") }}</nuxt-link | ||||
> | > | ||||
<span class="text-white/60 text-base font-normal px-2"> / </span> | <span class="text-white/60 text-base font-normal px-2"> / </span> | ||||
<nuxt-link :to="`${homepagePath}/faq`" class="text-white text-base font-normal">{{ | |||||
t("faq.title") | |||||
}}</nuxt-link> | |||||
<nuxt-link | |||||
:to="`${homepagePath}/faq`" | |||||
class="text-white text-base font-normal" | |||||
>{{ t("faq.title") }}</nuxt-link | |||||
> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div | <div | ||||
</div> | </div> | ||||
<div | <div | ||||
v-if="isFaqExpanded(faq)" | v-if="isFaqExpanded(faq)" | ||||
class="mt-4 text-white/80 text-base font-normal leading-relaxed" | |||||
class="mt-4" | |||||
> | > | ||||
<ContentRenderer class="text-white" :value="{ body: faq.content }" /> | |||||
<ContentRenderer | |||||
class="prose w-full max-w-none" | |||||
:value="{ body: faq.content }" | |||||
/> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div | <div | ||||
id?: string; | id?: string; | ||||
} | } | ||||
const homepagePath = computed(() => { | const homepagePath = computed(() => { | ||||
return locale.value === "zh" ? "" : `/${locale.value}`; | return locale.value === "zh" ? "" : `/${locale.value}`; | ||||
}); | }); | ||||
// 从content目录读取FAQ数据 | // 从content目录读取FAQ数据 | ||||
const faqs = ref<FAQ[]>([]); | const faqs = ref<FAQ[]>([]); | ||||
const categoriesList = ref<string[]>([]); | const categoriesList = ref<string[]>([]); | ||||
.where("path", "LIKE", `/faq/${locale.value}/%`) | .where("path", "LIKE", `/faq/${locale.value}/%`) | ||||
.all(); | .all(); | ||||
console.log("Raw FAQ content:", content); | |||||
if (!content || !Array.isArray(content)) { | if (!content || !Array.isArray(content)) { | ||||
console.error("No FAQ content found or invalid format:", content); | console.error("No FAQ content found or invalid format:", content); | ||||
return []; | return []; | ||||
// 转换数据格式 | // 转换数据格式 | ||||
const faqItems = content.map((item: any) => { | const faqItems = content.map((item: any) => { | ||||
console.log("Processing FAQ item:", item); | |||||
return { | return { | ||||
category: item.meta?.category || "", | category: item.meta?.category || "", | ||||
title: item.title || "", | title: item.title || "", | ||||
}; | }; | ||||
}); | }); | ||||
console.log("Processed FAQ items:", faqItems); | |||||
return faqItems.sort((a, b) => a.sort - b.sort); | return faqItems.sort((a, b) => a.sort - b.sort); | ||||
} catch (error) { | } catch (error) { | ||||
console.error("Error loading FAQ content:", error); | console.error("Error loading FAQ content:", error); | ||||
if (faqData.value) { | if (faqData.value) { | ||||
isLoading.value = true; | isLoading.value = true; | ||||
try { | try { | ||||
console.log("Processing FAQ data:", faqData.value); | |||||
// 设置分类列表和默认选中的分类 | // 设置分类列表和默认选中的分类 | ||||
const allOption: string = | const allOption: string = | ||||
locale.value === "en" | locale.value === "en" | ||||
.filter((category) => category) | .filter((category) => category) | ||||
.sort(); // 过滤掉空分类并排序 | .sort(); // 过滤掉空分类并排序 | ||||
console.log("Unique categories:", uniqueCategories); | |||||
// 设置分类列表和默认选中的分类 | // 设置分类列表和默认选中的分类 | ||||
categoriesList.value = [allOption, ...uniqueCategories]; | categoriesList.value = [allOption, ...uniqueCategories]; | ||||
selectedCategory.value = categoriesList.value[0]; | selectedCategory.value = categoriesList.value[0]; | ||||
// 过滤后的FAQ列表 | // 过滤后的FAQ列表 | ||||
const filteredFaqs = computed(() => { | const filteredFaqs = computed(() => { | ||||
if (!faqData.value) { | if (!faqData.value) { | ||||
console.log("No FAQ data available"); | |||||
return []; | return []; | ||||
} | } | ||||
let result = faqData.value; | let result = faqData.value; | ||||
// 分类过滤 | // 分类过滤 | ||||
if (selectedCategory.value !== categoriesList.value[0]) { | if (selectedCategory.value !== categoriesList.value[0]) { | ||||
result = result.filter( | result = result.filter( |
</div> | </div> | ||||
</div> | </div> | ||||
</SwiperSlide> | </SwiperSlide> | ||||
<SwiperSlide> | |||||
<SwiperSlide v-if="!isMobile"> | |||||
<div class="max-w-screen-2xl mx-auto h-full relative"> | <div class="max-w-screen-2xl mx-auto h-full relative"> | ||||
<video | <video | ||||
:src="homeA3Webp" | :src="homeA3Webp" | ||||
:key="usage.id" | :key="usage.id" | ||||
class="cursor-pointer select-none px-4 sm:px-7 py-2 sm:py-3 rounded-full border border-zinc-700 text-white transition-all duration-300 relative group" | class="cursor-pointer select-none px-4 sm:px-7 py-2 sm:py-3 rounded-full border border-zinc-700 text-white transition-all duration-300 relative group" | ||||
:class="{ | :class="{ | ||||
'bg-cyan-400/10 border-cyan-400 text-cyan-400': | |||||
'bg-gradient-to-r from-blue-700 to-blue-400 text-white border-zinc-900 pointer-events-none': | |||||
activeIndex === index, | activeIndex === index, | ||||
'hover:border-zinc-600': activeIndex !== index, | 'hover:border-zinc-600': activeIndex !== index, | ||||
}" | }" | ||||
// 处理数据 | // 处理数据 | ||||
usageList.value = usageData | usageList.value = usageData | ||||
.map((usage: any) => { | .map((usage: any) => { | ||||
console.log(`处理用途: ${usage.id} - ${usage.title}`, usage); | |||||
// 为每种用途找到对应的产品 | // 为每种用途找到对应的产品 | ||||
const usageProducts = []; | const usageProducts = []; | ||||
product.usage.includes(usage.title) | product.usage.includes(usage.title) | ||||
); | ); | ||||
console.log( | |||||
`用途"${usage.title}"匹配到 ${matchedProducts.length} 个产品` | |||||
); | |||||
// 将匹配的产品添加到列表 | // 将匹配的产品添加到列表 | ||||
if (matchedProducts.length > 0) { | if (matchedProducts.length > 0) { | ||||
matchedProducts.forEach((product: any) => { | matchedProducts.forEach((product: any) => { | ||||
}); | }); | ||||
} else { | } else { | ||||
// 如果没有找到匹配的产品,添加一个占位产品 | // 如果没有找到匹配的产品,添加一个占位产品 | ||||
console.log(`用途 ${usage.title} 没有匹配到任何产品,添加占位产品`); | |||||
usageProducts.push({ | usageProducts.push({ | ||||
id: `placeholder-${usage.id}`, | id: `placeholder-${usage.id}`, | ||||
} | } | ||||
const data = await response.json(); | const data = await response.json(); | ||||
console.log("Raw category data:", data); | |||||
// 处理数据 | // 处理数据 | ||||
categoryList.value = data | categoryList.value = data | ||||
loadCategoryData(); | loadCategoryData(); | ||||
}); | }); | ||||
// 处理数据变化 | |||||
watchEffect(() => { | |||||
if (usageList.value) { | |||||
console.log("Updated usage list:", usageList.value); | |||||
} | |||||
if (categoryList.value) { | |||||
console.log("Updated category list:", categoryList.value); | |||||
} | |||||
}); | |||||
// 计算当前用途列表 | // 计算当前用途列表 | ||||
const typedUsageList = computed(() => { | const typedUsageList = computed(() => { | ||||
console.log("Typed Usage List:", usageList.value); | |||||
return usageList.value as Usage[]; | return usageList.value as Usage[]; | ||||
}); | }); | ||||
const currentUsage = typedUsageList.value.find( | const currentUsage = typedUsageList.value.find( | ||||
(item: Usage) => item.id === activeUsageId.value | (item: Usage) => item.id === activeUsageId.value | ||||
); | ); | ||||
if (currentUsage?.products) { | |||||
console.log( | |||||
"Products:", | |||||
currentUsage.products.map((p: Product) => ({ | |||||
id: p.id, | |||||
title: p.title, | |||||
image: p.image, | |||||
link: p.link, | |||||
})) | |||||
); | |||||
} | |||||
return currentUsage?.products || []; | return currentUsage?.products || []; | ||||
}); | }); | ||||
watch( | watch( | ||||
activeProducts, | activeProducts, | ||||
(newProducts: Product[]) => { | (newProducts: Product[]) => { | ||||
console.log("Active Products Changed:", newProducts); | |||||
if (process.client) { | if (process.client) { | ||||
newProducts.forEach((product: Product) => { | newProducts.forEach((product: Product) => { | ||||
if (product.image) { | if (product.image) { | ||||
console.log( | |||||
`Checking image for product ${product.id}:`, | |||||
product.image | |||||
); | |||||
const img = new window.Image(); | const img = new window.Image(); | ||||
img.onload = () => handleImageLoad(product.id); | img.onload = () => handleImageLoad(product.id); | ||||
img.onerror = () => handleImageError(product.id); | img.onerror = () => handleImageError(product.id); | ||||
// 处理图片加载 | // 处理图片加载 | ||||
const handleImageLoad = (id: number) => { | const handleImageLoad = (id: number) => { | ||||
if (process.client) { | if (process.client) { | ||||
console.log(`Image loaded for product ${id}`); | |||||
isImageLoaded.value[id] = true; | isImageLoaded.value[id] = true; | ||||
imageErrors.value[id] = false; | imageErrors.value[id] = false; | ||||
} | } | ||||
// 处理用途点击 | // 处理用途点击 | ||||
const handleUsageClick = (id: number) => { | const handleUsageClick = (id: number) => { | ||||
if (process.client) { | if (process.client) { | ||||
console.log("Usage clicked:", id); | |||||
// 重置图片加载状态 | // 重置图片加载状态 | ||||
isImageLoaded.value = {}; | isImageLoaded.value = {}; | ||||
imageErrors.value = {}; | imageErrors.value = {}; |
<span class="text-white/60 text-base font-normal px-2"> / </span> | <span class="text-white/60 text-base font-normal px-2"> / </span> | ||||
<nuxt-link | <nuxt-link | ||||
v-if="product?.category" | v-if="product?.category" | ||||
:to="`${homepagePath}/products?category=${encodeURIComponent(product.category)}`" | |||||
:to="`${homepagePath}/products?category=${encodeURIComponent( | |||||
product.category | |||||
)}`" | |||||
class="text-white/60 text-base font-normal" | class="text-white/60 text-base font-normal" | ||||
>{{ product.category }}</nuxt-link | >{{ product.category }}</nuxt-link | ||||
> | > | ||||
<!-- 产品参数 --> | <!-- 产品参数 --> | ||||
<div class="bg-zinc-900 rounded-lg p-6"> | <div class="bg-zinc-900 rounded-lg p-6"> | ||||
<h2 class="text-white text-xl font-medium mb-6"> | |||||
{{ t("products.productSpecifications") }} | |||||
</h2> | |||||
<div class="grid grid-cols-1 gap-4"> | <div class="grid grid-cols-1 gap-4"> | ||||
<div | <div | ||||
class="flex justify-between items-center py-2 border-b border-zinc-800" | class="flex justify-between items-center py-2 border-b border-zinc-800" | ||||
</div> | </div> | ||||
<div class="bg-zinc-900 rounded-lg p-6"> | <div class="bg-zinc-900 rounded-lg p-6"> | ||||
<h2 class="text-white text-xl font-medium mb-6"> | |||||
{{ t("products.detailedDescription") }} | |||||
</h2> | |||||
<div | <div | ||||
class="text-stone-400 leading-relaxed space-y-4 prose prose-invert max-w-none" | class="text-stone-400 leading-relaxed space-y-4 prose prose-invert max-w-none" | ||||
> | > | ||||
// 创建新的图片对象并设置超时 | // 创建新的图片对象并设置超时 | ||||
const img = new Image(); | const img = new Image(); | ||||
const timeoutId = setTimeout(() => { | const timeoutId = setTimeout(() => { | ||||
console.error("Image load timeout:", index); | |||||
handleSlideImageError(index); | handleSlideImageError(index); | ||||
}, 10000); // 10秒超时 | }, 10000); // 10秒超时 | ||||
img.onload = () => { | img.onload = () => { | ||||
clearTimeout(timeoutId); | clearTimeout(timeoutId); | ||||
console.log("Image loaded successfully:", index); | |||||
handleSlideImageLoad(index); | handleSlideImageLoad(index); | ||||
}; | }; | ||||
} | } | ||||
}); | }); | ||||
console.log("Initialized thumbnail states:", { | |||||
loading: isSlideThumbnailLoading.value, | |||||
errors: slideThumbnailErrors.value, | |||||
}); | |||||
// 添加滚动监听 | // 添加滚动监听 | ||||
scrollContainer.value = document.querySelector(".max-w-screen-2xl"); | scrollContainer.value = document.querySelector(".max-w-screen-2xl"); | ||||
if (scrollContainer.value) { | if (scrollContainer.value) { |