feat: 新增财务交易流水模块页面与接口
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* 文件职责:交易流水列表表格与本页汇总行。
|
||||
*/
|
||||
import type { TablePaginationConfig, TableProps } from 'ant-design-vue';
|
||||
|
||||
import type { FinanceTransactionListItemDto } from '#/api/finance';
|
||||
|
||||
import { h } from 'vue';
|
||||
|
||||
import { Button, Table, Tag } from 'ant-design-vue';
|
||||
|
||||
import {
|
||||
formatCurrency,
|
||||
formatSignedAmount,
|
||||
resolveAmountToneClass,
|
||||
resolveTransactionTypeTagColor,
|
||||
} from '../composables/transaction-page/helpers';
|
||||
|
||||
interface PaginationState {
|
||||
page: number;
|
||||
pageSize: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
loading: boolean;
|
||||
pageIncomeAmount: number;
|
||||
pageRefundAmount: number;
|
||||
pagination: PaginationState;
|
||||
rows: FinanceTransactionListItemDto[];
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'detail', transactionId: string): void;
|
||||
(event: 'orderDetail', orderNo: string): void;
|
||||
(event: 'pageChange', page: number, pageSize: number): void;
|
||||
}>();
|
||||
|
||||
const columns: TableProps['columns'] = [
|
||||
{
|
||||
title: '流水号',
|
||||
dataIndex: 'transactionNo',
|
||||
width: 180,
|
||||
customRender: ({ record }) =>
|
||||
h(
|
||||
Button,
|
||||
{
|
||||
type: 'link',
|
||||
class: 'ft-link-action ft-mono',
|
||||
onClick: () => emit('detail', String(record.transactionId ?? '')),
|
||||
},
|
||||
() => String(record.transactionNo ?? '--'),
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '关联订单',
|
||||
dataIndex: 'orderNo',
|
||||
width: 170,
|
||||
customRender: ({ record }) => {
|
||||
const orderNo = String(record.orderNo ?? '').trim();
|
||||
if (!orderNo) {
|
||||
return h('span', { class: 'ft-mono' }, '--');
|
||||
}
|
||||
|
||||
return h(
|
||||
Button,
|
||||
{
|
||||
type: 'link',
|
||||
class: 'ft-link-action ft-mono',
|
||||
onClick: () => emit('orderDetail', orderNo),
|
||||
},
|
||||
() => `#${orderNo}`,
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
dataIndex: 'typeText',
|
||||
width: 120,
|
||||
customRender: ({ record }) =>
|
||||
h(
|
||||
Tag,
|
||||
{ color: resolveTransactionTypeTagColor(String(record.type ?? '')) },
|
||||
() => String(record.typeText ?? '--'),
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '渠道',
|
||||
dataIndex: 'channel',
|
||||
width: 90,
|
||||
},
|
||||
{
|
||||
title: '支付方式',
|
||||
dataIndex: 'paymentMethod',
|
||||
width: 110,
|
||||
},
|
||||
{
|
||||
title: '金额',
|
||||
dataIndex: 'amount',
|
||||
width: 140,
|
||||
align: 'right',
|
||||
customRender: ({ record }) => {
|
||||
const amount = Number(record.amount || 0);
|
||||
return h(
|
||||
'span',
|
||||
{
|
||||
class: `ft-amount ${resolveAmountToneClass(amount, Boolean(record.isIncome))}`,
|
||||
},
|
||||
formatSignedAmount(amount, Boolean(record.isIncome)),
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '交易时间',
|
||||
dataIndex: 'occurredAt',
|
||||
width: 180,
|
||||
customRender: ({ text }) => h('span', { class: 'ft-time' }, String(text)),
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'remark',
|
||||
ellipsis: true,
|
||||
customRender: ({ text }) =>
|
||||
h(
|
||||
'span',
|
||||
{
|
||||
class: 'ft-remark',
|
||||
title: String(text ?? ''),
|
||||
},
|
||||
String(text || '--'),
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
function handleTableChange(next: TablePaginationConfig) {
|
||||
emit('pageChange', Number(next.current || 1), Number(next.pageSize || 20));
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="ft-table-card">
|
||||
<Table
|
||||
row-key="transactionId"
|
||||
:columns="columns"
|
||||
:data-source="props.rows"
|
||||
:loading="props.loading"
|
||||
:pagination="{
|
||||
current: props.pagination.page,
|
||||
pageSize: props.pagination.pageSize,
|
||||
total: props.pagination.total,
|
||||
showSizeChanger: true,
|
||||
pageSizeOptions: ['20', '50', '100'],
|
||||
showTotal: (total: number) => `共 ${total} 条`,
|
||||
}"
|
||||
@change="handleTableChange"
|
||||
>
|
||||
<template #summary>
|
||||
<Table.Summary.Row class="ft-summary-row">
|
||||
<Table.Summary.Cell :index="0" :col-span="5" align="right">
|
||||
本页合计
|
||||
</Table.Summary.Cell>
|
||||
<Table.Summary.Cell :index="5" align="right">
|
||||
<span class="ft-summary-text">
|
||||
收入 {{ formatCurrency(props.pageIncomeAmount) }} / 退款
|
||||
{{ formatCurrency(props.pageRefundAmount) }}
|
||||
</span>
|
||||
</Table.Summary.Cell>
|
||||
<Table.Summary.Cell :index="6" />
|
||||
<Table.Summary.Cell :index="7" />
|
||||
</Table.Summary.Row>
|
||||
</template>
|
||||
</Table>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user