提交 f0bcd73c 作者: ZhangLingKun

功能:商品详情半成品

上级 140b3d6b
流水线 #7445 已通过 于阶段
in 5 分 18 秒
......@@ -38,7 +38,8 @@
"react-redux": "^8.1.3",
"redux": "^4.2.1",
"redux-persist": "^6.0.0",
"styled-components": "^6.1.0"
"styled-components": "^6.1.0",
"swiper": "^11.0.5"
},
"devDependencies": {
"@types/big.js": "^6.2.0",
......
......@@ -71,6 +71,9 @@ dependencies:
styled-components:
specifier: ^6.1.0
version: registry.npmmirror.com/styled-components@6.1.0(react-dom@18.2.0)(react@18.2.0)
swiper:
specifier: ^11.0.5
version: registry.npmmirror.com/swiper@11.0.5
devDependencies:
'@types/big.js':
......@@ -5062,6 +5065,13 @@ packages:
engines: {node: '>= 0.4'}
dev: true
registry.npmmirror.com/swiper@11.0.5:
resolution: {integrity: sha512-rhCwupqSyRnWrtNzWzemnBLMoyYuoDgGgspAm/8iBD3jCvAWycPLH4Z3TB0O5520DHLzMx94yUMH/B9Efpa48w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/swiper/-/swiper-11.0.5.tgz}
name: swiper
version: 11.0.5
engines: {node: '>= 4.7.0'}
dev: false
registry.npmmirror.com/synckit@0.8.5:
resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/synckit/-/synckit-0.8.5.tgz}
name: synckit
......
import React, { useEffect, useState } from 'react';
import { InputNumber } from 'antd';
import Big from 'big.js';
import styled from 'styled-components';
import { InterDataType } from '@/api/interface';
import { AppMallGoodsDetails } from '@/api/interface/mall';
import ProductSwiperView from '@/components/product-swiper';
// 商品详情类型
type DetailType = InterDataType<AppMallGoodsDetails>;
const ProductHeadView: React.FC<{ detail: DetailType }> = ({ detail }) => {
// 商品的购买数量
const [productNum, setProductNum] = useState<number>(1);
// 获取最低价格
const getLowerPrice = (item: DetailType) => {
const price =
Math.min(...(item.priceStock?.map((i) => i.salePrice) || [0])) || 0;
const money = Big(price).mul(Big(productNum)).toNumber().toLocaleString();
return money.endsWith('.00') ? money : `${money}.00`;
};
useEffect(() => {
console.log('detail --->', detail);
}, []);
return (
<ProductHeadWrap>
<div className="product-swiper">
<ProductSwiperView list={detail?.resourcesList} />
</div>
<div className="product-content">
<div className="content-title">{detail?.tradeName}</div>
<div className="content-desc">{detail?.description}</div>
<div className="content-price flex-start">
<div className="price-label">价格</div>
<div className="price-money">
{detail?.priceShow ? (
<>
<span className="label"></span>
<span className="num">{getLowerPrice(detail)}</span>
</>
) : (
<span className="label">咨询报价</span>
)}
</div>
</div>
<div className="content-item flex-start">
<div className="item-label">送至</div>
<div className="item-content">
{detail?.priceStock?.length || 0}种可选
</div>
</div>
<div className="content-item flex-start">
<div className="item-label">规格</div>
<div className="item-content">
{detail?.priceStock?.length || 0}种可选
</div>
</div>
<div className="content-item flex-start">
<div className="item-label">数量</div>
<div className="item-content">
<InputNumber
min={1}
max={9999}
precision={0}
value={productNum}
onChange={(e) => setProductNum(e || 1)}
/>
</div>
</div>
<div className="content-action flex-start select-none">
<div className="action-item">加入购物车</div>
<div className="action-item">提交意向</div>
<div className="action-item">确认购买</div>
</div>
</div>
</ProductHeadWrap>
);
};
export default ProductHeadView;
// 样式
const ProductHeadWrap = styled.div`
position: relative;
width: calc((100% - 0.83rem) / 10 * 7.5);
height: 28rem;
background: #ffffff;
border: 0.04rem solid #e3e3e3;
box-sizing: border-box;
margin-right: 0.83rem;
display: flex;
align-items: center;
justify-content: flex-start;
padding: 1rem;
.product-swiper {
position: relative;
width: 22rem;
height: 100%;
box-sizing: border-box;
}
.product-content {
position: relative;
width: calc(100% - 22rem);
box-sizing: border-box;
padding-left: 1rem;
//background: lightblue;
.content-title {
width: 100%;
font-size: 24px;
font-weight: 500;
color: #212121;
margin-bottom: 0.71rem;
// 双行省略
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
}
.content-desc {
font-weight: 400;
color: #666666;
margin-bottom: 0.71rem;
}
.content-price {
position: relative;
width: 100%;
background: #f3f3f3;
box-sizing: border-box;
padding: 0.8rem;
margin-bottom: 1rem;
.price-label {
width: 2rem;
color: #999999;
text-align: justify;
text-align-last: justify;
margin-right: 1rem;
}
.price-money {
font-size: 24px;
line-height: 1;
color: #ff6700;
.label {
font-size: 18px;
}
}
}
.content-item {
margin-bottom: 1rem;
padding: 0 0.8rem;
.item-label {
width: 2rem;
color: #999999;
text-align: justify;
text-align-last: justify;
margin-right: 1rem;
}
}
.content-action {
position: relative;
width: 100%;
margin-top: 2rem;
.action-item {
width: 8.63rem;
height: 2.33rem;
background: #fff0e5;
border: 0.04rem solid #ff552d;
text-align: center;
line-height: 2.33rem;
font-size: 13px;
font-weight: 400;
color: #ff552d;
cursor: pointer;
&:hover,
&:active {
filter: brightness(0.95);
}
}
.action-item:not(:last-child) {
margin-right: 0.8rem;
}
.action-item:last-child {
background: #ff552d;
color: #fff;
}
}
}
`;
import React from 'react';
import styled from 'styled-components';
import { InterDataType } from '@/api/interface';
import { AppMallGoodsDetails } from '@/api/interface/mall';
// 商品详情类型
type DetailType = InterDataType<AppMallGoodsDetails>;
// 样式
const ProductStoreWrap = styled.div`
position: relative;
width: calc((100% - 0.83rem) / 10 * 2.5);
height: 28rem;
background: #ffffff;
border: 0.04rem solid #e3e3e3;
box-sizing: border-box;
`;
const ProductStoreView: React.FC<{ detail: DetailType }> = ({ detail }) => {
return <ProductStoreWrap>ProductStoreView</ProductStoreWrap>;
};
export default ProductStoreView;
import React, { useState } from 'react';
import styled from 'styled-components';
import {
FreeMode,
Navigation,
Thumbs,
Autoplay,
Mousewheel,
} from 'swiper/modules';
import { Swiper, SwiperSlide } from 'swiper/react';
import 'swiper/css';
import 'swiper/css/free-mode';
import 'swiper/css/navigation';
import 'swiper/css/thumbs';
const ProductSwiperWrap = styled.div`
position: relative;
width: 200%;
height: 200%;
box-sizing: border-box;
transform: scale(0.5) translateX(-50%) translateY(-50%);
.swiper-main {
position: relative;
width: 100%;
height: calc(100% - 9rem);
margin-bottom: 0.5rem;
.swiper-slide {
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
}
.swiper-second {
position: relative;
width: 100%;
height: 9rem;
.swiper-slide {
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
}
`;
const ProductSwiperView: React.FC<{
list: { id: number; url: string }[];
}> = ({ list }) => {
const [thumbsSwiper, setThumbsSwiper] = useState(null);
// 图片列表
const SwiperListArr = list?.map((i, j) => (
<SwiperSlide key={j}>
<img src={i.url} alt={'图片'} />
</SwiperSlide>
));
return (
<ProductSwiperWrap>
<Swiper
className="swiper-main"
style={
{
'--swiper-navigation-color': '#fff',
'--swiper-pagination-color': '#fff',
} as any
}
loop={true}
// spaceBetween={10}
navigation={true}
thumbs={{ swiper: thumbsSwiper }}
modules={[FreeMode, Navigation, Thumbs, Autoplay, Mousewheel]}
autoplay={{
delay: 5000,
}}
mousewheel={true}
grabCursor={true}
>
{SwiperListArr}
</Swiper>
<Swiper
className="swiper-second"
// @ts-ignore
onSwiper={setThumbsSwiper}
loop={true}
spaceBetween={10}
slidesPerView={5}
freeMode={true}
watchSlidesProgress={true}
modules={[FreeMode, Navigation, Thumbs]}
grabCursor={true}
>
{SwiperListArr}
</Swiper>
</ProductSwiperWrap>
);
};
export default ProductSwiperView;
......@@ -8,6 +8,8 @@ import {
import { MallAPI } from '@/api/modules/mall';
import BreadcrumbView from '@/components/breadcrumb';
import LayoutView from '@/components/layout';
import ProductHeadView from '@/components/product-comp/product-head';
import ProductStoreView from '@/components/product-comp/product-store';
import { ProductWrap } from '@/pages/mall/product/styled';
// 商品详情类型
......@@ -59,7 +61,10 @@ const MallProductView: React.FC<{
<ProductWrap>
{/* 面包屑 */}
<BreadcrumbView />
<div className="product-wrap flex-start"></div>
<div className="flex-start">
<ProductHeadView detail={productDetail} />
<ProductStoreView detail={productDetail} />
</div>
{productDetail?.tradeName}
</ProductWrap>
</LayoutView>
......
......@@ -158,6 +158,13 @@ a {
text-overflow: ellipsis;
white-space: nowrap;
}
.select-none{
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
.scroll-view::-webkit-scrollbar {
background-color: transparent;
-webkit-border-radius: 2em;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论