zhangzf il y a 3 jours
Parent
commit
695cd5f3db

+ 48 - 0
src/app/(public)/_components/CategoryTabSwiper .tsx

@@ -0,0 +1,48 @@
+"use client";
+import React from "react";
+import Link from "next/link";
+import { Swiper, SwiperSlide } from "swiper/react";
+import { FreeMode } from "swiper/modules";
+import "swiper/css";
+
+// 标签数据,可自由增删修改文字、跳转路由
+const tabList = [
+  { label: "HD Lace Wigs", href: "/category/hd-lace-wigs" },
+  { label: "New Arrival", href: "/category/new-arrival" },
+  { label: "Wigs", href: "/category/wigs" },
+  { label: "Colored Wigs", href: "/category/colored-wigs" },
+  { label: "Body Wave", href: "/category/body-wave" },
+  { label: "Curly Hair", href: "/category/curly-hair" },
+];
+
+const CategoryTabSwiper = () => {
+  return (
+    <div className="py-4">
+      <Swiper
+        modules={[FreeMode]}
+        freeMode={true}
+        slidesOffsetBefore={16}
+        slidesOffsetAfter={0}
+        spaceBetween={8}
+        slidesPerView="auto"
+        pagination={false}
+        navigation={false}
+       
+        className="w-full overflow-hidden"
+      >
+        {tabList.map((tab, idx) => (
+          <SwiperSlide key={idx} className="!w-auto">
+            <Link
+              href={tab.href}
+              className="inline-block px-2 border-2 border-black leading-6.5 rounded-sm bg-[#ecfdf5] text-xs text-center font-normal "
+            >
+              {tab.label}
+            </Link>
+          </SwiperSlide>
+        ))}
+      </Swiper>
+    </div>
+  );
+};
+
+export default CategoryTabSwiper;

+ 276 - 0
src/app/(public)/_components/HomeBestSellers.tsx

@@ -0,0 +1,276 @@
+import React from "react";
+import { Swiper, SwiperSlide } from "swiper/react";
+import { Navigation, Pagination } from "swiper/modules";
+import { OpenAddToCartModalButton } from "@/components/common/AddToCartModal/OpenAddToCartModalButton";
+// 导入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 = () => {
+  return (
+    <div className="w-full max-w-[1200px] mx-auto px-4 py-8">
+      {/* 标题 */}
+      <h2 className="text-2xl font-bold mb-6">Best Sellers</h2>
+
+      {/* Swiper容器 */}
+      <Swiper
+        slidesPerView={1}
+        spaceBetween={20}
+        modules={[Navigation, Pagination]}
+        pagination={{
+          el: ".custom-pagination",
+          clickable: true,
+          renderBullet: (index, className) => {
+            // 所有分页默认底色为 #E5E5E5
+            return `<span class="${className} w-6 h-[5px] rounded-full mx-1 bg-[#E5E5E5]"></span>`;
+          },
+          // 激活时强制覆盖底色,加 !important 提高权重
+          bulletActiveClass: "!bg-[#333]",
+        }}
+        className="relative"
+      >
+        {/* 渲染2个滑动块 */}
+        {productBlocks.map((block, blockIndex) => (
+          <SwiperSlide key={blockIndex} className="!px-0">
+            {/* 每个块:6个产品,2列布局 */}
+            <div className="grid grid-cols-2 gap-4">
+              {block.map((product) => (
+                <div key={product.id} className="flex flex-col gap-2">
+                  {/* 产品图片 */}
+                  <img
+                    src={product.img}
+                    alt={product.title}
+                    className="w-full h-auto object-cover rounded-sm"
+                  />
+                  {/* 产品标题 */}
+                  <p className="text-sm text-gray-800 truncate">
+                    {product.title}
+                  </p>
+                  {/* 评分 + 评论数 */}
+                  <div className="flex items-center gap-1">
+                    <div className="flex">
+                      {/* 星级图标(简化版,可替换为真实星星图标) */}
+                      {[1, 2, 3, 4, 5].map((star) => (
+                        <svg
+                          key={star}
+                          className="w-4 h-4 text-yellow-400"
+                          fill="currentColor"
+                          viewBox="0 0 20 20"
+                        >
+                          <path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
+                        </svg>
+                      ))}
+                    </div>
+                    <span className="text-xs text-gray-600">
+                      {product.reviewCount}
+                    </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="text-xs text-gray-500 line-through">
+                        ${product.originalPrice}
+                      </span>
+                    </div>
+                    {/* 购物车图标 */}
+                    <OpenAddToCartModalButton
+                      productUrlKey={
+                        "http://nshop.test/hd-transparent-deep-wave-&-curly-lace-frontal-closure-wig"
+                      }
+                      icon={
+                        <svg
+                          xmlns="http://www.w3.org/2000/svg"
+                          width="32"
+                          height="32"
+                          viewBox="0 0 32 32"
+                          fill="none"
+                        >
+                          <rect
+                            x="0"
+                            y="0"
+                            width="32"
+                            height="32"
+                            rx="8"
+                            fill="#036141"
+                          ></rect>
+                          <path
+                            stroke="rgba(255, 255, 255, 1)"
+                            stroke-width="1.3333333333333333"
+                            stroke-linejoin="round"
+                            stroke-linecap="round"
+                            d="M6.40039 7.79993L8.03372 7.79993L8.73372 10.5999M8.73372 10.5999L11.0671 19.9333L23.2004 19.9333L25.5337 10.5999L8.73372 10.5999Z"
+                          ></path>
+                          <ellipse
+                            cx="11.066040515899658"
+                            cy="23.199928283691406"
+                            rx="1.4000248908996582"
+                            ry="1.4000015258789062"
+                            stroke="rgba(255, 255, 255, 1)"
+                            stroke-width="1.3333333333333333"
+                            stroke-linejoin="round"
+                            stroke-linecap="round"
+                          ></ellipse>
+                          <ellipse
+                            cx="23.1998291015625"
+                            cy="23.199928283691406"
+                            rx="1.4000244140625"
+                            ry="1.4000015258789062"
+                            stroke="rgba(255, 255, 255, 1)"
+                            stroke-width="1.3333333333333333"
+                            stroke-linejoin="round"
+                            stroke-linecap="round"
+                          ></ellipse>
+                          <path
+                            stroke="rgba(255, 255, 255, 1)"
+                            stroke-width="1.3333333333333333"
+                            stroke-linejoin="round"
+                            stroke-linecap="round"
+                            d="M15.2656 15.2665L18.999 15.2665"
+                          ></path>
+                          <path
+                            stroke="rgba(255, 255, 255, 1)"
+                            stroke-width="1.3333333333333333"
+                            stroke-linejoin="round"
+                            stroke-linecap="round"
+                            d="M17.1348 17.1332L17.1348 13.3999"
+                          ></path>
+                        </svg>
+                      }
+                    />
+                  </div>
+                </div>
+              ))}
+            </div>
+          </SwiperSlide>
+        ))}
+
+        {/* 自定义分页器容器(底部小按钮) */}
+        <div className="custom-pagination flex justify-center mt-4"></div>
+      </Swiper>
+    </div>
+  );
+};
+
+export default HomeBestSellers;

