订单详情
This commit is contained in:
@@ -138,7 +138,7 @@ export default function XinTable<T extends Record<string, any> = any>(props: Xin
|
||||
|
||||
// 暴露方法到 tableRef
|
||||
useImperativeHandle(tableRef, (): XinTableInstance<T> => ({
|
||||
reload: async () => { await handleRequest(); },
|
||||
reload: async () => { await handleRequest(requestParams); },
|
||||
reset: async () => {
|
||||
searchRef.resetFields();
|
||||
setRequestParams({ page: 1, pageSize: 10 });
|
||||
|
||||
@@ -35,6 +35,7 @@ export interface IStoreOrderItemUpdate {
|
||||
cost_price: number;
|
||||
quantity: number;
|
||||
weight: number;
|
||||
remark: string;
|
||||
}
|
||||
|
||||
/** 门店订单 */
|
||||
|
||||
+115
-84
@@ -42,7 +42,7 @@ import { getSupplierOptions } from '@/api/customer/supplier.ts';
|
||||
import type IStore from '@/domain/iStore.ts';
|
||||
import type ISupplier from '@/domain/iSupplier.ts';
|
||||
import AuthButton from '@/components/AuthButton';
|
||||
import { EditOutlined, SyncOutlined, UnorderedListOutlined } from '@ant-design/icons';
|
||||
import { EditOutlined, SettingOutlined, SyncOutlined, UnorderedListOutlined } from '@ant-design/icons';
|
||||
import TextArea from "antd/es/input/TextArea";
|
||||
|
||||
const { Title, Text } = Typography;
|
||||
@@ -57,16 +57,10 @@ const ITEM_EDITABLE_STATUS = [0, 1, 2, 3];
|
||||
* 状态流转合法路径:待接单→已接单/已取消;采购中→配送中/已完成;配送中→已完成
|
||||
* (已接单→采购中 通过「生成采购单」完成,不在流转按钮内)
|
||||
*/
|
||||
const NEXT_STATUS: Record<number, { status: number; label: string; danger?: boolean }[]> = {
|
||||
0: [
|
||||
{ status: 1, label: '接单' },
|
||||
{ status: 9, label: '取消订单', danger: true },
|
||||
],
|
||||
2: [
|
||||
{ status: 3, label: '开始配送' },
|
||||
{ status: 4, label: '完成订单' },
|
||||
],
|
||||
3: [{ status: 4, label: '完成订单' }],
|
||||
const NEXT_STATUS: Record<number, { status: number; label: string; }> = {
|
||||
0: { status: 1, label: '接单' },
|
||||
2: { status: 3, label: '开始配送' },
|
||||
3: { status: 4, label: '完成订单' },
|
||||
};
|
||||
|
||||
/** 批量流转可选目标状态(弹窗单选,后端全量校验,任一不允许则整批中止) */
|
||||
@@ -201,6 +195,7 @@ const StoreOrderPage: React.FC = () => {
|
||||
cost_price: Number(item.cost_price ?? 0),
|
||||
quantity: Number(item.quantity ?? 0),
|
||||
weight: Number(item.weight ?? 0),
|
||||
remark: item.remark ?? '',
|
||||
});
|
||||
setItemEditOpen(true);
|
||||
};
|
||||
@@ -254,28 +249,6 @@ const StoreOrderPage: React.FC = () => {
|
||||
valueType: 'text',
|
||||
hideInForm: true
|
||||
},
|
||||
{
|
||||
title: '商品信息',
|
||||
dataIndex: 'items',
|
||||
hideInForm: true,
|
||||
hideInSearch: true,
|
||||
width: 300,
|
||||
render: (_, record) => {
|
||||
return (
|
||||
<Space orientation={'vertical'} className={'max-h-30 w-60 overflow-y-auto pr-6'}>
|
||||
{ record.items && record.items.length > 0 && record.items.map(item => (
|
||||
<div className={'flex'}>
|
||||
<Image src={item.image} width={40} height={40} ></Image>
|
||||
<div className={'ml-2.5'}>
|
||||
<div>{item.product_name}</div>
|
||||
<div>{ item.price } ¥ × { item.quantity }</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</Space>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '基本信息',
|
||||
dataIndex: 'order_no',
|
||||
@@ -285,15 +258,42 @@ const StoreOrderPage: React.FC = () => {
|
||||
render: (_, record) => {
|
||||
return (
|
||||
<Space orientation={'vertical'}>
|
||||
<div>
|
||||
<Text type={'secondary'}>订货门店:</Text>
|
||||
<Tag color="blue">{record.store?.name ?? `门店#${record.store_id}`}</Tag>
|
||||
</div>
|
||||
<div>
|
||||
<Text type={'secondary'}>订单号:</Text>
|
||||
<Text copyable={{ text: record.order_no }}>{record.order_no}</Text>
|
||||
</div>
|
||||
<div><Text type={'secondary'}>订货时间:</Text>{record.created_at}</div>
|
||||
<div>
|
||||
<Text type={'secondary'}>订单状态:</Text>
|
||||
<Tag color={STORE_ORDER_STATUS_MAP[record.status ?? 0]?.color}>
|
||||
{STORE_ORDER_STATUS_MAP[record.status ?? 0]?.text}
|
||||
</Tag>
|
||||
</div>
|
||||
</Space>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '商品信息',
|
||||
dataIndex: 'items',
|
||||
hideInForm: true,
|
||||
hideInSearch: true,
|
||||
width: 550,
|
||||
render: (_, record) => {
|
||||
return (
|
||||
<Space wrap size={20}>
|
||||
{ record.items && record.items.length > 0 && record.items.map(item => (
|
||||
<div className={'flex'}>
|
||||
<Image src={item.image} width={60} height={60} ></Image>
|
||||
<div className={'ml-2.5'}>
|
||||
<div>{item.product_name}</div>
|
||||
<div className={'text-[12px] text-[#999]'}>{item.product_spec} {item.unit}</div>
|
||||
<div className={'text-[12px] text-[#999]'}>
|
||||
<span className={'text-[red]'}>{ item.price } ¥</span> × { item.quantity }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</Space>
|
||||
)
|
||||
}
|
||||
@@ -319,6 +319,10 @@ const StoreOrderPage: React.FC = () => {
|
||||
width: 300,
|
||||
render: (_, record) => (
|
||||
<Space orientation={'vertical'}>
|
||||
<div>
|
||||
<Text type={'secondary'}>订货门店:</Text>
|
||||
<Tag color="blue">{record.store?.name ?? `门店#${record.store_id}`}</Tag>
|
||||
</div>
|
||||
<div><Text type={'secondary'}>联系人:</Text>{ record.store?.contact ?? '-' }</div>
|
||||
<div><Text type={'secondary'}>联系电话:</Text>{ record.store?.phone ?? '-' }</div>
|
||||
<div><Text type={'secondary'}>门店地址:</Text>{ record.store?.address ?? '-' }</div>
|
||||
@@ -365,16 +369,16 @@ const StoreOrderPage: React.FC = () => {
|
||||
render: (_, record) => (
|
||||
<Space orientation={'vertical'}>
|
||||
<div>
|
||||
<Text type={'secondary'}>附加总金额:</Text>
|
||||
{record.added_amount} ¥
|
||||
<Text type={'secondary'}>商品总金额:</Text>
|
||||
<span className={'text-[red]'}>{record.product_amount} ¥</span>
|
||||
</div>
|
||||
<div>
|
||||
<Text type={'secondary'}>商品总金额:</Text>
|
||||
{record.product_amount} ¥
|
||||
<Text type={'secondary'}>附加总金额:</Text>
|
||||
<span className={'text-[red]'}>{record.added_amount} ¥</span>
|
||||
</div>
|
||||
<div>
|
||||
<Text type={'secondary'}>订单总金额:</Text>
|
||||
{record.total_amount} ¥
|
||||
<span className={'text-[red] text-[16px]'}>{record.total_amount} ¥</span>
|
||||
</div>
|
||||
</Space>
|
||||
)
|
||||
@@ -385,17 +389,13 @@ const StoreOrderPage: React.FC = () => {
|
||||
valueType: 'select',
|
||||
hideInForm: true,
|
||||
align: 'center',
|
||||
hideInTable: true,
|
||||
fieldProps: {
|
||||
options: Object.entries(STORE_ORDER_STATUS_MAP).map(([value, item]) => ({
|
||||
value: Number(value),
|
||||
label: item.text,
|
||||
})),
|
||||
},
|
||||
render: (_, record) => (
|
||||
<Tag color={STORE_ORDER_STATUS_MAP[record.status ?? 0]?.color}>
|
||||
{STORE_ORDER_STATUS_MAP[record.status ?? 0]?.text}
|
||||
</Tag>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '采购单ID',
|
||||
@@ -412,37 +412,49 @@ const StoreOrderPage: React.FC = () => {
|
||||
{
|
||||
title: '操作栏',
|
||||
dataIndex: 'operate',
|
||||
align: 'center',
|
||||
hideInForm: true,
|
||||
hideInSearch: true,
|
||||
width: 180,
|
||||
render: (_, record) => (
|
||||
<Space orientation={'vertical'}>
|
||||
<Button key="detail" type={'link'} icon={<UnorderedListOutlined />} onClick={() => openDetail(record.id!)}>
|
||||
详情
|
||||
</Button>
|
||||
{
|
||||
(NEXT_STATUS[record.status ?? -1] ?? []).map((action) => (
|
||||
<AuthButton key={action.status} auth="order.store.update">
|
||||
<Popconfirm
|
||||
title={`确认将订单状态更新为「${action.label}」?`}
|
||||
onConfirm={() => handleStatusChange(record.id!, action.status)}
|
||||
>
|
||||
<Button type={action.danger ? undefined : 'link'} danger={action.danger}>
|
||||
{action.label}
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</AuthButton>
|
||||
))
|
||||
}
|
||||
{
|
||||
CONTAINER_EDITABLE_STATUS.includes(record.status ?? -1) ? (
|
||||
<AuthButton key="container" auth="order.store.update">
|
||||
<Button type={'link'} onClick={() => openContainer(record)}>
|
||||
设置附加信息
|
||||
<Space size={5} wrap>
|
||||
<Button
|
||||
type={'primary'}
|
||||
icon={<UnorderedListOutlined />}
|
||||
onClick={() => openDetail(record.id!)}
|
||||
/>
|
||||
{ CONTAINER_EDITABLE_STATUS.includes(record.status ?? -1) && (
|
||||
<AuthButton key="container" auth="order.store.update">
|
||||
<Button
|
||||
icon={<SettingOutlined />}
|
||||
type={'primary'}
|
||||
onClick={() => openContainer(record)}
|
||||
/>
|
||||
</AuthButton>
|
||||
)}
|
||||
{ NEXT_STATUS[record.status!] && (
|
||||
<AuthButton auth="order.store.update">
|
||||
<Popconfirm
|
||||
title={`确认将订单状态更新为「${NEXT_STATUS[record.status!].label}」?`}
|
||||
onConfirm={() => handleStatusChange(record.id!, NEXT_STATUS[record.status!].status)}
|
||||
>
|
||||
<Button type={'primary'} color='green' variant="solid">
|
||||
{NEXT_STATUS[record.status!].label}
|
||||
</Button>
|
||||
</AuthButton>
|
||||
) : null
|
||||
}
|
||||
</Popconfirm>
|
||||
</AuthButton>
|
||||
)}
|
||||
{ record.status === 0 && (
|
||||
<AuthButton auth="order.store.update">
|
||||
<Popconfirm
|
||||
title={`确认取消该订单吗?`}
|
||||
onConfirm={() => handleStatusChange(record.id!, 9)}
|
||||
>
|
||||
<Button type={'primary'} color='danger' variant="solid">
|
||||
取消订单
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</AuthButton>
|
||||
)}
|
||||
</Space>
|
||||
)
|
||||
}
|
||||
@@ -497,20 +509,39 @@ const StoreOrderPage: React.FC = () => {
|
||||
size={1000}
|
||||
loading={detailLoading}
|
||||
footer={
|
||||
detail && NEXT_STATUS[detail.status ?? -1] ? (
|
||||
<Space className="flex justify-end">
|
||||
{NEXT_STATUS[detail.status!].map((action) => (
|
||||
<AuthButton key={action.status} auth="order.store.update">
|
||||
detail ? (
|
||||
<Space className="flex justify-end" wrap>
|
||||
{CONTAINER_EDITABLE_STATUS.includes(detail.status ?? -1) && (
|
||||
<AuthButton auth="order.store.update">
|
||||
<Button icon={<SettingOutlined />} onClick={() => openContainer(detail)}>
|
||||
设置附加信息
|
||||
</Button>
|
||||
</AuthButton>
|
||||
)}
|
||||
{ NEXT_STATUS[detail.status!] && (
|
||||
<AuthButton auth="order.store.update">
|
||||
<Popconfirm
|
||||
title={`确认将订单状态更新为「${action.label}」?`}
|
||||
onConfirm={() => handleStatusChange(detail.id!, action.status)}
|
||||
title={`确认将订单状态更新为「${NEXT_STATUS[detail.status!].label}」?`}
|
||||
onConfirm={() => handleStatusChange(detail.id!, NEXT_STATUS[detail.status!].status)}
|
||||
>
|
||||
<Button type={action.danger ? undefined : 'primary'} danger={action.danger}>
|
||||
{action.label}
|
||||
<Button type={'primary'} color='green' variant="solid">
|
||||
{NEXT_STATUS[detail.status!].label}
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</AuthButton>
|
||||
))}
|
||||
)}
|
||||
{ detail.status === 0 && (
|
||||
<AuthButton auth="order.store.update">
|
||||
<Popconfirm
|
||||
title={`确认取消该订单吗?`}
|
||||
onConfirm={() => handleStatusChange(detail.id!, 9)}
|
||||
>
|
||||
<Button type={'primary'} color='danger' variant="solid">
|
||||
取消订单
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</AuthButton>
|
||||
)}
|
||||
</Space>
|
||||
) : null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user