feat: 订单列表

This commit is contained in:
2025-10-16 16:32:59 +08:00
parent a5b7207f44
commit 3c7473f8d1
48 changed files with 1917 additions and 624 deletions

View File

@@ -0,0 +1,140 @@
import type { ProColumns } from '@ant-design/pro-components';
import { Space, Typography } from 'antd';
import type { TradeOrderPageRespVO } from '@/services/trade/order';
const { Text } = Typography;
export const baseOrderColumns: ProColumns<TradeOrderPageRespVO>[] = [
{
title: '商品',
dataIndex: 'id',
width: '20%',
hideInSearch: true,
ellipsis: true,
render: (_, record) =>
// <Space style={{ width: "100%" }}>
// <Image
// src={record.picUrl}
// width={64}
// fallback="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3PTWBSGcbGzM6GCKqlIBRV0dHRJFarQ0eUT8LH4BnRU0NHR0UEFVdIlFRV7TzRksomPY8uykTk/zewQfKw/9znv4yvJynLv4uLiV2dBoDiBf4qP3/ARuCRABEFAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghgg0Aj8i0JO4OzsrPv69Wv+hi2qPHr0qNvf39+iI97soRIh4f3z58/u7du3SXX7Xt7Z2enevHmzfQe+oSN2apSAPj09TSrb+XKI/f379+08+A0cNRE2ANkupk+ACNPvkSPcAAEibACyXUyfABGm3yNHuAECRNgAZLuYPgEirKlHu7u7XdyytGwHAd8jjNyng4OD7vnz51dbPT8/7z58+NB9+/bt6jU/TI+AGWHEnrx48eJ/EsSmHzx40L18+fLyzxF3ZVMjEyDCiEDjMYZZS5wiPXnyZFbJaxMhQIQRGzHvWR7XCyOCXsOmiDAi1HmPMMQjDpbpEiDCiL358eNHurW/5SnWdIBbXiDCiA38/Pnzrce2YyZ4//59F3ePLNMl4PbpiL2J0L979+7yDtHDhw8vtzzvdGnEXdvUigSIsCLAWavHp/+qM0BcXMd/q25n1vF57TYBp0a3mUzilePj4+7k5KSLb6gt6ydAhPUzXnoPR0dHl79WGTNCfBnn1uvSCJdegQhLI1vvCk+fPu2ePXt2tZOYEV6/fn31dz+shwAR1sP1cqvLntbEN9MxA9xcYjsxS1jWR4AIa2Ibzx0tc44fYX/16lV6NDFLXH+YL32jwiACRBiEbf5KcXoTIsQSpzXx4N28Ja4BQoK7rgXiydbHjx/P25TaQAJEGAguWy0+2Q8PD6/Ki4R8EVl+bzBOnZY95fq9rj9zAkTI2SxdidBHqG9+skdw43borCXO/ZcJdraPWdv22uIEiLA4q7nvvCug8WTqzQveOH26fodo7g6uFe/a17W3+nFBAkRYENRdb1vkkz1CH9cPsVy/jrhr27PqMYvENYNlHAIesRiBYwRy0V+8iXP8+/fvX11Mr7L7ECueb/r48eMqm7FuI2BGWDEG8cm+7G3NEOfmdcTQw4h9/55lhm7DekRYKQPZF2ArbXTAyu4kDYB2YxUzwg0gi/41ztHnfQG26HbGel/crVrm7tNY+/1btkOEAZ2M05r4FB7r9GbAIdxaZYrHdOsgJ/wCEQY0J74TmOKnbxxT9n3FgGGWWsVdowHtjt9Nnvf7yQM2aZU/TIAIAxrw6dOnAWtZZcoEnBpNuTuObWMEiLAx1HY0ZQJEmHJ3HNvGCBBhY6jtaMoEiJB0Z29vL6ls58vxPcO8/zfrdo5qvKO+d3Fx8Wu8zf1dW4p/cPzLly/dtv9Ts/EbcvGAHhHyfBIhZ6NSiIBTo0LNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiEC/wGgKKC4YMA4TAAAAABJRU5ErkJggg=="
// />
record.spuName,
// <Paragraph ellipsis>
// <Paragraph ellipsis>{record.spuName}</Paragraph>
// <div>{record.skuName}</div>
// <Space>
// <div>
// <Text type="secondary">数量:</Text>
// <Text>{record.count}</Text>
// </div>
// <div>
// <Text type="secondary">单价:</Text>
// <Text>
// {record.price}/{record.unit}
// </Text>
// </div>
// <div>
// <Text type="secondary">到手价:</Text>
// <Text>
// {record.handedPrice}/{record.unit}
// </Text>
// </div>
// </Space>
// </Paragraph>
// </Space>
},
{
title: '服务',
dataIndex: 'serveAddress',
hideInSearch: true,
render: (_, record) => (
<Space direction="vertical">
<div>
<Text type="secondary"></Text>
<Text>{record.subTime}</Text>
</div>
<div>
<Text type="secondary"></Text>
<Text>{record.serveAddress}</Text>
</div>
<div>
<Text type="secondary"></Text>
<Text>{record.userRemark}</Text>
</div>
</Space>
),
},
{
title: '财务',
dataIndex: 'price',
hideInSearch: true,
render: (_, record) => (
<Space direction="vertical">
<div>
<Text type="secondary"></Text>
<Text>{record.payPrice}</Text>
</div>
<div>
<Text type="secondary"></Text>
<Text>{record.payType}</Text>
</div>
<div>
<Text type="secondary"></Text>
<Text>{record.financeStatus}</Text>
</div>
</Space>
),
},
{
title: '卖家名称',
dataIndex: 'merchantName',
hideInTable: true,
},
{
title: '买家昵称/手机号',
dataIndex: 'userSearch',
hideInTable: true,
},
{
title: '订单类目',
dataIndex: 'orderCategoryId',
valueType: 'select',
hideInTable: true,
},
{
title: '订单来源',
dataIndex: 'orderTerminal',
valueType: 'select',
hideInTable: true,
},
{
title: '财务状态',
dataIndex: 'financeStatus',
valueType: 'select',
hideInTable: true,
},
{
title: '售后状态',
dataIndex: 'afterSaleStatus',
valueType: 'select',
hideInTable: true,
},
{
title: '预约状态',
dataIndex: 'subType',
valueType: 'select',
hideInTable: true,
},
{
title: '创建时间',
dataIndex: 'createTime',
valueType: 'dateRange',
hideInTable: true,
},
{
title: '预约时间',
dataIndex: 'subTime',
valueType: 'dateRange',
hideInTable: true,
},
];