Fichier diff supprimé car celui-ci est trop grand
+ 120 - 0
src/app/(public)/_components/HomeContent.tsx


+ 75 - 0
src/app/(public)/_components/HomeMiddleBanner.tsx

@@ -0,0 +1,75 @@
+"use client";
+import { useState } from "react";
+import { Swiper, SwiperSlide } from "swiper/react";
+import { Navigation } from "swiper/modules";
+import "swiper/css";
+import "swiper/css/navigation";
+import Image from "next/image";
+export default function HomeMiddleBanner() {
+  const [activeIndex, setActiveIndex] = useState(0);
+
+  const [swiperRef, setSwiperRef] = useState(null);
+
+  const handleSlideChange = (swiper) => {
+    setActiveIndex(swiper.activeIndex);
+  };
+
+  const handleIndicatorClick = (index) => {
+    if (swiperRef) {
+      setActiveIndex(index);
+    }
+  };
+
+  return (
+    <div className="max-w-screen-md mx-auto p-4">
+      <Swiper
+        modules={[Navigation]}
+        spaceBetween={10}
+        slidesPerView={1}
+        onSlideChange={handleSlideChange}
+        className="mb-6"
+      >
+        <SwiperSlide>
+          <div className="relative w-full h-42">
+            <Image
+              src={
+                "https://cdn.asteriahair.com/media/wysiwyg/home/1750041184.png"
+              }
+              alt={"bbbb"}
+              fill
+              className="w-full h-auto object-cover rounded-md"
+            />
+          </div>
+        </SwiperSlide>
+        <SwiperSlide>
+          <div className="relative w-full h-42">
+            <Image
+              src={
+                "https://cdn.asteriahair.com/media/wysiwyg/home/1750041184.png"
+              }
+              alt={"bbbb"}
+              fill
+              className="w-full h-auto object-cover rounded-md"
+            />
+          </div>
+        </SwiperSlide>
+      </Swiper>
+      <div className="flex justify-center gap-2">
+        <button
+          onClick={() => handleIndicatorClick(0)}
+          className={`w-6 h-[5px] rounded-full  opacity-100 ${
+            activeIndex === 0 ? "bg-[#333]" : "bg-[#E5E5E5]"
+          }`}
+          aria-label="切换到第一块"
+        />
+        <button
+          onClick={() => handleIndicatorClick(1)}
+          className={`w-6 h-[5px] rounded-full  opacity-100 ${
+            activeIndex === 1 ? "bg-[#333]" : "bg-[#E5E5E5]"
+          }`}
+          aria-label="切换到第二块"
+        />
+      </div>
+    </div>
+  );
+}

+ 276 - 0
src/app/(public)/_components/HomeNewArrival.tsx

@@ -0,0 +1,276 @@
+import React from "react";
+import { Swiper, SwiperSlide } from "swiper/react";
+import { Navigation, Pagination } from "swiper/modules";
+import { OpenAddToCartModalButton } from "@/components/common/AddToCartModal/OpenAddToCartModalButton";
+// 导入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 = () => {
+  return (
+    <div className="w-full max-w-[1200px] mx-auto px-4 py-8">
+      {/* 标题 */}
+      <h2 className="text-2xl font-bold mb-6">New Arrival</h2>
+
+      {/* Swiper容器 */}
+      <Swiper
+        slidesPerView={1}
+        spaceBetween={20}
+        modules={[Navigation, Pagination]}
+        pagination={{
+          el: ".custom-pagination",
+          clickable: true,
+          renderBullet: (index, className) => {
+            // 所有分页默认底色为 #E5E5E5
+            return `<span class="${className} w-6 h-[5px] rounded-full mx-1 bg-[#E5E5E5]"></span>`;
+          },
+          // 激活时强制覆盖底色,加 !important 提高权重
+          bulletActiveClass: "!bg-[#333]",
+        }}
+        className="relative"
+      >
+        {/* 渲染2个滑动块 */}
+        {productBlocks.map((block, blockIndex) => (
+          <SwiperSlide key={blockIndex} className="!px-0">
+            {/* 每个块:6个产品,2列布局 */}
+            <div className="grid grid-cols-2 gap-4">
+              {block.map((product) => (
+                <div key={product.id} className="flex flex-col gap-2">
+                  {/* 产品图片 */}
+                  <img
+                    src={product.img}
+                    alt={product.title}
+                    className="w-full h-auto object-cover rounded-sm"
+                  />
+                  {/* 产品标题 */}
+                  <p className="text-sm text-gray-800 truncate">
+                    {product.title}
+                  </p>
+                  {/* 评分 + 评论数 */}
+                  <div className="flex items-center gap-1">
+                    <div className="flex">
+                      {/* 星级图标(简化版,可替换为真实星星图标) */}
+                      {[1, 2, 3, 4, 5].map((star) => (
+                        <svg
+                          key={star}
+                          className="w-4 h-4 text-yellow-400"
+                          fill="currentColor"
+                          viewBox="0 0 20 20"
+                        >
+                          <path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
+                        </svg>
+                      ))}
+                    </div>
+                    <span className="text-xs text-gray-600">
+                      {product.reviewCount}
+                    </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="text-xs text-gray-500 line-through">
+                        ${product.originalPrice}
+                      </span>
+                    </div>
+                    {/* 购物车图标 */}
+                    <OpenAddToCartModalButton
+                      productUrlKey={
+                        "http://nshop.test/hd-transparent-deep-wave-&-curly-lace-frontal-closure-wig"
+                      }
+                      icon={
+                        <svg
+                          xmlns="http://www.w3.org/2000/svg"
+                          width="32"
+                          height="32"
+                          viewBox="0 0 32 32"
+                          fill="none"
+                        >
+                          <rect
+                            x="0"
+                            y="0"
+                            width="32"
+                            height="32"
+                            rx="8"
+                            fill="#036141"
+                          ></rect>
+                          <path
+                            stroke="rgba(255, 255, 255, 1)"
+                            stroke-width="1.3333333333333333"
+                            stroke-linejoin="round"
+                            stroke-linecap="round"
+                            d="M6.40039 7.79993L8.03372 7.79993L8.73372 10.5999M8.73372 10.5999L11.0671 19.9333L23.2004 19.9333L25.5337 10.5999L8.73372 10.5999Z"
+                          ></path>
+                          <ellipse
+                            cx="11.066040515899658"
+                            cy="23.199928283691406"
+                            rx="1.4000248908996582"
+                            ry="1.4000015258789062"
+                            stroke="rgba(255, 255, 255, 1)"
+                            stroke-width="1.3333333333333333"
+                            stroke-linejoin="round"
+                            stroke-linecap="round"
+                          ></ellipse>
+                          <ellipse
+                            cx="23.1998291015625"
+                            cy="23.199928283691406"
+                            rx="1.4000244140625"
+                            ry="1.4000015258789062"
+                            stroke="rgba(255, 255, 255, 1)"
+                            stroke-width="1.3333333333333333"
+                            stroke-linejoin="round"
+                            stroke-linecap="round"
+                          ></ellipse>
+                          <path
+                            stroke="rgba(255, 255, 255, 1)"
+                            stroke-width="1.3333333333333333"
+                            stroke-linejoin="round"
+                            stroke-linecap="round"
+                            d="M15.2656 15.2665L18.999 15.2665"
+                          ></path>
+                          <path
+                            stroke="rgba(255, 255, 255, 1)"
+                            stroke-width="1.3333333333333333"
+                            stroke-linejoin="round"
+                            stroke-linecap="round"
+                            d="M17.1348 17.1332L17.1348 13.3999"
+                          ></path>
+                        </svg>
+                      }
+                    />
+                  </div>
+                </div>
+              ))}
+            </div>
+          </SwiperSlide>
+        ))}
+
+        {/* 自定义分页器容器(底部小按钮) */}
+        <div className="custom-pagination flex justify-center mt-4"></div>
+      </Swiper>
+    </div>
+  );
+};
+
+export default HomeNewArrival;

