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