View File

@@ -0,0 +1,90 @@
import { ProCard } from '@ant-design/pro-components';
import { Button, Card, Steps, Typography } from 'antd';
import RcResizeObserver from 'rc-resize-observer';
import React, { useCallback, useState } from 'react';
import styles from './index.module.less';
const { Title, Text } = Typography;
const BasicInfo: React.FC = () => {
const [responsive, setResponsive] = useState(false);
const renderTitle = useCallback(() => {
return <div></div>;
}, []);
return (
<div className={styles['order-info']}>
<Card title="基本信息">
<ProCard
size="small"
title={renderTitle()}
bordered
headerBordered
gutter={8}
className="order-info-card"
>
<ProCard colSpan="200px">
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: 10,
alignItems: 'center',
}}
>
<Title type="danger" level={4} style={{ margin: 0 }}>
</Title>
<span>
<Text type="secondary"></Text>
<Text>430</Text>
</span>
<Button type="primary" block>
</Button>
<Button block></Button>
</div>
</ProCard>
<ProCard layout="center">
<RcResizeObserver
key="resize-observer"
onResize={(offset) => {
setResponsive(offset.width < 460);
}}
>
<Steps
size="small"
progressDot
style={{ width: '100%' }}
current={1}
direction={responsive ? 'vertical' : 'horizontal'}
items={[
{
title: '创建订单',
description: 'This is a description.',
},
{
title: '等待付款',
},
{
title: '等待确定',
},
{
title: '等待服务',
},
{
title: '等待验收',
},
{
title: '完成',
},
]}
/>
</RcResizeObserver>
</ProCard>
</ProCard>
</Card>
</div>
);
};
export default React.memo(BasicInfo);