+ 148 - 0
src/app/(public)/_components/JinGangSwiper.tsx

@@ -0,0 +1,148 @@
+"use client";
+import { useState } from "react";
+import { Swiper, SwiperSlide } from "swiper/react";
+import { Navigation } from "swiper/modules";
+import "swiper/css";
+import "swiper/css/navigation";
+import Image from "next/image";
+
+const MOCK_DATA = [
+  [
+    {
+      name: "Hd Lace Wig",
+      img: "https://cdn.asteriahair.com/uploads/202602/11/20260211095740_8181b0e039800e07.png",
+    },
+    {
+      name: "Ready To Go",
+      img: "https://cdn.asteriahair.com/uploads/202602/11/20260211095740_8181b0e039800e07.png",
+    },
+    {
+      name: "Colored Wig",
+      img: "https://cdn.asteriahair.com/uploads/202602/11/20260211095740_8181b0e039800e07.png",
+    },
+    {
+      name: "U&V Part Wig",
+      img: "https://cdn.asteriahair.com/uploads/202602/11/20260211095740_8181b0e039800e07.png",
+    },
+    {
+      name: "New Arrival",
+      img: "https://cdn.asteriahair.com/uploads/202602/11/20260211095740_8181b0e039800e07.png",
+    },
+    {
+      name: "360 Wig",
+      img: "https://cdn.asteriahair.com/uploads/202602/11/20260211095740_8181b0e039800e07.png",
+    },
+  ],
+
+  [
+    {
+      name: "13x4 Lace Wig",
+      img: "https://cdn.asteriahair.com/uploads/202602/11/20260211095800_8181b0e039800e07.png",
+    },
+    {
+      name: "Body Wave Wig",
+      img: "https://cdn.asteriahair.com/uploads/202602/11/20260211095800_8181b0e039800e07.png",
+    },
+    {
+      name: "Deep Wave Wig",
+      img: "https://cdn.asteriahair.com/uploads/202602/11/20260211095800_8181b0e039800e07.png",
+    },
+    {
+      name: "Straight Wig",
+      img: "https://cdn.asteriahair.com/uploads/202602/11/20260211095800_8181b0e039800e07.png",
+    },
+    {
+      name: "Curly Wig",
+      img: "https://cdn.asteriahair.com/uploads/202602/11/20260211095800_8181b0e039800e07.png",
+    },
+    {
+      name: "Bob Wig",
+      img: "https://cdn.asteriahair.com/uploads/202602/11/20260211095800_8181b0e039800e07.png",
+    },
+  ],
+];
+
+export default function JinGangSwiper() {
+  const [activeIndex, setActiveIndex] = useState(0);
+
+  const [swiperRef, setSwiperRef] = useState(null);
+
+  const handleSlideChange = (swiper) => {
+    setActiveIndex(swiper.activeIndex);
+  };
+
+  const handleIndicatorClick = (index) => {
+    if (swiperRef) {
+      swiperRef.slideTo(index);
+      setActiveIndex(index);
+    }
+  };
+
+  return (
+    <div className="max-w-screen-md mx-auto p-4">
+      <Swiper
+        modules={[Navigation]}
+        spaceBetween={10}
+        slidesPerView={1}
+        onSwiper={setSwiperRef}
+        onSlideChange={handleSlideChange}
+        className="mb-6"
+      >
+        <SwiperSlide>
+          <div className="grid grid-cols-3 gap-2">
+            {MOCK_DATA[0].map((item, idx) => (
+              <div key={`block1-${idx}`} className="relative w-full aspect-[3/4]">
+                <Image
+                  src={item.img}
+                  alt={item.name}
+                  fill
+                  className="object-cover rounded-md"
+                />
+                {/* <div className="absolute bottom-2 left-2 text-white text-sm font-medium bg-black/50 px-2 py-1 rounded">
+                  {item.name}
+                </div> */}
+              </div>
+            ))}
+          </div>
+        </SwiperSlide>
+
+        {/* 第二大块:6个分类卡片(2行3列) */}
+        <SwiperSlide>
+          <div className="grid grid-cols-3 gap-2">
+            {MOCK_DATA[1].map((item, idx) => (
+              <div key={`block2-${idx}`} className="relative w-full aspect-[3/4]">
+                <Image
+                  src={item.img}
+                  alt={item.name}
+                  fill
+                  className="object-cover rounded-md"
+                />
+                {/* <div className="absolute bottom-2 left-2 text-white text-sm font-medium bg-black/50 px-2 py-1 rounded">
+                  {item.name}
+                </div> */}
+              </div>
+            ))}
+          </div>
+        </SwiperSlide>
+      </Swiper>
+
+      {/* 底部指示器按钮:2个,激活态黑色,未激活灰色 */}
+      <div className="flex justify-center gap-2">
+        <button
+          onClick={() => handleIndicatorClick(0)}
+          className={`w-6 h-[5px] rounded-full  opacity-100 ${
+            activeIndex === 0 ? "bg-[#333]" : "bg-[#E5E5E5]"
+          }`}
+          aria-label="切换到第一块"
+        />
+        <button
+          onClick={() => handleIndicatorClick(1)}
+          className={`w-6 h-[5px] rounded-full  opacity-100 ${
+            activeIndex === 1 ? "bg-[#333]" : "bg-[#E5E5E5]"
+          }`}
+          aria-label="切换到第二块"
+        />
+      </div>
+    </div>
+  );
+}

