Преглед изворни кода

Merge branch 'zzf-account' of http://gogs.hnwmzp.cn/fogwind/nshop-front-m into zzf-account

zgl пре 1 недеља
родитељ
комит
b0042e5883

+ 18 - 129
src/app/(public)/_components/HomeBestSellers.tsx

@@ -5,129 +5,18 @@ import { OpenAddToCartModalButton } from "@/components/common/AddToCartModal/Ope
 // 导入Swiper基础样式
 import "swiper/css";
 import "swiper/css/navigation";
-
-// 模拟产品数据(12个产品,分2块,每块6个)
-const productData = [
-  // 第一块(6个)
-  {
-    id: 1,
-    img: "https://picsum.photos/400/500?random=1",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 2,
-    img: "https://picsum.photos/400/500?random=2",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 3,
-    img: "https://picsum.photos/400/500?random=3",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 4,
-    img: "https://picsum.photos/400/500?random=4",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 5,
-    img: "https://picsum.photos/400/500?random=5",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 6,
-    img: "https://picsum.photos/400/500?random=6",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-
-  // 第二块(6个)
-  {
-    id: 7,
-    img: "https://picsum.photos/400/500?random=7",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 8,
-    img: "https://picsum.photos/400/500?random=8",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 9,
-    img: "https://picsum.photos/400/500?random=9",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 10,
-    img: "https://picsum.photos/400/500?random=10",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 11,
-    img: "https://picsum.photos/400/500?random=11",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 12,
-    img: "https://picsum.photos/400/500?random=12",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-];
-
-// 拆分数据为2个块(每块6个)
-const productBlocks = [
-  productData.slice(0, 6), // 第一块
-  productData.slice(6, 12), // 第二块
-];
-
-const HomeBestSellers = () => {
+import {HomeProduct} from "@/types/home/type"
+interface HomeBestSellersProps {
+  bestSellers: HomeProduct[];
+}
+const HomeBestSellers = ({ bestSellers }: HomeBestSellersProps) => {
+    if (!bestSellers || bestSellers.length === 0) return null;
+      // 4. 真实数据按每6个拆分一组,替换原来的模拟拆分逻辑
+  const chunkSize = 6;
+  const productBlocks:  HomeProduct[][] = [];
+  for (let i = 0; i < bestSellers.length; i += chunkSize) {
+    productBlocks.push(bestSellers.slice(i, i + chunkSize));
+  }
   return (
     <div className="w-full max-w-[1200px] mx-auto px-4 py-8">
       {/* 标题 */}
@@ -159,13 +48,13 @@ const HomeBestSellers = () => {
                 <div key={product.id} className="flex flex-col gap-2">
                   {/* 产品图片 */}
                   <img
-                    src={product.img}
-                    alt={product.title}
+                    src={product.image_url}
+                    alt={product.name}
                     className="w-full h-auto object-cover rounded-sm"
                   />
                   {/* 产品标题 */}
                   <p className="text-sm text-gray-800 truncate">
-                    {product.title}
+                    {product.name}
                   </p>
                   {/* 评分 + 评论数 */}
                   <div className="flex items-center gap-1">
@@ -183,15 +72,15 @@ const HomeBestSellers = () => {
                       ))}
                     </div>
                     <span className="text-xs text-gray-600">
-                      {product.reviewCount}
+                      { product.review_count}
                     </span>
                   </div>
                   {/* 价格 + 购物车图标 */}
                   <div className="flex items-center justify-between">
                     <div className="flex items-center gap-1">
-                      <span className="font-semibold">${product.price}</span>
+                      <span className="font-semibold">${product.min_price}</span>
                       <span className="text-xs text-gray-500 line-through">
-                        ${product.originalPrice}
+                        ${product.price}
                       </span>
                     </div>
                     {/* 购物车图标 */}

+ 31 - 8
src/app/(public)/_components/HomeContent.tsx

@@ -12,7 +12,11 @@ import RecommendedProducts from "./RecommendedProducts";
 import CategoryTabSwiper  from "./CategoryTabSwiper ";
 import "swiper/css";
 import "swiper/css/navigation";
-
+import {HomeApiData,HomeProduct } from "@/types/home/type"
+// 定义组件入参类型
+interface HomeContentProps {
+  homeData: HomeApiData;
+}
 // 模拟假数据
 const MOCK_DATA = {
   // 服务标签
@@ -88,12 +92,31 @@ const MOCK_DATA = {
   ],
 };
 
-export default function HoHomeContentme() {
+export default function HomeContent({ homeData }: HomeContentProps) {
+    const { channel, sections, categories } = homeData;
+      // 过滤出 banner 板块
+  const bannerSection = sections.find(sec => sec.name === "banner");
+  const bannerImages = bannerSection?.images ?? [];
+    // 2. 筛选热销板块,假设后端name为 best_sellers,自行修改匹配后端标识
+  const bestSellerSection = sections.find(sec => sec.name === "BestSellers");
+  const bestSellers: HomeProduct[] = bestSellerSection?.products ?? [];
+   // 3. 筛选new Arrival板块
+  const newArrivalSection = sections.find(sec => sec.name === "New_Arrival");
+  const newArrival: HomeProduct[] = newArrivalSection?.products ?? [];
+   // 4. 筛选7板块
+  const zeroWearSection = sections.find(sec => sec.name === "7");
+  const zeroWear: HomeProduct[] = zeroWearSection?.products ?? [];
+   // 4. 筛选trendingSection板块
+  const trendingSection = sections.find(sec => sec.name === "Trending_Now");
+  const trending: HomeProduct[] = trendingSection?.products ?? [];
+   // 4. Recommended
+  const recommendedSection = sections.find(sec => sec.name === "Recommended_For_You");
+  const recommended: HomeProduct[] = recommendedSection?.products ?? [];
   return (
     <div className="min-h-screen bg-white font-sans">
       {/* 顶部Banner */}
       <div className="w-full relative">
-        <TopImageSwiper />
+        <TopImageSwiper  bannerImages={bannerImages}  />
       </div>
 
       {/* 服务标签栏 */}
@@ -108,12 +131,12 @@ export default function HoHomeContentme() {
       {/* 分类快捷入口 */}
       <JinGangSwiper />
       {/* 热销商品区 */}
-      <HomeBestSellers/>
+      <HomeBestSellers bestSellers={bestSellers} />
       <HomeMiddleBanner />
-      <HomeNewArrival/>
-      <MiddleImageSwiper/>
-      <Trending/>
-      <RecommendedProducts/>
+      <HomeNewArrival newArrival={newArrival} />
+      <MiddleImageSwiper zeroWear={zeroWear}  />
+      <Trending trending={trending}/>
+      <RecommendedProducts recommended={recommended} />
       <CategoryTabSwiper />
     </div>
   );

+ 18 - 129
src/app/(public)/_components/HomeNewArrival.tsx

@@ -5,129 +5,18 @@ import { OpenAddToCartModalButton } from "@/components/common/AddToCartModal/Ope
 // 导入Swiper基础样式
 import "swiper/css";
 import "swiper/css/navigation";
-
-// 模拟产品数据(12个产品,分2块,每块6个)
-const productData = [
-  // 第一块(6个)
-  {
-    id: 1,
-    img: "https://picsum.photos/400/500?random=1",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 2,
-    img: "https://picsum.photos/400/500?random=2",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 3,
-    img: "https://picsum.photos/400/500?random=3",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 4,
-    img: "https://picsum.photos/400/500?random=4",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 5,
-    img: "https://picsum.photos/400/500?random=5",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 6,
-    img: "https://picsum.photos/400/500?random=6",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-
-  // 第二块(6个)
-  {
-    id: 7,
-    img: "https://picsum.photos/400/500?random=7",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 8,
-    img: "https://picsum.photos/400/500?random=8",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 9,
-    img: "https://picsum.photos/400/500?random=9",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 10,
-    img: "https://picsum.photos/400/500?random=10",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 11,
-    img: "https://picsum.photos/400/500?random=11",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-  {
-    id: 12,
-    img: "https://picsum.photos/400/500?random=12",
-    title: "14-36 In Water Wave Huma...",
-    rating: 4.5,
-    reviewCount: 342,
-    price: 143.35,
-    originalPrice: 143.35,
-  },
-];
-
-// 拆分数据为2个块(每块6个)
-const productBlocks = [
-  productData.slice(0, 4), // 第一块
-  productData.slice(4, 8), // 第二块
-];
-
-const HomeNewArrival = () => {
+import {HomeProduct} from "@/types/home/type"
+interface NewArrivalProps {
+  newArrival: HomeProduct[];
+}
+const HomeNewArrival = ({ newArrival }: NewArrivalProps) => {
+     if (!newArrival || newArrival.length === 0) return null;
+        // 4. 真实数据按每6个拆分一组,替换原来的模拟拆分逻辑
+    const chunkSize = 6;
+    const productBlocks:  HomeProduct[][] = [];
+    for (let i = 0; i < newArrival.length; i += chunkSize) {
+      productBlocks.push(newArrival.slice(i, i + chunkSize));
+    }
   return (
     <div className="w-full max-w-[1200px] mx-auto px-4 py-8">
       {/* 标题 */}
@@ -159,13 +48,13 @@ const HomeNewArrival = () => {
                 <div key={product.id} className="flex flex-col gap-2">
                   {/* 产品图片 */}
                   <img
-                    src={product.img}
-                    alt={product.title}
+                    src={product.image_url}
+                    alt={product.name}
                     className="w-full h-auto object-cover rounded-sm"
                   />
                   {/* 产品标题 */}
                   <p className="text-sm text-gray-800 truncate">
-                    {product.title}
+                    {product.name}
                   </p>
                   {/* 评分 + 评论数 */}
                   <div className="flex items-center gap-1">
@@ -183,15 +72,15 @@ const HomeNewArrival = () => {
                       ))}
                     </div>
                     <span className="text-xs text-gray-600">
-                      {product.reviewCount}
+                      {product.review_count}
                     </span>
                   </div>
                   {/* 价格 + 购物车图标 */}
                   <div className="flex items-center justify-between">
                     <div className="flex items-center gap-1">
-                      <span className="font-semibold">${product.price}</span>
+                      <span className="font-semibold">${product.min_price}</span>
                       <span className="text-xs text-gray-500 line-through">
-                        ${product.originalPrice}
+                        ${product.price}
                       </span>
                     </div>
                     {/* 购物车图标 */}

+ 37 - 32
src/app/(public)/_components/MiddleImageSwiper.tsx

@@ -6,35 +6,40 @@ import "swiper/css/pagination";
 import "swiper/css/navigation";
 import "./css/swiper-custom.css";
 import { OpenAddToCartModalButton } from "@/components/common/AddToCartModal/OpenAddToCartModalButton";
+import {HomeProduct} from "@/types/home/type"
+interface zeroWearProps {
+  zeroWear: HomeProduct[];
+}
+// const productList = [
+//   {
+//     id: 1,
+//     img: "https://picsum.photos/400/500?random=1",
+//     title: "14-36 In Water Wave Hum...",
+//     price: 143.35,
+//   },
+//   {
+//     id: 2,
+//     img: "https://picsum.photos/400/500?random=2",
+//     title: "14-36 In Water Wave Hum.",
+//     price: 143.35,
+//   },
+//   {
+//     id: 3,
+//     img: "https://picsum.photos/400/500?random=3",
+//     title: "14-36 In Water Wave Hum...",
+//     price: 143.35,
+//   },
+//   {
+//     id: 4,
+//     img: "https://picsum.photos/400/500?random=4",
+//     title: "14-36 In Water Wave Hum.",
+//     price: 143.35,
+//   },
+// ];
 
-const productList = [
-  {
-    id: 1,
-    img: "https://picsum.photos/400/500?random=1",
-    title: "14-36 In Water Wave Hum...",
-    price: 143.35,
-  },
-  {
-    id: 2,
-    img: "https://picsum.photos/400/500?random=2",
-    title: "14-36 In Water Wave Hum.",
-    price: 143.35,
-  },
-  {
-    id: 3,
-    img: "https://picsum.photos/400/500?random=3",
-    title: "14-36 In Water Wave Hum...",
-    price: 143.35,
-  },
-  {
-    id: 4,
-    img: "https://picsum.photos/400/500?random=4",
-    title: "14-36 In Water Wave Hum.",
-    price: 143.35,
-  },
-];
-
-const MiddleImageSwiper = () => {
+const MiddleImageSwiper = ({ zeroWear }: zeroWearProps) => {
+  if (!zeroWear || zeroWear.length === 0) return null;
+  const  productList = zeroWear
   return (
     <div className="w-full pr-4 pl-4 mx-auto  rounded-lg  ">
       <div className="w-full">
@@ -64,19 +69,19 @@ const MiddleImageSwiper = () => {
               <SwiperSlide key={item.id}>
                 <div className="bg-white rounded overflow-hidden  flex flex-col">
                   <img
-                    src={item.img}
-                    alt={item.title}
+                    src={item.image_url}
+                    alt={item.name}
                     className="w-full aspect-[3/4] object-cover"
                   />
 
                   <div className="p-2 flex flex-col gap-2">
                     <p className="text-sm text-gray-800 truncate">
-                      {item.title}
+                      {item.name}
                     </p>
                     {/* 价格 + 购物车图标 */}
                     <div className="flex items-center justify-between">
                       <div className="flex items-center gap-1">
-                        <span className="font-semibold">${item.price}</span>
+                        <span className="font-semibold">${item.min_price}</span>
                         <span className="text-xs text-gray-500 line-through">
                           ${item.price}
                         </span>

+ 17 - 12
src/app/(public)/_components/RecommendedProducts.tsx

@@ -2,6 +2,10 @@
 import React, { useState, useEffect, useCallback } from "react";
 import Image from "next/image";
 import { OpenAddToCartModalButton } from "@/components/common/AddToCartModal/OpenAddToCartModalButton";
+import {HomeProduct} from "@/types/home/type"
+interface recommendedProps {
+  recommended: HomeProduct[];
+}
 // 商品类型定义
 interface ProductItem {
   id: number;
@@ -50,9 +54,10 @@ const mockGetProductApi = async (page: number, pageSize: number) => {
 
 const PAGE_SIZE = 6;
 
-export default function RecommendedProducts() {
+export default function RecommendedProducts({ recommended }: recommendedProps) {
+    if (!recommended || recommended.length === 0) return null;
   // 已渲染的全部商品
-  const [productList, setProductList] = useState<ProductItem[]>([]);
+  const [productList, setProductList] = useState<HomeProduct[]>(recommended);
   // 当前页码
   const [page, setPage] = useState(1);
   // 数据总条数
@@ -70,9 +75,9 @@ export default function RecommendedProducts() {
       const res = await mockGetProductApi(currentPage, PAGE_SIZE);
       setTotal(res.total);
       // 函数式更新,稳定依赖
-      setProductList((prev) =>
-        currentPage === 1 ? res.list : [...prev, ...res.list],
-      );
+      // setProductList((prev) =>
+      //   currentPage === 1 ? res.list : [...prev, ...res.list],
+      // );
     } catch (err) {
       // 屏蔽 no-console 警告
       // eslint-disable-next-line no-console
@@ -124,8 +129,8 @@ export default function RecommendedProducts() {
             {/* Next.Image 商品图容器 */}
             <div className="relative w-full aspect-[3/4] overflow-hidden rounded-md">
               <Image
-                src={item.img}
-                alt={item.title}
+                src={item.image_url}
+                alt={item.name}
                 fill
                 sizes="(max-width:768px) 50vw, 33vw"
                 className="object-cover"
@@ -133,13 +138,13 @@ export default function RecommendedProducts() {
             </div>
 
             {/* 标题 */}
-            <p className="text-sm text-gray-800 truncate">{item.title}</p>
+            <p className="text-sm text-gray-800 truncate">{item.name}</p>
 
             {/* 星级 + 评论数 */}
             <div className="flex items-center gap-1">
-              {renderStars(item.star)}
+              {renderStars(item.rating)}
               <span className="text-sm text-gray-600 ml-1 underline">
-                {item.reviewCount}
+                {item.review_count}
               </span>
             </div>
 
@@ -171,9 +176,9 @@ export default function RecommendedProducts() {
             {/* 价格 + 购物车图标 */}
             <div className="flex items-center justify-between">
               <div className="flex items-center gap-1">
-                <span className="font-semibold">${item.price}</span>
+                <span className="font-semibold">${item.min_price}</span>
                 <span className="text-xs text-gray-500 line-through">
-                  ${item.originPrice}
+                  ${item.price}
                 </span>
               </div>
               {/* 购物车图标 */}

+ 16 - 5
src/app/(public)/_components/TopImageSwiper.tsx

@@ -2,8 +2,19 @@ import React from 'react';
 import { Swiper, SwiperSlide } from 'swiper/react';
 import 'swiper/css';
 // import { Navigation, Pagination, Mousewheel, Keyboard } from 'swiper/modules';
-
-const TopImageSwiper = () => {
+// 定义图片类型
+type BannerImageItem = {
+  link: string;
+  image: string;
+  title: string;
+};
+// 组件入参
+interface TopImageSwiperProps {
+  bannerImages: BannerImageItem[];
+}
+const TopImageSwiper = ({ bannerImages }: TopImageSwiperProps) => {
+  // 兜底:没有图片不渲染,防止报错
+  if (!bannerImages || bannerImages.length === 0) return null;
   // ✅ 直接在这里放你的图片数组,想加多少加多少
   const images = [
     'https://cdn.asteriahair.com/uploads/202607/01/20260701165056_761989a0fdc11d5e.jpg',
@@ -25,11 +36,11 @@ const TopImageSwiper = () => {
         className="h-auto md:h-[80vh]  overflow-hidden"
       >
         {/* ✅ 自动遍历图片数组,一行代码搞定所有图片 */}
-        {images.map((img, index) => (
+        {bannerImages .map((item, index) => (
           <SwiperSlide key={index}>
             <img
-              src={img}
-              alt={`slide-${index}`}
+                 src={item.image}
+              alt={item.title}
               className="w-full h-full object-cover"
             />
           </SwiperSlide>

+ 50 - 45
src/app/(public)/_components/Trending.tsx

@@ -6,48 +6,53 @@ import "swiper/css/scrollbar";
 import "swiper/css/navigation";
 import Image from "next/image";
 import { OpenAddToCartModalButton } from "@/components/common/AddToCartModal/OpenAddToCartModalButton";
+import {HomeProduct} from "@/types/home/type"
+interface trendingProps {
+  trending: HomeProduct[];
+}
+// // 商品数据,每个卡片携带videoUrl视频地址
+// type ProductItem = {
+//   id: number;
+//   img: string;
+//   title: string;
+//   price: number;
+//   videoUrl: string;
+// };
 
-// 商品数据,每个卡片携带videoUrl视频地址
-type ProductItem = {
-  id: number;
-  img: string;
-  title: string;
-  price: number;
-  videoUrl: string;
-};
-
-const productList: ProductItem[] = [
-  {
-    id: 1,
-    img: "/img/hair-video-1.jpg",
-    title: "14-36 In Water Wave Human Hair HD Inv...",
-    price: 146.1,
-    videoUrl: "/video/hair-demo-1.mp4",
-  },
-  {
-    id: 2,
-    img: "/img/hair-video-2.jpg",
-    title: "14-36 In Water Wave Human Hair HD Inv...",
-    price: 146.1,
-    videoUrl: "/video/hair-demo-2.mp4",
-  },
-  {
-    id: 3,
-    img: "/img/hair-video-3.jpg",
-    title: "14-36 In Water Wave Human Hair HD Inv...",
-    price: 146.1,
-    videoUrl: "/video/hair-demo-3.mp4",
-  },
-  {
-    id: 4,
-    img: "/img/hair-video-4.jpg",
-    title: "14-36 In Water Wave Human Hair HD Inv...",
-    price: 146.1,
-    videoUrl: "/video/hair-demo-4.mp4",
-  },
-];
+// const productList: ProductItem[] = [
+//   {
+//     id: 1,
+//     img: "/img/hair-video-1.jpg",
+//     title: "14-36 In Water Wave Human Hair HD Inv...",
+//     price: 146.1,
+//     videoUrl: "/video/hair-demo-1.mp4",
+//   },
+//   {
+//     id: 2,
+//     img: "/img/hair-video-2.jpg",
+//     title: "14-36 In Water Wave Human Hair HD Inv...",
+//     price: 146.1,
+//     videoUrl: "/video/hair-demo-2.mp4",
+//   },
+//   {
+//     id: 3,
+//     img: "/img/hair-video-3.jpg",
+//     title: "14-36 In Water Wave Human Hair HD Inv...",
+//     price: 146.1,
+//     videoUrl: "/video/hair-demo-3.mp4",
+//   },
+//   {
+//     id: 4,
+//     img: "/img/hair-video-4.jpg",
+//     title: "14-36 In Water Wave Human Hair HD Inv...",
+//     price: 146.1,
+//     videoUrl: "/video/hair-demo-4.mp4",
+//   },
+// ];
 
-const Trending = () => {
+const Trending = ({ trending }: trendingProps) => {
+  if (!trending || trending.length === 0) return null;
+  const  productList = trending
   // 视频弹窗状态
   const [openVideoModal, setOpenVideoModal] = useState(false);
   const [currentVideoSrc, setCurrentVideoSrc] = useState("");
@@ -134,13 +139,13 @@ const Trending = () => {
                   {/* 图片区域 + 中间播放按钮 */}
                   <div className="relative rounded-xl w-full aspect-[4/5] overflow-hidden rounded-xl">
                     <img
-                      src={item.img}
-                      alt={item.title}
+                      src={item.image_url}
+                      alt={item.name}
                       className="w-full h-full object-cover"
                     />
                     {/* 居中圆形播放按钮 */}
                     <button
-                      onClick={() => handlePlayClick(item.videoUrl)}
+                      onClick={() => handlePlayClick("/video/hair-demo-1.mp4"||item.videoUrl)}
                       className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2
                       w-24 h-24 rounded-full bg-white/60 backdrop-blur-sm
                       flex items-center justify-center transition hover:bg-white/80"
@@ -161,12 +166,12 @@ const Trending = () => {
                   {/* 底部文字价格区域 */}
                   <div className="p-3 flex flex-col rounded-xl mt-3 bg-[#f0f8f5] gap-3">
                     <p className="text-base text-gray-900 truncate">
-                      {item.title}
+                      {item.name}
                     </p>
                     {/* 价格 + 购物车图标 */}
                     <div className="flex items-center justify-between">
                       <div className="flex items-center gap-1">
-                        <span className="font-semibold">${item.price}</span>
+                        <span className="font-semibold">${item.min_price}</span>
                         <span className="text-xs text-gray-500 line-through">
                           ${item.price}
                         </span>

+ 18 - 5
src/app/(public)/page.tsx

@@ -3,25 +3,38 @@
 import HomeImageBanner from "@components/home/HomeImageBanner";
 // import { ThemeCustomizationResponse } from "@/types/theme/theme-customization";
 // import { cachedGraphQLRequest } from "@/utils/hooks/useCache";
-import {DatePicker} from "@heroui/date-picker";
-import HomeContent from "./_components/HomeContent"
+import { DatePicker } from "@heroui/date-picker";
+import HomeContent from "./_components/HomeContent";
+import { restApiFetch } from "@utils/bagisto/index";
+import {HomeApiData} from "@/types/home/type"
 export const revalidate = 3600;
 
+
 export default async function Home() {
-  // const 
+  // const
   // const {data} = await cachedGraphQLRequest<ThemeCustomizationResponse>(
   //   "home",
   //   GET_THEME_CUSTOMIZATION,
   //   { first: 20 }
   // );
+// 2. 服务端 fetch 请求我们自己的 Next.js API
+const res = await restApiFetch({
+  api: `/home`,
+  method: "GET",
+  isCookies: true, // 关键开关
+  headers: {
+    "X-Channel": "wap",
+  },
+});
+console.log("res----------------------",res);
+const homeData: HomeApiData = res.body.data;
 
   return (
     <>
       {/* <HomeImageBanner /> */}
       <DatePicker label={"Birth date"} labelPlacement={"outside"} />
       {/* <RenderThemeCustomization themeCustomizations={data?.themeCustomizations ?? {edges: []}} /> */}
-      <HomeContent />
+      <HomeContent homeData={homeData} />
     </>
-    
   );
 }

+ 46 - 0
src/app/api/home/route.ts

@@ -0,0 +1,46 @@
+import { NextRequest, NextResponse } from "next/server";
+import { restApiFetch } from "@/utils/bagisto";
+import { isBagistoError } from "@/utils/type-guards";
+import { getAuthToken } from "@/utils/helper";
+type Params = Promise<{ id: string }>;
+export async function GET(req: NextRequest, { params }: { params: Params }) {
+  try {
+     const { id } = await params; // 解包拿到订单ID
+    const guestToken = getAuthToken(req);
+
+   const apiUrl = `/home`;
+
+    console.log("最终请求API地址:", apiUrl);
+
+    const response = await restApiFetch<any>({
+      api: apiUrl,
+      method: "GET",
+      cache: "no-store",
+      guestToken,
+    });
+
+    return NextResponse.json({
+      status: response.status,
+      data: response.body,
+    });
+
+  } catch (error) {
+    if (isBagistoError(error)) {
+      return NextResponse.json(
+        {
+          data: null,
+          error: error.cause ?? error,
+        },
+        { status: 200 }
+      );
+    }
+
+    return NextResponse.json(
+      {
+        message: "Network error",
+        error: error instanceof Error ? error.message : error,
+      },
+      { status: 500 }
+    );
+  }
+}

+ 52 - 0
src/types/home/type.ts

@@ -0,0 +1,52 @@
+type HomeSectionImage = {
+  link: string;
+  image: string;
+  title: string;
+};
+export type HomeProduct = {
+  id: number;
+  sku: string;
+  name: string;
+  slug: string | null;
+  type: string;
+  price: string;
+  special_price: string | null;
+  min_price: string;
+  image_url: string ;
+  rating:number,
+  review_count: number,
+  is_new: boolean;
+  is_featured: boolean;
+  short_description: string;
+};
+type HomeSection = {
+  id: number;
+  type: "image_carousel" | "product_carousel";
+  name: string;
+  sort_order: number;
+  title?: string;
+  images?: HomeSectionImage[];
+  products?: HomeProduct[];
+};
+type HomeCategoryChild = {
+  id: number;
+  name: string;
+  slug: string;
+  description: string;
+  image_url: string | null;
+  banner_url: string | null;
+};
+type HomeCategory = {
+  id: number;
+  name: string;
+  slug: string;
+  description: string;
+  image_url: string | null;
+  banner_url: string | null;
+  children: HomeCategoryChild[];
+};
+export type HomeApiData = {
+  channel: string;
+  sections: HomeSection[];
+  categories: HomeCategory[];
+};