feat(components): 添加供应商瓜农组件和支付任务管理功能

- 添加 SupplierFarmerList 和 SupplierStallList 组件
- 添加 PaymentTaskList、PaymentTaskCreate、InvoicerStatisticCard 等支付任务相关组件
- 将 MelonFarmerList 重命名为 SupplierFarmerList 并移至 Supplier 目录
- 在 BizContainer 中添加 supplier 类型渲染支持
- 为 BizDetail 组件添加 formContextMode 属性和渲染逻辑
- 添加供应商类型到 BizValueType 类型定义中
- 添加开票方统计卡片和订单供应商发票列表组件
- 更新组件导出配置和本地化文件
This commit is contained in:
shenyifei 2026-01-06 11:10:08 +08:00
parent d8920e9c37
commit b53d26ec65
31 changed files with 21342 additions and 14110 deletions

View File

@ -1,7 +1,6 @@
export { default as MelonFarmerList } from './MelonFarmerList';
export { default as BoxProductList } from './BoxProductList'
export { default as BoxBrandList } from './BoxBrandList'; export { default as BoxBrandList } from './BoxBrandList';
export { default as CostList } from './CostList'; export { default as BoxProductList } from './BoxProductList';
export { default as CostItemList } from './CostItemList';
export { default as BoxSpecList } from './BoxSpecList'; export { default as BoxSpecList } from './BoxSpecList';
export { default as CostItemList } from './CostItemList';
export { default as CostList } from './CostList';
export { default as ProductDataList } from './ProductDataList'; export { default as ProductDataList } from './ProductDataList';

View File

