优化积分明细与商户中心UI排版

This commit is contained in:
yml2213
2026-08-04 11:07:52 +08:00
parent 627d5cafa6
commit 71bdbf527c
+85 -35
View File
@@ -3,12 +3,14 @@ import { useLocation } from 'react-router-dom'
import {
Button,
Card,
Col,
Descriptions,
Form,
Input,
InputNumber,
Modal,
Popconfirm,
Row,
Select,
Space,
Table,
@@ -19,7 +21,9 @@ import {
} from 'antd'
import {
ApiOutlined,
ClockCircleOutlined,
CopyOutlined,
DollarOutlined,
LinkOutlined,
PlusOutlined,
ReloadOutlined,
@@ -28,6 +32,7 @@ import {
import type { ColumnsType } from 'antd/es/table'
import { merchantApi } from '../api'
import { formatDateTime } from '../utils/time'
import { PageHeader } from '../components/PageHeader'
import type {
ApiClient,
ApiCredential,
@@ -553,13 +558,13 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
]
const ledgerColumns: ColumnsType<WalletLedgerEntry> = [
{ 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: 'entry_no', width: 260, render: (v) => <Typography.Text code copyable={{ tooltips: false }}>{v}</Typography.Text> },
{ title: '类型', dataIndex: 'type', width: 90, render: ledgerTypeTag },
{ title: '变动积分', dataIndex: 'amount', width: 130, render: moneyWithSign },
{ title: '结余积分', dataIndex: 'balance_after', width: 130, render: (v) => <span style={{ fontWeight: 600, color: '#0f172a' }}>{money(v)}</span> },
{ 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 },
{ title: '备注说明', dataIndex: 'note', width: 220, 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> = [
@@ -645,38 +650,88 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
const walletContent = (
<Space direction="vertical" style={{ width: '100%' }} size="middle">
<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>
<Row gutter={[16, 16]}>
<Col xs={24} sm={8}>
<div className="metric-card-box">
<div className="metric-card-header">
<span className="metric-card-title"></span>
<div className="metric-card-icon metric-card-icon--emerald"><WalletOutlined /></div>
</div>
<div className="metric-card-value" style={{ color: '#16a34a' }}>
{(wallet?.available_balance ?? 0).toLocaleString('zh-CN')}
<span style={{ fontSize: 13, fontWeight: 500, marginLeft: 4, color: '#64748b' }}></span>
</div>
{canFinance && (
<div className="metric-card-footer">
<span>/</span>
<Button
type="primary"
type="link"
size="small"
icon={<WalletOutlined />}
style={{ padding: 0, height: 'auto' }}
onClick={() => {
walletForm.resetFields()
walletForm.setFieldsValue({ idempotency_key: `manual-${Date.now()}` })
setWalletOpen(true)
}}
>
/
</Button>
</div>
)}
</Space>
</div>
</Col>
<Col xs={24} sm={8}>
<div className="metric-card-box">
<div className="metric-card-header">
<span className="metric-card-title"></span>
<div className="metric-card-icon"><ClockCircleOutlined /></div>
</div>
<div className="metric-card-value">
{(wallet?.frozen_balance ?? 0).toLocaleString('zh-CN')}
<span style={{ fontSize: 13, fontWeight: 500, marginLeft: 4, color: '#64748b' }}></span>
</div>
<div className="metric-card-footer">
<span>/</span>
<span style={{ fontWeight: 600, color: '#0f172a' }}>0 </span>
</div>
</div>
</Col>
<Col xs={24} sm={8}>
<div className="metric-card-box">
<div className="metric-card-header">
<span className="metric-card-title"></span>
<div className="metric-card-icon metric-card-icon--purple"><DollarOutlined /></div>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 4 }}>
<Tag color="blue" style={{ fontSize: 13, padding: '2px 8px', borderRadius: 4, margin: 0, fontWeight: 600 }}>
{wallet?.currency || 'POINT'}
</Tag>
<span className="status-tag status-tag--green">
<span className="status-dot"></span>
</span>
</div>
<div className="metric-card-footer">
<span></span>
<span style={{ fontWeight: 600, color: '#0f172a' }}></span>
</div>
</div>
</Col>
</Row>
{canFinance && (
<Card size="small" style={{ background: '#fafafa' }}>
<Card size="small" style={{ background: '#f8fafc', border: '1px solid #e2e8f0', borderRadius: 8 }}>
<Form form={walletFilterForm} layout="inline" onFinish={handleWalletFilter}>
<Form.Item name="reference_no" label="关联单号">
<Input placeholder="店铺单号 / 充值单号" allowClear style={{ width: 220 }} />
<Input placeholder="店铺单号 / 充值单号" allowClear style={{ width: 220, borderRadius: 6 }} />
</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>
<Form.Item name="type" label="收支类型">
<Select placeholder="全部类型" allowClear style={{ width: 140 }}>
<Select.Option value="credit"> (Credit)</Select.Option>
<Select.Option value="debit"> (Debit)</Select.Option>
<Select.Option value="refund">退 (Refund)</Select.Option>
<Select.Option value="adjust"> (Adjust)</Select.Option>
</Select>
</Form.Item>
<Form.Item>
@@ -796,21 +851,16 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
return (
<div>
<Space style={{ marginBottom: 16, width: '100%', justifyContent: 'space-between' }}>
<div>
<Typography.Title level={4} style={{ margin: 0 }}>
{title}
</Typography.Title>
{!fixedTab && (
<Typography.Text type="secondary">
{merchant ? `${merchant.name} / ${merchant.code}` : '加载中'} · {merchantRole ? roleText(merchantRole) : '-'}
</Typography.Text>
)}
</div>
<PageHeader
title={title}
subtitle={merchant ? `${merchant.name} (${merchant.code}) · 当前身份: ${merchantRole ? roleText(merchantRole) : '-'}` : '商户配置与管理中心'}
breadcrumbs={[{ title: title }]}
extra={
<Button icon={<ReloadOutlined />} loading={loading} onClick={loadAll}>
</Button>
</Space>
}
/>
{fixedTab ? fixedTabContent : (
<Tabs