+ 163 - 0
src/app/(public)/_components/MiddleImageSwiper.tsx

@@ -0,0 +1,163 @@
+import React from "react";
+import { Swiper, SwiperSlide } from "swiper/react";
+import { Scrollbar, Pagination, Navigation } from "swiper/modules";
+import "swiper/css";
+import "swiper/css/pagination";
+import "swiper/css/navigation";
+import "./css/swiper-custom.css";
+import { OpenAddToCartModalButton } from "@/components/common/AddToCartModal/OpenAddToCartModalButton";
+
+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 = () => {
+  return (
+    <div className="w-full pr-4 pl-4 mx-auto  rounded-lg  ">
+      <div className="w-full">
+        <img
+          src="https://cdn.asteriahair.com/uploads/202602/11/20260211095330_7ec9031a4ab36e44.gif"
+          alt="ZEROWEAR hair banner"
+          className="w-full h-auto object-cover block"
+        />
+      </div>
+      <div className="py-4 px-4 pb-6 relative min-h-83 bg-[#f0f5f3] pb-10">
+        <div className="w-full relative">
+          <Swiper
+            modules={[Pagination]}
+            spaceBetween={16}
+            slidesPerView={2}
+            pagination={{
+              type: "progressbar",
+              el: ".my-progress-bar",
+            }}
+            className="mySwiper"
+            breakpoints={{
+              480: { slidesPerView: 1 },
+              768: { slidesPerView: 2 },
+            }}
+          >
+            {productList.map((item) => (
+              <SwiperSlide key={item.id}>
+                <div className="bg-white rounded overflow-hidden  flex flex-col">
+                  <img
+                    src={item.img}
+                    alt={item.title}
+                    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}
+                    </p>
+                    {/* 价格 + 购物车图标 */}
+                    <div className="flex items-center justify-between">
+                      <div className="flex items-center gap-1">
+                        <span className="font-semibold">${item.price}</span>
+                        <span className="text-xs text-gray-500 line-through">
+                          ${item.price}
+                        </span>
+                      </div>
+                      {/* 购物车图标 */}
+                      <OpenAddToCartModalButton
+                        productUrlKey={
+                          "http://nshop.test/hd-transparent-deep-wave-&-curly-lace-frontal-closure-wig"
+                        }
+                        icon={
+                          <svg
+                            xmlns="http://www.w3.org/2000/svg"
+                            width="32"
+                            height="32"
+                            viewBox="0 0 32 32"
+                            fill="none"
+                          >
+                            <rect
+                              x="0"
+                              y="0"
+                              width="32"
+                              height="32"
+                              rx="8"
+                              fill="#036141"
+                            ></rect>
+                            <path
+                              stroke="rgba(255, 255, 255, 1)"
+                              stroke-width="1.3333333333333333"
+                              stroke-linejoin="round"
+                              stroke-linecap="round"
+                              d="M6.40039 7.79993L8.03372 7.79993L8.73372 10.5999M8.73372 10.5999L11.0671 19.9333L23.2004 19.9333L25.5337 10.5999L8.73372 10.5999Z"
+                            ></path>
+                            <ellipse
+                              cx="11.066040515899658"
+                              cy="23.199928283691406"
+                              rx="1.4000248908996582"
+                              ry="1.4000015258789062"
+                              stroke="rgba(255, 255, 255, 1)"
+                              stroke-width="1.3333333333333333"
+                              stroke-linejoin="round"
+                              stroke-linecap="round"
+                            ></ellipse>
+                            <ellipse
+                              cx="23.1998291015625"
+                              cy="23.199928283691406"
+                              rx="1.4000244140625"
+                              ry="1.4000015258789062"
+                              stroke="rgba(255, 255, 255, 1)"
+                              stroke-width="1.3333333333333333"
+                              stroke-linejoin="round"
+                              stroke-linecap="round"
+                            ></ellipse>
+                            <path
+                              stroke="rgba(255, 255, 255, 1)"
+                              stroke-width="1.3333333333333333"
+                              stroke-linejoin="round"
+                              stroke-linecap="round"
+                              d="M15.2656 15.2665L18.999 15.2665"
+                            ></path>
+                            <path
+                              stroke="rgba(255, 255, 255, 1)"
+                              stroke-width="1.3333333333333333"
+                              stroke-linejoin="round"
+                              stroke-linecap="round"
+                              d="M17.1348 17.1332L17.1348 13.3999"
+                            ></path>
+                          </svg>
+                        }
+                      />
+                    </div>
+                
+                  </div>
+                </div>
+              </SwiperSlide>
+            ))}
+          </Swiper>
+          <div className="my-progress-bar mt-5 w-full h-1 bg-gray-200 rounded-full bottom-0 [top:unset]"></div>
+        </div>
+      </div>
+    </div>
+  );
+};
+
+export default MiddleImageSwiper;

