提交 b5145004 作者: ZhangLingKun

功能:产品商城列表

上级 eda8e5f1
......@@ -40,7 +40,7 @@ export type AppCategoryInfoType = InterFunction<
icon?: string;
createTime?: string;
updateTime?: null;
subDTOList?: Array<{
subDTOList: Array<{
id: number;
name: string;
description?: string;
......
......@@ -28,6 +28,13 @@ const BreadcrumbView: React.FC = () => {
{ name: '执照培训', path: '/train' },
{ name: '飞手约单', path: '/flyer' },
];
// 转换路由
const getCurrentRouter = () => {
return `/${router?.pathname
?.split('/')
?.filter((i) => i)
?.at(0)}`;
};
return (
<BreadcrumbWrap>
<div className="title">您的位置:</div>
......@@ -39,7 +46,7 @@ const BreadcrumbView: React.FC = () => {
href: '/',
},
{
title: routerList.find((i) => i.path === router?.pathname)?.name,
title: routerList.find((i) => i.path === getCurrentRouter())?.name,
href: router?.pathname,
},
]}
......
import React, { useEffect, useState } from 'react';
import { DownOutlined, UpOutlined } from '@ant-design/icons';
import { useRouter } from 'next/router';
import styled from 'styled-components';
const CategorySelectWrap = styled.div`
......@@ -83,6 +84,8 @@ const CategorySelectView: React.FC<{
color: 'rgba(153,153,153,0.5)',
transform: 'scaleX(1.2)',
};
// 路由钩子
const router = useRouter();
// 当前选择索引
const [currentIndex, setCurrentIndex] = useState<number>(0);
// 二级索引列表
......@@ -109,14 +112,39 @@ const CategorySelectView: React.FC<{
// 清空二级分类,并返回全部二级分类
onSecond?.(list[index]?.children?.map((i) => i?.value) || []);
};
// 选择全部商品
const handleAll = () => {
setSecondIndex([]);
onSecond?.(list[currentIndex]?.children?.map((i) => i?.value) || []);
};
// 组件挂载
useEffect(() => {
if (!list?.length) return;
// 初始化返回一级分类
onMain?.(list[currentIndex]?.value);
// 初始化全部二级分类
onSecond?.(list[currentIndex]?.children?.map((i) => i?.value) || []);
}, [list]);
// 一级分类id
const mainID = Number(router?.query?.main);
// 二级分类id
const secondID = Number(router?.query?.second);
// 如果路由里面有一级分类id,则初始化一级分类
if (mainID) {
const index = list?.findIndex((i) => i?.value === mainID);
setCurrentIndex(index);
onMain?.(list[index]?.value);
if (!secondID) onSecond?.([]);
}
// 如果路由里面有二级分类id,则初始化二级分类
if (secondID) {
const children = list?.find((i) => i?.value === mainID)?.children;
const index = children?.findIndex((i) => i?.value === secondID) || 0;
setSecondIndex([index]);
onSecond?.(children?.[index]?.value ? [children?.[index]?.value] : []);
}
if (!router?.query?.main && !router?.query?.second) {
// 初始化返回一级分类
onMain?.(list[currentIndex]?.value);
// 初始化全部二级分类
onSecond?.(list[currentIndex]?.children?.map((i) => i?.value) || []);
}
}, [list, router]);
return (
<CategorySelectWrap>
<div className="category-select flex-start">
......@@ -137,6 +165,12 @@ const CategorySelectView: React.FC<{
))}
</div>
<div className="category-list flex-start">
<div
className={`list-item ${secondIndex?.length === 0 && 'item-active'}`}
onClick={handleAll}
>
全部商品
</div>
{list[currentIndex]?.children?.map((i, j) => (
<div
className={`list-item ${secondIndex?.includes(j) && 'item-active'}`}
......
......@@ -51,6 +51,7 @@ const ProductItemWrap = styled.div`
font-size: 12px;
font-weight: 400;
color: #999999;
margin-bottom: 0.1rem;
.label {
width: 60%;
}
......@@ -59,6 +60,15 @@ const ProductItemWrap = styled.div`
text-align: right;
}
}
.product-money {
font-size: 16px;
font-weight: 500;
color: #ff1b1b;
.label {
font-size: 12px;
font-weight: bold;
}
}
.product-store {
position: absolute;
left: 0.67rem;
......@@ -95,6 +105,14 @@ type GoodsInfoListType = InterDataType<QueryGoodsInfoByCategorySub>[0];
const ProductItemView: React.FC<{
detail: GoodsInfoListType;
}> = ({ detail }) => {
// 获取最低价格
const getLowerPrice = (item: GoodsInfoListType) => {
const price =
item.priceStock?.reduce((a: any, b: any) =>
a.salePrice < b.salePrice ? a : b,
).salePrice || 0;
return price.toLocaleString();
};
return (
<ProductItemWrap>
<div className="product-image">
......@@ -110,6 +128,16 @@ const ProductItemView: React.FC<{
<div className="label text-ellipsis">{detail?.description}</div>
<div className="text text-ellipsis">成交{detail?.id}</div>
</div>
<div className="product-money">
{detail?.priceShow ? (
<>
<span className="label"></span>
<span className="num">{getLowerPrice(detail)}</span>
</>
) : (
<span className="label">咨询报价</span>
)}
</div>
<div className="product-store flex-start">
<PropertySafetyFilled style={{ color: '#FF552D' }} />
<div className="title text-ellipsis">{detail?.companyName}</div>
......
import React from 'react';
import { Pagination } from 'antd';
import styled from 'styled-components';
// 样式
const ProductListWrap = styled.div`
position: relative;
width: 100%;
.mall-list {
position: relative;
width: 100%;
min-height: 60vh;
flex-wrap: wrap;
align-items: flex-start;
}
.list-empty {
position: relative;
width: 100%;
height: 60vh;
}
.mall-pagination {
position: relative;
width: 100%;
height: 4rem;
box-sizing: border-box;
margin-bottom: 1rem;
}
`;
// 分页数据类型
type PaginationProps = {
pageNo: number;
pageSize: number;
totalCount: number;
};
const ProductListView: React.FC<{
children: React.ReactNode;
pagination: PaginationProps;
onChange: (pageNo: number, pageSize: number) => void;
}> = ({ children, pagination, onChange }) => {
return (
<ProductListWrap>
<div className="mall-list flex-start">{children}</div>
<div className="mall-pagination flex-end">
<Pagination
showSizeChanger
onChange={onChange}
defaultPageSize={pagination.pageSize}
current={pagination.pageNo}
total={pagination.totalCount}
showTotal={(total) => `共 ${total} 条`}
pageSizeOptions={['6', '12', '18', '36', '72']}
/>
</div>
</ProductListWrap>
);
};
export default ProductListView;
......@@ -24,30 +24,42 @@ const TabView01 = () => {
// console.log('获取云享商城分类 --->', tabList);
}
};
// 跳转详情
const handleDetail = () => {
router.push('/mall');
// 跳转一级分类详情
const handleMain = (i: ListType[0]) => {
router.push(`/mall/${i?.id}`).then();
};
// 跳转二级分类详情
const handleSecond = (i: ListType[0], n: ListType[0]['subDTOList'][0]) => {
router.push(`/mall/${i?.id}/${n?.id}`).then();
};
// 组件挂载
useEffect(() => {
getAppCategoryInfo().then();
}, []);
return (
<TabViewWrap
className="animate__animated animate__fast animate__fadeIn"
onClick={() => handleDetail()}
>
<TabViewWrap className="animate__animated animate__fast animate__fadeIn">
{tabList.map((i, j) => (
<div key={j}>
<div className={'tab-little flex-start'}>
{!!i.icon && (
<img src={i.icon} alt={i.name} className="title-image" />
)}
<div className="title-name">{i.name}</div>
<Button
type={'link'}
className="title-name"
onClick={() => handleMain(i)}
>
{i.name}
</Button>
</div>
<div className="tab-list flex-start">
{i.subDTOList?.map((n, m) => (
<Button type={'link'} key={m} className="list-item">
<Button
type={'link'}
key={m}
className="list-item"
onClick={() => handleSecond(i, n)}
>
{n.name}
</Button>
))}
......@@ -80,6 +92,7 @@ const TabViewWrap = styled.div`
font-size: 0.75rem;
font-weight: 550;
color: #333333;
padding: 0;
}
}
.tab-list {
......
import React from 'react';
import { InterDataType } from '@/api/interface';
import { GetAppCategoryInfo } from '@/api/interface/mall';
import { MallAPI } from '@/api/modules/mall';
import MallView from '@/pages/mall/view';
// 分类列表类型
type CategoryListType = InterDataType<GetAppCategoryInfo>;
// 每次加载页面都会执行
export async function getServerSideProps() {
// 分类数据
let categoryList: CategoryListType = [];
// 获取各个目录及分类信息
const getAppCategoryInfo = async () => {
const res = await MallAPI.getAppCategoryInfo({
type: 4,
});
if (res && res.code === '200') {
categoryList = res?.result || [];
}
};
// 依次获取接口数据
await (async () => {
await getAppCategoryInfo();
})();
return { props: { categoryList } };
}
const MallSecondView: React.FC<{
categoryList: CategoryListType;
}> = (props) => MallView(props);
export default MallSecondView;
import React from 'react';
import { InterDataType } from '@/api/interface';
import { GetAppCategoryInfo } from '@/api/interface/mall';
import { MallAPI } from '@/api/modules/mall';
import MallView from '@/pages/mall/view';
// 分类列表类型
type CategoryListType = InterDataType<GetAppCategoryInfo>;
// 每次加载页面都会执行
export async function getServerSideProps() {
// 分类数据
let categoryList: CategoryListType = [];
// 获取各个目录及分类信息
const getAppCategoryInfo = async () => {
const res = await MallAPI.getAppCategoryInfo({
type: 4,
});
if (res && res.code === '200') {
categoryList = res?.result || [];
}
};
// 依次获取接口数据
await (async () => {
await getAppCategoryInfo();
})();
return { props: { categoryList } };
}
const MallMainView: React.FC<{
categoryList: CategoryListType;
}> = (props) => MallView(props);
export default MallMainView;
import React, { useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import React from 'react';
import { InterDataType } from '@/api/interface';
import {
GetAppCategoryInfo,
QueryGoodsInfoByCategorySub,
} from '@/api/interface/mall';
import { GetAppCategoryInfo } from '@/api/interface/mall';
import { MallAPI } from '@/api/modules/mall';
import BreadcrumbView from '@/components/breadcrumb';
import CategorySelectView, { CategoryType } from '@/components/categorySelect';
import LayoutView from '@/components/layout';
import ProductItemView from '@/components/productItem';
import { MallWrap } from '@/pages/mall/styled';
import MallView from '@/pages/mall/view';
// 分类列表类型
type CategoryListType = InterDataType<GetAppCategoryInfo>;
// 商品列表类型
type GoodsInfoListType = InterDataType<QueryGoodsInfoByCategorySub>;
// 每次加载页面都会执行
export async function getServerSideProps() {
......@@ -30,74 +20,14 @@ export async function getServerSideProps() {
categoryList = res?.result || [];
}
};
// fetch测试
// const getAppCategoryInfo = async () => {
// const res = await fetch(
// 'https://test.iuav.com/pms/category/appCategoryInfo?type=4',
// );
// console.log('fetch测试 res --->', await res?.json());
// };
// 依次获取接口数据
await (async () => {
await getAppCategoryInfo();
})();
return { props: { categoryList } };
}
const MallView: React.FC<{
const MallPageView: React.FC<{
categoryList: CategoryListType;
}> = (props) => {
// 路由钩子
const router = useRouter();
// 分类列表
const [categoryList, setCategoryList] = useState<CategoryType>([]);
// 商品列表
const [goodsInfoList, setGoodsInfoList] = useState<GoodsInfoListType>([]);
// 转换分类列表
const getCategoryList = () => {
setCategoryList(
props?.categoryList?.map((i) => ({
value: i.id,
label: i.name,
children: i.subDTOList?.map((n) => ({ value: n.id, label: n.name })),
})),
);
};
// 获取商品列表
const getGoodsInfoByCategorySub = async (list: number[]) => {
const res = await MallAPI.queryGoodsInfoByCategorySub(list);
if (res && res.code === '200') {
setGoodsInfoList(res.result || []);
console.log('商品列表 --->', res.result);
}
};
// 组件挂载
useEffect(() => {
if (!props) return;
getCategoryList();
// console.log('执行到此处12312 --->', props);
}, [props]);
// 路由变化
useEffect(() => {
console.log('路由变化 --->', router);
}, [router]);
return (
<>
<LayoutView placeholder={true}>
<MallWrap>
<BreadcrumbView />
<CategorySelectView
list={categoryList}
onSecond={getGoodsInfoByCategorySub}
/>
<div className="mall-list flex-start">
{goodsInfoList?.map((i, j) => (
<ProductItemView key={j} detail={i} />
))}
</div>
</MallWrap>
</LayoutView>
</>
);
};
}> = (props) => MallView(props);
export default MallView;
export default MallPageView;
......@@ -10,9 +10,4 @@ export const MallWrap = styled.div`
box-sizing: border-box;
padding: 2rem 0 0 0;
margin: 0 auto;
.mall-list {
position: relative;
width: 100%;
flex-wrap: wrap;
}
`;
import React, { useEffect, useState } from 'react';
import { Empty } from 'antd';
import { InterDataType } from '@/api/interface';
import {
GetAppCategoryInfo,
QueryGoodsInfoByCategorySub,
} from '@/api/interface/mall';
import { MallAPI } from '@/api/modules/mall';
import BreadcrumbView from '@/components/breadcrumb';
import CategorySelectView, { CategoryType } from '@/components/categorySelect';
import LayoutView from '@/components/layout';
import ProductItemView from '@/components/productItem';
import ProductListView from '@/components/productList';
import { MallWrap } from '@/pages/mall/styled';
// 分类列表类型
type CategoryListType = InterDataType<GetAppCategoryInfo>;
// 商品列表类型
type GoodsInfoListType = InterDataType<QueryGoodsInfoByCategorySub>;
const MallView: React.FC<{
categoryList: CategoryListType;
}> = (props) => {
// 分类列表
const [categoryList, setCategoryList] = useState<CategoryType>([]);
// 商品列表
const [goodsInfoList, setGoodsInfoList] = useState<GoodsInfoListType>([]);
// 分页数据
const [pagination, setPagination] = useState({
pageNo: 1,
pageSize: 18,
totalCount: 0,
});
// 转换分类列表
const getCategoryList = () => {
setCategoryList(
props?.categoryList?.map((i) => ({
value: i.id,
label: i.name,
children: i.subDTOList?.map((n) => ({ value: n.id, label: n.name })),
})),
);
};
// 获取商品列表
const getGoodsInfoByCategorySub = async (list: number[]) => {
const res = await MallAPI.queryGoodsInfoByCategorySub(list);
if (res && res.code === '200') {
setGoodsInfoList(res.result || []);
setPagination({ ...pagination, totalCount: res.result?.length || 0 });
// console.log('商品列表 --->', res.result);
}
};
// 根据分页数据返回商品列表
const getGoodsInfoListByPage = () => {
const { pageNo, pageSize } = pagination;
return goodsInfoList?.slice((pageNo - 1) * pageSize, pageNo * pageSize);
};
// 翻页回调
const handlePageChange = (pageNo: number, pageSize: number) => {
setPagination({ ...pagination, pageNo, pageSize });
};
// 组件挂载
useEffect(() => {
if (!props) return;
getCategoryList();
// console.log('执行到此处12312 --->', props);
}, [props]);
return (
<>
<LayoutView placeholder={true}>
<MallWrap>
{/* 面包屑 */}
<BreadcrumbView />
{/* 类型筛选 */}
<CategorySelectView
list={categoryList}
onSecond={getGoodsInfoByCategorySub}
/>
{/* 产品列表 */}
<ProductListView pagination={pagination} onChange={handlePageChange}>
{getGoodsInfoListByPage()?.length ? (
getGoodsInfoListByPage()?.map((i, j) => (
<ProductItemView key={j} detail={i} />
))
) : (
<div className="list-empty flex-center">
<Empty />
</div>
)}
</ProductListView>
</MallWrap>
</LayoutView>
</>
);
};
export default MallView;
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论