优化积分明细与商户中心UI排版
This commit is contained in:
@@ -3,12 +3,14 @@ import { useLocation } from 'react-router-dom'
|
|||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
|
Col,
|
||||||
Descriptions,
|
Descriptions,
|
||||||
Form,
|
Form,
|
||||||
Input,
|
Input,
|
||||||
InputNumber,
|
InputNumber,
|
||||||
Modal,
|
Modal,
|
||||||
Popconfirm,
|
Popconfirm,
|
||||||
|
Row,
|
||||||
Select,
|
Select,
|
||||||
Space,
|
Space,
|
||||||
Table,
|
Table,
|
||||||
@@ -19,7 +21,9 @@ import {
|
|||||||
} from 'antd'
|
} from 'antd'
|
||||||
import {
|
import {
|
||||||
ApiOutlined,
|
ApiOutlined,
|
||||||
|
ClockCircleOutlined,
|
||||||
CopyOutlined,
|
CopyOutlined,
|
||||||
|
DollarOutlined,
|
||||||
LinkOutlined,
|
LinkOutlined,
|
||||||
PlusOutlined,
|
PlusOutlined,
|
||||||
ReloadOutlined,
|
ReloadOutlined,
|
||||||
@@ -28,6 +32,7 @@ import {
|
|||||||
import type { ColumnsType } from 'antd/es/table'
|
import type { ColumnsType } from 'antd/es/table'
|
||||||
import { merchantApi } from '../api'
|
import { merchantApi } from '../api'
|
||||||
import { formatDateTime } from '../utils/time'
|
import { formatDateTime } from '../utils/time'
|
||||||
|
import { PageHeader } from '../components/PageHeader'
|
||||||
import type {
|
import type {
|
||||||
ApiClient,
|
ApiClient,
|
||||||
ApiCredential,
|
ApiCredential,
|
||||||
@@ -553,13 +558,13 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
|
|||||||
]
|
]
|
||||||
|
|
||||||
const ledgerColumns: ColumnsType<WalletLedgerEntry> = [
|
const ledgerColumns: ColumnsType<WalletLedgerEntry> = [
|
||||||
{ title: '流水号', dataIndex: 'entry_no', width: 300, render: (v) => <Typography.Text code copyable={{ tooltips: false }}>{v}</Typography.Text> },
|
{ title: '流水号', dataIndex: 'entry_no', width: 260, render: (v) => <Typography.Text code copyable={{ tooltips: false }}>{v}</Typography.Text> },
|
||||||
{ title: '类型', dataIndex: 'type', width: 80, render: ledgerTypeTag },
|
{ title: '类型', dataIndex: 'type', width: 90, render: ledgerTypeTag },
|
||||||
{ title: '金额', dataIndex: 'amount', width: 120, render: moneyWithSign },
|
{ title: '变动积分', dataIndex: 'amount', width: 130, render: moneyWithSign },
|
||||||
{ title: '余额', dataIndex: 'balance_after', width: 120, render: money },
|
{ 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: '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: 'note', width: 220, ellipsis: { showTitle: false }, render: (v) => <Typography.Text ellipsis title={v}>{v || '-'}</Typography.Text> },
|
||||||
{ title: '时间', dataIndex: 'created_at', width: 170, render: formatDateTime },
|
{ title: '变动时间', dataIndex: 'created_at', width: 170, render: formatDateTime },
|
||||||
]
|
]
|
||||||
|
|
||||||
const apiClientColumns: ColumnsType<ApiClient> = [
|
const apiClientColumns: ColumnsType<ApiClient> = [
|
||||||
@@ -645,38 +650,88 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
|
|||||||
|
|
||||||
const walletContent = (
|
const walletContent = (
|
||||||
<Space direction="vertical" style={{ width: '100%' }} size="middle">
|
<Space direction="vertical" style={{ width: '100%' }} size="middle">
|
||||||
<Space style={{ width: '100%', justifyContent: 'space-between' }} size="large">
|
<Row gutter={[16, 16]}>
|
||||||
<Descriptions size="small" bordered column={3}>
|
<Col xs={24} sm={8}>
|
||||||
<Descriptions.Item label="可用余额">{money(wallet?.available_balance ?? 0)}</Descriptions.Item>
|
<div className="metric-card-box">
|
||||||
<Descriptions.Item label="冻结余额">{money(wallet?.frozen_balance ?? 0)}</Descriptions.Item>
|
<div className="metric-card-header">
|
||||||
<Descriptions.Item label="币种">{wallet?.currency || 'POINT'}</Descriptions.Item>
|
<span className="metric-card-title">可用余额</span>
|
||||||
</Descriptions>
|
<div className="metric-card-icon metric-card-icon--emerald"><WalletOutlined /></div>
|
||||||
{canFinance && (
|
</div>
|
||||||
<Button
|
<div className="metric-card-value" style={{ color: '#16a34a' }}>
|
||||||
type="primary"
|
{(wallet?.available_balance ?? 0).toLocaleString('zh-CN')}
|
||||||
icon={<WalletOutlined />}
|
<span style={{ fontSize: 13, fontWeight: 500, marginLeft: 4, color: '#64748b' }}>积分</span>
|
||||||
onClick={() => {
|
</div>
|
||||||
walletForm.resetFields()
|
{canFinance && (
|
||||||
walletForm.setFieldsValue({ idempotency_key: `manual-${Date.now()}` })
|
<div className="metric-card-footer">
|
||||||
setWalletOpen(true)
|
<span>手动划拨/调账</span>
|
||||||
}}
|
<Button
|
||||||
>
|
type="link"
|
||||||
调整
|
size="small"
|
||||||
</Button>
|
icon={<WalletOutlined />}
|
||||||
)}
|
style={{ padding: 0, height: 'auto' }}
|
||||||
</Space>
|
onClick={() => {
|
||||||
|
walletForm.resetFields()
|
||||||
|
walletForm.setFieldsValue({ idempotency_key: `manual-${Date.now()}` })
|
||||||
|
setWalletOpen(true)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
充值/调账
|
||||||
|
</Button>
|
||||||
|
</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"><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 && (
|
{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 form={walletFilterForm} layout="inline" onFinish={handleWalletFilter}>
|
||||||
<Form.Item name="reference_no" label="关联单号">
|
<Form.Item name="reference_no" label="关联单号">
|
||||||
<Input placeholder="店铺单号 / 充值单号" allowClear style={{ width: 220 }} />
|
<Input placeholder="店铺单号 / 充值单号" allowClear style={{ width: 220, borderRadius: 6 }} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="type" label="收支">
|
<Form.Item name="type" label="收支类型">
|
||||||
<Select placeholder="请选择" allowClear style={{ width: 120 }}>
|
<Select placeholder="全部类型" allowClear style={{ width: 140 }}>
|
||||||
<Select.Option value="credit">入账</Select.Option>
|
<Select.Option value="credit">入账 (Credit)</Select.Option>
|
||||||
<Select.Option value="debit">扣款</Select.Option>
|
<Select.Option value="debit">扣款 (Debit)</Select.Option>
|
||||||
<Select.Option value="refund">退款</Select.Option>
|
<Select.Option value="refund">退款 (Refund)</Select.Option>
|
||||||
<Select.Option value="adjust">调整</Select.Option>
|
<Select.Option value="adjust">调账 (Adjust)</Select.Option>
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
@@ -796,21 +851,16 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Space style={{ marginBottom: 16, width: '100%', justifyContent: 'space-between' }}>
|
<PageHeader
|
||||||
<div>
|
title={title}
|
||||||
<Typography.Title level={4} style={{ margin: 0 }}>
|
subtitle={merchant ? `${merchant.name} (${merchant.code}) · 当前身份: ${merchantRole ? roleText(merchantRole) : '-'}` : '商户配置与管理中心'}
|
||||||
{title}
|
breadcrumbs={[{ title: title }]}
|
||||||
</Typography.Title>
|
extra={
|
||||||
{!fixedTab && (
|
<Button icon={<ReloadOutlined />} loading={loading} onClick={loadAll}>
|
||||||
<Typography.Text type="secondary">
|
刷新
|
||||||
{merchant ? `${merchant.name} / ${merchant.code}` : '加载中'} · {merchantRole ? roleText(merchantRole) : '-'}
|
</Button>
|
||||||
</Typography.Text>
|
}
|
||||||
)}
|
/>
|
||||||
</div>
|
|
||||||
<Button icon={<ReloadOutlined />} loading={loading} onClick={loadAll}>
|
|
||||||
刷新
|
|
||||||
</Button>
|
|
||||||
</Space>
|
|
||||||
|
|
||||||
{fixedTab ? fixedTabContent : (
|
{fixedTab ? fixedTabContent : (
|
||||||
<Tabs
|
<Tabs
|
||||||
|
|||||||
Reference in New Issue
Block a user