View File

@@ -0,0 +1,64 @@
import type { ProColumns } from '@ant-design/pro-components';
import { Tag } from 'antd';
import type { DeptVO } from '@/services/system/dept';
export const baseOrderColumns: ProColumns<DeptVO>[] = [
{
title: '商品',
dataIndex: 'name',
width: '33.33%',
render: (_, record) => (
<Tag color={record.status === 1 ? 'green' : 'red'}>{record.name}</Tag>
),
},
{
title: '服务',
dataIndex: 'leaderUserId',
hideInSearch: true,
},
{
title: '财务',
dataIndex: 'sort',
hideInSearch: true,
},
];
const sharedOnCell = (_: DeptVO, index?: number) => {
if (index === 3) {
return { colSpan: 0 };
}
return {};
};
export const surchargeInfoColumns: ProColumns<DeptVO>[] = [
{
title: '服务附加费',
dataIndex: 'name',
width: '33.33%',
render: (_, record, index) => {
if (index === 3) {
return 33333;
}
return (
<Tag color={record.status === 1 ? 'green' : 'red'}>{record.name}</Tag>
);
},
onCell: (_, index) => ({
colSpan: index === 3 ? 4 : 1,
}),
},
{
title: '费用详情',
dataIndex: 'leaderUserId',
onCell: sharedOnCell,
},
{
title: '付款信息',
dataIndex: 'sort',
onCell: sharedOnCell,
},
{
title: '退款信息',
dataIndex: 'leaderUserId1',
onCell: sharedOnCell,
},
];

View File

@@ -0,0 +1,25 @@
.order-info {
:global {
.ant-pro-card-header {
background: rgba(0, 0, 0, 0.02);
}
.ant-pro-card-col {
flex: 1 auto;
overflow: auto;
}
.order-info-card {
.ant-pro-card-col {
flex: 1 auto;
overflow: auto;
display: flex;
align-items: center;
}
}
.order-paragraph {
margin-bottom: 0;
}
.ant-pro-card-body {
padding: 0px;
}
}
}

View File