+ 258 - 0
src/app/(public)/_components/RecommendedProducts.tsx

@@ -0,0 +1,258 @@
+"use client";
+import React, { useState, useEffect, useCallback } from "react";
+import Image from "next/image";
+import { OpenAddToCartModalButton } from "@/components/common/AddToCartModal/OpenAddToCartModalButton";
+// 商品类型定义
+interface ProductItem {
+  id: number;
+  img: string;
+  title: string;
+  price: number;
+  originPrice: number;
+  star: number;
+  reviewCount: number;
+}
+
+// ========== 模拟后端分页接口(真实场景替换为axios/fetch请求) ==========
+/**
+ * @param page 当前页码
+ * @param pageSize 每页条数
+ * @returns Promise<{ list: ProductItem[], total: number }>
+ */
+const mockGetProductApi = async (page: number, pageSize: number) => {
+  // 模拟总数据22条,后端固定总数
+  const TOTAL = 22;
+  // 模拟全部源数据
+  const allMockData: ProductItem[] = Array.from({ length: TOTAL }).map(
+    (_, idx) => ({
+      id: idx + 1,
+      img: `/img/hair${(idx % 6) + 1}.jpg`,
+      title: "14-36 In Water Wave Human Hair Wig",
+      price: 143.35,
+      originPrice: 143.35,
+      star: 5,
+      reviewCount: 342,
+    }),
+  );
+
+  // 分页切片
+  const start = (page - 1) * pageSize;
+  const end = page * pageSize;
+  const pageList = allMockData.slice(start, end);
+
+  // 模拟网络延迟
+  await new Promise((resolve) => setTimeout(resolve, 600));
+  return {
+    list: pageList,
+    total: TOTAL,
+  };
+};
+
+const PAGE_SIZE = 6;
+
+export default function RecommendedProducts() {
+  // 已渲染的全部商品
+  const [productList, setProductList] = useState<ProductItem[]>([]);
+  // 当前页码
+  const [page, setPage] = useState(1);
+  // 数据总条数
+  const [total, setTotal] = useState(0);
+  // 加载状态
+  const [loading, setLoading] = useState(false);
+
+  // 是否还有下一页:已渲染数量 < 总条数
+  const hasMore = productList.length < total;
+
+  // 请求分页数据
+  const fetchPageData = useCallback(async (currentPage: number) => {
+    setLoading(true);
+    try {
+      const res = await mockGetProductApi(currentPage, PAGE_SIZE);
+      setTotal(res.total);
+      // 第一页直接覆盖,后续页码追加数据
+      setProductList((prev) =>
+        currentPage === 1 ? res.list : [...prev, ...res.list],
+      );
+    } catch (err) {
+      console.error("商品分页加载失败", err);
+    } finally {
+      setLoading(false);
+    }
+  }, []);
+
+  // 页面初始化:加载第一页
+  useEffect(() => {
+    fetchPageData(1);
+  }, [fetchPageData]);
+
+  // 点击View More 加载下一页
+  const handleViewMore = () => {
+    const nextPage = page + 1;
+    setPage(nextPage);
+    fetchPageData(nextPage);
+  };
+
+  // 五星星星渲染
+  const renderStars = (count: number) => {
+    return Array.from({ length: count }).map((_, idx) => (
+      <svg
+        key={idx}
+        className="w-4 h-4 text-green-600 inline-block"
+        viewBox="0 0 24 24"
+        fill="currentColor"
+      >
+        <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" />
+      </svg>
+    ));
+  };
+
+  return (
+    <section className="py-6 px-4 pt-8">
+      <h2 className="text-[clamp(1.5rem,4vw,2.2rem)] font-semibold mb-6">
+        Recommended For You
+      </h2>
+
+      {/* 商品2列网格 */}
+      <div className="grid grid-cols-2 gap-4">
+        {productList.map((item) => (
+          <div key={item.id} className="flex flex-col gap-3">
+            {/* Next.Image 商品图容器 */}
+            <div className="relative w-full aspect-[3/4] overflow-hidden rounded-md">
+              <Image
+                src={item.img}
+                alt={item.title}
+                fill
+                sizes="(max-width:768px) 50vw, 33vw"
+                className="object-cover"
+              />
+            </div>
+
+            {/* 标题 */}
+            <p className="text-sm text-gray-800 truncate">{item.title}</p>
+
+            {/* 星级 + 评论数 */}
+            <div className="flex items-center gap-1">
+              {renderStars(item.star)}
+              <span className="text-sm text-gray-600 ml-1 underline">
+                {item.reviewCount}
+              </span>
+            </div>
+
+            {/* 价格 + 购物车按钮 */}
+            {/* <div className="flex items-center justify-between">
+              <div className="flex items-center gap-2">
+                <span className="text-xl font-bold text-black">
+                  ${item.price}
+                </span>
+                <span className="text-sm text-gray-400 line-through">
+                  ${item.originPrice}
+                </span>
+              </div>
+              <button className="w-10 h-10 bg-emerald-600 rounded-lg flex items-center justify-center text-white">
+                <svg
+                  width="18"
+                  height="18"
+                  viewBox="0 0 24 24"
+                  fill="none"
+                  stroke="currentColor"
+                  strokeWidth="2"
+                >
+                  <path d="M6 3h12M3 6h18l-2 11H5L3 6z" />
+                  <circle cx="9" cy="20" r="1" />
+                  <circle cx="15" cy="20" r="1" />
+                </svg>
+              </button>
+            </div> */}
+            {/* 价格 + 购物车图标 */}
+            <div className="flex items-center justify-between">
+              <div className="flex items-center gap-1">
+                <span className="font-semibold">${item.price}</span>
+                <span className="text-xs text-gray-500 line-through">
+                  ${item.originPrice}
+                </span>
+              </div>
+              {/* 购物车图标 */}
+              <OpenAddToCartModalButton
+                productUrlKey={
+                  "http://nshop.test/hd-transparent-deep-wave-&-curly-lace-frontal-closure-wig"
+                }
+                icon={
+                  <svg
+                    xmlns="http://www.w3.org/2000/svg"
+                    width="32"
+                    height="32"
+                    viewBox="0 0 32 32"
+                    fill="none"
+                  >
+                    <rect
+                      x="0"
+                      y="0"
+                      width="32"
+                      height="32"
+                      rx="8"
+                      fill="#036141"
+                    ></rect>
+                    <path
+                      stroke="rgba(255, 255, 255, 1)"
+                      stroke-width="1.3333333333333333"
+                      stroke-linejoin="round"
+                      stroke-linecap="round"
+                      d="M6.40039 7.79993L8.03372 7.79993L8.73372 10.5999M8.73372 10.5999L11.0671 19.9333L23.2004 19.9333L25.5337 10.5999L8.73372 10.5999Z"
+                    ></path>
+                    <ellipse
+                      cx="11.066040515899658"
+                      cy="23.199928283691406"
+                      rx="1.4000248908996582"
+                      ry="1.4000015258789062"
+                      stroke="rgba(255, 255, 255, 1)"
+                      stroke-width="1.3333333333333333"
+                      stroke-linejoin="round"
+                      stroke-linecap="round"
+                    ></ellipse>
+                    <ellipse
+                      cx="23.1998291015625"
+                      cy="23.199928283691406"
+                      rx="1.4000244140625"
+                      ry="1.4000015258789062"
+                      stroke="rgba(255, 255, 255, 1)"
+                      stroke-width="1.3333333333333333"
+                      stroke-linejoin="round"
+                      stroke-linecap="round"
+                    ></ellipse>
+                    <path
+                      stroke="rgba(255, 255, 255, 1)"
+                      stroke-width="1.3333333333333333"
+                      stroke-linejoin="round"
+                      stroke-linecap="round"
+                      d="M15.2656 15.2665L18.999 15.2665"
+                    ></path>
+                    <path
+                      stroke="rgba(255, 255, 255, 1)"
+                      stroke-width="1.3333333333333333"
+                      stroke-linejoin="round"
+                      stroke-linecap="round"
+                      d="M17.1348 17.1332L17.1348 13.3999"
+                    ></path>
+                  </svg>
+                }
+              />
+            </div>
+          </div>
+        ))}
+      </div>
+
+      {/* View More 按钮:有下一页且非加载中显示 */}
+      {hasMore && (
+        <div className="flex justify-center mt-8">
+          <button
+            onClick={handleViewMore}
+            disabled={loading}
+            className="px-8 py-2 border border-black rounded-full text-base hover:bg-gray-100 transition disabled:opacity-50 disabled:cursor-not-allowed"
+          >
+            {loading ? "Loading..." : "View More"}
+          </button>
+        </div>
+      )}
+    </section>
+  );
+}

