diff --git a/app/[...slug]/page.jsx b/app/[...slug]/page.jsx
index e82c78d..e8dc7cd 100644
--- a/app/[...slug]/page.jsx
+++ b/app/[...slug]/page.jsx
@@ -1,11 +1,38 @@
import Banner from "@/components/banner/Banner";
import Category from "@/components/sidebar/Category";
-import Pagination1 from "@/components/common/Pagination1";
import { getSiteSettings } from "@/utlis/siteSettings";
-import ListPageTemplate from "@/components/common/ListPageTemplate";
import { notFound } from 'next/navigation';
+import DynamicListPage from "@/components/common/DynamicListPage";
+import { Suspense } from 'react';
+
+const LoadingSpinner = () => (
+
+);
export const revalidate = 3600;
+export const dynamicParams = true;
+
+export async function generateStaticParams() {
+ try {
+ const res = await fetch(`${process.env.SITE_URL}/api/get-all-slugs`);
+ if (!res.ok) {
+ throw new Error(`Failed to fetch slugs: ${res.status}`);
+ }
+ const slugs = await res.json();
+ if (!Array.isArray(slugs)) {
+ console.error("generateStaticParams: received non-array from /api/get-all-slugs", slugs);
+ return [];
+ }
+ return slugs.map(slug => ({
+ slug: slug,
+ }));
+ } catch (error) {
+ console.error("Could not generate static params:", error);
+ return [];
+ }
+}
export async function generateMetadata({ params }) {
const resolvedParams = await params;
@@ -35,20 +62,18 @@ export async function generateMetadata({ params }) {
};
}
-export default async function DynamicPage({ params, searchParams }) {
+export default async function DynamicPage({ params }) {
const resolvedParams = await params;
- const resolvedSearchParams = await searchParams;
const slugArr = resolvedParams.slug;
- const currentPage = Number(resolvedSearchParams?.page) || 1;
- // Get global site settings
const siteSettings = await getSiteSettings(process.env.SITE_URL);
const pageSize = Number(siteSettings.page_size) || 12;
+ // 始终获取第一页的数据用于静态生成
const res = await fetch(`${process.env.SITE_URL}/api/get-page-data`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ slug_list: slugArr, page: currentPage, page_size: pageSize })
+ body: JSON.stringify({ slug_list: slugArr, page: 1, page_size: pageSize })
});
const result = await res.json();
const { data, error, total } = result;
@@ -60,26 +85,9 @@ export default async function DynamicPage({ params, searchParams }) {
const bannerComponentName = 'Banner-' + (slugArr[0] || 'home');
const categoryComponentName = 'Category-' + (slugArr[0] || 'home');
- // Infer pagetype and name from slugArr
- const pagetype = slugArr?.[0] || '';
- const name = slugArr?.[1] || '';
-
if (Array.isArray(data)) {
const currentPath = '/' + (Array.isArray(slugArr) ? slugArr.join('/') : '');
- const lastSlug = Array.isArray(slugArr) ? slugArr[slugArr.length - 1] : '';
- const totalPages = Math.ceil((total || 0) / pageSize);
-
- // Adapt template required fields
- const listItems = data.map(item => ({
- slug: item.slug,
- title: item.title,
- image: item.image || item.cover || item.img || '',
- additional_title: item.additional_title || '',
- subtitle: item.subtitle || item.content || '',
- }));
-
- // 新增:允许通过变量控制列数,默认4
- const listColumns = 4; // 可根据需要改为变量
+ const listColumns = 4;
return (
<>
@@ -89,14 +97,16 @@ export default async function DynamicPage({ params, searchParams }) {
diff --git a/app/api/get-all-slugs/route.js b/app/api/get-all-slugs/route.js
new file mode 100644
index 0000000..2433fb1
--- /dev/null
+++ b/app/api/get-all-slugs/route.js
@@ -0,0 +1,26 @@
+import axios from 'axios';
+
+const JINGROW_SERVER_URL = process.env.JINGROW_SERVER_URL;
+
+export async function GET() {
+ try {
+ const response = await axios.get(
+ `${JINGROW_SERVER_URL}/api/method/jsite.api.v1.get_all_slugs`
+ );
+
+ const slugs = response.data.message?.data;
+
+ if (!Array.isArray(slugs)) {
+ console.error('API did not return an array of slugs:', response.data);
+ return Response.json({ error: '返回的slugs格式不正确' }, { status: 500 });
+ }
+
+ return Response.json(slugs);
+ } catch (error) {
+ console.error('Error fetching slugs:', error.message, error?.response?.data);
+ return Response.json(
+ { error: '获取slugs失败', detail: error?.response?.data || error.message },
+ { status: 500 }
+ );
+ }
+}
\ No newline at end of file
diff --git a/app/products/[...slug]/page.jsx b/app/products/[...slug]/page.jsx
index c60ee83..ad942be 100644
--- a/app/products/[...slug]/page.jsx
+++ b/app/products/[...slug]/page.jsx
@@ -1,16 +1,24 @@
import Banner from "@/components/banner/Banner";
import Category from "@/components/sidebar/Category";
-import Pagination1 from "@/components/common/Pagination1";
import { getSiteSettings } from "@/utlis/siteSettings";
-import ListPageTemplate from "@/components/common/ListPageTemplate";
import { notFound } from 'next/navigation';
+import DynamicListPage from "@/components/common/DynamicListPage";
+import { Suspense } from 'react';
const baseSlug = 'products';
+const LoadingSpinner = () => (
+
+);
+
export const revalidate = 3600;
export async function generateMetadata({ params }) {
- const slugArr = [baseSlug, ...(params.slug ? (Array.isArray(params.slug) ? params.slug : [params.slug]) : [])];
+ const resolvedParams = await params;
+ const slug = resolvedParams.slug || [];
+ const slugArr = [baseSlug, ...(Array.isArray(slug) ? slug : [slug])];
const res = await fetch(`${process.env.SITE_URL}/api/get-page-data`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
@@ -36,15 +44,19 @@ export async function generateMetadata({ params }) {
};
}
-export default async function Page({ params, searchParams }) {
- const slugArr = [baseSlug, ...(params.slug ? (Array.isArray(params.slug) ? params.slug : [params.slug]) : [])];
- const currentPage = Number(searchParams?.page) || 1;
+export default async function Page({ params }) {
+ const resolvedParams = await params;
+ const slug = resolvedParams.slug || [];
+ const slugArr = [baseSlug, ...(Array.isArray(slug) ? slug : [slug])];
+
const siteSettings = await getSiteSettings(process.env.SITE_URL);
const pageSize = Number(siteSettings.page_size) || 12;
+
+ // Fetch only page 1 for initial static render
const res = await fetch(`${process.env.SITE_URL}/api/get-page-data`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ slug_list: slugArr, page: currentPage, page_size: pageSize })
+ body: JSON.stringify({ slug_list: slugArr, page: 1, page_size: pageSize })
});
const result = await res.json();
const { data, error, total } = result;
@@ -54,14 +66,8 @@ export default async function Page({ params, searchParams }) {
const bannerComponentName = 'Banner-' + baseSlug;
const categoryComponentName = 'Category-' + baseSlug;
if (Array.isArray(data)) {
- const currentPath = '/' + [baseSlug, ...(params.slug ? (Array.isArray(params.slug) ? params.slug : [params.slug]) : [])].join('/');
- const totalPages = Math.ceil((total || 0) / pageSize);
- const listItems = data.map(item => ({
- slug: item.slug,
- title: item.title,
- image: item.image || item.cover || item.img || '',
- content: item.content || item.description || '',
- }));
+ const currentPath = '/' + slugArr.join('/');
+ const listColumns = 4;
return (
<>
@@ -70,14 +76,16 @@ export default async function Page({ params, searchParams }) {
diff --git a/components/common/DynamicListPage.jsx b/components/common/DynamicListPage.jsx
new file mode 100644
index 0000000..12a02a9
--- /dev/null
+++ b/components/common/DynamicListPage.jsx
@@ -0,0 +1,77 @@
+'use client';
+
+import { useState, useEffect } from 'react';
+import { useSearchParams } from 'next/navigation';
+import ListPageTemplate from '@/components/common/ListPageTemplate';
+import Pagination1 from '@/components/common/Pagination1';
+import axios from 'axios';
+
+const LoadingSpinner = () => (
+
+);
+
+export default function DynamicListPage({ initialItems, slugArr, basePath, columns, pageSize, totalItems }) {
+ const [items, setItems] = useState(initialItems);
+ const [total, setTotal] = useState(totalItems);
+ const [isLoading, setIsLoading] = useState(false);
+ const searchParams = useSearchParams();
+ const page = searchParams.get('page');
+ const currentPage = Number(page) || 1;
+
+ useEffect(() => {
+ const fetchPageData = async () => {
+ if (currentPage === 1) {
+ setItems(initialItems);
+ setTotal(totalItems);
+ return;
+ }
+ setIsLoading(true);
+ try {
+ const res = await axios.post('/api/get-page-data', {
+ slug_list: slugArr,
+ page: currentPage,
+ page_size: pageSize,
+ });
+ setItems(res.data.data);
+ setTotal(res.data.total);
+ } catch (error) {
+ console.error('Failed to fetch page data:', error);
+ // Optionally, handle the error in the UI
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ fetchPageData();
+ }, [currentPage, slugArr, pageSize, initialItems, totalItems]);
+
+ const listItems = items.map(item => ({
+ ...item,
+ slug: item.slug,
+ title: item.title,
+ image: item.image || item.cover || item.img || '',
+ additional_title: item.additional_title || '',
+ subtitle: item.subtitle || item.content || '',
+ }));
+
+ const totalPages = Math.ceil((total || 0) / pageSize);
+
+ return (
+ <>
+ {isLoading ? (
+
+ ) : (
+
+ )}
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/components/homes/home-15/SwiperItems.jsx b/components/homes/home-15/SwiperItems.jsx
index 883d77b..62169a6 100644
--- a/components/homes/home-15/SwiperItems.jsx
+++ b/components/homes/home-15/SwiperItems.jsx
@@ -1,5 +1,5 @@
"use client";
-import { useEffect, useState, useRef } from "react";
+import { useEffect, useState } from "react";
import { Swiper, SwiperSlide } from "swiper/react";
import { Navigation, Pagination, Grid } from "swiper/modules";
import Link from "next/link";
@@ -24,9 +24,6 @@ export default function SwiperItems(props) {
const rows = (data?.p1 && !isNaN(Number(data.p1))) ? Number(data.p1) : (props.rows || 1);
const button_text = data?.button_text || props.button_text;
- const prevRef = useRef(null);
- const nextRef = useRef(null);
-
useEffect(() => {
async function fetchComponentData() {
try {
@@ -192,13 +189,9 @@ export default function SwiperItems(props) {
slidesPerGroup={columns * rows}
grid={{ rows }}
pagination={{ clickable: true, el: ".spdb15" }}
- navigation={{ prevEl: prevRef.current, nextEl: nextRef.current }}
- onInit={swiper => {
- // Swiper 8+ 需要手动传递 ref.current
- swiper.params.navigation.prevEl = prevRef.current;
- swiper.params.navigation.nextEl = nextRef.current;
- swiper.navigation.init();
- swiper.navigation.update();
+ navigation={{
+ prevEl: '.swiper-nav-prev-swiperitems',
+ nextEl: '.swiper-nav-next-swiperitems'
}}
breakpoints={{
0: { slidesPerView: 1, slidesPerGroup: 1, grid: { rows: 1 } },
@@ -249,8 +242,7 @@ export default function SwiperItems(props) {
{/* 美化后的导航按钮 */}