@ -15,12 +15,13 @@ import {
BizValueType, BizValueType,
DealerFormItem, DealerFormItem,
DealerList, DealerList,
PageContainer,
OrderFormItem, OrderFormItem,
OrderList, OrderList,
PageContainer,
Remark, Remark,
RemarkFormItem, RemarkFormItem,
SmartActionBar, SmartActionBar,
SupplierFarmerList,
UserFormItem, UserFormItem,
UserList, UserList,
} from '@/components'; } from '@/components';
@ -847,11 +848,27 @@ export default function BizContainer<
); );
}, },
}, },
supplier: {
render: (supplierVO: BusinessAPI.SupplierVO) => {
return (
supplierVO && (
<SupplierFarmerList
ghost={true}
mode={'detail'}
supplierId={supplierVO.supplierId}
trigger={() => (
<Space>
<a>{supplierVO.name}</a>
</Space>
)}
/>
)
);
},
},
order: { order: {
renderFormItem: (_, props) => { renderFormItem: (_, props) => {
return ( return <OrderFormItem {...props} {...props?.fieldProps} />;
<OrderFormItem {...props} {...props?.fieldProps} />
);
}, },
render: (orderVO: BusinessAPI.OrderVO) => { render: (orderVO: BusinessAPI.OrderVO) => {
return ( return (

View File

@ -27,6 +27,7 @@ export default function BizDetail<
methodUpper, methodUpper,
func, func,
formContext, formContext,
formContextMode = 'tab',
trigger, trigger,
fieldProps, fieldProps,
initValues, initValues,
@ -40,6 +41,63 @@ export default function BizDetail<
const intl = useIntl(); const intl = useIntl();
/** 渲染 formContext 内容 */
const renderFormContext = (data: any, form: any, colSpan: number) => {
if (!formContext) return null;
const contextItems = formContext(data?.[`${method}VO`], async () => {
const { data } = await func?.[`show${methodUpper}`]({
[`${method}ShowQry`]: {
[`${rowKey}`]: rowId,
},
});
form.setFieldValue(`${method}VO`, data);
})?.filter((item) => {
// @ts-ignore
return !item.display || item.display(data?.[`${method}VO`]);
});
// 平铺模式:直接垂直堆叠所有内容
if (formContextMode === 'flat') {
return (
<ProCard ghost={true} direction={'column'}>
{contextItems?.map((item, index) => (
<ProCard
key={item.key || index}
bordered={true}
headerBordered={false}
title={item.label}
style={{
marginBottom: 16,
}}
// @ts-ignore
subTitle={item.subTitle}
>
{item.children}
</ProCard>
))}
</ProCard>
);
}
// Tab 模式:使用 tabs 渲染
return (
<ProCard
bordered={true}
headerBordered={true}
colSpan={colSpan}
tabs={{
tabPosition: 'top',
activeKey: data.activeKey,
items: contextItems,
onChange: (key) => {
form.setFieldValue('activeKey', key);
},
}}
/>
);
};
let rest = { let rest = {
title: intl.formatMessage({ title: intl.formatMessage({
id: intlPrefix + '.modal.view.title', id: intlPrefix + '.modal.view.title',
@ -115,40 +173,7 @@ export default function BizDetail<
column={column(data.isMobile, formContext)} column={column(data.isMobile, formContext)}
/> />
</ProCard> </ProCard>
{formContext && ( {renderFormContext(data, form, data.isMobile ? 24 : 18)}
<ProCard
bordered={true}
headerBordered={true}
colSpan={data.isMobile ? 24 : 18}
tabs={{
tabPosition: 'top',
activeKey: data.activeKey,
items: formContext?.(
data?.[`${method}VO`],
async () => {
const { data } = await func?.[
`show${methodUpper}`
]({
[`${method}ShowQry`]: {
[`${rowKey}`]: rowId,
},
});
form.setFieldValue(`${method}VO`, data);
},
)?.filter((item) => {
//@ts-ignore
return (
!item.display ||
item.display(data?.[`${method}VO`])
);
}),
onChange: (key) => {
form.setFieldValue('activeKey', key);
},
}}
/>
)}
</ProCard> </ProCard>
); );
}} }}
@ -179,7 +204,7 @@ export default function BizDetail<
{...rest} {...rest}
> >
{columns && ( {columns && (
<ProFormDependency name={[`${method}VO`, 'isMobile']}> <ProFormDependency name={[`${method}VO`, 'isMobile', 'activeKey']}>
{(data, form) => { {(data, form) => {
return ( return (
<ProCard ghost={true} gutter={24} direction={'row'}> <ProCard ghost={true} gutter={24} direction={'row'}>
@ -202,40 +227,7 @@ export default function BizDetail<
column={column(data.isMobile, formContext)} column={column(data.isMobile, formContext)}
/> />
</ProCard> </ProCard>
{formContext && ( {renderFormContext(data, form, data.isMobile ? 24 : 18)}
<ProCard
bordered={true}
headerBordered={true}
colSpan={data.isMobile ? 24 : 18}
tabs={{
tabPosition: 'top',
activeKey: data.activeKey,
items: formContext?.(
data?.[`${method}VO`],
async () => {
const { data } = await func?.[
`show${methodUpper}`
]({
[`${method}ShowQry`]: {
[`${rowKey}`]: rowId,
},
});
form.setFieldValue(`${method}VO`, data);
},
)?.filter((item) => {
//@ts-ignore
return (
!item.display ||
item.display(data?.[`${method}VO`])
);
}),
onChange: (key) => {
form.setFieldValue('activeKey', key);
},
}}
/>
)}
</ProCard> </ProCard>
); );
}} }}

View File

@ -9,11 +9,11 @@ import {
ProDescriptionsItemProps, ProDescriptionsItemProps,
ProTableProps, ProTableProps,
} from '@ant-design/pro-components'; } from '@ant-design/pro-components';
import { ProListMetas, ProListProps } from '@ant-design/pro-list';
import { TourStepProps } from 'antd'; import { TourStepProps } from 'antd';
import { TabsProps } from 'antd/es/tabs'; import { TabsProps } from 'antd/es/tabs';
import { Dayjs } from 'dayjs'; import { Dayjs } from 'dayjs';
import React, { MutableRefObject } from 'react'; import React, { MutableRefObject } from 'react';
import { ProListMetas, ProListProps } from '@ant-design/pro-list';
export type BizValueType = export type BizValueType =
| 'user' | 'user'
@ -21,7 +21,8 @@ export type BizValueType =
| 'status' | 'status'
| 'remark' | 'remark'
| 'order' | 'order'
| 'dealer'; | 'dealer'
| 'supplier';
export type FormType = 'modal' | 'drawer' | 'step'; export type FormType = 'modal' | 'drawer' | 'step';
export type ModeType = export type ModeType =
| 'tree' | 'tree'
@ -176,6 +177,8 @@ export interface BizCalenderProps<
trigger?: () => React.ReactNode; trigger?: () => React.ReactNode;
} }
export type FormContextMode = 'tab' | 'flat';
export type BizDetailProps< export type BizDetailProps<
BizVO extends Record<string, any>, BizVO extends Record<string, any>,
Func extends Record<string, any>, Func extends Record<string, any>,
@ -187,6 +190,7 @@ export type BizDetailProps<
record: BizVO, record: BizVO,
onValueChange: () => void, onValueChange: () => void,
) => TabsProps['items']; ) => TabsProps['items'];
formContextMode?: FormContextMode;
initValues?: (rowId: string) => Record<string, any>; initValues?: (rowId: string) => Record<string, any>;
onFinish?: (record: BizVO) => void; onFinish?: (record: BizVO) => void;
trigger?: (record?: BizVO) => React.ReactNode; trigger?: (record?: BizVO) => React.ReactNode;

View File

@ -0,0 +1,402 @@
import { OrderList } from '@/components';
import { business } from '@/services';
import { formatParam } from '@/utils/formatParam';
import { pagination } from '@/utils/pagination';
import { useIntl } from '@@/exports';
import {
ActionType,
LightFilter,
ProColumns,
ProFormSelect,
} from '@ant-design/pro-components';
import { SelectModal } from '@chageable/components';
import { Alert, ModalProps, Row, Space, Tag } from 'antd';
import React, { useEffect, useRef, useState } from 'react';
export interface IOrderSupplierModalProps extends ModalProps {
title: string;
selectedList?: BusinessAPI.OrderSupplierVO[];
onFinish: (orderSupplierVOList: BusinessAPI.OrderSupplierVO[]) => void;
type: 'checkbox' | 'radio' | undefined;
params?: BusinessAPI.OrderSupplierPageQry;
num?: number;
tips?: string;
extraFilter?: React.ReactNode[];
extraColumns?: ProColumns<BusinessAPI.OrderSupplierVO>[];
}
export default function OrderSupplierModal(props: IOrderSupplierModalProps) {
const {
title,
onFinish,
type,
selectedList,
params: initParams,
num = 10,
tips,
extraFilter = [],
extraColumns: initExtraColumns = [],
...rest
} = props;
const actionRef = useRef<ActionType>();
const sessionKey = `orderSupplierList`;
const intl = useIntl();
const intlPrefix = 'orderSupplier';
const [params, setParams] = useState<BusinessAPI.OrderSupplierPageQry>(
initParams || {},
);
useEffect(() => {
if (initParams) {
setParams({
...params,
...initParams,
});
}
}, [initParams]);
const columns: ProColumns<BusinessAPI.OrderSupplierVO>[] = [
{
title: intl.formatMessage({ id: intlPrefix + '.column.order' }),
dataIndex: ['orderVO', 'orderSn'],
key: 'orderSn',
search: false,
render: (_, orderSupplierVO: BusinessAPI.OrderSupplierVO) => {
const orderVO = orderSupplierVO.orderVO;
return (
orderVO && (
<OrderList
ghost={true}
mode={'detail'}
orderId={orderVO.orderId}
trigger={() => (
<Space>
<a>
{`${orderVO.orderVehicle?.dealerName} - 第 ${orderVO.orderVehicle?.vehicleNo || '暂无'} 车 - ${orderVO.orderSn || '暂无'}`}
</a>
</Space>
)}
/>
)
);
},
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.name' }),
dataIndex: 'name',
key: 'name',
renderText: (text: string) => <span className="font-medium">{text}</span>,
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.idCard' }),
dataIndex: 'idCard',
key: 'idCard',
search: false,
ellipsis: true,
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.phone' }),
dataIndex: 'phone',
key: 'phone',
search: false,
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.bankName' }),
dataIndex: 'bankName',
key: 'bankName',
search: false,
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.bankCard' }),
dataIndex: 'bankCard',
key: 'bankCard',
search: false,
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.invoiceAmount' }),
dataIndex: 'invoiceAmount',
key: 'invoiceAmount',
valueType: 'money',
search: false,
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.depositAmount' }),
dataIndex: 'depositAmount',
key: 'depositAmount',
valueType: 'money',
search: false,
},
{
title: intl.formatMessage({
id: intlPrefix + '.column.remainingAmount',
}),
dataIndex: 'remainingAmount',
key: 'remainingAmount',
valueType: 'money',
search: false,
renderText: (_, record) => {
return record.invoiceAmount - record.depositAmount || 0;
},
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.orderCompany' }),
dataIndex: ['orderCompany', 'shortName'],
key: 'orderCompany',
search: false,
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.isPaid' }),
dataIndex: 'isPaid',
key: 'isPaid',
valueType: 'select',
valueEnum: {
true: {
text: intl.formatMessage({ id: intlPrefix + '.column.isPaid.paid' }),
status: 'Success',
},
false: {
text: intl.formatMessage({
id: intlPrefix + '.column.isPaid.unpaid',
}),
status: 'Default',
},
},
},
// {
// title: intl.formatMessage({ id: intlPrefix + '.column.type' }),
// dataIndex: 'type',
// key: 'type',
// valueType: 'select',
// valueEnum: {
// FARMER: { text: intl.formatMessage({ id: intlPrefix + '.column.type.farmer' }), status: 'Default' },
// STALL: { text: intl.formatMessage({ id: intlPrefix + '.column.type.stall' }), status: 'Processing' },
// OTHER_STALL: { text: intl.formatMessage({ id: intlPrefix + '.column.type.otherStall' }), status: 'Warning' },
// },
// },
...(initExtraColumns || []),
];
function setOrderSupplierVOStorage(
orderSupplierVO: BusinessAPI.OrderSupplierVO,
) {
const localOrderSupplierList = localStorage.getItem(sessionKey);
const orderSupplierList = localOrderSupplierList
? JSON.parse(localOrderSupplierList)
: [];
orderSupplierList.forEach(
(item: BusinessAPI.OrderSupplierVO, index: number) => {
if (item.orderSupplierId === orderSupplierVO.orderSupplierId) {
orderSupplierList.splice(index, 1);
}
},
);
if (orderSupplierList.length < 5) {
orderSupplierList.unshift(orderSupplierVO);
localStorage.setItem(sessionKey, JSON.stringify(orderSupplierList));
} else {
orderSupplierList.pop();
orderSupplierList.unshift(orderSupplierVO);
localStorage.setItem(sessionKey, JSON.stringify(orderSupplierList));
}
}
return (
<SelectModal<BusinessAPI.OrderSupplierVO, BusinessAPI.OrderSupplierPageQry>
rowKey={'orderSupplierId'}
modalProps={{
title: title || '选择瓜农订单',
...rest,
destroyOnHidden: true,
afterOpenChange: (open) => {
if (!open) {
setParams({
...initParams,
});
}
},
}}
selectedList={selectedList}
tableProps={{
rowKey: 'orderSupplierId',
columns: columns,
columnsState: {
persistenceType: 'sessionStorage',
persistenceKey: 'orderSupplierModalColumnStateKey',
},
params: {
...params,
},
request: async (params, sorter, filter) => {
const { data, success, totalCount } =
await business.orderSupplier.pageOrderSupplier({
orderSupplierPageQry: formatParam<typeof params>(
params,
sorter,
filter,
),
});
return {
data: data || [],
total: totalCount,
success,
};
},
pagination: {
...pagination(),
position: ['bottomRight'],
},
tableAlertRender: ({ selectedRowKeys, selectedRows }) => {
const selectedRowsMap = new Map<
string,
BusinessAPI.OrderSupplierVO
>();
selectedRows.forEach((item: BusinessAPI.OrderSupplierVO) => {
if (item) {
if (!selectedRowsMap.has(item.orderSupplierId)) {
selectedRowsMap.set(item.orderSupplierId, item);
}
}
});
selectedList?.forEach((item: BusinessAPI.OrderSupplierVO) => {
if (!selectedRowsMap.has(item.orderSupplierId)) {
selectedRowsMap.set(item.orderSupplierId, item);
}
});
let selectedTempList: BusinessAPI.OrderSupplierVO[] = [];
selectedRowsMap.forEach((item: BusinessAPI.OrderSupplierVO) => {
if (selectedRowKeys.includes(item.orderSupplierId)) {
selectedTempList.push(item);
}
});
return (
<Space size={12}>
<span> {selectedRowKeys.length} </span>
<Space wrap={true}>
{selectedTempList?.map((item: BusinessAPI.OrderSupplierVO) => {
return (
item && <span key={item.orderSupplierId}>{item.name}</span>
);
})}
</Space>
</Space>
);
},
...(tips && {
tableExtraRender: () => {
return tips && <Alert type={'info'} message={tips} />;
},
}),
...(type === 'radio' && {
tableExtraRender: () => {
const localOrderSupplierList = localStorage.getItem(sessionKey);
if (localOrderSupplierList) {
const orderSupplierList = JSON.parse(localOrderSupplierList);
return (
<>
{tips && <Alert type={'info'} message={tips} />}
<Row gutter={16}>
{orderSupplierList.map(
(item: BusinessAPI.OrderSupplierVO) => {
return (
<Tag
style={{
cursor: 'pointer',
}}
onClick={() => {
// 直接使用 localStorage 中保存的数据
onFinish([item]);
setOrderSupplierVOStorage(item);
}}
key={item.orderSupplierId}
>
{item.name}
</Tag>
);
},
)}
</Row>
</>
);
}
},
}),
actionRef: actionRef,
toolbar: {
filter: (
<LightFilter
onFinish={async (values) => {
setParams({
...initParams,
...values,
});
}}
>
{extraFilter}
{/*<ProFormSelect*/}
{/* label={'供应商类型'}*/}
{/* name={'type'}*/}
{/* placeholder={'请选择供应商类型'}*/}
{/* valueEnum={{*/}
{/* FARMER: intl.formatMessage({*/}
{/* id: intlPrefix + '.column.type.farmer',*/}
{/* }),*/}
{/* STALL: intl.formatMessage({*/}
{/* id: intlPrefix + '.column.type.stall',*/}
{/* }),*/}
{/* OTHER_STALL: intl.formatMessage({*/}
{/* id: intlPrefix + '.column.type.otherStall',*/}
{/* }),*/}
{/* }}*/}
{/* fieldProps={{*/}
{/* showSearch: true,*/}
{/* allowClear: true,*/}
{/* autoClearSearchValue: true,*/}
{/* }}*/}
{/*/>*/}
<ProFormSelect
label={'是否付款'}
name={'isPaid'}
placeholder={'请选择是否付款'}
valueEnum={{
true: intl.formatMessage({
id: intlPrefix + '.column.isPaid.paid',
}),
false: intl.formatMessage({
id: intlPrefix + '.column.isPaid.unpaid',
}),
}}
fieldProps={{
showSearch: true,
allowClear: true,
autoClearSearchValue: true,
}}
/>
</LightFilter>
),
search: {
placeholder: '请输入供应商姓名',
onSearch: async (value: string) => {
setParams({
...params,
//@ts-ignore
name: value,
});
},
},
},
}}
onFinish={(orderSupplierVOList) => {
if (type === 'radio') {
if (orderSupplierVOList.length > 0) {
setOrderSupplierVOStorage(orderSupplierVOList[0]);
}
}
onFinish(orderSupplierVOList);
}}
num={num}
type={type}
/>
);
}

View File

@ -0,0 +1,38 @@
import { formatCurrency } from '@/utils/format';
import { ProCard } from '@ant-design/pro-components';
type IInvoicerStatisticCardProps = {
/** 开票方统计 */
title: string;
/** 车次 */
count: number;
/** 金额 */
amount: number;
/** 颜色 */
color: string;
};
/** 开票方统计卡片组件 */
export default function InvoicerStatisticCard(
props: IInvoicerStatisticCardProps,
) {
const { title, count, amount, color } = props;
return (
<ProCard bordered style={{ backgroundColor: color + '10' }}>
<div style={{ fontSize: 14, fontWeight: 500, marginBottom: 8, color }}>
{title}
</div>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<div>
<div style={{ fontSize: 12, color: '#999' }}></div>
<div style={{ fontSize: 20, fontWeight: 600 }}>{count}</div>
</div>
<div style={{ textAlign: 'right' }}>
<div style={{ fontSize: 12, color: '#999' }}></div>
<div style={{ fontSize: 20, fontWeight: 600 }}>
{formatCurrency(amount)}
</div>
</div>
</div>
</ProCard>
);
}

View File

@ -0,0 +1,84 @@
import { OrderList, SupplierFarmerList } from '@/components';
import { Space, Table, TableProps } from 'antd';
type IOrderSupplierInvoiceListProps = TableProps<BusinessAPI.OrderSupplierVO>;
export default function OrderSupplierInvoiceList(
props: IOrderSupplierInvoiceListProps,
) {
const { ...tableProps } = props;
// 订单列表列定义
const orderColumns = [
{
title: '采购单',
dataIndex: 'orderVO',
key: 'orderId',
render: (orderVO: BusinessAPI.OrderVO) => {
return (
orderVO && (
<OrderList
ghost={true}
mode={'detail'}
orderId={orderVO.orderId}
trigger={() => (
<Space>
<a>
{`${orderVO.orderVehicle?.dealerName} - 第 ${orderVO.orderVehicle?.vehicleNo || '暂无'} 车 - ${orderVO.orderSn || '暂无'}`}
</a>
</Space>
)}
/>
)
);
},
},
{
title: '瓜农名称',
key: 'name',
render: (orderSupplierVO: BusinessAPI.OrderSupplierVO) => {
return (
orderSupplierVO && (
<SupplierFarmerList
ghost={true}
mode={'detail'}
supplierId={orderSupplierVO.supplierId}
trigger={() => <a>{orderSupplierVO.name}</a>}
/>
)
);
},
},
{
title: '货款金额(元)',
dataIndex: 'invoiceAmount',
key: 'invoiceAmount',
valueType: 'money',
},
{
title: '定金金额(元)',
dataIndex: 'depositAmount',
key: 'depositAmount',
valueType: 'money',
},
{
title: '应付金额(元)',
key: 'remainingAmount',
valueType: 'money',
search: false,
render: (record: BusinessAPI.OrderSupplierVO) => {
return record.invoiceAmount - record.depositAmount || 0;
},
},
...(tableProps.columns || []),
];
return (
<Table
{...tableProps}
rowKey="orderSupplierId"
columns={orderColumns}
pagination={false}
size="small"
/>
);
}

View File

@ -0,0 +1,459 @@
import {
BizEditor,
ButtonAccess,
InsertPosition,
OrderSupplierInvoiceList,
} from '@/components';
import OrderSupplierModal from '@/components/Order/OrderSupplierModal';
import { business } from '@/services';
import { formatCurrency } from '@/utils/format';
import { formLayout } from '@/utils/formLayout';
import { useIntl } from '@@/exports';
import { PlusOutlined } from '@ant-design/icons';
import {
DrawerForm,
ProCard,
ProFormDependency,
ProFormItem,
ProFormSelect,
ProFormText,
RouteContext,
RouteContextType,
} from '@ant-design/pro-components';
import { Button, Col, Image, message, Row, Table, Tag } from 'antd';
import { useState } from 'react';
export interface IPaymentTaskCreateProps {
onFinish: () => void;
insertPosition?: InsertPosition;
}
export default function PaymentTaskCreate(props: IPaymentTaskCreateProps) {
const { onFinish } = props;
const intl = useIntl();
const intlPrefix = 'paymentTask';
const [selectedSupplier, setSelectedSupplier] =
useState<BusinessAPI.SupplierVO | null>(null);
const [selectedOrderSupplierList, setSelectedOrderSupplierList] = useState<
BusinessAPI.OrderSupplierVO[]
>([]);
const [orderSupplierModalOpen, setOrderSupplierModalOpen] = useState(false);
// 计算总金额和订单数量
const totalAmount = selectedOrderSupplierList.reduce(
(sum, order) =>
sum + (order.invoiceAmount || 0) - (order.depositAmount || 0),
0,
);
const orderCount = selectedOrderSupplierList.length;
const handleReset = () => {
setSelectedSupplier(null);
setSelectedOrderSupplierList([]);
};
console.log(selectedOrderSupplierList);
const handleSubmit = async (formData: any) => {
if (!selectedSupplier) {
message.error('请选择付款瓜农');
return false;
}
if (selectedOrderSupplierList.length === 0) {
message.error('请选择付款车次');
return false;
}
// 构建付款任务数据
const paymentTaskData: BusinessAPI.PaymentTaskCreateCmd = {
taskName: formData.taskName,
taskType: 'MELON_FARMER', // 瓜农付款任务
paymentCode: `PAY-${Date.now()}`, // 生成付款编码
targetId: selectedSupplier.supplierId,
totalAmount: totalAmount,
paidAmount: 0,
state: 'PENDING', // 待付款任务
orderCount: orderCount,
remark: formData.remark,
orderSupplierVOList: selectedOrderSupplierList,
};
const { success } =
await business.paymentTask.createPaymentTask(paymentTaskData);
if (success) {
message.success(
intl.formatMessage({
id: intlPrefix + '.modal.create.success',
}),
);
handleReset();
onFinish();
}
return success;
};
// 获取瓜农列表
const loadSupplierList = async () => {
const { data } = await business.supplier.listSupplier({
supplierListQry: {
type: 'FARMER',
status: true,
},
});
return (data || []).map((supplier: BusinessAPI.SupplierVO) => ({
label: supplier.name,
value: supplier.supplierId,
...supplier,
}));
};
return (
<>
<RouteContext.Consumer>
{(value: RouteContextType) => {
const { isMobile } = value;
return (
<DrawerForm<any>
title={intl.formatMessage({
id: intlPrefix + '.modal.create.title',
})}
{...formLayout(isMobile)}
width={isMobile ? '100%' : '85%'}
drawerProps={{
destroyOnHidden: true,
onClose: handleReset,
}}
trigger={
<ButtonAccess
key={'createPaymentTask'}
permission={'operation-paymentTask-create'}
type={'primary'}
size={'middle'}
icon={<PlusOutlined />}
>
{intl.formatMessage({
id: intlPrefix + '.modal.create.button',
})}
</ButtonAccess>
}
onFinish={handleSubmit}
>
{/* 选择瓜农 */}
<ProFormSelect
name="supplierId"
label={intl.formatMessage({
id: intlPrefix + '.form.supplier.label',
})}
placeholder={intl.formatMessage({
id: intlPrefix + '.form.supplier.placeholder',
})}
required={true}
showSearch={true}
request={loadSupplierList}
fieldProps={{
labelInValue: true,
}}
rules={[
{
required: true,
message: intl.formatMessage({
id: intlPrefix + '.form.supplier.required',
}),
},
]}
onChange={(value: any) => {
setSelectedSupplier(value);
// 切换瓜农时清空已选订单
setSelectedOrderSupplierList([]);
}}
/>
{/* 显示瓜农信息 */}
{selectedSupplier && (
<ProFormItem
label={'瓜农信息'}
style={{
width: '100%',
}}
>
<ProCard bordered style={{ marginBottom: 16 }}>
<Row gutter={[16, 16]}>
<Col span={6}>
<div>
<div style={{ color: '#999', marginBottom: 4 }}>
</div>
<div style={{ fontWeight: 'bold' }}>
{selectedSupplier.name}
</div>
</div>
</Col>
<Col span={6}>
<div>
<div style={{ color: '#999', marginBottom: 4 }}>
</div>
<div style={{ fontWeight: 'bold' }}>
{selectedSupplier.phone}
</div>
</div>
</Col>
<Col span={6}>
<div>
<div style={{ color: '#999', marginBottom: 4 }}>
</div>
<div style={{ fontWeight: 'bold' }}>
{selectedSupplier.bankCard}
</div>
</div>
</Col>
<Col span={6}>
<div>
<div style={{ color: '#999', marginBottom: 4 }}>
</div>
<div style={{ fontWeight: 'bold' }}>
{selectedSupplier.wechatQr ? (
<Image
width={80}
alt={'暂无'}
src={selectedSupplier.wechatQr}
/>
) : (
<div></div>
)}
</div>
</div>
</Col>
</Row>
</ProCard>
</ProFormItem>
)}
{/* 选择车次 */}
{selectedSupplier && (
<ProFormItem
label={'付款车次'}
style={{
width: '100%',
}}
>
<ProCard
bordered
title="选择需要付款的车次"
extra={
<Button
type="primary"
size="middle"
onClick={() => setOrderSupplierModalOpen(true)}
>
</Button>
}
style={{ marginBottom: 16 }}
>
{selectedOrderSupplierList.length > 0 ? (
<OrderSupplierInvoiceList
rowKey="orderSupplierId"
dataSource={selectedOrderSupplierList}
columns={[
{
title: '操作',
key: 'action',
render: (
_: any,
record: BusinessAPI.OrderSupplierVO,
) => (
<Button
type="link"
danger
onClick={() => {
setSelectedOrderSupplierList(
selectedOrderSupplierList.filter(
(item) =>
item.orderSupplierId !==
record.orderSupplierId,
),
);
}}
>
</Button>
),
},
]}
pagination={false}
size="small"
summary={(pageData) => {
let totalAmount = 0;
pageData.forEach(
({ invoiceAmount, depositAmount }) => {
totalAmount +=
(invoiceAmount || 0) - (depositAmount || 0);
},
);
return (
<Table.Summary fixed>
<Table.Summary.Row>
<Table.Summary.Cell index={0} colSpan={4}>
<strong></strong>
</Table.Summary.Cell>
<Table.Summary.Cell index={1}>
<strong style={{ color: '#ff4d4f' }}>
{formatCurrency(totalAmount)}
</strong>
</Table.Summary.Cell>
<Table.Summary.Cell index={2} />
</Table.Summary.Row>
</Table.Summary>
);
}}
/>
) : (
<div
style={{
textAlign: 'center',
padding: '40px 0',
color: '#999',
}}
>
</div>
)}
</ProCard>
</ProFormItem>
)}
{/* 任务信息 */}
{selectedOrderSupplierList.length > 0 && (
<>
<ProFormItem label={'任务摘要'} style={{ width: '100%' }}>
{/* 任务摘要 */}
<ProCard bordered style={{ marginBottom: 16 }}>
<Row gutter={[16, 16]}>
<Col span={6}>
<div>
<div style={{ color: '#999', marginBottom: 4 }}>
</div>
<div style={{ fontWeight: 'bold' }}>
{selectedSupplier?.name}
</div>
</div>
</Col>
<Col span={6}>
<div>
<div style={{ color: '#999', marginBottom: 4 }}>
</div>
<div style={{ fontWeight: 'bold' }}>
{orderCount}
</div>
</div>
</Col>
<Col span={6}>
<div>
<div style={{ color: '#999', marginBottom: 4 }}>
</div>
<div
style={{ fontWeight: 'bold', color: '#ff4d4f' }}
>
{formatCurrency(totalAmount)}
</div>
</div>
</Col>
<Col span={6}>
<div>
<div style={{ color: '#999', marginBottom: 4 }}>
</div>
<div>
<Tag color="orange"></Tag>
</div>
</div>
</Col>
</Row>
</ProCard>
</ProFormItem>
{/* 任务名称和备注 */}
<ProFormText
name="taskName"
label={intl.formatMessage({
id: intlPrefix + '.form.taskName.label',
})}
placeholder={intl.formatMessage({
id: intlPrefix + '.form.taskName.placeholder',
})}
required={true}
rules={[
{
required: true,
message: intl.formatMessage({
id: intlPrefix + '.form.taskName.required',
}),
},
]}
/>
<ProFormDependency key={'remark'} name={['remark']}>
{({ remark }, form) => {
return (
<BizEditor
key={'remark'}
value={remark}
onChange={(value) => {
form.setFieldValue('remark', value);
}}
label={intl.formatMessage({
id: intlPrefix + '.form.remark.label',
})}
name={'remark'}
placeholder={intl.formatMessage({
id: intlPrefix + '.form.remark.placeholder',
})}
/>
);
}}
</ProFormDependency>
</>
)}
</DrawerForm>
);
}}
</RouteContext.Consumer>
{/* 选择车次模态框 */}
<OrderSupplierModal
open={orderSupplierModalOpen}
title="选择需要付款的车次"
type="checkbox"
selectedList={selectedOrderSupplierList}
onFinish={(orderSupplierList) => {
// 过滤掉已经选择的订单
const newOrders = orderSupplierList.filter(
(item) =>
!selectedOrderSupplierList.some(
(selected) => selected.orderSupplierId === item.orderSupplierId,
),
);
setSelectedOrderSupplierList([
...selectedOrderSupplierList,
...newOrders,
]);
setOrderSupplierModalOpen(false);
}}
onCancel={() => setOrderSupplierModalOpen(false)}
params={{
type: 'FARMER',
isPaid: false,
}}
tips="请选择该瓜农未付款的车次"
num={999}
/>
</>
);
}

View File

@ -0,0 +1,505 @@
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,
}}
/>
);
}

View File

@ -0,0 +1,4 @@
export { default as InvoicerStatisticCard } from './InvoicerStatisticCard';
export { default as OrderSupplierInvoiceList } from './OrderSupplierInvoiceList';
export { default as PaymentTaskCreate } from './PaymentTaskCreate';
export { default as PaymentTaskList } from './PaymentTaskList';

View File

@ -18,7 +18,7 @@ import { ProDescriptionsItemProps } from '@ant-design/pro-descriptions';
import { ProFormUploadMaterial } from '@chageable/components'; import { ProFormUploadMaterial } from '@chageable/components';
import React, { useRef, useState } from 'react'; import React, { useRef, useState } from 'react';
interface IMelonFarmerListProps { interface ISupplierFarmerListProps {
ghost?: boolean; ghost?: boolean;
supplierId?: BusinessAPI.SupplierVO['supplierId']; supplierId?: BusinessAPI.SupplierVO['supplierId'];
search?: boolean; search?: boolean;
@ -27,7 +27,7 @@ interface IMelonFarmerListProps {
trigger?: () => React.ReactNode; trigger?: () => React.ReactNode;
} }
export default function MelonFarmerList(props: IMelonFarmerListProps) { export default function SupplierFarmerList(props: ISupplierFarmerListProps) {
const { const {
ghost = false, ghost = false,
supplierId, supplierId,
@ -37,7 +37,7 @@ export default function MelonFarmerList(props: IMelonFarmerListProps) {
onValueChange, onValueChange,
} = props; } = props;
const intl = useIntl(); const intl = useIntl();
const intlPrefix = 'melonFarmer'; const intlPrefix = 'supplierFarmer';
const actionRef = useRef<ActionType>(); const actionRef = useRef<ActionType>();
const [showIdCard, setShowIdCard] = useState<Record<string, boolean>>({}); const [showIdCard, setShowIdCard] = useState<Record<string, boolean>>({});
@ -60,7 +60,7 @@ export default function MelonFarmerList(props: IMelonFarmerListProps) {
render: (_, record) => ( render: (_, record) => (
<div className="flex items-center"> <div className="flex items-center">
<span> <span>
{formatIdCard(record.idCard, showIdCard[record.supplierId])} {formatIdCard(record.idCard!, showIdCard[record.supplierId])}
</span> </span>
<span <span
className="ml-2 cursor-pointer" className="ml-2 cursor-pointer"
@ -105,6 +105,12 @@ export default function MelonFarmerList(props: IMelonFarmerListProps) {
</div> </div>
), ),
}, },
{
title: intl.formatMessage({ id: intlPrefix + '.column.bankName' }),
dataIndex: 'bankName',
key: 'bankName',
search: false,
},
{ {
title: intl.formatMessage({ id: intlPrefix + '.column.bankCard' }), title: intl.formatMessage({ id: intlPrefix + '.column.bankCard' }),
dataIndex: 'bankCard', dataIndex: 'bankCard',
@ -201,6 +207,23 @@ export default function MelonFarmerList(props: IMelonFarmerListProps) {
}, },
]} ]}
/>, />,
<ProFormText
key={'bankName'}
name={'bankName'}
label={intl.formatMessage({ id: intlPrefix + '.form.bankName.label' })}
required={true}
placeholder={intl.formatMessage({
id: intlPrefix + '.form.bankName.placeholder',
})}
rules={[
{
required: true,
message: intl.formatMessage({
id: intlPrefix + '.form.bankName.required',
}),
},
]}
/>,
<ProFormText <ProFormText
key={'bankCard'} key={'bankCard'}
name={'bankCard'} name={'bankCard'}
@ -286,7 +309,9 @@ export default function MelonFarmerList(props: IMelonFarmerListProps) {
intlPrefix={intlPrefix} intlPrefix={intlPrefix}
modeType={mode} modeType={mode}
onValueChange={onValueChange} onValueChange={onValueChange}
container={{}} container={{
ghost,
}}
remark={{ remark={{
mode: 'editor', mode: 'editor',
}} }}

View File

@ -0,0 +1,309 @@
import {
BizContainer,
BizValueType,
MaterialList,
ModeType,
} from '@/components';
import { business } from '@/services';
import { formatBankCard, formatPhone } from '@/utils/format';
import { formatParam } from '@/utils/formatParam';
import { useIntl } from '@@/exports';
import { EyeInvisibleOutlined, EyeTwoTone } from '@ant-design/icons';
import {
ActionType,
ProColumns,
ProFormText,
} from '@ant-design/pro-components';
import { ProDescriptionsItemProps } from '@ant-design/pro-descriptions';
import { ProFormUploadMaterial } from '@chageable/components';
import React, { useRef, useState } from 'react';
interface ISupplierStallListProps {
ghost?: boolean;
supplierId?: BusinessAPI.SupplierVO['supplierId'];
search?: boolean;
onValueChange?: () => void;
mode?: ModeType;
trigger?: () => React.ReactNode;
}
export default function SupplierStallList(props: ISupplierStallListProps) {
const {
ghost = false,
supplierId,
search = true,
mode = 'page',
trigger,
onValueChange,
} = props;
const intl = useIntl();
const intlPrefix = 'supplierStall';
const actionRef = useRef<ActionType>();
const [showBankCard, setShowBankCard] = useState<Record<string, boolean>>({});
const [showPhone, setShowPhone] = useState<Record<string, boolean>>({});
const columns: ProColumns<BusinessAPI.SupplierVO, BizValueType>[] = [
{
title: intl.formatMessage({ id: intlPrefix + '.column.name' }),
dataIndex: 'name',
key: 'name',
renderText: (text: string) => <span className="font-medium">{text}</span>,
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.payeeName' }),
dataIndex: 'payeeName',
key: 'payeeName',
search: false,
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.phone' }),
dataIndex: 'phone',
key: 'phone',
render: (_, record) => (
<div className="flex items-center">
<span>{formatPhone(record.phone, showPhone[record.supplierId])}</span>
<span
className="ml-2 cursor-pointer"
onClick={() => {
setShowPhone((prev) => ({
...prev,
[record.supplierId]: !prev[record.supplierId],
}));
}}
>
{showPhone[record.supplierId] ? (
<EyeTwoTone />
) : (
<EyeInvisibleOutlined />
)}
</span>
</div>
),
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.bankName' }),
dataIndex: 'bankName',
key: 'bankName',
search: false,
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.bankCard' }),
dataIndex: 'bankCard',
key: 'bankCard',
render: (_, record) => (
<div className="flex items-center">
<span>
{formatBankCard(record.bankCard, showBankCard[record.supplierId])}
</span>
<span
className="ml-2 cursor-pointer"
onClick={() => {
setShowBankCard((prev) => ({
...prev,
[record.supplierId]: !prev[record.supplierId],
}));
}}
>
{showBankCard[record.supplierId] ? (
<EyeTwoTone />
) : (
<EyeInvisibleOutlined />
)}
</span>
</div>
),
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.wechatQr' }),
dataIndex: 'wechatQr',
valueType: 'image',
key: 'wechatQr',
search: false,
},
];
const formContext = [
<ProFormText key={'type'} name={'type'} hidden={true} />,
<ProFormText key={'payeeName'} name={'payeeName'} hidden={true} />,
<ProFormText
key={'name'}
name={'name'}
label={intl.formatMessage({ id: intlPrefix + '.form.name.label' })}
required={true}
placeholder={intl.formatMessage({
id: intlPrefix + '.form.name.placeholder',
})}
transform={(value) => {
return {
name: value,
payeeName: value,
};
}}
rules={[
{
required: true,
message: intl.formatMessage({
id: intlPrefix + '.form.name.required',
}),
},
]}
/>,
<ProFormText
key={'phone'}
name={'phone'}
label={intl.formatMessage({ id: intlPrefix + '.form.phone.label' })}
required={true}
placeholder={intl.formatMessage({
id: intlPrefix + '.form.phone.placeholder',
})}
rules={[
{
required: true,
message: intl.formatMessage({
id: intlPrefix + '.form.phone.required',
}),
},
]}
/>,
<ProFormText
key={'bankName'}
name={'bankName'}
label={intl.formatMessage({ id: intlPrefix + '.form.bankName.label' })}
required={true}
placeholder={intl.formatMessage({
id: intlPrefix + '.form.bankName.placeholder',
})}
rules={[
{
required: true,
message: intl.formatMessage({
id: intlPrefix + '.form.bankName.required',
}),
},
]}
/>,
<ProFormText
key={'bankCard'}
name={'bankCard'}
label={intl.formatMessage({ id: intlPrefix + '.form.bankCard.label' })}
required={true}
placeholder={intl.formatMessage({
id: intlPrefix + '.form.bankCard.placeholder',
})}
rules={[
{
required: true,
message: intl.formatMessage({
id: intlPrefix + '.form.bankCard.required',
}),
},
]}
/>,
<ProFormUploadMaterial
key={'wechatQr'}
label={intl.formatMessage({
id: intlPrefix + '.form.wechatQr.label',
})}
name={'wechatQrList'}
transform={(value) => {
return {
wechatQrList: value,
wechatQr: value[0],
};
}}
fieldProps={{
maxCount: 1,
actionRef: actionRef,
toolBarRender: () => [
<MaterialList
key={'create'}
ghost={true}
mode={'create'}
search={false}
onValueChange={() => actionRef.current?.reload()}
/>,
],
request: async (params, sorter, filter) => {
const { data, success, totalCount } =
await business.material.pageMaterial({
materialPageQry: formatParam<typeof params>(
params,
sorter,
filter,
),
});
return {
data: data || [],
total: totalCount,
success,
};
},
}}
/>,
];
const detailColumns: ProDescriptionsItemProps<
BusinessAPI.SupplierVO,
BizValueType
>[] = columns as ProDescriptionsItemProps<
BusinessAPI.SupplierVO,
BizValueType
>[];
return (
<BizContainer<
typeof business.supplier,
BusinessAPI.SupplierVO,
BusinessAPI.SupplierPageQry,
BusinessAPI.SupplierCreateCmd,
BusinessAPI.SupplierUpdateCmd
>
rowKey={'supplierId'}
permission={'operation-supplier'}
func={business.supplier}
method={'supplier'}
methodUpper={'Supplier'}
intlPrefix={intlPrefix}
modeType={mode}
onValueChange={onValueChange}
container={{}}
remark={{
mode: 'editor',
}}
status
page={{
fieldProps: {
bordered: true,
ghost,
//@ts-ignore
search,
params: {
type: 'OTHER_STALL',
},
},
columns,
}}
create={{
formType: 'drawer',
formContext,
initValues: {
status: true,
type: 'OTHER_STALL',
},
}}
update={{
formType: 'drawer',
formContext,
}}
destroy={{}}
detail={{
rowId: supplierId,
formType: 'drawer',
columns: detailColumns,
trigger,
}}
/>
);
}

View File

@ -0,0 +1,2 @@
export { default as SupplierFarmerList } from './SupplierFarmerList';
export { default as SupplierStallList } from './SupplierStallList';

View File

@ -8,16 +8,18 @@ export * from './Dealer';
export * from './Delivery'; export * from './Delivery';
export * from './Editor'; export * from './Editor';
export * from './Employee'; export * from './Employee';
export * from './Expense';
export { default as IconFont } from './Iconfont'; export { default as IconFont } from './Iconfont';
export { default as IconPicker } from './Iconfont/IconPicker'; export { default as IconPicker } from './Iconfont/IconPicker';
export * from './Material'; export * from './Material';
export * from './Menu'; export * from './Menu';
export * from './Order';
export * from './PaymentTask';
export * from './Permission'; export * from './Permission';
export { default as PhoneContainer } from './PhoneContainer'; export { default as PhoneContainer } from './PhoneContainer';
export * from './Platform'; export * from './Platform';
export * from './Order';
export * from './Remark'; export * from './Remark';
export * from './Role'; export * from './Role';
export * from './Setting'; export * from './Setting';
export * from './Supplier';
export * from './User'; export * from './User';
export * from './Expense';

View File

@ -1209,96 +1209,6 @@ export default {
}, },
}, },
}, },
melonFarmer: {
column: {
name: '瓜农姓名',
idCard: '身份证号',
phone: '手机号',
bankCard: '银行卡号',
wechatQr: '微信收款码',
remark: '备注',
status: '状态',
'status.enum.enabled': '正常',
'status.enum.disabled': '禁用',
'status.placeholder': '请选择状态',
createdAt: '创建时间',
option: '操作',
},
form: {
name: {
label: '姓名',
placeholder: '请输入姓名',
required: '姓名为必填项',
},
idCard: {
label: '身份证号',
placeholder: '请输入身份证号',
required: '身份证号为必填项',
},
phone: {
label: '手机号',
placeholder: '请输入手机号',
required: '手机号为必填项',
},
bankCard: {
label: '银行卡号',
placeholder: '请输入银行卡号',
required: '银行卡号为必填项',
},
wechatQr: {
label: '微信收款码',
placeholder: '请输入微信收款码',
required: '微信收款码为必填项',
},
remark: {
label: '备注',
placeholder: '请输入备注',
},
status: {
label: '状态',
placeholder: '请选择状态',
required: '状态为必填项',
enum: {
enabled: '正常',
disabled: '禁用',
},
},
},
modal: {
create: {
title: '新增瓜农',
button: '新增瓜农',
success: '新增瓜农成功',
},
update: {
title: '更新瓜农',
button: '编辑',
success: '更新瓜农成功',
status: {
success: '修改状态成功',
},
},
delete: {
success: '删除瓜农成功',
button: '删除',
confirm: {
title: '确认删除',
content: '您确定要删除该瓜农吗?',
okText: '确定',
cancelText: '取消',
},
},
import: {
title: '导入瓜农',
button: '导入',
success: '导入瓜农成功',
},
view: {
title: '查看瓜农',
button: '查看',
},
},
},
boxSpec: { boxSpec: {
column: { column: {
name: '规格名称', name: '规格名称',
@ -2541,6 +2451,289 @@ export default {
}, },
}, },
supplierFarmer: {
column: {
name: '瓜农姓名',
idCard: '身份证号',
phone: '手机号',
bankName: '银行名称',
bankCard: '银行卡号',
wechatQr: '微信收款码',
remark: '备注',
status: '状态',
'status.enum.enabled': '正常',
'status.enum.disabled': '禁用',
'status.placeholder': '请选择状态',
createdAt: '创建时间',
option: '操作',
},
form: {
name: {
label: '姓名',
placeholder: '请输入姓名',
required: '姓名为必填项',
},
idCard: {
label: '身份证号',
placeholder: '请输入身份证号',
required: '身份证号为必填项',
},
phone: {
label: '手机号',
placeholder: '请输入手机号',
required: '手机号为必填项',
},
bankName: {
label: '银行名称',
placeholder: '请输入银行名称',
required: '银行名为必填项',
},
bankCard: {
label: '银行卡号',
placeholder: '请输入银行卡号',
required: '银行卡号为必填项',
},
wechatQr: {
label: '微信收款码',
placeholder: '请输入微信收款码',
required: '微信收款码为必填项',
},
remark: {
label: '备注',
placeholder: '请输入备注',
},
status: {
label: '状态',
placeholder: '请选择状态',
required: '状态为必填项',
enum: {
enabled: '正常',
disabled: '禁用',
},
},
},
modal: {
create: {
title: '新增瓜农',
button: '新增瓜农',
success: '新增瓜农成功',
},
update: {
title: '更新瓜农',
button: '编辑',
success: '更新瓜农成功',
status: {
success: '修改状态成功',
},
},
delete: {
success: '删除瓜农成功',
button: '删除',
confirm: {
title: '确认删除',
content: '您确定要删除该瓜农吗?',
okText: '确定',
cancelText: '取消',
},
},
import: {
title: '导入瓜农',
button: '导入',
success: '导入瓜农成功',
},
view: {
title: '查看瓜农',
button: '查看',
},
},
},
paymentTask: {
column: {
taskName: '任务名称',
paymentCode: '付款编码',
supplier: '瓜农信息',
totalAmount: '付款总金额',
paidAmount: '已付金额',
unpaidAmount: '未付金额',
orderCount: '订单数量',
state: '付款状态',
createdAt: '创建时间',
remark: '备注',
option: '操作',
},
detail: {
tab: {
statistics: '瓜农车次统计',
invoicerStatistics: '开票方统计',
selfInvoiceList: '自开车次列表',
'selfInvoiceList.subTitle': '(实际瓜农=收款人,建议银行转账)',
proxyInvoiceList: '代开车次列表',
'proxyInvoiceList.subTitle':
'(实际瓜农≠开票方,注意核实收款人)',
noInvoiceList: '无发票车次列表',
'noInvoiceList.subTitle': '(需微信个人支付,必须上传截图)',
},
invoiceType: {
selfInvoice: '自开票',
proxyInvoice: '代开票',
noInvoice: '无发票',
},
},
tab: {
all: '全部',
pending: '待付款',
partial: '部分付款',
completed: '已完成',
cancelled: '已取消',
},
state: {
all: '全部',
pending: '待付款任务',
partial: '部分付款任务',
completed: '已完成任务',
cancelled: '已取消任务',
},
form: {
supplier: {
label: '付款瓜农',
placeholder: '请选择付款瓜农',
required: '请选择付款瓜农',
},
taskName: {
label: '任务名称',
placeholder: '请输入任务名称',
required: '任务名称为必填项',
},
remark: {
label: '任务备注',
placeholder: '请输入任务备注',
},
},
modal: {
create: {
title: '创建付款任务',
button: '创建付款任务',
success: '创建付款任务成功',
},
update: {
title: '更新付款任务',
button: '编辑',
success: '更新付款任务成功',
},
delete: {
success: '删除付款任务成功',
button: '删除',
confirm: {
title: '确认删除',
content: '您确定要删除该付款任务吗?',
okText: '确定',
cancelText: '取消',
},
},
view: {
title: '查看付款任务',
button: '详情',
},
},
},
supplierStall: {
column: {
name: '其他家档口姓名',
payeeName: '收款方名称',
phone: '手机号',
bankName: '银行名称',
bankCard: '银行卡号',
wechatQr: '微信收款码',
remark: '备注',
status: '状态',
'status.enum.enabled': '正常',
'status.enum.disabled': '禁用',
'status.placeholder': '请选择状态',
createdAt: '创建时间',
option: '操作',
},
form: {
name: {
label: '姓名',
placeholder: '请输入姓名',
required: '姓名为必填项',
},
payeeName: {
label: '收款方名称',
placeholder: '请输入收款方名称',
required: '收款方名称为必填项',
},
phone: {
label: '手机号',
placeholder: '请输入手机号',
required: '手机号为必填项',
},
bankName: {
label: '银行名称',
placeholder: '请输入银行名称',
required: '银行名称为必填项',
},
bankCard: {
label: '银行卡号',
placeholder: '请输入银行卡号',
required: '银行卡号为必填项',
},
wechatQr: {
label: '微信收款码',
placeholder: '请输入微信收款码',
required: '微信收款码为必填项',
},
remark: {
label: '备注',
placeholder: '请输入备注',
},
status: {
label: '状态',
placeholder: '请选择状态',
required: '状态为必填项',
enum: {
enabled: '正常',
disabled: '禁用',
},
},
},
modal: {
create: {
title: '新增其他家档口',
button: '新增其他家档口',
success: '新增其他家档口成功',
},
update: {
title: '更新其他家档口',
button: '编辑',
success: '更新其他家档口成功',
status: {
success: '修改状态成功',
},
},
delete: {
success: '删除其他家档口成功',
button: '删除',
confirm: {
title: '确认删除',
content: '您确定要删除该其他家档口吗?',
okText: '确定',
cancelText: '取消',
},
},
import: {
title: '导入其他家档口',
button: '导入',
success: '导入其他家档口成功',
},
view: {
title: '查看其他家档口',
button: '查看',
},
},
},
form: { form: {
orderId: { orderId: {
label: '采购单', label: '采购单',

View File

@ -0,0 +1,5 @@
import { PaymentTaskList } from '@/components';
export default function FarmerPaymentTask() {
return <PaymentTaskList />;
}

View File

@ -1,5 +0,0 @@
import { MelonFarmerList } from '@/components';
export default function Page() {
return <MelonFarmerList />;
}

View File

@ -0,0 +1,5 @@
import { SupplierFarmerList } from '@/components';
export default function Page() {
return <SupplierFarmerList />;
}

View File

@ -0,0 +1,5 @@
import { SupplierStallList } from '@/components';
export default function Page() {
return <SupplierStallList />;
}

View File

@ -29,19 +29,23 @@ import * as orderCost from './orderCost';
import * as orderRebate from './orderRebate'; import * as orderRebate from './orderRebate';
import * as orderShip from './orderShip'; import * as orderShip from './orderShip';
import * as orderSupplier from './orderSupplier'; import * as orderSupplier from './orderSupplier';
import * as paymentTask from './paymentTask';
import * as permission from './permission'; import * as permission from './permission';
import * as platform from './platform'; import * as platform from './platform';
import * as product from './product'; import * as product from './product';
import * as role from './role'; import * as role from './role';
import * as setting from './setting'; import * as setting from './setting';
import * as supplier from './supplier'; import * as supplier from './supplier';
import * as supplierInvoice from './supplierInvoice';
import * as user from './user'; import * as user from './user';
export default { export default {
user, user,
supplier, supplier,
supplierInvoice,
setting, setting,
product, product,
platform, platform,
paymentTask,
order, order,
orderSupplier, orderSupplier,
orderShip, orderShip,

View File

@ -2,21 +2,6 @@
/* eslint-disable */ /* eslint-disable */
import request from '../request'; import request from '../request';
/** 批量上传供应商发票 POST /operation/batchUploadInvoice */
export async function batchUploadInvoice(
body: BusinessAPI.OrderSupplierBatchInvoiceUploadCmd,
options?: { [key: string]: any },
) {
return request<BusinessAPI.Response>('/operation/batchUploadInvoice', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 订单供应商列表 GET /operation/pageOrderSupplier */ /** 订单供应商列表 GET /operation/pageOrderSupplier */
export async function pageOrderSupplier( export async function pageOrderSupplier(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象) // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)

View File

@ -0,0 +1,152 @@
// @ts-ignore
/* eslint-disable */
import request from '../request';
/** 创建付款任务 POST /operation/createPaymentTask */
export async function createPaymentTask(
body: BusinessAPI.PaymentTaskCreateCmd,
options?: { [key: string]: any },
) {
return request<BusinessAPI.SingleResponsePaymentTaskVO>(
'/operation/createPaymentTask',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
},
);
}
/** 付款任务删除 DELETE /operation/destroyPaymentTask */
export async function destroyPaymentTask(
body: BusinessAPI.PaymentTaskDestroyCmd,
options?: { [key: string]: any },
) {
return request<BusinessAPI.Response>('/operation/destroyPaymentTask', {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 付款任务列表 GET /operation/listPaymentTask */
export async function listPaymentTask(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: BusinessAPI.listPaymentTaskParams,
options?: { [key: string]: any },
) {
return request<BusinessAPI.MultiResponsePaymentTaskVO>(
'/operation/listPaymentTask',
{
method: 'GET',
params: {
...params,
paymentTaskListQry: undefined,
...params['paymentTaskListQry'],
},
...(options || {}),
},
);
}
/** 付款任务列表 GET /operation/pagePaymentTask */
export async function pagePaymentTask(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: BusinessAPI.pagePaymentTaskParams,
options?: { [key: string]: any },
) {
return request<BusinessAPI.PageResponsePaymentTaskVO>(
'/operation/pagePaymentTask',
{
method: 'GET',
params: {
...params,
paymentTaskPageQry: undefined,
...params['paymentTaskPageQry'],
},
...(options || {}),
},
);
}
/** 付款任务详情 GET /operation/showPaymentTask */
export async function showPaymentTask(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: BusinessAPI.showPaymentTaskParams,
options?: { [key: string]: any },
) {
return request<BusinessAPI.SingleResponsePaymentTaskVO>(
'/operation/showPaymentTask',
{
method: 'GET',
params: {
...params,
paymentTaskShowQry: undefined,
...params['paymentTaskShowQry'],
},
...(options || {}),
},
);
}
/** 付款任务统计 GET /operation/statisticsPaymentTask */
export async function statisticsPaymentTask(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: BusinessAPI.statisticsPaymentTaskParams,
options?: { [key: string]: any },
) {
return request<BusinessAPI.SingleResponsePaymentTaskStatisticsVO>(
'/operation/statisticsPaymentTask',
{
method: 'GET',
params: {
...params,
statisticsQry: undefined,
...params['statisticsQry'],
},
...(options || {}),
},
);
}
/** 付款任务更新 PUT /operation/updatePaymentTask */
export async function updatePaymentTask(
body: BusinessAPI.PaymentTaskUpdateCmd,
options?: { [key: string]: any },
) {
return request<BusinessAPI.SingleResponsePaymentTaskVO>(
'/operation/updatePaymentTask',
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
},
);
}
/** 付款任务更新 PATCH /operation/updatePaymentTask */
export async function updatePaymentTask1(
body: BusinessAPI.PaymentTaskUpdateCmd,
options?: { [key: string]: any },
) {
return request<BusinessAPI.SingleResponsePaymentTaskVO>(
'/operation/updatePaymentTask',
{
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
},
);
}

View File

@ -0,0 +1,132 @@
// @ts-ignore
/* eslint-disable */
import request from '../request';
/** 创建发票 POST /operation/createSupplierInvoice */
export async function createSupplierInvoice(
body: BusinessAPI.SupplierInvoiceCreateCmd,
options?: { [key: string]: any },
) {
return request<BusinessAPI.SingleResponseSupplierInvoiceVO>(
'/operation/createSupplierInvoice',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
},
);
}
/** 瓜农发票删除 DELETE /operation/destroySupplierInvoice */
export async function destroySupplierInvoice(
body: BusinessAPI.SupplierInvoiceDestroyCmd,
options?: { [key: string]: any },
) {
return request<BusinessAPI.Response>('/operation/destroySupplierInvoice', {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 瓜农发票列表 GET /operation/listSupplierInvoice */
export async function listSupplierInvoice(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: BusinessAPI.listSupplierInvoiceParams,
options?: { [key: string]: any },
) {
return request<BusinessAPI.MultiResponseSupplierInvoiceVO>(
'/operation/listSupplierInvoice',
{
method: 'GET',
params: {
...params,
supplierInvoiceListQry: undefined,
...params['supplierInvoiceListQry'],
},
...(options || {}),
},
);
}
/** 瓜农发票列表 GET /operation/pageSupplierInvoice */
export async function pageSupplierInvoice(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: BusinessAPI.pageSupplierInvoiceParams,
options?: { [key: string]: any },
) {
return request<BusinessAPI.PageResponseSupplierInvoiceVO>(
'/operation/pageSupplierInvoice',
{
method: 'GET',
params: {
...params,
supplierInvoicePageQry: undefined,
...params['supplierInvoicePageQry'],
},
...(options || {}),
},
);
}
/** 瓜农发票详情 GET /operation/showSupplierInvoice */
export async function showSupplierInvoice(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: BusinessAPI.showSupplierInvoiceParams,
options?: { [key: string]: any },
) {
return request<BusinessAPI.SingleResponseSupplierInvoiceVO>(
'/operation/showSupplierInvoice',
{
method: 'GET',
params: {
...params,
supplierInvoiceShowQry: undefined,
...params['supplierInvoiceShowQry'],
},
...(options || {}),
},
);
}
/** 瓜农发票更新 PUT /operation/updateSupplierInvoice */
export async function updateSupplierInvoice(
body: BusinessAPI.SupplierInvoiceUpdateCmd,
options?: { [key: string]: any },
) {
return request<BusinessAPI.SingleResponseSupplierInvoiceVO>(
'/operation/updateSupplierInvoice',
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
},
);
}
/** 瓜农发票更新 PATCH /operation/updateSupplierInvoice */
export async function updateSupplierInvoice1(
body: BusinessAPI.SupplierInvoiceUpdateCmd,
options?: { [key: string]: any },
) {
return request<BusinessAPI.SingleResponseSupplierInvoiceVO>(
'/operation/updateSupplierInvoice',
{
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
},
);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,135 @@
/** 订单供应商车次统计接口 */
interface IOrderSupplierStatistics {
/** 自开车次列表 */
selfInvoiceList: BusinessAPI.OrderSupplierVO[];
/** 代开车次列表 */
proxyInvoiceList: BusinessAPI.OrderSupplierVO[];
/** 无发票车次列表 */
noInvoiceList: BusinessAPI.OrderSupplierVO[];
/** 自开车次数量 */
selfInvoiceCount: number;
/** 代开车次数量 */
proxyInvoiceCount: number;
/** 无发票车次数量 */
noInvoiceCount: number;
/** 自开车次金额 */
selfInvoiceAmount: number;
/** 代开车次金额 */
proxyInvoiceAmount: number;
/** 无发票金额 */
noInvoiceAmount: number;
/** 开票方统计 */
invoicerStatistics: {
supplierName: string;
supplierId: string;
count: number;
amount: number;
}[];
}
/** 统计车次数据 */
const calculateOrderSupplierStatistics = (
orderSupplierList?: BusinessAPI.OrderSupplierVO[],
): IOrderSupplierStatistics => {
if (!orderSupplierList || orderSupplierList.length === 0) {
return {
selfInvoiceList: [],
proxyInvoiceList: [],
noInvoiceList: [],
selfInvoiceCount: 0,
proxyInvoiceCount: 0,
noInvoiceCount: 0,
selfInvoiceAmount: 0,
proxyInvoiceAmount: 0,
noInvoiceAmount: 0,
invoicerStatistics: [],
};
}
const selfInvoiceList: BusinessAPI.OrderSupplierVO[] = [];
const proxyInvoiceList: BusinessAPI.OrderSupplierVO[] = [];
const noInvoiceList: BusinessAPI.OrderSupplierVO[] = [];
const invoicerMap = new Map<
string,
{ count: number; amount: number; supplierName: string }
>();
for (const orderSupplier of orderSupplierList) {
const hasInvoice = !!orderSupplier.invoiceId;
const supplierInvoiceVO = orderSupplier.supplierInvoiceVO;
if (!hasInvoice) {
// 无发票车次
noInvoiceList.push(orderSupplier);
} else if (
supplierInvoiceVO &&
orderSupplier.supplierId === supplierInvoiceVO.supplierId
) {
// 自开车次
selfInvoiceList.push(orderSupplier);
// 统计开票方 - 使用 supplierId 作为分组键
const key = supplierInvoiceVO.supplierId;
const existing = invoicerMap.get(key) || {
count: 0,
amount: 0,
supplierName: supplierInvoiceVO.supplierName,
};
invoicerMap.set(key, {
count: existing.count + 1,
amount: existing.amount + (orderSupplier.invoiceAmount || 0),
supplierName: supplierInvoiceVO.supplierName,
});
} else {
// 代开车次
proxyInvoiceList.push(orderSupplier);
// 代开也统计开票方 - 使用 supplierId 作为分组键
if (supplierInvoiceVO) {
const key = supplierInvoiceVO.supplierId;
const existing = invoicerMap.get(key) || {
count: 0,
amount: 0,
supplierName: supplierInvoiceVO.supplierName,
};
invoicerMap.set(key, {
count: existing.count + 1,
amount:
existing.amount + (orderSupplier.invoiceAmount || 0),
supplierName: supplierInvoiceVO.supplierName,
});
}
}
}
const invoicerStatistics = Array.from(invoicerMap.entries()).map(
([supplierId, data]) => ({
supplierId,
supplierName: data.supplierName,
count: data.count,
amount: data.amount,
}),
);
return {
selfInvoiceList,
proxyInvoiceList,
noInvoiceList,
selfInvoiceCount: selfInvoiceList.length,
proxyInvoiceCount: proxyInvoiceList.length,
noInvoiceCount: noInvoiceList.length,
selfInvoiceAmount: selfInvoiceList.reduce(
(sum, item) => sum + (item.invoiceAmount || 0),
0,
),
proxyInvoiceAmount: proxyInvoiceList.reduce(
(sum, item) => sum + (item.invoiceAmount || 0),
0,
),
noInvoiceAmount: noInvoiceList.reduce(
(sum, item) => sum + (item.invoiceAmount || 0),
0,
),
invoicerStatistics,
};
};
export { calculateOrderSupplierStatistics };

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long