+ 43 - 0
src/app/(public)/_components/TopImageSwiper.tsx

@@ -0,0 +1,43 @@
+import React from 'react';
+import { Swiper, SwiperSlide } from 'swiper/react';
+import 'swiper/css';
+import { Navigation, Pagination, Mousewheel, Keyboard } from 'swiper/modules';
+
+const TopImageSwiper = () => {
+  // ✅ 直接在这里放你的图片数组,想加多少加多少
+  const images = [
+    'https://cdn.asteriahair.com/uploads/202607/01/20260701165056_761989a0fdc11d5e.jpg',
+    'https://cdn.asteriahair.com/uploads/202607/01/20260701165110_3fff435adf276b89.jpg',
+    'https://cdn.asteriahair.com/uploads/202607/01/20260701165123_c424f6f1d0b29522.jpg',
+    'https://cdn.asteriahair.com/uploads/202607/01/20260701165056_761989a0fdc11d5e.jpg',
+  ];
+
+  return (
+    <div className="w-full max-w-[1200px] mx-auto ">
+      <Swiper
+        slidesPerView={1}
+        spaceBetween={0}
+        loop={true} // 无限轮播
+      
+        // pagination={{ clickable: true }}
+        // mousewheel
+        // keyboard={{ enabled: true }}
+        className="h-auto md:h-[80vh]  overflow-hidden"
+      >
+        {/* ✅ 自动遍历图片数组,一行代码搞定所有图片 */}
+        {images.map((img, index) => (
+          <SwiperSlide key={index}>
+            <img
+              src={img}
+              alt={`slide-${index}`}
+              className="w-full h-full object-cover"
+            />
+          </SwiperSlide>
+        ))}
+        
+      </Swiper>
+    </div>
+  );
+};
+
+export default TopImageSwiper;

+ 317 - 0
src/app/(public)/_components/Trending.tsx

