提交 6c4a45b6 作者: ZhangLingKun

功能:订单列表/订单详情

上级 6b887a61
// 商城订单-列表
import { InterFunction, InterListFunction } from '@/api/interface';
// 商城订单-列表(新)
export type MallOrderListType = InterListFunction<
{ keyword?: string; statusCode?: number },
OrderDetail
>;
// 订单详情
type OrderDetail = {
companyName: string;
confirmReceiptTime: string;
createTime: string;
deliveryTime: string;
id: number;
kdnExpDTO: {
logisticCode: string;
shipperCode: string;
stateEx: string;
traces: Array<{
acceptStation: string;
acceptTime: string;
action: string;
location: string;
}>;
};
orderNo: string;
orderTotalAmount: number;
orderType: number;
otherAmount: number;
payDTOList: Array<{
checkStatus: number;
createTime: string;
id: number;
payAmount: number;
payImgList: string;
payRemark: string;
payType: number;
refuseReason: string;
uavOrderId: number;
}>;
payTime: string;
payType: string;
remarkStatus: number;
salaryAmount: number;
sellerRemark: string;
shareAmount: number;
skuDTOList: Array<{
createTime: string;
id: number;
mallGoodsId: number;
orderNum: number;
priceStockId: number;
productSpec: string;
skuImage: string;
skuNo: string;
tradeName: string;
uavOrderId: number;
unitPrice: number;
}>;
statusCode: number;
thirdBackUserAccountId: number;
uavOrderExpressDTO: {
id: number;
receive: number;
receiveTime: string;
sendExpCode: string;
sendExpNo: string;
sendTime: string;
takeAddress: string;
takeName: string;
takePhone: string;
takeRegion: string;
uavOrderId: number;
};
updateTime: string;
userAccountId: number;
userAddressId: number;
userRemark: string;
version: number;
contractInfoDTO: {
archiveDate: null;
aremark: null;
atransactionId: null;
bremark: null;
btransactionId: null;
contractNo: string;
contractTitle: string;
createTime: string;
id: number;
orderNo: string;
signStatus: number;
singerTime: null;
unionId: string;
updateTime: null;
};
};
// 订单流程字典
export type UavOrderStatusListType = InterFunction<
{},
{
code: number;
id: number;
nextCode: number;
status: string;
}[]
>;
// 订单详情
export type UavOrderDetailType = InterFunction<
{
id: number;
},
OrderDetail
>;
import {
MallOrderListType,
UavOrderDetailType,
UavOrderStatusListType,
} from '@/api/interface/order';
import request from '@/api/request';
export class OrderAPI {
// 商城订单-列表(新)
static getMallOrderList: MallOrderListType = (data) =>
request.post('/oms/uav-order/listByUid', data);
// 订单流程字典
static uavOrderStatusList: UavOrderStatusListType = (params) =>
request.get('/oms/uav-order/statusList', params);
// 订单详情
static uavOrderDetail: UavOrderDetailType = (params) =>
request.get('/oms/uav-order/detail', { params });
}
......@@ -22,34 +22,55 @@ const BreadcrumbView: React.FC = () => {
const router = useRouter();
// 路由对应列表
const routerList = [
{ name: '云享商城', path: 'mall' },
{ name: '行业服务', path: 'service' },
{
name: '云享商城',
path: 'mall',
children: [{ name: '商品详情', path: 'product' }],
},
{
name: '行业服务',
path: 'service',
children: [{ name: '服务详情', path: 'detail' }],
},
{
name: '购物车',
path: 'cart',
children: [{ name: '提交订单', path: 'submit' }],
},
{
name: '我的订单',
path: 'order',
children: [
{ name: '提交成功', path: 'success' },
{ name: '订单详情', path: 'product' },
],
},
{ name: '设备租赁', path: 'rent' },
{ name: '执照培训', path: 'train' },
{ name: '飞手约单', path: 'flyer' },
{ name: '商品详情', path: 'product' },
{ name: '购物车', path: 'cart' },
{ name: '提交订单', path: 'submit' },
{ name: '服务详情', path: 'detail' },
{ name: '产品订单', path: 'order' },
{ name: '提交成功', path: 'success' },
];
// 转换路由
const getCurrentRouter = () => {
const arr = router?.pathname
?.split('/')
// 首先分割所有的路由
const route = router?.pathname?.split('/').filter((i) => i);
// 找到一级路由的元素
const item = routerList?.find((v) => v.path === route[0]);
// 拍平一级元素的路由地址
const arr = [item, ...(item?.children || [])];
// 转换路由数据
const brr = route
?.map((i, j) => {
const title = arr?.find((n) => n?.path === i)?.name;
const href = `/${router?.pathname
.split('/')
.slice(1, j + 1)
.slice(1, j + 2)
.join('/')}`;
const title = routerList?.find((n) => n.path === i)?.name;
return { title, href };
})
?.filter((i) => i.title); // 过滤掉没有title的项
// 最后一项不跳转
arr[arr.length - 1] = { title: arr[arr.length - 1]?.title, href: '' };
return arr;
brr[brr.length - 1] = { title: brr[brr.length - 1]?.title, href: '' };
return brr;
};
return (
<BreadcrumbWrap>
......
......@@ -7,6 +7,7 @@ import {
import { Button, Dropdown, MenuProps, Modal } from 'antd';
import dayjs from 'dayjs';
import Cookies from 'js-cookie';
import { useRouter } from 'next/router';
import { useDispatch, useSelector } from 'react-redux';
import { CommonAPI } from '@/api';
import { HeaderWrap } from '@/components/layout/header/styled';
......@@ -23,7 +24,7 @@ const HeaderView: React.FC<{
}> = ({ placeholder }) => {
const token = Cookies.get('SHAREFLY-WEB-TOKEN');
// 当前的路由数据
// const router = useRouter();
const router = useRouter();
// store
const dispatch = useDispatch();
// system
......@@ -60,6 +61,10 @@ const HeaderView: React.FC<{
dispatch(setAddress(res));
});
};
// 跳转详情
const handleDetail = async (item: { label: string; value: string }) => {
await router.push(item.value);
};
// 组件挂载
useEffect(() => {
if (!address?.city) {
......@@ -77,12 +82,12 @@ const HeaderView: React.FC<{
}
}, []);
// 顶部Tab列表
const tabList = [
{ label: '个人中心', value: 'pages/mine/index' },
{ label: '购物车', value: 'page-cart/cart-list/index' },
{ label: '我的订单', value: 'pages/order/index' },
{ label: '消息', value: 'pages/message/index' },
{ label: '联系客服', value: 'page-mine/help-center/index' },
const tabList: { label: string; value: string; isQrcode?: boolean }[] = [
{ label: '个人中心', value: 'pages/mine/index', isQrcode: true },
{ label: '购物车', value: 'page-cart/cart-list/index', isQrcode: true },
{ label: '我的订单', value: '/order', isQrcode: false },
{ label: '消息', value: 'pages/message/index', isQrcode: true },
{ label: '联系客服', value: 'page-mine/help-center/index', isQrcode: true },
];
// 右上角按钮
const items: MenuProps['items'] = [
......@@ -148,16 +153,37 @@ const HeaderView: React.FC<{
onClick={() => handleReload()}
></Button>
<div className="location-hello">Hi,欢迎来到云享飞</div>
{router?.pathname !== '/' && (
<Button
type={'link'}
className="text-[#fff]"
title="返回首页"
onClick={() => router.push('/')}
>
首页
</Button>
)}
</div>
<div className="header-nav">
<div className="nav-tab">
{tabList?.map((i, j) => (
<QrcodePopover path={i.value} key={j}>
<Button type={'link'} className="tab-item">
{tabList?.map((i, j) =>
!i.isQrcode ? (
<Button
type={'link'}
className="tab-item"
key={j}
onClick={() => handleDetail(i)}
>
{i.label}
</Button>
</QrcodePopover>
))}
) : (
<QrcodePopover path={i.value} key={j}>
<Button type={'link'} className="tab-item">
{i.label}
</Button>
</QrcodePopover>
),
)}
</div>
{!!userInfo?.id && (
<div className="nav-user">
......
......@@ -36,7 +36,7 @@ export const HeaderWrap = styled.div`
color: #ffffff;
}
.location-hello {
width: 8rem;
//width: 8rem;
}
.location-address {
margin: 0 0.25rem 0 0 !important;
......
import React from 'react';
import styled from 'styled-components';
const TableItem: React.FC<{
td?: React.ReactNode;
tr?: React.ReactNode;
}> = ({ td, tr }) => {
return (
<OrderTableItem>
<div className="item-td">{td}</div>
<div className="item-tr">{tr}</div>
</OrderTableItem>
);
};
export default TableItem;
// 样式
const OrderTableItem = styled.div`
.item-td {
position: absolute;
top: 0;
left: 0;
height: 36px;
width: 100%;
background: rgba(22, 119, 255, 0.1);
line-height: 36px;
}
.item-tr {
//min-height: 50px;
width: 100%;
margin-top: 28px;
}
`;
import React, { useEffect, useState } from 'react';
import { Button, Table } from 'antd';
import { ColumnsType } from 'antd/es/table';
import { useRouter } from 'next/router';
import { InterDataType, InterListType, PaginationProps } from '@/api/interface';
import {
MallOrderListType,
UavOrderStatusListType,
} from '@/api/interface/order';
import { OrderAPI } from '@/api/modules/order';
import TableItem from '@/components/orderTableItem';
// 列表类型
type ListType = InterListType<MallOrderListType>;
// 状态列表
type StatusType = InterDataType<UavOrderStatusListType>;
const MallOrderListTable: React.FC = () => {
// 路由钩子
const router = useRouter();
// 订单状态列表
const [statusList, setStatusList] = useState<StatusType>();
// 订单列表
const [tableData, setTableData] = useState<ListType>();
// 表格分页配置
const [pagination, setPagination] = useState<
PaginationProps & { totalCount: number }
>({
pageSize: 10,
pageNo: 1,
totalCount: 0,
});
// 获取商城订单
const getGoodsOrderList = async () => {
const res = await OrderAPI.getMallOrderList({
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
});
if (res && res.code === '200') {
const { list, pageNo, pageSize, totalCount } = res.result; // 解构
setPagination({
...pagination,
pageNo,
pageSize,
totalCount,
});
setTableData(list || []);
// console.log('商城订单 --->', list);
}
};
// 翻页
const paginationChange = (pageNo: number, pageSize: number) => {
pagination.pageNo = pageNo;
pagination.pageSize = pageSize;
getGoodsOrderList().then();
};
// 获取订单状态字典
const getMallOrderStatusList = async () => {
const res = await OrderAPI.uavOrderStatusList();
if (res && res.code === '200') {
setStatusList(res.result);
}
};
// 获取订单价格
const getOrderPrice = (item: ListType[0]) => {
const total = item?.skuDTOList?.reduce(
(sum, value) => sum + Number(value.orderNum) * Number(value.unitPrice),
0,
);
// 求和
return `¥${total?.toLocaleString()}`;
};
// 跳转商品详情
const handleProduct = async (item: ListType[0]['skuDTOList'][0]) => {
await router.push(`/mall/product/${item?.mallGoodsId}`);
};
// 跳转订单详情
const handleDetail = async (item: ListType[0]) => {
await router.push(`/order/product/${item?.id}`);
};
// 页面挂载
useEffect(() => {
getMallOrderStatusList().then();
getGoodsOrderList().then();
}, []);
const tableColumns: ColumnsType<ListType[0]> = [
{
title: '商品',
dataIndex: 'id',
align: 'center',
width: 200,
render: (_text, record) => (
<TableItem
td={<>订单编号:{record?.orderNo}</>}
tr={
<>
{record.skuDTOList?.map((i, j) => (
<div className="flex items-start pt-2" key={j}>
<img
className="h-12 w-12"
src={i.skuImage}
alt={i.tradeName}
/>
<div className="ml-2 flex flex-col items-start">
<Button
className="h-auto w-48 text-ellipsis p-0 text-left"
type="link"
onClick={() => handleProduct(i)}
>
{i.tradeName}
</Button>
<div>
{Object.entries(JSON.parse(i.productSpec)).map(
(v, index) => (
<span key={index} className="mr-2 last:mr-0">
{v.join(':')}
</span>
),
)}
</div>
</div>
</div>
))}
</>
}
/>
),
},
{
title: '数量',
dataIndex: 'id',
align: 'center',
render: (_text, record) => (
<TableItem
tr={
<>
{record.skuDTOList?.reduce(
(sum, value) => sum + Number(value?.orderNum),
0,
)}
</>
}
/>
),
},
{
title: '价格',
dataIndex: 'id',
align: 'center',
render: (_text, record) => (
<TableItem
td={<>下单时间:{record?.createTime}</>}
tr={<>{getOrderPrice(record)}</>}
/>
),
},
{
title: '订单状态',
dataIndex: 'statusCode',
align: 'center',
width: 150,
render: (text) => (
<TableItem
tr={<>{statusList?.find((i) => i.code === text)?.status || text}</>}
/>
),
},
{
title: '操作',
dataIndex: 'id',
align: 'center',
width: 150,
render: (_text, record) => (
<TableItem
tr={
<>
<Button type={'link'} onClick={() => handleDetail(record)}>
订单详情
</Button>
</>
}
/>
),
},
];
return (
<>
<Table
rowKey={'id'}
bordered={false}
dataSource={tableData}
columns={tableColumns}
pagination={{
total: pagination.totalCount,
pageSize: pagination.pageSize,
current: pagination.pageNo,
showSizeChanger: true,
showQuickJumper: true,
onChange: (page: number, pageSize: number) =>
paginationChange(page, pageSize),
showTotal: (total, range) =>
`当前 ${range[0]}-${range[1]} 条记录 / ${total} 条数据`,
}}
/>
</>
);
};
export default MallOrderListTable;
import React, { useEffect, useState } from 'react';
import { Image, Table } from 'antd';
import { ColumnsType } from 'antd/es/table';
import styled from 'styled-components';
import { InterDataType } from '@/api/interface';
import { UavOrderDetailType } from '@/api/interface/order';
import { OrderAPI } from '@/api/modules/order';
// 接口返回的类型
type DataType = InterDataType<UavOrderDetailType>;
// 参数类型
type PropsType = {
detail: DataType | undefined;
};
const MallOrderSpecView: React.FC<PropsType> = (props) => {
const { detail } = props;
// 表格结构
const columns: ColumnsType<DataType['skuDTOList'][0]> = [
{
title: '商品',
align: 'center',
width: '20%',
render: (_text, record) => (
<div className="mall-sku-item">
<Image src={record.skuImage} className="sku-img" />
<div className="sku-info">
<div className="info-name">{record.tradeName}</div>
<div className="info-spec">
{Object.entries(JSON.parse(record.productSpec)).map(
(v, index) => (
<span key={index}>{v.join(':')}</span>
),
)}
</div>
</div>
</div>
),
},
{
title: '单价(元)',
dataIndex: 'unitPrice',
align: 'center',
render: (text) => `¥${text?.toLocaleString()}`,
},
{
title: '数量',
dataIndex: 'orderNum',
align: 'center',
},
{
title: '订单状态',
align: 'center',
render: () =>
orderStatusList.find((v) => v.value === detail?.statusCode)?.label,
},
{
title: '订单金额(元)',
align: 'center',
render: () => `${detail?.orderTotalAmount}`,
},
];
// 订单状态
const [orderStatusList, setOrderStatusList] = useState<
{ value: number; label: string }[]
>([]);
// 获取订单状态
const getOrderStatus = () => {
OrderAPI.uavOrderStatusList().then(({ result }) => {
if (result) {
const list = result.map((item) => ({
value: item.code,
label: item.status,
}));
setOrderStatusList(list);
}
});
};
useEffect(() => {
getOrderStatus();
}, []);
return (
<DetailInfoWrap>
<div className="detail-title">订单明细</div>
<Table
size="small"
dataSource={detail?.skuDTOList || []}
columns={columns}
rowKey="id"
bordered
pagination={false}
// rowSelection={{ selectedRowKeys, onChange: onSelectChange }}
/>
</DetailInfoWrap>
);
};
export default MallOrderSpecView;
// 样式
const DetailInfoWrap = styled.div`
.detail-title {
font-weight: bold;
margin: 1rem 0 0.5rem 0;
}
.mall-sku-item {
display: flex;
align-items: center;
margin-bottom: 10px;
.sku-img {
width: 48px;
height: 48px;
}
.sku-info {
margin-left: 10px;
line-height: 16px;
text-align: left;
.info-name {
color: #1677ff;
}
.info-spec {
margin-top: 10px;
span:not(:last-child) {
&:after {
content: ';';
}
}
}
}
}
`;
import React from 'react';
import { Table } from 'antd';
const OrderListTable = () => {
return (
<>
<Table
dataSource={[]}
columns={[
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
]}
/>
</>
);
};
export default OrderListTable;
......@@ -4,7 +4,7 @@ import { Menu, MenuProps } from 'antd';
import styled from 'styled-components';
import BreadcrumbView from '@/components/breadcrumb';
import LayoutView from '@/components/layout';
import OrderListTable from '@/pages/order/comp/orderLsit/_index';
import MallOrderListTable from '@/pages/order/comp/mallOrderLsit/_index';
type MenuItem = Required<MenuProps>['items'];
......@@ -32,7 +32,7 @@ const OrderListView = () => {
<LayoutView>
<OrderListWrap>
<BreadcrumbView />
<div className="flex w-full items-start justify-start pt-2">
<div className="flex w-full items-start justify-start pb-8 pt-2">
<div className="select">
<Menu
mode="inline"
......@@ -43,7 +43,7 @@ const OrderListView = () => {
/>
</div>
<div className="list">
<OrderListTable />
<MallOrderListTable />
</div>
</div>
</OrderListWrap>
......
import React, { useEffect, useState } from 'react';
import { Descriptions, DescriptionsProps, Result } from 'antd';
import { useRouter } from 'next/router';
import styled from 'styled-components';
import { InterDataType } from '@/api/interface';
import { UavOrderDetailType } from '@/api/interface/order';
import { OrderAPI } from '@/api/modules/order';
import BreadcrumbView from '@/components/breadcrumb';
import LayoutView from '@/components/layout';
import MallOrderSpecView from '@/pages/order/comp/mallOrderSpec';
// 详情类型
type DetailType = InterDataType<UavOrderDetailType>;
const OrderProductDetail = () => {
// 路由钩子
const router = useRouter();
// 订单详情
const [orderDetail, setOrderDetail] = useState<DetailType>();
// 获取订单详情
const getOrderDetail = async () => {
const res = await OrderAPI.uavOrderDetail({
id: Number(router.query?.id),
});
if (res && res.code === '200') {
// console.log(res.result);
setOrderDetail(res.result);
}
};
useEffect(() => {
if (router.query?.id) getOrderDetail().then();
}, [router.query]);
// 订单信息
const items: DescriptionsProps['items'] = [
{
key: '1',
label: '收货人',
children: (
<>
{orderDetail?.uavOrderExpressDTO?.takeName}{' '}
{orderDetail?.uavOrderExpressDTO?.takePhone}
</>
),
},
{
key: '2',
label: '收货地址',
children: (
<>
{orderDetail?.uavOrderExpressDTO?.takeRegion?.replaceAll('/', ' ')}{' '}
{orderDetail?.uavOrderExpressDTO?.takeAddress}
</>
),
},
{
key: '3',
label: '订单编号',
children: <>{orderDetail?.orderNo}</>,
},
{
key: '4',
label: '下单时间',
children: <>{orderDetail?.createTime}</>,
},
{
key: '5',
label: '付款时间',
children: <>{orderDetail?.createTime}</>,
},
{
key: '6',
label: '订单备注',
children: <>{orderDetail?.userRemark}</>,
},
];
return (
<LayoutView>
<OrderProductWrap>
<BreadcrumbView />
<div className="order-detail">
<div className="detail-content">
<Descriptions title="订单信息" items={items} column={1} />
</div>
<div className="detail-result">
<Result title="订单状态:意向提交成功!请等待专员联系您,根据实际需求报价~" />
</div>
</div>
<MallOrderSpecView detail={orderDetail} />
</OrderProductWrap>
</LayoutView>
);
};
export default OrderProductDetail;
// 样式
const OrderProductWrap = styled.div`
position: relative;
max-width: 1190px;
box-sizing: border-box;
padding: 2rem 0 0 0;
margin: 0 auto;
.order-detail {
position: relative;
width: 100%;
box-sizing: border-box;
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: nowrap;
margin-top: 1rem;
border: 0.02rem solid #e3e3e3;
border-radius: 0.5rem;
overflow: hidden;
.detail-content {
position: relative;
width: 30%;
background: #f7f8fa;
box-sizing: border-box;
padding: 0.5rem 1rem;
}
.detail-result {
position: relative;
width: 70%;
min-height: 14rem;
display: flex;
justify-content: center;
align-items: center;
}
}
`;
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论