import React, { useEffect, useState } from 'react'; import { Button, DatePicker, Form, Modal, Select, Typography } from 'antd'; import { DownloadOutlined } from '@ant-design/icons'; import dayjs from 'dayjs'; import XinTable from '@/components/XinTable'; import type { XinTableColumn, XinTableProps } from '@/components/XinTable/typings.ts'; import type IContainerReturn from '@/domain/iContainerReturn.ts'; import { getStoreOptions } from '@/api/customer/store.ts'; import { exportContainerReturns } from '@/api/recon/containerReturn.ts'; import type IStore from '@/domain/iStore.ts'; import AuthButton from '@/components/AuthButton'; const { Title, Text } = Typography; const { RangePicker } = DatePicker; /** 汇总导出表单值 */ interface ExportFormValues { date_range: [dayjs.Dayjs, dayjs.Dayjs]; store_ids?: number[]; } /** 有符号数量展示:正数=压筐(橙色 +N),负数=回筐(绿色 N),0 置灰 */ const SignedNum: React.FC<{ value?: number }> = ({ value }) => { const num = Number(value ?? 0); if (num > 0) { return +{num}; } if (num < 0) { return {num}; } return 0; }; /** 有符号金额展示:正=压筐附加(橙),负=回筐抵扣(绿) */ const SignedAmount: React.FC<{ value?: string }> = ({ value }) => { const num = Number(value ?? 0); if (num > 0) { return +¥{num.toFixed(2)}; } if (num < 0) { return -¥{Math.abs(num).toFixed(2)}; } return ¥0.00; }; /** * 压回筐记录(周转筐/托盘跟账单走:生成账单时自动写入完整快照,只读) * 数量正数=压筐(附加金额),负数=回筐(抵扣金额) */ const ContainerReturnPage: React.FC = () => { const [stores, setStores] = useState([]); // 汇总导出(日期区间 + 门店:行=日期,列=门店,单元格为抵扣/附加金额) const [exportOpen, setExportOpen] = useState(false); const [exporting, setExporting] = useState(false); const [exportForm] = Form.useForm(); useEffect(() => { getStoreOptions().then((res) => setStores(res.data.data ?? [])); }, []); /** 提交汇总导出:下载失败时 downloadBlob 内部已提示 */ const handleExport = async (values: ExportFormValues) => { const [start, end] = values.date_range; setExporting(true); try { await exportContainerReturns( start.format('YYYY-MM-DD'), end.format('YYYY-MM-DD'), values.store_ids ?? [] ); setExportOpen(false); } finally { setExporting(false); } }; const columns: XinTableColumn[] = [ { title: '门店', dataIndex: 'store_id', valueType: 'select', hideInForm: true, fieldProps: { options: stores.map((s) => ({ label: s.name, value: s.id })), showSearch: true, optionFilterProp: 'label', }, render: (_, record) => record.store?.name ?? `门店#${record.store_id}`, }, { title: '关联账单', dataIndex: 'bill_id', hideInForm: true, hideInSearch: true, render: (_, record) => record.bill ? ( <> {record.bill.bill_no}
{record.bill.bill_date}
) : '-', }, { title: '压(回)筐数量', dataIndex: 'box_num', hideInForm: true, hideInSearch: true, align: 'center', render: (_, record) => , }, { title: '压(回)托盘数量', dataIndex: 'tray_num', hideInForm: true, hideInSearch: true, align: 'center', render: (_, record) => , }, { title: '筐单价', dataIndex: 'box_price', hideInForm: true, hideInSearch: true, align: 'center', render: (_, record) => `¥${Number(record.box_price ?? 0).toFixed(2)}`, }, { title: '托盘单价', dataIndex: 'tray_price', hideInForm: true, hideInSearch: true, align: 'center', render: (_, record) => `¥${Number(record.tray_price ?? 0).toFixed(2)}`, }, { title: '抵扣(附加)金额', dataIndex: 'amount', hideInForm: true, hideInSearch: true, align: 'center', render: (_, record) => , }, { title: '操作人', dataIndex: 'operator', hideInForm: true, hideInSearch: true, align: 'center', render: (_, record) => record.operator?.nickname ?? '-', }, { title: '记录时间', dataIndex: 'created_at', valueType: 'dateRange', hideInForm: true, hideInTable: true, align: 'center', }, { title: '记录时间', dataIndex: 'created_at', hideInForm: true, hideInSearch: true, align: 'center', }, ]; const tableProps: XinTableProps = { api: '/recon/container-return', columns, rowKey: 'id', accessName: 'recon.containerReturn', // 记录随账单生成,只读:不新增、不编辑、不删除 addShow: false, editShow: false, deleteShow: false, formProps: false, toolBarRender: (dom) => [ , dom.columnSetting, dom.hideBorder, dom.reload, dom.columnHeight, ], }; return ( <>
回筐记录 周转筐/托盘跟账单走:生成账单时按填写数量自动写入;正数=压筐(附加金额),负数=回筐(抵扣金额),数量为 0 不生成记录; 可按日期区间与门店汇总导出(行=日期,列=门店,含行列合计)。
{...tableProps} /> {/* 汇总导出:日期区间 + 门店,同日记录合并,无记录填 0 */} setExportOpen(false)} onOk={() => exportForm.submit()} confirmLoading={exporting} okText="导出" destroyOnHidden >
按日期区间与门店导出抵扣(附加)金额汇总表:行=日期(同日记录合并),列=门店, 当天门店无记录填 0,含行合计与列合计。门店不选默认导出全部门店。