@@ -0,0 +1,317 @@
+import React, { useState, useRef, useEffect } from "react";
+import { Swiper, SwiperSlide } from "swiper/react";
+import { Scrollbar, Navigation } from "swiper/modules";
+import "swiper/css";
+import "swiper/css/scrollbar";
+import "swiper/css/navigation";
+import Image from "next/image";
+import { OpenAddToCartModalButton } from "@/components/common/AddToCartModal/OpenAddToCartModalButton";
+
+// 商品数据,每个卡片携带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 Trending = () => {
+  // 视频弹窗状态
+  const [openVideoModal, setOpenVideoModal] = useState(false);
+  const [currentVideoSrc, setCurrentVideoSrc] = useState("");
+  const videoRef = useRef<HTMLVideoElement>(null);
+
+  // 打开弹窗并赋值视频地址
+  const handlePlayClick = (videoUrl: string) => {
+    setCurrentVideoSrc(videoUrl);
+    setOpenVideoModal(true);
+  };
+
+  // 关闭弹窗,暂停视频
+  const closeModal = () => {
+    setOpenVideoModal(false);
+    if (videoRef.current) {
+      videoRef.current.pause();
+      videoRef.current.currentTime = 0;
+    }
+  };
+
+  // 弹窗打开自动播放
+  useEffect(() => {
+    if (openVideoModal && videoRef.current) {
+      videoRef.current.play().catch((err) => console.log("播放拦截", err));
+    }
+  }, [openVideoModal]);
+
+  return (
+    <div className="w-full max-w-[960px] mx-auto">
+      <div className="w-full max-w-[960px] mx-auto px-4 py-6">
+        {/* 顶部标题 */}
+        <h2 className="text-[clamp(1.5rem,4vw,2.2rem)] font-bold mb-6 text-black">
+          Real looks,Trending Now
+        </h2>
+
+        {/* Swiper外层容器:进度条深层Tailwind样式 */}
+        <div
+          className="
+          [&_.custom-scrollbar]:h-[3px]
+          [&_.custom-scrollbar]:bg-gray-200
+          [&_.custom-scrollbar]:rounded-full
+          [&_.swiper-scrollbar-drag]:h-full
+          [&_.swiper-scrollbar-drag]:bg-black
+          [&_.swiper-scrollbar-drag]:rounded-full
+          [&_.swiper-scrollbar-drag]:shadow-none
+          [&_.swiper-scrollbar]:bg-transparent
+          /* 自定义左右箭头样式 匹配截图灰色圆形按钮 */
+          [&_.swiper-button-next]:w-11
+          [&_.swiper-button-next]:h-11
+          [&_.swiper-button-next]:rounded-full
+          [&_.swiper-button-next]:bg-black/40
+          [&_.swiper-button-next]:text-white
+          [&_.swiper-button-next]:after:text-base
+          [&_.swiper-button-next]:after:font-bold
+          [&_.swiper-button-prev]:w-11
+          [&_.swiper-button-prev]:h-11
+          [&_.swiper-button-prev]:rounded-full
+          [&_.swiper-button-prev]:bg-black/40
+          [&_.swiper-button-prev]:text-white
+          [&_.swiper-button-prev]:after:text-base
+          [&_.swiper-button-prev]:after:font-bold
+          [&_.swiper-button-next]:right-3
+          [&_.swiper-button-prev]:left-3
+        "
+        >
+          <Swiper
+            modules={[Scrollbar, Navigation]}
+            spaceBetween={16}
+            slidesPerView={1.2} // 露出右侧下一张,和截图一致
+            navigation={{
+              prevEl: ".btn-prev", // 左箭头class
+              nextEl: ".btn-next", // 右箭头class
+              disabledClass: "opacity-20", // 滑到首尾自动加这个类,Tailwind直接用
+            }}
+            breakpoints={{
+              640: { slidesPerView: 2.2 },
+              1024: { slidesPerView: 2.5 },
+            }}
+          >
+            {productList.map((item) => (
+              <SwiperSlide key={item.id} className="!h-auto">
+                {/* 单个商品卡片 */}
+                <div className=" overflow-hidden  flex flex-col">
+                  {/* 图片区域 + 中间播放按钮 */}
+                  <div className="relative rounded-xl w-full aspect-[4/5] overflow-hidden rounded-xl">
+                    <img
+                      src={item.img}
+                      alt={item.title}
+                      className="w-full h-full object-cover"
+                    />
+                    {/* 居中圆形播放按钮 */}
+                    <button
+                      onClick={() => handlePlayClick(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"
+                    >
+                      <svg
+                        width="36"
+                        height="36"
+                        viewBox="0 0 24 24"
+                        fill="none"
+                        stroke="#222"
+                        strokeWidth="2"
+                      >
+                        <polygon points="5 3 19 12 5 21 5 3" />
+                      </svg>
+                    </button>
+                  </div>
+
+                  {/* 底部文字价格区域 */}
+                  <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}
+                    </p>
+                    {/* 价格 + 购物车图标 */}
+                    <div className="flex items-center justify-between">
+                      <div className="flex items-center gap-1">
+                        <span className="font-semibold">${item.price}</span>
+                        <span className="text-xs text-gray-500 line-through">
+                          ${item.price}
+                        </span>
+                      </div>
+                      {/* 购物车图标 */}
+                      <OpenAddToCartModalButton
+                        productUrlKey={
+                          "http://nshop.test/hd-transparent-deep-wave-&-curly-lace-frontal-closure-wig"
+                        }
+                        icon={
+                          <svg
+                            xmlns="http://www.w3.org/2000/svg"
+                            width="32"
+                            height="32"
+                            viewBox="0 0 32 32"
+                            fill="none"
+                          >
+                            <rect
+                              x="0"
+                              y="0"
+                              width="32"
+                              height="32"
+                              rx="8"
+                              fill="#036141"
+                            ></rect>
+                            <path
+                              stroke="rgba(255, 255, 255, 1)"
+                              stroke-width="1.3333333333333333"
+                              stroke-linejoin="round"
+                              stroke-linecap="round"
+                              d="M6.40039 7.79993L8.03372 7.79993L8.73372 10.5999M8.73372 10.5999L11.0671 19.9333L23.2004 19.9333L25.5337 10.5999L8.73372 10.5999Z"
+                            ></path>
+                            <ellipse
+                              cx="11.066040515899658"
+                              cy="23.199928283691406"
+                              rx="1.4000248908996582"
+                              ry="1.4000015258789062"
+                              stroke="rgba(255, 255, 255, 1)"
+                              stroke-width="1.3333333333333333"
+                              stroke-linejoin="round"
+                              stroke-linecap="round"
+                            ></ellipse>
+                            <ellipse
+                              cx="23.1998291015625"
+                              cy="23.199928283691406"
+                              rx="1.4000244140625"
+                              ry="1.4000015258789062"
+                              stroke="rgba(255, 255, 255, 1)"
+                              stroke-width="1.3333333333333333"
+                              stroke-linejoin="round"
+                              stroke-linecap="round"
+                            ></ellipse>
+                            <path
+                              stroke="rgba(255, 255, 255, 1)"
+                              stroke-width="1.3333333333333333"
+                              stroke-linejoin="round"
+                              stroke-linecap="round"
+                              d="M15.2656 15.2665L18.999 15.2665"
+                            ></path>
+                            <path
+                              stroke="rgba(255, 255, 255, 1)"
+                              stroke-width="1.3333333333333333"
+                              stroke-linejoin="round"
+                              stroke-linecap="round"
+                              d="M17.1348 17.1332L17.1348 13.3999"
+                            ></path>
+                          </svg>
+                        }
+                      />
+                    </div>
+                  </div>
+                </div>
+              </SwiperSlide>
+            ))}
+            {/* 自定义左右按钮,放在Swiper内部,同级slide */}
+            <button className="btn-prev absolute left-2 top-1/2 -translate-y-1/2 z-10 w-9 h-9 rounded-full bg-black/50 shadow flex items-center justify-center">
+              {/* 自定义左箭头SVG */}
+              <svg
+                width="16"
+                height="16"
+                viewBox="0 0 24 24"
+                fill="none"
+                stroke="#fff"
+                stroke-width="2"
+              >
+                <path d="M15 18l-6-6 6-6" />
+              </svg>
+            </button>
+            <button className="btn-next absolute right-2 top-1/2 -translate-y-1/2 z-10 w-9 h-9 rounded-full bg-black/50 shadow flex items-center justify-center">
+              {/* 自定义右箭头SVG */}
+              <svg
+                width="16"
+                height="16"
+                viewBox="0 0 24 24"
+                fill="none"
+                stroke="#fff"
+                stroke-width="2"
+              >
+                <path d="M9 18l6-6-6-6" />
+              </svg>
+            </button>
+          </Swiper>
+        </div>
+
+        {/* ====================== 全屏视频遮罩弹窗 ====================== */}
+        {openVideoModal && (
+          <div
+            className="fixed inset-0 z-[9999] bg-black/95 flex items-center justify-center p-4"
+            onClick={closeModal} // 点击遮罩空白关闭
+          >
+            {/* 弹窗内层,阻止冒泡 */}
+            <div
+              className="relative w-full max-w-4xl"
+              onClick={(e) => e.stopPropagation()}
+            >
+              {/* 右上角关闭按钮 */}
+              <button
+                onClick={closeModal}
+                className="absolute -top-12 right-0 text-white text-3xl hover:text-gray-300"
+              >
+                ✕
+              </button>
+              {/* 视频播放器 */}
+              <video
+                ref={videoRef}
+                src={currentVideoSrc}
+                controls
+                className="w-full rounded-lg"
+              />
+            </div>
+          </div>
+        )}
+      </div>
+      <div className="relative w-full aspect-[3/4] mt-8">
+        <Image
+          src={
+            "https://cdn.asteriahair.com/uploads/202607/01/20260701165110_3fff435adf276b89.jpg"
+          }
+          alt={"cscscs"}
+          fill
+          className="object-cover rounded-md"
+        />
+      </div>
+    </div>
+  );
+};
+
+export default Trending;

