187 lines
6.4 KiB
TypeScript
187 lines
6.4 KiB
TypeScript
import {Table, Typography} from "@douyinfe/semi-ui";
|
|
import {ColumnProps} from "@douyinfe/semi-ui/lib/es/table";
|
|
import dayjs from "dayjs";
|
|
import React, {useMemo, useState} from "react";
|
|
import {useTranslation} from "react-i18next";
|
|
import MoneyFormat from "@/components/money-format.tsx";
|
|
import {clone} from "lodash";
|
|
|
|
type BillListProps = {
|
|
type: 'query' | 'reconciliation';
|
|
operationRender?: (record: BillModel) => React.ReactNode;
|
|
onRowSelection?: (selectedRowKeys?: (string | number)[]) => void;
|
|
}
|
|
|
|
const mockBill: BillModel = {
|
|
actual_payment_amount: 110,
|
|
amount: 110,
|
|
application_no: "123123",
|
|
apply_status: "pending",
|
|
bill_status: "pending",
|
|
created_at: new Date(),
|
|
currency: "HKD",
|
|
department: "经管学院",
|
|
expiration_time: dayjs().add(30, "minute").toDate(),
|
|
id: 1123123,
|
|
paid_area: "HongKong,China",
|
|
paid_at: new Date(),
|
|
pay_amount: 110,
|
|
pay_method: "WechatHk",
|
|
payment_channel: "AsiaPay",
|
|
program_id: 123123,
|
|
service_charge: 0,
|
|
student_en_name: "SanF Chung",
|
|
student_no: "123123",
|
|
student_sc_name: "张三丰",
|
|
student_semester: "1",
|
|
student_tc_name: "张三丰",
|
|
student_year: "2024",
|
|
updated_at: "",
|
|
detail: [
|
|
{amount: 55, bill_id: 1123123, id: 1, type: "APPLICATION FEE"},
|
|
{amount: 50, bill_id: 1123123, id: 1, type: "TUITION FEE"},
|
|
{amount: 5, bill_id: 1123123, id: 1, type: "VISA FEE"},
|
|
]
|
|
}
|
|
|
|
export const BillList: React.FC<BillListProps> = (props) => {
|
|
const {t, i18n} = useTranslation()
|
|
const [data, setData] = useState<RecordList<BillModel>>({
|
|
list: Array(10).fill(mockBill).map((it, i) => {
|
|
const s = clone(it);
|
|
s.id = i;
|
|
if (i % 2 == 0) s.service_charge = 10
|
|
return s;
|
|
}),
|
|
pagination: {current: 1, pageSize: 10, total: 250}
|
|
});
|
|
console.log(data)
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
const handlePageChange = (current: number) => {
|
|
setLoading(true)
|
|
setTimeout(() => {
|
|
setData({
|
|
...data,
|
|
pagination: {current, pageSize: 10, total: 250}
|
|
})
|
|
setLoading(false)
|
|
}, 500)
|
|
};
|
|
|
|
const scroll = useMemo(() => ({y: 600, x: 800}), []);
|
|
|
|
const columns = useMemo<ColumnProps<BillModel>[]>(() => {
|
|
const cols: ColumnProps<BillModel>[] = [
|
|
{
|
|
title: '#',
|
|
dataIndex: 'id',
|
|
width: 80,
|
|
fixed: true,
|
|
},
|
|
{
|
|
title: t('bill.title_student_name_en'),
|
|
dataIndex: 'student_en_name',
|
|
fixed: true,
|
|
},
|
|
{
|
|
title: t('bill.title_student_name_sc'),
|
|
dataIndex: 'student_sc_name',
|
|
render: (_, record) => (`${record.student_tc_name}(${record.student_sc_name})`)
|
|
},
|
|
{
|
|
title: t('bill.title_bill_detail'),
|
|
dataIndex: 'detail',
|
|
width: 200,
|
|
render: (_, record) => (<div>
|
|
{record.detail.map(it => (<div>{it.type}:{it.amount}</div>))}
|
|
</div>),
|
|
},
|
|
{
|
|
title: t('bill.title_amount'),
|
|
dataIndex: 'amount',
|
|
render: (_) => (<MoneyFormat money={_}/>),
|
|
},
|
|
{
|
|
title: t('bill.title_pay_amount'),
|
|
dataIndex: 'pay_amount',
|
|
render: (_, record) => {
|
|
if (record.service_charge > 0) {
|
|
return <div>
|
|
<MoneyFormat money={record.pay_amount}/><br/>
|
|
<Typography.Text type={'quaternary'} size={'small'} style={{position: "absolute"}}>
|
|
{t('bill.title_service_charge')}: <MoneyFormat money={record.service_charge}/>
|
|
</Typography.Text>
|
|
</div>
|
|
}
|
|
return (<div>HK$ {_}</div>)
|
|
},
|
|
},
|
|
{
|
|
title: t('bill.title_actual_payment_amount'),
|
|
dataIndex: 'actual_payment_amount',
|
|
render: (_) => (<MoneyFormat money={_}/>),
|
|
},
|
|
{
|
|
title: t('bill.title_pay_method'),
|
|
dataIndex: 'pay_method',
|
|
render: (_, {pay_method, payment_channel}) => (<div>
|
|
{payment_channel}<br/>
|
|
<Typography.Text type={'quaternary'} size={'small'} style={{position: "absolute"}}>
|
|
({pay_method})
|
|
</Typography.Text>
|
|
</div>),
|
|
},
|
|
{
|
|
title: t('bill.title_bill_status'),
|
|
dataIndex: 'bill_status',
|
|
// render: value => dayjs(value).format('YYYY-MM-DD'),
|
|
},
|
|
]
|
|
if (props.type != 'reconciliation') {
|
|
cols.push({
|
|
title: t('bill.title_reconciliation_status'),
|
|
dataIndex: 'apply_status',
|
|
// render: value => dayjs(value).format('YYYY-MM-DD'),
|
|
})
|
|
}
|
|
if (props.operationRender) {
|
|
cols.push({
|
|
title: '',
|
|
dataIndex: 'operate',
|
|
fixed: 'right',
|
|
width: 300,
|
|
render: (_, record) => props.operationRender?.(record),
|
|
})
|
|
}
|
|
return cols;
|
|
}, [props.operationRender, props.type, i18n.language]);
|
|
|
|
|
|
return <div>
|
|
|
|
<div className="bill-list-table">
|
|
<Table<BillModel>
|
|
sticky={{top: 60}}
|
|
bordered
|
|
scroll={scroll}
|
|
columns={columns}
|
|
dataSource={data.list}
|
|
rowKey={'id'}
|
|
pagination={{
|
|
currentPage: data.pagination.current,
|
|
pageSize: data.pagination.pageSize,
|
|
total: data.pagination.total,
|
|
onPageChange: handlePageChange,
|
|
}}
|
|
loading={loading}
|
|
rowSelection={props.onRowSelection? {
|
|
fixed: true,
|
|
onChange: (selectedRowKeys, _selectedRows) => {
|
|
props.onRowSelection?.(selectedRowKeys)
|
|
}
|
|
}:undefined}
|
|
/>
|
|
</div>
|
|
</div>
|
|
} |