@@ -0,0 +1,134 @@
import { ProCard } from '@ant-design/pro-components';
import { Button, Card, Image, Space, Tag, Typography } from 'antd';
import React, { useCallback } from 'react';
import styles from './index.module.less';
const { Text, Paragraph } = Typography;
const ProdInfo: React.FC = () => {
const renderTitle = useCallback(() => {
return (
<Space style={{ height: '100%' }} size={16}>
<Paragraph className="order-paragraph"></Paragraph>
<Paragraph className="order-paragraph">
<Text type="secondary"> ID</Text>
<Text copyable>8877777</Text>
</Paragraph>
<Paragraph className="order-paragraph">
<Text type="secondary">SKU ID</Text>
<Text copyable>8877777</Text>
</Paragraph>
</Space>
);
}, []);
return (
<div className={styles['order-info']}>
<Card title="商品信息">
<ProCard
size="small"
title={renderTitle()}
bordered
headerBordered
gutter={8}
extra={<Button size="small"></Button>}
>
<ProCard
layout="default"
colSpan={'50%'}
style={{ borderRight: '1px solid rgba(5,5,5,0.06)' }}
>
<Space>
<Image
width={64}
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
/>
<div>
<Text></Text>
<Paragraph className="order-paragraph">
<Text></Text>
<Text type="secondary"> ,,</Text>
</Paragraph>
<Space wrap size={0} direction="horizontal">
<Paragraph
className="order-paragraph"
style={{ marginRight: 16 }}
>
<Text type="secondary"></Text>
<Text> 1</Text>
</Paragraph>
<Paragraph
className="order-paragraph"
style={{ marginRight: 16 }}
>
<Text type="secondary"></Text>
<Text> ¥100 </Text>
</Paragraph>
<Paragraph
className="order-paragraph"
style={{ marginRight: 16 }}
>
<Text type="secondary"></Text>
<Text> ¥80 </Text>
</Paragraph>
<Paragraph className="order-paragraph">
<Text type="secondary"></Text>
<Text> ¥50 /-</Text>
</Paragraph>
</Space>
</div>
</Space>
<Paragraph style={{ marginTop: 16 }}>
<Tag></Tag>
<Tag></Tag>
<Tag></Tag>
<Tag></Tag>
<Tag></Tag>
</Paragraph>
<Paragraph className="order-paragraph">
<Text type="secondary"></Text>
<Paragraph className="order-paragraph">
</Paragraph>
</Paragraph>
</ProCard>
<ProCard
style={{
borderRight: '1px solid rgba(5,5,5,0.06)',
height: '100%',
}}
>
<Space direction="vertical">
<Text></Text>
<Paragraph className="order-paragraph">
<Text type="secondary"></Text>
<Text>¥500</Text>
</Paragraph>
<Paragraph className="order-paragraph">
<Text type="secondary"></Text>
<Text>¥500</Text>
</Paragraph>
<Paragraph>
<Text type="secondary"></Text>
<Text>¥500</Text>
</Paragraph>
</Space>
</ProCard>
<ProCard>
<Space direction="vertical">
<Text>退</Text>
<Paragraph className="order-paragraph">
<Text type="secondary">退</Text>
<Text>¥500</Text>
</Paragraph>
<Paragraph className="order-paragraph">
<Text type="secondary">退</Text>
<Text>1</Text>
</Paragraph>
</Space>
</ProCard>
</ProCard>
</Card>
</div>
);
};
export default React.memo(ProdInfo);

View File

@@ -0,0 +1,76 @@
import { ProCard } from '@ant-design/pro-components';
import { Card, Space } from 'antd';
import React from 'react';
import EnhancedProTable from '@/components/EnhancedProTable';
import {
type DeptReqVO,
type DeptVO,
getDeptPage,
} from '@/services/system/dept';
import { baseOrderColumns } from '../../../config';
import styles from './index.module.less';
const SelectInfo: React.FC = () => {
const onFetch = async (
params: DeptReqVO & {
pageSize?: number;
current?: number;
},
) => {
const data = await getDeptPage({
...params,
pageNo: params.current,
pageSize: params.pageSize,
});
return {
data: data,
success: true,
total: data.total,
};
};
return (
<div className={styles['order-info']}>
<Card title="可选服务">
<Space direction="vertical" style={{ width: '100%' }} size={16}>
<ProCard split="vertical" bordered>
<ProCard size="small" title="服务" headerBordered>
1111
</ProCard>
<ProCard size="small" title="付款信息" headerBordered>
1111
</ProCard>
<ProCard size="small" title="退款信息" headerBordered>
1111
</ProCard>
</ProCard>
<EnhancedProTable<DeptVO>
columns={baseOrderColumns}
request={onFetch}
showIndex={false}
size="small"
search={false}
showActions={false}
showSelection={false}
bordered
pagination={false}
/>
<ProCard split="vertical" bordered>
<ProCard size="small" title="纪念品" headerBordered>
1111
</ProCard>
<ProCard size="small" title="付款信息" headerBordered>
1111
</ProCard>
<ProCard size="small" title="退款摘要" headerBordered>
1111
</ProCard>
</ProCard>
</Space>
</Card>
</div>
);
};
export default React.memo(SelectInfo);

View File

