HomeBestSellers.tsx 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import React from "react";
  2. import { Swiper, SwiperSlide } from "swiper/react";
  3. import { Navigation, Pagination } from "swiper/modules";
  4. import { OpenAddToCartModalButton } from "@/components/common/AddToCartModal/OpenAddToCartModalButton";
  5. // 导入Swiper基础样式
  6. import "swiper/css";
  7. import "swiper/css/navigation";
  8. import {HomeProduct} from "@/types/home/type"
  9. interface HomeBestSellersProps {
  10. bestSellers: HomeProduct[];
  11. }
  12. const HomeBestSellers = ({ bestSellers }: HomeBestSellersProps) => {
  13. if (!bestSellers || bestSellers.length === 0) return null;
  14. // 4. 真实数据按每6个拆分一组,替换原来的模拟拆分逻辑
  15. const chunkSize = 6;
  16. const productBlocks: HomeProduct[][] = [];
  17. for (let i = 0; i < bestSellers.length; i += chunkSize) {
  18. productBlocks.push(bestSellers.slice(i, i + chunkSize));
  19. }
  20. return (
  21. <div className="w-full max-w-[1200px] mx-auto px-4 py-8">
  22. {/* 标题 */}
  23. <h2 className="text-2xl font-bold mb-6">Best Sellers</h2>
  24. {/* Swiper容器 */}
  25. <Swiper
  26. slidesPerView={1}
  27. spaceBetween={20}
  28. modules={[Navigation, Pagination]}
  29. pagination={{
  30. el: ".custom-pagination",
  31. clickable: true,
  32. renderBullet: (index, className) => {
  33. // 所有分页默认底色为 #E5E5E5
  34. return `<span class="${className} w-6 h-[5px] rounded-full mx-1 bg-[#E5E5E5]"></span>`;
  35. },
  36. // 激活时强制覆盖底色,加 !important 提高权重
  37. bulletActiveClass: "!bg-[#333]",
  38. }}
  39. className="relative"
  40. >
  41. {/* 渲染2个滑动块 */}
  42. {productBlocks.map((block, blockIndex) => (
  43. <SwiperSlide key={blockIndex} className="!px-0">
  44. {/* 每个块:6个产品,2列布局 */}
  45. <div className="grid grid-cols-2 gap-4">
  46. {block.map((product) => (
  47. <div key={product.id} className="flex flex-col gap-2">
  48. {/* 产品图片 */}
  49. <img
  50. src={product.image_url}
  51. alt={product.name}
  52. className="w-full h-auto object-cover rounded-sm"
  53. />
  54. {/* 产品标题 */}
  55. <p className="text-sm text-gray-800 truncate">
  56. {product.name}
  57. </p>
  58. {/* 评分 + 评论数 */}
  59. <div className="flex items-center gap-1">
  60. <div className="flex">
  61. {/* 星级图标(简化版,可替换为真实星星图标) */}
  62. {[1, 2, 3, 4, 5].map((star) => (
  63. <svg
  64. key={star}
  65. className="w-4 h-4 text-yellow-400"
  66. fill="currentColor"
  67. viewBox="0 0 20 20"
  68. >
  69. <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" />
  70. </svg>
  71. ))}
  72. </div>
  73. <span className="text-xs text-gray-600">
  74. { product.review_count}
  75. </span>
  76. </div>
  77. {/* 价格 + 购物车图标 */}
  78. <div className="flex items-center justify-between">
  79. <div className="flex items-center gap-1">
  80. <span className="font-semibold">${product.min_price}</span>
  81. <span className="text-xs text-gray-500 line-through">
  82. ${product.price}
  83. </span>
  84. </div>
  85. {/* 购物车图标 */}
  86. <OpenAddToCartModalButton
  87. productUrlKey={
  88. "http://nshop.test/hd-transparent-deep-wave-&-curly-lace-frontal-closure-wig"
  89. }
  90. icon={
  91. <svg
  92. xmlns="http://www.w3.org/2000/svg"
  93. width="32"
  94. height="32"
  95. viewBox="0 0 32 32"
  96. fill="none"
  97. >
  98. <rect
  99. x="0"
  100. y="0"
  101. width="32"
  102. height="32"
  103. rx="8"
  104. fill="#036141"
  105. ></rect>
  106. <path
  107. stroke="rgba(255, 255, 255, 1)"
  108. stroke-width="1.3333333333333333"
  109. stroke-linejoin="round"
  110. stroke-linecap="round"
  111. 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"
  112. ></path>
  113. <ellipse
  114. cx="11.066040515899658"
  115. cy="23.199928283691406"
  116. rx="1.4000248908996582"
  117. ry="1.4000015258789062"
  118. stroke="rgba(255, 255, 255, 1)"
  119. stroke-width="1.3333333333333333"
  120. stroke-linejoin="round"
  121. stroke-linecap="round"
  122. ></ellipse>
  123. <ellipse
  124. cx="23.1998291015625"
  125. cy="23.199928283691406"
  126. rx="1.4000244140625"
  127. ry="1.4000015258789062"
  128. stroke="rgba(255, 255, 255, 1)"
  129. stroke-width="1.3333333333333333"
  130. stroke-linejoin="round"
  131. stroke-linecap="round"
  132. ></ellipse>
  133. <path
  134. stroke="rgba(255, 255, 255, 1)"
  135. stroke-width="1.3333333333333333"
  136. stroke-linejoin="round"
  137. stroke-linecap="round"
  138. d="M15.2656 15.2665L18.999 15.2665"
  139. ></path>
  140. <path
  141. stroke="rgba(255, 255, 255, 1)"
  142. stroke-width="1.3333333333333333"
  143. stroke-linejoin="round"
  144. stroke-linecap="round"
  145. d="M17.1348 17.1332L17.1348 13.3999"
  146. ></path>
  147. </svg>
  148. }
  149. />
  150. </div>
  151. </div>
  152. ))}
  153. </div>
  154. </SwiperSlide>
  155. ))}
  156. {/* 自定义分页器容器(底部小按钮) */}
  157. <div className="custom-pagination flex justify-center mt-4"></div>
  158. </Swiper>
  159. </div>
  160. );
  161. };
  162. export default HomeBestSellers;