feat: 基本信息

This commit is contained in:
2025-10-17 17:43:42 +08:00
parent 3c7473f8d1
commit 263a7d3e20
20 changed files with 1745 additions and 492 deletions

View File

@@ -1,87 +1,192 @@
import { ProCard } from '@ant-design/pro-components';
import { Button, Card, Steps, Typography } from 'antd';
import { Avatar, Button, Card, Empty, Space, Steps, Typography } from 'antd';
import dayjs from 'dayjs';
import RcResizeObserver from 'rc-resize-observer';
import React, { useCallback, useState } from 'react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { OrderStatus, OrderStatusLabels } from '@/constants/trade';
import type { TradeOrderBaseInfo } from '@/services/trade/order';
import { type BtnType, renderBaseInfoOrder } from './config';
import styles from './index.module.less';
const { Title, Text } = Typography;
const BasicInfo: React.FC = () => {
const BasicInfo: React.FC<{ data?: TradeOrderBaseInfo; id: number }> = (
props,
) => {
const { data } = props;
const [orderStatus, setOrderStatus] = useState<number>(0);
useEffect(() => {
if (data) {
setOrderStatus(Number(data.orderStatus));
}
}, [data]);
const [responsive, setResponsive] = useState(false);
const renderTitle = useCallback(() => {
return <div></div>;
}, []);
return (
<Space size={16}>
<div>
<Text type="secondary"></Text>
<Text copyable>{data?.orderNo}</Text>
</div>
<div>
<Text type="secondary"></Text>
<Text>{data?.orderCategoryId}</Text>
<Text>ID:</Text>
<Text copyable>{data?.id}</Text>
</div>
<div>
<Text type="secondary"></Text>
<Text>{data?.orderCategoryName}</Text>
</div>
<div>
<Avatar size={20} src={data?.userAvatar} />
<Text>{data?.userInfo}</Text>
</div>
</Space>
);
}, [data]);
const handleClick = useCallback(
(type: BtnType) => {
if (type === 'confirm') {
//还未完成的按钮事件
console.log(data?.orderStatus);
} else if (type === 'sales') {
//新建售后事件
}
console.log(type);
},
[data],
);
const renderOrderStatus = useMemo(() => {
if (data) return renderBaseInfoOrder(data, handleClick);
}, [data]);
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>
{data ? (
<ProCard
size="small"
title={renderTitle()}
bordered
headerBordered
gutter={8}
className="order-info-card"
>
<ProCard colSpan="300px">
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: 10,
alignItems: 'center',
}}
>
{renderOrderStatus}
</div>
</ProCard>
<ProCard layout="center">
<RcResizeObserver
key="resize-observer"
onResize={(offset) => {
setResponsive(offset.width < 460);
}}
>
<Steps
size="small"
progressDot
style={{ width: '100%' }}
current={orderStatus / 10}
direction={responsive ? 'vertical' : 'horizontal'}
items={[
{
title: `创建订单`,
description: (
<Space direction="vertical" size={0}>
{dayjs(data.createTime).format('YYYY-MM-DD')}
{dayjs(data.createTime).format('HH:mm:ss')}
</Space>
),
},
{
title: `${
OrderStatusLabels[OrderStatus.PendingPayment].label
} ${
orderStatus > OrderStatus.PendingPayment
? '(已付款)'
: ''
}`,
description: (
<Space direction="vertical" size={0}>
{dayjs(data.createTime).format('YYYY-MM-DD')}
{dayjs(data.createTime).format('HH:mm:ss')}
</Space>
),
},
{
title: `${
OrderStatusLabels[OrderStatus.PendingConfirmation].label
} ${
orderStatus > OrderStatus.PendingConfirmation
? '(已确定)'
: ''
}`,
description: (
<Space direction="vertical" size={0}>
{/* {dayjs(data.finishTime).format("YYYY-MM-DD")}
{dayjs(data.finishTime).format("HH:mm:ss")} */}
</Space>
),
},
{
title: `${
OrderStatusLabels[OrderStatus.PendingService].label
} ${
orderStatus > OrderStatus.PendingService
? '(已开始)'
: ''
}`,
description: (
<Space direction="vertical" size={0}>
{/* {dayjs(data.finishTime).format("YYYY-MM-DD")}
{dayjs(data.finishTime).format("HH:mm:ss")} */}
</Space>
),
},
{
title: `${
OrderStatusLabels[OrderStatus.PendingAcceptance].label
} ${
orderStatus > OrderStatus.PendingAcceptance
? '(已验收)'
: ''
}`,
description: (
<Space direction="vertical" size={0}>
{/* {dayjs(data.finishTime).format("YYYY-MM-DD")}
{dayjs(data.finishTime).format("HH:mm:ss")} */}
</Space>
),
},
{
title: '完成',
description: (
<Space direction="vertical" size={0}>
{dayjs(data.finishTime).format('YYYY-MM-DD')}
{dayjs(data.finishTime).format('HH:mm:ss')}
</Space>
),
},
]}
/>
</RcResizeObserver>
</ProCard>
</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>
) : (
<Empty />
)}
</Card>
</div>
);