@@ -0,0 +1,98 @@
import { ProCard } from '@ant-design/pro-components';
import { Button, Card, Image, Space, Typography } from 'antd';
import React from 'react';
import styles from './index.module.less';
const { Text, Paragraph } = Typography;
const ServiceInfo: React.FC = () => {
return (
<div className={styles['order-info']}>
<Card title="服务信息">
<ProCard split="vertical">
<ProCard
title="遗体信息"
extra={<Button size="small"></Button>}
size="small"
colSpan="30%"
headerBordered
>
<Paragraph>
<Text type="secondary"></Text>
<Text></Text>
</Paragraph>
<Paragraph>
<Text type="secondary"></Text>
<Text></Text>
</Paragraph>
<Paragraph>
<Text type="secondary">/</Text>
<Text></Text>
</Paragraph>
<Paragraph>
<Text type="secondary"></Text>
<Text></Text>
</Paragraph>
<Paragraph>
<Text type="secondary"></Text>
<Text></Text>
</Paragraph>
<Paragraph>
<Text type="secondary"></Text>
<Space wrap>
<Image
width={48}
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
/>
<Image
width={48}
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
/>
<Image
width={48}
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
/>
<Image
width={48}
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
/>
<Image
width={48}
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
/>
</Space>
</Paragraph>
</ProCard>
<ProCard
size="small"
title="预约信息"
headerBordered
extra={<Button size="small"></Button>}
>
<Paragraph>
<Text type="secondary"></Text>
<Text></Text>
</Paragraph>
<Paragraph>
<Text type="secondary"></Text>
<Text></Text>
</Paragraph>
<Paragraph>
<Text type="secondary"></Text>
<Text></Text>
</Paragraph>
<Paragraph>
<Text type="secondary"></Text>
<Text></Text>
</Paragraph>
<Paragraph>
<Text type="secondary"></Text>
<Text></Text>
</Paragraph>
</ProCard>
</ProCard>
</Card>
</div>
);
};
export default React.memo(ServiceInfo);

View File

@@ -0,0 +1,49 @@
import { Card } from 'antd';
import React from 'react';
import EnhancedProTable from '@/components/EnhancedProTable';
import {
type DeptReqVO,
type DeptVO,
getDeptPage,
} from '@/services/system/dept';
import { surchargeInfoColumns } from './config';
import styles from './index.module.less';
const SurchargeInfo: React.FC = () => {
const onFetch = async (
params: DeptReqVO & {
pageSize?: number;
current?: number;
},
) => {
const data = await getDeptPage({
...params,
pageNo: params.current,
pageSize: params.pageSize,
});
return {
data: data,
success: true,
total: data.total,
};
};
return (
<div className={styles['order-info']}>
<Card title="服务信息">
<EnhancedProTable<DeptVO>
columns={surchargeInfoColumns}
request={onFetch}
showIndex={false}
size="small"
search={false}
showActions={false}
showSelection={false}
bordered
pagination={false}
/>
</Card>
</div>
);
};
export default React.memo(SurchargeInfo);

View File

@@ -0,0 +1,26 @@
import { Tabs, type TabsProps } from 'antd';
import React from 'react';
import OrderInfo from './order-info';
const DetailCom: React.FC = () => {
const items: TabsProps['items'] = [
{
key: '1',
label: '订单信息 ',
children: <OrderInfo />,
},
{
key: '2',
label: '服务履约',
children: '服务履约',
},
{
key: '3',
label: '商品配送',
children: '商品配送',
},
];
return <Tabs defaultActiveKey="1" items={items} />;
};
export default React.memo(DetailCom);

View File

