优化钱包界面:改名积分明细,添加筛选功能,优化表格列宽

- 侧边栏和页面标题改为'积分明细'
- 新增关联单号、收支类型筛选功能
- 后端 ledger API 支持 reference_no 和 type 筛选参数
- 表格列宽优化,流水号完整展示,备注列限制宽度
- 隐藏固定 tab 模式下的商户介绍文字
This commit is contained in:
yml2213
2026-07-31 20:18:06 +08:00
parent 8672ab2dca
commit 9a3471cc61
5 changed files with 76 additions and 19 deletions
+63 -14
View File
@@ -2,6 +2,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'
import { useLocation } from 'react-router-dom'
import {
Button,
Card,
Descriptions,
Form,
Input,
@@ -112,6 +113,7 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
const [testOrderResult, setTestOrderResult] = useState<CreateTestOrderResult | null>(null)
const [productForm] = Form.useForm()
const [walletForm] = Form.useForm()
const [walletFilterForm] = Form.useForm()
const [apiClientForm] = Form.useForm()
const [callbackForm] = Form.useForm()
const [memberForm] = Form.useForm()
@@ -192,11 +194,12 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
page = ledger.page,
size = ledger.size,
role = merchantRole,
filters?: { reference_no?: string; type?: string },
) => {
const walletData = await merchantApi.wallet()
setWallet(walletData)
if (role === 'owner' || role === 'finance') {
const ledgerData = await merchantApi.ledger({ page, size })
const ledgerData = await merchantApi.ledger({ page, size, ...filters })
setLedger(ledgerData)
} else {
setLedger({ list: [], total: 0, page, size })
@@ -337,6 +340,19 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
}
}
const handleWalletFilter = async () => {
const values = await walletFilterForm.validateFields()
loadWallet(1, ledger.size, merchantRole, {
reference_no: values.reference_no || undefined,
type: values.type || undefined,
})
}
const handleWalletFilterReset = () => {
walletFilterForm.resetFields()
loadWallet(1, ledger.size, merchantRole, {})
}
const openTestOrderCreate = () => {
testOrderForm.resetFields()
testOrderForm.setFieldsValue({
@@ -515,13 +531,13 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
]
const ledgerColumns: ColumnsType<WalletLedgerEntry> = [
{ title: '流水号', dataIndex: 'entry_no', width: 210, ellipsis: true },
{ title: '类型', dataIndex: 'type', width: 90, render: ledgerTypeTag },
{ title: '金额', dataIndex: 'amount', width: 110, render: moneyWithSign },
{ title: '余额', dataIndex: 'balance_after', width: 110, render: money },
{ title: '关联单号', dataIndex: 'reference_no', ellipsis: true },
{ title: '备注', dataIndex: 'note', ellipsis: true, render: (v) => v || '-' },
{ title: '时间', dataIndex: 'created_at', width: 180, render: formatDateTime },
{ title: '流水号', dataIndex: 'entry_no', width: 300, render: (v) => <Typography.Text code copyable={{ tooltips: false }}>{v}</Typography.Text> },
{ title: '类型', dataIndex: 'type', width: 80, render: ledgerTypeTag },
{ title: '金额', dataIndex: 'amount', width: 120, render: moneyWithSign },
{ title: '余额', dataIndex: 'balance_after', width: 120, render: money },
{ title: '关联单号', dataIndex: 'reference_no', width: 200, ellipsis: true, render: (v) => v ? <Typography.Text code ellipsis style={{ maxWidth: '100%' }}>{v}</Typography.Text> : '-' },
{ title: '备注', dataIndex: 'note', width: 150, ellipsis: { showTitle: false }, render: (v) => <Typography.Text ellipsis title={v}>{v || '-'}</Typography.Text> },
{ title: '时间', dataIndex: 'created_at', width: 170, render: formatDateTime },
]
const apiClientColumns: ColumnsType<ApiClient> = [
@@ -612,14 +628,15 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
const walletContent = (
<Space direction="vertical" style={{ width: '100%' }} size="middle">
<Space style={{ width: '100%', justifyContent: 'space-between' }}>
<Descriptions size="small" bordered column={3} style={{ flex: 1 }}>
<Space style={{ width: '100%', justifyContent: 'space-between' }} size="large">
<Descriptions size="small" bordered column={3}>
<Descriptions.Item label="可用余额">{money(wallet?.available_balance ?? 0)}</Descriptions.Item>
<Descriptions.Item label="冻结余额">{money(wallet?.frozen_balance ?? 0)}</Descriptions.Item>
<Descriptions.Item label="币种">{wallet?.currency || 'POINT'}</Descriptions.Item>
</Descriptions>
{canFinance && (
<Button
type="primary"
icon={<WalletOutlined />}
onClick={() => {
walletForm.resetFields()
@@ -631,6 +648,29 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
</Button>
)}
</Space>
{canFinance && (
<Card size="small" style={{ background: '#fafafa' }}>
<Form form={walletFilterForm} layout="inline" onFinish={handleWalletFilter}>
<Form.Item name="reference_no" label="关联单号">
<Input placeholder="店铺单号 / 充值单号" allowClear style={{ width: 220 }} />
</Form.Item>
<Form.Item name="type" label="收支">
<Select placeholder="请选择" allowClear style={{ width: 120 }}>
<Select.Option value="credit"></Select.Option>
<Select.Option value="debit"></Select.Option>
<Select.Option value="refund">退</Select.Option>
<Select.Option value="adjust"></Select.Option>
</Select>
</Form.Item>
<Form.Item>
<Space>
<Button onClick={handleWalletFilterReset}></Button>
<Button type="primary" htmlType="submit"></Button>
</Space>
</Form.Item>
</Form>
</Card>
)}
{canFinance ? (
<Table
rowKey="id"
@@ -638,7 +678,14 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
columns={ledgerColumns}
dataSource={ledger.list}
tableLayout="fixed"
pagination={pageConfig(ledger, loadWallet)}
scroll={{ x: 1300 }}
pagination={pageConfig(ledger, (page, size) => {
const values = walletFilterForm.getFieldsValue()
loadWallet(page, size, merchantRole, {
reference_no: values.reference_no || undefined,
type: values.type || undefined,
})
})}
/>
) : (
<Typography.Text type="secondary"></Typography.Text>
@@ -705,9 +752,11 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
<Typography.Title level={4} style={{ margin: 0 }}>
{title}
</Typography.Title>
<Typography.Text type="secondary">
{merchant ? `${merchant.name} / ${merchant.code}` : '加载中'} · {merchantRole ? roleText(merchantRole) : '-'}
</Typography.Text>
{!fixedTab && (
<Typography.Text type="secondary">
{merchant ? `${merchant.name} / ${merchant.code}` : '加载中'} · {merchantRole ? roleText(merchantRole) : '-'}
</Typography.Text>
)}
</div>
<Button icon={<ReloadOutlined />} loading={loading} onClick={loadAll}>