View File

@@ -1,6 +1,17 @@
import type { ProColumns } from '@ant-design/pro-components';
import { Tag } from 'antd';
import { Button, Tag, Typography } from 'antd';
import type { BaseType } from 'antd/es/typography/Base';
import dayjs from 'dayjs';
import { dateFormat } from '@/constants';
import {
OrderBtnLableMap,
OrderStatus,
OrderStatusLabels,
} from '@/constants/trade';
import type { DeptVO } from '@/services/system/dept';
import type { TradeOrderBaseInfo } from '@/services/trade/order';
const { Title, Text, Paragraph } = Typography;
export const baseOrderColumns: ProColumns<DeptVO>[] = [
{
@@ -62,3 +73,100 @@ export const surchargeInfoColumns: ProColumns<DeptVO>[] = [
onCell: sharedOnCell,
},
];
export type BtnType = 'sales' | 'confirm';
export const renderBaseInfoOrder = (
data: TradeOrderBaseInfo,
handleClick: (type: BtnType) => void,
): React.ReactNode => {
const orderStatusObj =
OrderStatusLabels[data.orderStatus as unknown as OrderStatus];
console.log(orderStatusObj, data);
return (
<>
<Title
type={(orderStatusObj.color as BaseType) || ''}
level={4}
style={{ margin: 0 }}
>
{data?.orderStatus && orderStatusObj.label}
</Title>
<span>
<Text type="secondary"></Text>
<Text>430</Text>
</span>
{data.orderStatus &&
Number(data.orderStatus) === OrderStatus.Refunded && (
<Paragraph>
<Text type="secondary">退</Text>
<Text>退</Text>
</Paragraph>
)}
{data.orderStatus &&
(Number(data.orderStatus) === OrderStatus.Completed ||
Number(data.orderStatus) === OrderStatus.Refunded) && (
<Paragraph>
<Text type="secondary"></Text>
<Text>{dayjs(data.finishTime).format(dateFormat)}</Text>
</Paragraph>
)}
{data.orderStatus &&
Number(data.orderStatus) === OrderStatus.Completed && (
<Paragraph>
<Text type="secondary"></Text>
<Tag
color={
data.propertyStatus && Number(data.propertyStatus) === 1
? 'default'
: 'gay'
}
>
</Tag>
<Tag
color={
data.propertyStatus && Number(data.propertyStatus) === 1
? 'gay'
: 'default'
}
>
</Tag>
<Text>{data.propertyTime}</Text>
</Paragraph>
)}
{/* 取消 */}
{data.orderStatus &&
Number(data.orderStatus) === OrderStatus.Cancelled && (
<>
<Paragraph>
<Text type="secondary"></Text>
<Text></Text>
</Paragraph>
<Paragraph>
<Text type="secondary"></Text>
<Text>{data.cancelReason}</Text>
</Paragraph>
<Paragraph>
<Text type="secondary"></Text>
<Text>{data?.merchantRemark}</Text>
</Paragraph>
</>
)}
{data.orderStatus &&
Number(data.orderStatus) <= OrderStatus.PendingAcceptance && (
<Button type="primary" block onClick={() => handleClick('confirm')}>
{OrderBtnLableMap[data.orderStatus as unknown as OrderStatus]}
</Button>
)}
{data.orderStatus &&
Number(data.orderStatus) <= OrderStatus.Completed && (
<Button block onClick={() => handleClick('sales')}>
</Button>
)}
</>
);
};

View File

@@ -21,5 +21,14 @@
.ant-pro-card-body {
padding: 0px;
}
.ant-steps-item-icon {
height: 8px !important;
line-height: 8px !important;
}
.ant-steps-item-active {
.ant-steps-icon-dot {
height: 10px !important;
}
}
}
}