@@ -0,0 +1,21 @@
import { Space } from 'antd';
import React from 'react';
import BasicInfo from './component/info/basic-info'; //基本信息(通版)
import ProdInfo from './component/info/prod-info'; //商品信息(通版)
import SelectInfo from './component/info/select-info'; //可选服务(殡葬专属字段)
import ServiceInfo from './component/info/service-info';
import SurchargeInfo from './component/info/surcharge-info'; //服务附加费(殡葬专属字段)
const OrderDetail: React.FC = () => {
return (
<Space direction="vertical" size={24} style={{ width: '100%' }}>
<BasicInfo />
<ProdInfo />
<ServiceInfo />
<SelectInfo />
<SurchargeInfo />
</Space>
);
};
export default React.memo(OrderDetail);

View File

@@ -0,0 +1,9 @@
.trade-order {
:global {
.expanded-row-top {
order: -1; /* 在 Flex 布局中将元素移到前面 */
position: relative;
margin: 0 -16px 16px -16px; /* 调整边距以填满整行 */
}
}
}

View File

@@ -0,0 +1,37 @@
import type { TabsProps } from 'antd';
import { Tabs } from 'antd';
import React from 'react';
import styles from './index.module.less';
import OrderListItem from './list';
const onChange = (key: string) => {
console.log(key);
};
const status: string[] = [
'所有订单',
'等待付款',
'等待确定',
'等待服务',
'等待验收',
'等待评价',
'已完成',
'已取消',
'已退款',
];
const OrderList: React.FC = () => {
const items: TabsProps['items'] = status.map((item, index) => ({
key: `${index + 1}`,
label: item,
children: <OrderListItem />,
}));
return (
<div className={`${styles['trade-order']} "page-container" `}>
<Tabs defaultActiveKey="1" items={items} onChange={onChange} />
</div>
);
};
export default OrderList;

View File