+ 5 - 0
src/app/(public)/_components/css/swiper-custom.css

@@ -0,0 +1,5 @@
+/* swiper-custom.css */
+.swiper-horizontal > .swiper-pagination-progressbar, .swiper-pagination-progressbar.swiper-pagination-horizontal{
+    bottom: -16px ;
+    top: unset;
+}

+ 3 - 1
src/app/(public)/page.tsx

@@ -4,6 +4,7 @@ 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"
 export const revalidate = 3600;
 
 export default async function Home() {
@@ -18,7 +19,8 @@ export default async function Home() {
     <>
       <HomeImageBanner />
       <DatePicker label={"Birth date"} labelPlacement={"outside"} />
-      <RenderThemeCustomization themeCustomizations={data?.themeCustomizations ?? {edges: []}} />
+      {/* <RenderThemeCustomization themeCustomizations={data?.themeCustomizations ?? {edges: []}} /> */}
+      <HomeContent />
     </>
     
   );

+ 10 - 4
src/components/common/AddToCartModal/OpenAddToCartModalButton.tsx

@@ -1,5 +1,5 @@
 "use client";
-
+import { FC, ReactNode } from "react";
 import { useAppDispatch } from "@/store/hooks";
 import { openAddToCartDialog } from '@/store/slices/addToCartDialogSlice';
 import { GET_PRODUCT_BY_URL_KEY } from "@/graphql";
@@ -8,8 +8,14 @@ import { SingleProductResponse } from "@/components/catalog/type";
 import { LoadingSpinner } from "@components/common/LoadingSpinner";
 import ShoppingCartIcon from "@components/common/icons/ShoppingCartIcon";
 import { useCustomToast } from "@utils/hooks/useToast";
-
-export function OpenAddToCartModalButton({productUrlKey}: {productUrlKey: string}) {
+interface OpenAddToCartModalButtonProps {
+  productUrlKey: string;
+  icon?: ReactNode;
+}
+export const OpenAddToCartModalButton: FC<OpenAddToCartModalButtonProps> = ({
+  productUrlKey,
+  icon,
+}) => {
     const dispatch = useAppDispatch();
     // const [loading, setLoading] = useState(false);
     const { showToast } = useCustomToast();
@@ -54,7 +60,7 @@ export function OpenAddToCartModalButton({productUrlKey}: {productUrlKey: string
     return (
 
         <button onClick={openDialog} disabled={loading}>
-            { loading ? <LoadingSpinner colorClassName={"text-ly-green"} /> : <ShoppingCartIcon />}
+            { loading ? <LoadingSpinner colorClassName={"text-ly-green"} /> : <ShoppingCartIcon icon={icon} />}
         </button>
         
     );

+ 16 - 5
src/components/common/icons/ShoppingCartIcon.tsx

@@ -1,12 +1,23 @@
+import { ComponentProps, ReactNode } from "react";
 import clsx from "clsx";
 
-export default function ShoppingCartIcon(props: React.ComponentProps<"svg">) {
+interface ShoppingCartIconProps extends ComponentProps<"svg"> {
+  icon?: ReactNode;
+}
+
+export default function ShoppingCartIcon({
+  className,
+  icon,
+}: ShoppingCartIconProps) {
+  // 如果传了 icon → 直接返回自定义图标
+  if (icon) {
+    return <>{icon}</>;
+  }
+
+  // 没传 → 返回默认购物车图标
   return (
     <svg
-      className={clsx(
-        "fill-ptimary h-5 w-5 dark:fill-transparent",
-        props.className,
-      )}
+      className={clsx("fill-primary h-5 w-5 dark:fill-transparent", className)}
       fill="none"
       stroke="currentColor"
       strokeWidth="1.5"

+ 4 - 2
src/components/customer/accountSwiper.tsx

@@ -1,5 +1,6 @@
 "use client";
 import { Swiper, SwiperSlide } from 'swiper/react';
+import Image from 'next/image';
 import 'swiper/css';
 // 模拟商品数据(和图片内容匹配)
 const productList = [
@@ -41,10 +42,11 @@ const AccountSwiper = () => {
           <SwiperSlide key={product.id} className="rounded-lg overflow-hidden">
             <div className="flex flex-col h-full">
               {/* 商品图片(带标签) */}
-              <div className="relative">
-                <img
+              <div className="relative w-full aspect-[3/4]">
+                <Image
                   src={product.imgUrl}
                   alt={product.title}
+                  fill
                   className="w-full h-auto object-cover rounded-t-lg"
                 />
                 {/* 促销标签(有内容才显示) */}