View File

@@ -1,10 +1,13 @@
import { ProCard } from '@ant-design/pro-components';
import { Button, Card, Image, Space, Tag, Typography } from 'antd';
import React, { useCallback } from 'react';
import type { TradeProductInfo } from '@/services/trade/order';
import styles from './index.module.less';
const { Text, Paragraph } = Typography;
const ProdInfo: React.FC = () => {
const ProdInfo: React.FC<{ data?: TradeProductInfo; id: number }> = (props) => {
const { data = {}, id } = props;
const renderTitle = useCallback(() => {
return (
<Space style={{ height: '100%' }} size={16}>

View File

@@ -7,10 +7,14 @@ import {
type DeptVO,
getDeptPage,
} from '@/services/system/dept';
import type { TradeExtendCostInfo } from '@/services/trade/order';
import { baseOrderColumns } from '../../../config';
import styles from './index.module.less';
const SelectInfo: React.FC = () => {
const SelectInfo: React.FC<{ data?: TradeExtendCostInfo; id: number }> = (
props,
) => {
const { data = {}, id } = props;
const onFetch = async (
params: DeptReqVO & {
pageSize?: number;

View File

@@ -1,10 +1,14 @@
import { ProCard } from '@ant-design/pro-components';
import { Button, Card, Image, Space, Typography } from 'antd';
import React from 'react';
import type { TradeServeInfo } from '@/services/trade/order';
import styles from './index.module.less';
const { Text, Paragraph } = Typography;
const ServiceInfo: React.FC = () => {
const ServiceInfo: React.FC<{ data?: TradeServeInfo; id: number }> = (
props,
) => {
const { data = {}, id } = props;
return (
<div className={styles['order-info']}>
<Card title="服务信息">

View File

@@ -6,10 +6,14 @@ import {
type DeptVO,
getDeptPage,
} from '@/services/system/dept';
import type { TradeExtendServeInfo } from '@/services/trade/order';
import { surchargeInfoColumns } from './config';
import styles from './index.module.less';
const SurchargeInfo: React.FC = () => {
const SurchargeInfo: React.FC<{ data?: TradeExtendServeInfo; id: number }> = (
props,
) => {
const { data, id } = props;
const onFetch = async (
params: DeptReqVO & {
pageSize?: number;

View File

@@ -1,13 +1,14 @@
import { Tabs, type TabsProps } from 'antd';
import React from 'react';
import type { TradeOrderPageRespVO } from '@/services/trade/order';
import OrderInfo from './order-info';
const DetailCom: React.FC = () => {
const DetailCom: React.FC<{ data?: TradeOrderPageRespVO }> = (props) => {
const items: TabsProps['items'] = [
{
key: '1',
label: '订单信息 ',
children: <OrderInfo />,
children: <OrderInfo data={props.data} />,
},
{
key: '2',

View File

@@ -1,19 +1,36 @@
import { Space } from 'antd';
import React from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import {
getTradeOrderDetail,
type TradeOrderDetailRespVO,
} from '@/services/trade/order';
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 = () => {
const OrderDetail: React.FC<{ data?: TradeOrderDetailRespVO }> = (props) => {
const { data } = props;
const [detais, setDetails] = useState<TradeOrderDetailRespVO>();
const fetch = useCallback(async () => {
if (data?.id) {
const res = await getTradeOrderDetail(data.id);
setDetails(res);
}
}, [data]);
useEffect(() => {
fetch();
}, [data]);
return (
<Space direction="vertical" size={24} style={{ width: '100%' }}>
<BasicInfo />
<ProdInfo />
<ServiceInfo />
<SelectInfo />
<SurchargeInfo />
<BasicInfo data={detais?.tradeOrderInfoBase} id={data?.id} />
<ProdInfo data={detais?.tradeProductInfo} id={data?.id} />
<ServiceInfo data={detais?.tradeServeInfo} id={data?.id} />
<SelectInfo data={detais?.tradeExtendCostInfo} id={data?.id} />
<SurchargeInfo data={detais?.tradeExtendServeInfo} id={data?.id} />
</Space>
);
};