import React, { useEffect, useRef, useState } from 'react'; import { Button, Descriptions, Drawer, Dropdown, Tag, Typography, } from 'antd'; import { DownloadOutlined } from '@ant-design/icons'; import XinTable from '@/components/XinTable'; import type { XinTableColumn, XinTableInstance, XinTableProps, } from '@/components/XinTable/typings.ts'; import type ISettlement from '@/domain/iSettlement.ts'; import { SETTLEMENT_STATUS_MAP } from '@/domain/iSettlement.ts'; import { getStoreOptions } from '@/api/customer/store.ts'; import type IStore from '@/domain/iStore.ts'; import { downloadSettlement } from '@/api/recon/settlement.ts'; import { Get } from '@/api/common/table.ts'; import AuthButton from '@/components/AuthButton'; const { Title, Text } = Typography; /** * 结算表(D9 生成于对账结算,D10 导出存档) */ const SettlementPage: React.FC = () => { const tableRef = useRef>(null); const [stores, setStores] = useState([]); const [detailOpen, setDetailOpen] = useState(false); const [detail, setDetail] = useState(null); const [detailLoading, setDetailLoading] = useState(false); useEffect(() => { getStoreOptions().then((res) => setStores(res.data.data ?? [])); }, []); const openDetail = async (id: number) => { setDetailOpen(true); setDetailLoading(true); try { const res = await Get('/recon/settlement', id); setDetail(res.data.data ?? null); } finally { setDetailLoading(false); } }; const columns: XinTableColumn[] = [ { title: '结算单号', dataIndex: 'settlement_no', valueType: 'text', hideInForm: true, render: (_, record) => {record.settlement_no}, }, { 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 ?? '-', }, { title: '来源对账单', dataIndex: 'recon', hideInForm: true, hideInSearch: true, render: (_, record) => record.recon ? ( {record.recon.recon_no} ({record.recon.title}) ) : ( '-' ), }, { title: '结算周期', dataIndex: 'period', hideInForm: true, hideInSearch: true, render: (_, record) => `${record.period_start} ~ ${record.period_end}`, }, { title: '公布金额', dataIndex: 'total_amount', hideInForm: true, hideInSearch: true, align: 'right', render: (_, record) => `¥${record.total_amount}`, }, { title: '实际金额', dataIndex: 'actual_amount', hideInForm: true, hideInSearch: true, align: 'right', render: (_, record) => ¥{record.actual_amount}, }, { title: '差额', dataIndex: 'diff_amount', hideInForm: true, hideInSearch: true, align: 'right', render: (_, record) => { const num = Number(record.diff_amount ?? 0); return ( ¥{record.diff_amount} ); }, }, { title: '状态', dataIndex: 'status', valueType: 'select', hideInForm: true, fieldProps: { options: Object.entries(SETTLEMENT_STATUS_MAP).map(([value, item]) => ({ value: Number(value), label: item.text, })), }, render: (_, record) => { const item = SETTLEMENT_STATUS_MAP[record.status ?? 0]; return {item?.text}; }, align: 'center', }, { title: '结算时间', dataIndex: 'settled_at', hideInForm: true, hideInSearch: true, align: 'center', render: (_, record) => record.settled_at ?? '-', }, ]; const operateRender: XinTableProps['operateRender'] = (record) => [ , downloadSettlement(record.id!, 'xlsx') }, { key: 'pdf', label: '下载 PDF', onClick: () => downloadSettlement(record.id!, 'pdf') }, ], }} > , ]; const tableProps: XinTableProps = { api: '/recon/settlement', columns, rowKey: 'id', accessName: 'recon.settlement', tableRef, operateRender, formProps: false, scroll: { x: 1200 }, }; return ( <>
结算表 由财务对账结算按门店聚合生成;支持 Excel / PDF 导出存档(回框统计表规则待业务确认后补充)。
{...tableProps} /> setDetailOpen(false)} width={640} loading={detailLoading} > {detail ? ( {detail.store?.name} {SETTLEMENT_STATUS_MAP[detail.status ?? 0]?.text} {detail.recon?.recon_no ?? '-'} {detail.period_start} ~ {detail.period_end} ¥{detail.total_amount} ¥{detail.actual_amount} ¥{detail.diff_amount} {detail.settled_at ?? '-'} {detail.file_path ?? 未导出} {detail.remark ? ( {detail.remark} ) : null} ) : null} ); }; export default SettlementPage;