详情页主图支持多图显示

This commit is contained in:
jingrow 2025-09-05 00:48:23 +08:00
parent 032022c465
commit 13d6d2e94d
12 changed files with 38 additions and 55 deletions

View File

@ -4,7 +4,8 @@ import { getSiteSettings } from "@/utils/data";
import { notFound } from 'next/navigation'; import { notFound } from 'next/navigation';
import DynamicListPage from "@/components/common/DynamicListPage"; import DynamicListPage from "@/components/common/DynamicListPage";
import { Suspense } from 'react'; import { Suspense } from 'react';
import { getPageData, getAllSlugs } from "@/utils/data"; import { getPageData } from "@/utils/data";
import ProductImageGallery from "@/components/products/ProductImageGallery";
const LoadingSpinner = () => ( const LoadingSpinner = () => (
<div className="flex justify-center items-center p-8"> <div className="flex justify-center items-center p-8">
@ -12,29 +13,13 @@ const LoadingSpinner = () => (
</div> </div>
); );
// Using a static value to comply with Next.js 15 build requirements.
// On-demand revalidation will be handled via the API route.
export const revalidate = 3600; export const revalidate = 3600;
export async function generateStaticParams() {
try {
const slugs = await getAllSlugs();
return slugs.map(slug => ({
slug: slug,
}));
} catch (error) {
console.error("Failed to generate static params:", error);
return [];
}
}
export async function generateMetadata({ params }) { export async function generateMetadata({ params }) {
const resolvedParams = await params; const resolvedParams = await params;
const slugArr = resolvedParams.slug; const slug = resolvedParams.slug || [];
const { data, error, page_info } = await getPageData({ const slugArr = Array.isArray(slug) ? slug : [slug];
slug_list: slugArr, const { data, error, page_info } = await getPageData({ slug_list: slugArr });
downloadFiles: false // Do not download files for metadata
});
const siteSettings = await getSiteSettings(); const siteSettings = await getSiteSettings();
const siteTitle = siteSettings.site_title || ''; const siteTitle = siteSettings.site_title || '';
const siteName = siteSettings.site_name || ''; const siteName = siteSettings.site_name || '';
@ -76,31 +61,30 @@ export async function generateMetadata({ params }) {
}; };
} }
export default async function DynamicPage({ params, searchParams }) { export default async function Page({ params, searchParams }) {
const resolvedParams = await params; const resolvedParams = await params;
const slugArr = resolvedParams.slug; const slug = resolvedParams.slug || [];
const slugArr = Array.isArray(slug) ? slug : [slug];
const siteSettings = await getSiteSettings(); const siteSettings = await getSiteSettings();
const pageSize = Number(siteSettings.page_size) || 12; const pageSize = Number(siteSettings.page_size) || 12;
//
const { data, error, total } = await getPageData({ const { data, error, total } = await getPageData({
slug_list: slugArr, slug_list: slugArr,
page: 1, page: 1,
page_size: pageSize, page_size: pageSize,
downloadFiles: true // Download files for page rendering downloadFiles: true,
}); });
if (error) { if (error) {
notFound(); notFound();
} }
const pageSlugBase = slugArr.length ? slugArr[slugArr.length - 1] : '';
const bannerComponentName = 'Banner-' + (slugArr[0] || 'home'); const bannerComponentName = `Banner-${pageSlugBase}`;
const categoryComponentName = 'Category-' + (slugArr[0] || 'home'); const categoryComponentName = `Category-${pageSlugBase}`;
if (Array.isArray(data)) { if (Array.isArray(data)) {
const currentPath = '/' + (Array.isArray(slugArr) ? slugArr.join('/') : ''); const currentPath = '/' + slugArr.join('/');
const listColumns = 4; const listColumns = 4;
return ( return (
<> <>
<Banner componentName={bannerComponentName} /> <Banner componentName={bannerComponentName} />
@ -138,31 +122,30 @@ export default async function DynamicPage({ params, searchParams }) {
<div className="bg-white rounded-lg shadow-md p-6 md:p-10"> <div className="bg-white rounded-lg shadow-md p-6 md:p-10">
{/* 图片和附加信息并排显示,响应式优化 */} {/* 图片和附加信息并排显示,响应式优化 */}
{(data.image || data.subtitle) && ( {(data.image || data.subtitle) && (
<div className="flex flex-col md:flex-row gap-4 md:gap-8 mb-6 md:mb-8 items-center md:items-start w-full max-w-full"> <div className="flex flex-col md:flex-row gap-4 md:gap-10 mb-6 md:mb-8 items-center md:items-start w-full max-w-full">
{data.image && ( {/* 图片轮播区块 */}
<div className="flex-shrink-0 w-full md:w-72 flex justify-center md:justify-start mb-4 md:mb-0 max-w-full"> <ProductImageGallery data={data} />
<img
src={data.image} <div className="flex-1 min-w-0">
alt={data.title} {/* 产品标题 */}
className="w-full max-w-[320px] md:max-w-full max-h-60 md:max-h-72 rounded-xl shadow-lg object-contain" {data.title && (
/> <h1 className="text-2xl md:text-3xl font-bold text-gray-900 mb-10 md:mb-10 leading-tight">
</div> {data.title}
)} </h1>
{data.subtitle && ( )}
<div className="bg-gray-50 rounded-md p-3 md:p-4 whitespace-pre-line text-gray-700 w-full shadow-sm max-w-full prose prose-sm"> {/* 产品副标题 */}
{data.subtitle} {data.subtitle && (
</div> <div className="bg-gray-50 whitespace-pre-line text-gray-700 w-full max-w-full prose prose-sm pt-6">
)} {data.subtitle}
</div>
)}
</div>
</div> </div>
)} )}
{/* Product Description 标题 */} {/* 内容区域 */}
<div className="prose max-w-none text-gray-700 mb-6 md:mb-8 px-1 md:px-0 prose-img:max-w-full prose-img:h-auto prose-table:border prose-table:border-gray-300 prose-th:border prose-th:border-gray-300 prose-td:border prose-td:border-gray-300 prose-th:bg-gray-50 prose-table:rounded-lg prose-table:overflow-hidden" dangerouslySetInnerHTML={{ __html: data.content || '' }} /> <div className="">
{data.additional_content && ( <div className="prose max-w-none text-gray-700 px-1 md:px-0 prose-img:max-w-full prose-img:h-auto prose-table:border prose-table:border-gray-300 prose-th:border prose-th:border-gray-300 prose-td:border prose-td:border-gray-300 prose-th:bg-gray-50 prose-table:rounded-lg prose-table:overflow-hidden" dangerouslySetInnerHTML={{ __html: data.content || '' }} />
<> </div>
{/* Testing Report 标题 */}
<div className="prose max-w-none text-gray-700 mt-6 md:mt-8 px-1 md:px-0 prose-img:max-w-full prose-img:h-auto prose-table:border prose-table:border-gray-300 prose-th:border prose-th:border-gray-300 prose-td:border prose-td:border-gray-300 prose-th:bg-gray-50 prose-table:rounded-lg prose-table:overflow-hidden" dangerouslySetInnerHTML={{ __html: data.additional_content }} />
</>
)}
</div> </div>
</div> </div>
</div> </div>
@ -173,4 +156,4 @@ export default async function DynamicPage({ params, searchParams }) {
} else { } else {
notFound(); notFound();
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 883 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 620 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 KiB