@@ -0,0 +1,259 @@
import {
type ActionType,
ProCard,
type ProColumns,
} from '@ant-design/pro-components';
import {
Avatar,
Badge,
Button,
Divider,
Input,
message,
Space,
Statistic,
} from 'antd';
import React, { useCallback, useRef, useState } from 'react';
import ConfigurableDrawerForm, {
type ConfigurableDrawerFormRef,
} from '@/components/DrawerForm';
import EnhancedProTable from '@/components/EnhancedProTable';
import { baseOrderColumns } from './config';
const { Search } = Input;
import { DownOutlined, UpOutlined, UserOutlined } from '@ant-design/icons';
import PopconfirmForm, {
type PopconfirmFormRef,
} from '@/components/PopconfirmForm';
import {
getTradeOrderPage,
type TradeOrderPageRespVO,
type TradeReq,
} from '@/services/trade/order';
import DetailCom from './detail';
const OrderListItem: React.FC = () => {
const tableRef = useRef<ActionType>(null);
const configurableDrawerRef = useRef<ConfigurableDrawerFormRef>(null);
const [modalTitle, setModalTitle] = useState<string>('订单BZ000548787');
const [isShowTotal, setIsShowTotal] = useState<boolean>(false);
const popconfirmFormRef = useRef<PopconfirmFormRef>(null);
const onFetch = async (
params: TradeReq & {
pageSize?: number;
current?: number;
},
) => {
const data = await getTradeOrderPage({
...params,
pageNo: params.current,
pageSize: params.pageSize,
});
return {
data: data.list,
success: true,
total: data.total,
};
};
const handleDetail = useCallback((record: TradeOrderPageRespVO) => {
setModalTitle(`订单:${record.orderNum}`);
configurableDrawerRef.current?.open();
}, []);
const handleOrder = useCallback((id?: number) => {
console.log(id, '取消订单');
// await updateTradeOrder(values.id);
}, []);
const handleUpdate = async (_values: TradeOrderPageRespVO) => {
try {
// await updateTradeOrder(values.id);
return true;
} finally {
message.success('更新成功');
}
// await updateTradeOrder(values.id);
};
const actionColumns: ProColumns<TradeOrderPageRespVO> = {
title: '操作',
dataIndex: 'option',
valueType: 'option',
fixed: 'right',
width: 100,
render: (_text: React.ReactNode, record: TradeOrderPageRespVO) => [
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: 4,
justifyContent: 'center',
}}
key={record.id}
>
<a key="cancel" onClick={() => handleOrder(record.id)}>
</a>
<a key="detail" onClick={() => handleDetail(record)}>
</a>
<PopconfirmForm
ref={popconfirmFormRef}
columns={[
{
title: '备注',
name: 'userRemark',
valueType: 'textarea',
fieldProps: { rows: 4, autoFocus: false },
},
]}
onSubmit={handleUpdate}
>
<a
key="remark"
onClick={() => popconfirmFormRef.current?.open(record)}
>
</a>
</PopconfirmForm>
</div>,
],
};
const onClose = useCallback(() => {
configurableDrawerRef.current?.close();
}, []);
const handleRow = (record: TradeOrderPageRespVO) => {
return {
'data-record': JSON.stringify(record),
className: 'order-row-with-info',
};
};
const components = {
body: {
row: (props: any) => {
const { children, ...restProps } = props;
const record = props['data-record']
? JSON.parse(props['data-record'])
: {};
return (
<>
{record && (
<tr style={{ background: 'rgba(0, 0, 0, 0.06)' }}>
<td
colSpan={columns.length}
style={{
padding: '0px 8px',
borderBottom: '1px solid #f0f0f0',
fontSize: '12px',
color: '#666',
}}
>
<Space>
<span>
<Badge
status="success"
text={record.orderStatus}
size="small"
/>
</span>
<Divider />
<span> {record.orderCategoryName}</span>
<span> {record.createTime}</span>
<span>{record.orderNum}</span>
<span> {record.payType}</span>
<Space>
<Avatar icon={<UserOutlined />} />
{/* <Image src={record.picUrl} width={64} /> */}
</Space>
<Space>
{record.userAvatar ? (
<Avatar src={record.userAvatar} />
) : (
<Avatar icon={<UserOutlined />} />
)}
{record.userNickName || record.userName}
<span>{record.userMobile} </span>
</Space>
</Space>
</td>
</tr>
)}
<tr {...restProps}>{children}</tr>
</>
);
},
},
};
const columns = [...baseOrderColumns, actionColumns];
const handleIsTotal = useCallback(() => {
setIsShowTotal(!isShowTotal);
}, [isShowTotal]);
const handleSearch = useCallback((value: string) => {
console.log('搜索', value);
tableRef.current?.reload();
}, []);
return (
<>
<Space>
<Search
placeholder="商品名称/商品ID/订单号"
enterButton
onSearch={handleSearch}
/>
<Button
icon={isShowTotal ? <DownOutlined /> : <UpOutlined />}
onClick={handleIsTotal}
>
</Button>
</Space>
{isShowTotal && (
<ProCard.Group direction="row" bordered style={{ marginTop: 16 }}>
<ProCard layout="center" style={{ background: '#f5f5f5' }}>
<Statistic title="订单数量" value={79.0} precision={2} />
</ProCard>
<ProCard layout="center" style={{ background: '#f5f5f5' }}>
<Statistic title="实付金额" value={112893.0} precision={2} />
</ProCard>
<ProCard layout="center" style={{ background: '#f5f5f5' }}>
<Statistic title="实收金额" value={93} suffix="/ 100" />
</ProCard>
</ProCard.Group>
)}
<EnhancedProTable<TradeOrderPageRespVO>
ref={tableRef}
columns={columns}
request={onFetch}
headerTitle="销售管理"
showIndex={false}
showSelection={false}
search={{ defaultCollapsed: true }}
onRow={handleRow}
components={components}
/>
<ConfigurableDrawerForm
ref={configurableDrawerRef}
width="80vw"
title={modalTitle}
bodyStyle={{
background: '#f5f5f5',
paddingTop: 8,
}}
footer={<Button onClick={onClose}></Button>}
>
<DetailCom />
</ConfigurableDrawerForm>
</>
);
};
export default OrderListItem;