- 添加 SupplierFarmerList 和 SupplierStallList 组件 - 添加 PaymentTaskList、PaymentTaskCreate、InvoicerStatisticCard 等支付任务相关组件 - 将 MelonFarmerList 重命名为 SupplierFarmerList 并移至 Supplier 目录 - 在 BizContainer 中添加 supplier 类型渲染支持 - 为 BizDetail 组件添加 formContextMode 属性和渲染逻辑 - 添加供应商类型到 BizValueType 类型定义中 - 添加开票方统计卡片和订单供应商发票列表组件 - 更新组件导出配置和本地化文件
506 lines
13 KiB
TypeScript
506 lines
13 KiB
TypeScript
import {
|
|
BizContainer,
|
|
BizValueType,
|
|
InvoicerStatisticCard,
|
|
ModeType,
|
|
OrderSupplierInvoiceList,
|
|
PaymentTaskCreate,
|
|
} from '@/components';
|
|
import { business } from '@/services';
|
|
import { calculateOrderSupplierStatistics } from '@/utils/calculateOrderSupplierStatistics';
|
|
import { formatCurrency } from '@/utils/format';
|
|
import { useIntl } from '@@/exports';
|
|
import {
|
|
ActionType,
|
|
ProColumns,
|
|
StatisticCard,
|
|
} from '@ant-design/pro-components';
|
|
import { ProDescriptionsItemProps } from '@ant-design/pro-descriptions';
|
|
import { Image } from 'antd';
|
|
import React, { useEffect, useRef, useState } from 'react';
|
|
|
|
interface IPaymentTaskListProps {
|
|
ghost?: boolean;
|
|
paymentTaskId?: BusinessAPI.PaymentTaskVO['paymentTaskId'];
|
|
search?: boolean;
|
|
onValueChange?: () => void;
|
|
mode?: ModeType;
|
|
trigger?: () => React.ReactNode;
|
|
}
|
|
|
|
export default function PaymentTaskList(props: IPaymentTaskListProps) {
|
|
const {
|
|
ghost = false,
|
|
paymentTaskId,
|
|
search = true,
|
|
mode = 'page',
|
|
trigger,
|
|
onValueChange,
|
|
} = props;
|
|
const intl = useIntl();
|
|
const intlPrefix = 'paymentTask';
|
|
const actionRef = useRef<ActionType>();
|
|
|
|
const [activeKey, setActiveKey] = useState<string>('PENDING');
|
|
const [statisticsPaymentTask, setStatisticsPaymentTask] =
|
|
useState<BusinessAPI.PaymentTaskStatisticsVO>();
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
const initStatistic = async () => {
|
|
const { data } = await business.paymentTask.statisticsPaymentTask({
|
|
statisticsQry: {},
|
|
});
|
|
setStatisticsPaymentTask(data);
|
|
setLoading(false);
|
|
};
|
|
useEffect(() => {
|
|
initStatistic().then();
|
|
}, []);
|
|
|
|
/** 状态文本映射 */
|
|
const stateMap: Record<string, { text: string; color: string }> = {
|
|
PENDING: {
|
|
text: intl.formatMessage({ id: intlPrefix + '.state.pending' }),
|
|
color: 'orange',
|
|
},
|
|
PARTIAL: {
|
|
text: intl.formatMessage({ id: intlPrefix + '.state.partial' }),
|
|
color: 'blue',
|
|
},
|
|
COMPLETED: {
|
|
text: intl.formatMessage({ id: intlPrefix + '.state.completed' }),
|
|
color: 'green',
|
|
},
|
|
CANCELLED: {
|
|
text: intl.formatMessage({ id: intlPrefix + '.state.cancelled' }),
|
|
color: 'red',
|
|
},
|
|
};
|
|
|
|
const columns: ProColumns<BusinessAPI.PaymentTaskVO, BizValueType>[] = [
|
|
{
|
|
title: intl.formatMessage({ id: intlPrefix + '.column.paymentCode' }),
|
|
dataIndex: 'paymentCode',
|
|
key: 'paymentCode',
|
|
},
|
|
{
|
|
title: intl.formatMessage({ id: intlPrefix + '.column.taskName' }),
|
|
dataIndex: 'taskName',
|
|
key: 'taskName',
|
|
},
|
|
{
|
|
title: intl.formatMessage({ id: intlPrefix + '.column.supplier' }),
|
|
dataIndex: 'supplierVO',
|
|
key: 'supplier',
|
|
valueType: 'supplier',
|
|
},
|
|
{
|
|
title: intl.formatMessage({ id: intlPrefix + '.column.totalAmount' }),
|
|
dataIndex: 'totalAmount',
|
|
key: 'totalAmount',
|
|
valueType: 'money',
|
|
search: false,
|
|
renderText: (value: number) => formatCurrency(value),
|
|
},
|
|
{
|
|
title: intl.formatMessage({ id: intlPrefix + '.column.paidAmount' }),
|
|
dataIndex: 'paidAmount',
|
|
key: 'paidAmount',
|
|
valueType: 'money',
|
|
search: false,
|
|
renderText: (value: number) => formatCurrency(value),
|
|
},
|
|
{
|
|
title: intl.formatMessage({ id: intlPrefix + '.column.unpaidAmount' }),
|
|
key: 'unpaidAmount',
|
|
search: false,
|
|
render: (_, record) => {
|
|
const unpaid = (record.totalAmount || 0) - (record.paidAmount || 0);
|
|
return <span>{formatCurrency(unpaid)}</span>;
|
|
},
|
|
},
|
|
{
|
|
title: intl.formatMessage({ id: intlPrefix + '.column.orderCount' }),
|
|
dataIndex: 'orderCount',
|
|
key: 'orderCount',
|
|
search: false,
|
|
},
|
|
{
|
|
title: intl.formatMessage({ id: intlPrefix + '.column.state' }),
|
|
dataIndex: 'state',
|
|
key: 'state',
|
|
valueType: 'select',
|
|
valueEnum: {
|
|
PENDING: { text: stateMap.PENDING.text, status: 'Warning' },
|
|
PARTIAL: { text: stateMap.PARTIAL.text, status: 'Processing' },
|
|
COMPLETED: { text: stateMap.COMPLETED.text, status: 'Success' },
|
|
CANCELLED: { text: stateMap.CANCELLED.text, status: 'Error' },
|
|
},
|
|
search: false,
|
|
render: (_, record) => {
|
|
const stateInfo = stateMap[record.state] || stateMap.PENDING;
|
|
return <span style={{ color: stateInfo.color }}>{stateInfo.text}</span>;
|
|
},
|
|
},
|
|
];
|
|
|
|
const detailColumns: ProDescriptionsItemProps<
|
|
BusinessAPI.PaymentTaskVO,
|
|
BizValueType
|
|
>[] = columns as ProDescriptionsItemProps<
|
|
BusinessAPI.PaymentTaskVO,
|
|
BizValueType
|
|
>[];
|
|
|
|
const detailContext = (paymentTaskVO: BusinessAPI.PaymentTaskVO) => {
|
|
// 统计车次数据
|
|
const statistics = calculateOrderSupplierStatistics(
|
|
paymentTaskVO.orderSupplierVOList,
|
|
);
|
|
|
|
return [
|
|
// 统计卡片 Tab
|
|
{
|
|
label: intl.formatMessage({
|
|
id: intlPrefix + '.detail.tab.statistics',
|
|
}),
|
|
key: 'statistics',
|
|
children: (
|
|
<div
|
|
style={{
|
|
display: 'grid',
|
|
gridTemplateColumns: 'repeat(3, 1fr)',
|
|
gap: 12,
|
|
marginBottom: 16,
|
|
}}
|
|
>
|
|
<InvoicerStatisticCard
|
|
title={intl.formatMessage({
|
|
id: intlPrefix + '.detail.invoiceType.selfInvoice',
|
|
})}
|
|
count={statistics.selfInvoiceCount}
|
|
amount={statistics.selfInvoiceAmount}
|
|
color={'#52c41a'}
|
|
/>
|
|
<InvoicerStatisticCard
|
|
title={intl.formatMessage({
|
|
id: intlPrefix + '.detail.invoiceType.proxyInvoice',
|
|
})}
|
|
count={statistics.proxyInvoiceCount}
|
|
amount={statistics.proxyInvoiceAmount}
|
|
color={'#1890ff'}
|
|
/>
|
|
<InvoicerStatisticCard
|
|
title={intl.formatMessage({
|
|
id: intlPrefix + '.detail.invoiceType.noInvoice',
|
|
})}
|
|
count={statistics.noInvoiceCount}
|
|
amount={statistics.noInvoiceAmount}
|
|
color={'#ff4d4f'}
|
|
/>
|
|
</div>
|
|
),
|
|
},
|
|
// 开票方统计 Tab
|
|
...(statistics.invoicerStatistics.length > 0
|
|
? [
|
|
{
|
|
label: intl.formatMessage({
|
|
id: intlPrefix + '.detail.tab.invoicerStatistics',
|
|
}),
|
|
key: 'invoicerStatistics',
|
|
children: (
|
|
<div
|
|
style={{
|
|
display: 'grid',
|
|
gridTemplateColumns:
|
|
'repeat(auto-fill, minmax(250px, 1fr))',
|
|
gap: 12,
|
|
}}
|
|
>
|
|
{statistics.invoicerStatistics.map((stat, index) => (
|
|
<InvoicerStatisticCard
|
|
key={index}
|
|
title={stat.supplierName}
|
|
count={stat.count}
|
|
amount={stat.amount}
|
|
color={'#722ed1'}
|
|
/>
|
|
))}
|
|
</div>
|
|
),
|
|
},
|
|
]
|
|
: []),
|
|
// 自开车次列表 Tab
|
|
...(statistics.selfInvoiceList.length > 0
|
|
? [
|
|
{
|
|
label: intl.formatMessage(
|
|
{ id: intlPrefix + '.detail.tab.selfInvoiceList' },
|
|
{ count: statistics.selfInvoiceCount },
|
|
),
|
|
key: 'selfInvoiceList',
|
|
subTitle: intl.formatMessage(
|
|
{ id: intlPrefix + '.detail.tab.selfInvoiceList.subTitle' },
|
|
{ count: statistics.selfInvoiceCount },
|
|
),
|
|
children: (
|
|
<OrderSupplierInvoiceList
|
|
rowKey="orderSupplierId"
|
|
dataSource={statistics.selfInvoiceList}
|
|
columns={[
|
|
{
|
|
title: '开票瓜农',
|
|
dataIndex: ['supplierInvoiceVO', 'supplierName'],
|
|
key: 'supplierName',
|
|
},
|
|
{
|
|
title: '发票编码',
|
|
dataIndex: 'supplierInvoiceVO',
|
|
key: 'invoiceSn',
|
|
render: (
|
|
supplierInvoiceVO: BusinessAPI.SupplierInvoiceVO,
|
|
) => {
|
|
return <a>{supplierInvoiceVO.invoiceSn}</a>;
|
|
},
|
|
},
|
|
]}
|
|
pagination={false}
|
|
size="small"
|
|
/>
|
|
),
|
|
},
|
|
]
|
|
: []),
|
|
// 代开车次列表 Tab
|
|
...(statistics.proxyInvoiceList.length > 0
|
|
? [
|
|
{
|
|
label: intl.formatMessage(
|
|
{ id: intlPrefix + '.detail.tab.proxyInvoiceList' },
|
|
{ count: statistics.proxyInvoiceCount },
|
|
),
|
|
key: 'proxyInvoiceList',
|
|
subTitle: intl.formatMessage(
|
|
{ id: intlPrefix + '.detail.tab.proxyInvoiceList.subTitle' },
|
|
{ count: statistics.proxyInvoiceCount },
|
|
),
|
|
children: (
|
|
<OrderSupplierInvoiceList
|
|
rowKey="orderSupplierId"
|
|
dataSource={statistics.proxyInvoiceList}
|
|
columns={[
|
|
{
|
|
title: '开票瓜农',
|
|
dataIndex: ['supplierInvoiceVO', 'supplierName'],
|
|
key: 'supplierName',
|
|
},
|
|
{
|
|
title: '发票编码',
|
|
dataIndex: ['supplierInvoiceVO', 'invoiceNo'],
|
|
key: 'invoiceNo',
|
|
},
|
|
]}
|
|
pagination={false}
|
|
size="small"
|
|
/>
|
|
),
|
|
},
|
|
]
|
|
: []),
|
|
// 无发票车次列表 Tab
|
|
...(statistics.noInvoiceList.length > 0
|
|
? [
|
|
{
|
|
label: intl.formatMessage(
|
|
{ id: intlPrefix + '.detail.tab.noInvoiceList' },
|
|
{ count: statistics.noInvoiceCount },
|
|
),
|
|
key: 'noInvoiceList',
|
|
subTitle: intl.formatMessage(
|
|
{ id: intlPrefix + '.detail.tab.noInvoiceList.subTitle' },
|
|
{ count: statistics.noInvoiceCount },
|
|
),
|
|
children: (
|
|
<OrderSupplierInvoiceList
|
|
rowKey="orderSupplierId"
|
|
columns={[
|
|
{
|
|
title: '瓜农收款码',
|
|
dataIndex: 'wechatQr',
|
|
key: 'wechatQr',
|
|
render: (wechatQr: string) => {
|
|
if (!wechatQr) {
|
|
return '暂无微信收款码';
|
|
}
|
|
return (
|
|
<Image
|
|
src={wechatQr}
|
|
alt="微信收款码"
|
|
style={{ width: 40, height: 40 }}
|
|
/>
|
|
);
|
|
},
|
|
},
|
|
]}
|
|
dataSource={statistics.noInvoiceList}
|
|
pagination={false}
|
|
size="small"
|
|
/>
|
|
),
|
|
},
|
|
]
|
|
: []),
|
|
];
|
|
};
|
|
|
|
return (
|
|
<BizContainer<
|
|
typeof business.paymentTask,
|
|
BusinessAPI.PaymentTaskVO,
|
|
BusinessAPI.PaymentTaskPageQry,
|
|
BusinessAPI.PaymentTaskCreateCmd,
|
|
BusinessAPI.PaymentTaskUpdateCmd
|
|
>
|
|
rowKey={'paymentTaskId'}
|
|
permission={'operation-payment-task'}
|
|
func={business.paymentTask}
|
|
method={'paymentTask'}
|
|
methodUpper={'PaymentTask'}
|
|
intlPrefix={intlPrefix}
|
|
modeType={mode}
|
|
onValueChange={onValueChange}
|
|
container={{
|
|
fieldProps: {
|
|
ghost,
|
|
loading,
|
|
},
|
|
}}
|
|
remark={{
|
|
mode: 'editor',
|
|
}}
|
|
page={{
|
|
fieldProps: {
|
|
bordered: true,
|
|
...(!ghost && {
|
|
tableExtraRender: () => (
|
|
<StatisticCard.Group className={'statistics'}>
|
|
<StatisticCard
|
|
statistic={{
|
|
title: '全部',
|
|
value: statisticsPaymentTask?.totalCount || 0,
|
|
}}
|
|
/>
|
|
<StatisticCard.Operation>=</StatisticCard.Operation>
|
|
<StatisticCard
|
|
statistic={{
|
|
title: '待付款数量',
|
|
value: statisticsPaymentTask?.pendingCount || 0,
|
|
}}
|
|
/>
|
|
<StatisticCard.Operation>+</StatisticCard.Operation>
|
|
<StatisticCard
|
|
statistic={{
|
|
title: '部分付款数量',
|
|
value: statisticsPaymentTask?.partialCount || 0,
|
|
}}
|
|
/>
|
|
<StatisticCard.Operation>+</StatisticCard.Operation>
|
|
<StatisticCard
|
|
statistic={{
|
|
title: '已完成数量',
|
|
value: statisticsPaymentTask?.completedCount || 0,
|
|
}}
|
|
/>
|
|
<StatisticCard.Operation>+</StatisticCard.Operation>
|
|
<StatisticCard
|
|
statistic={{
|
|
title: '已取消数量',
|
|
value: statisticsPaymentTask?.cancelledCount || 0,
|
|
}}
|
|
/>
|
|
</StatisticCard.Group>
|
|
),
|
|
}),
|
|
ghost,
|
|
//@ts-ignore
|
|
search,
|
|
params: {
|
|
...(activeKey !== 'ALL' && {
|
|
state: activeKey as BusinessAPI.PaymentTaskVO['state'],
|
|
}),
|
|
taskType: 'MELON_FARMER',
|
|
},
|
|
toolbar: {
|
|
menu: {
|
|
type: 'tab',
|
|
activeKey: activeKey,
|
|
items: [
|
|
{
|
|
key: 'ALL',
|
|
label: intl.formatMessage({
|
|
id: intlPrefix + '.tab.all',
|
|
}),
|
|
},
|
|
{
|
|
key: 'PENDING',
|
|
label: intl.formatMessage({
|
|
id: intlPrefix + '.tab.pending',
|
|
}),
|
|
},
|
|
{
|
|
key: 'PARTIAL',
|
|
label: intl.formatMessage({
|
|
id: intlPrefix + '.tab.partial',
|
|
}),
|
|
},
|
|
{
|
|
key: 'COMPLETED',
|
|
label: intl.formatMessage({
|
|
id: intlPrefix + '.tab.completed',
|
|
}),
|
|
},
|
|
{
|
|
key: 'CANCELLED',
|
|
label: intl.formatMessage({
|
|
id: intlPrefix + '.tab.cancelled',
|
|
}),
|
|
},
|
|
],
|
|
onChange: (key) => {
|
|
setActiveKey(key as string);
|
|
},
|
|
},
|
|
actions: [
|
|
<PaymentTaskCreate
|
|
key={'create'}
|
|
onFinish={() => {
|
|
actionRef.current?.reload();
|
|
onValueChange?.();
|
|
}}
|
|
/>,
|
|
],
|
|
},
|
|
},
|
|
columns,
|
|
actionRef: actionRef,
|
|
}}
|
|
create={false}
|
|
update={{
|
|
formType: 'drawer',
|
|
formContext: [],
|
|
}}
|
|
destroy={{}}
|
|
detail={{
|
|
rowId: paymentTaskId,
|
|
formType: 'drawer',
|
|
columns: detailColumns,
|
|
formContext: detailContext,
|
|
formContextMode: 'flat',
|
|
trigger,
|
|
}}
|
|
/>
|
|
);
|
|
}
|