订单详情

This commit is contained in:
liu
2026-08-12 09:20:36 +08:00
parent ce958d690f
commit fa4bf6fe61
3 changed files with 117 additions and 85 deletions
+1 -1
View File
@@ -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 });
+1
View File
@@ -35,6 +35,7 @@ export interface IStoreOrderItemUpdate {
cost_price: number;
quantity: number;
weight: number;
remark: string;
}
/** 门店订单 */
+115 -84
View File
@@ -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
}