fix(distribution-admin): 全面优化大盘、对账单、钱包与前台商城的列宽排版、中文化与防换行体验
This commit is contained in:
@@ -34,6 +34,46 @@ import {
|
||||
} from '../api'
|
||||
import { useMember } from '../MemberContext'
|
||||
|
||||
const ORDER_STATUS_MAP: Record<string, { label: string; color: string }> = {
|
||||
pending_payment: { label: '待支付', color: 'orange' },
|
||||
pending_handoff: { label: '待上号交付', color: 'processing' },
|
||||
renting: { label: '在租中', color: 'cyan' },
|
||||
overdue: { label: '已逾期', color: 'volcano' },
|
||||
pending_checkout_confirm: { label: '待结单确认', color: 'blue' },
|
||||
pending_checkout_accept: { label: '待号主验收', color: 'blue' },
|
||||
checkout_disputing: { label: '结单争议中', color: 'magenta' },
|
||||
disputing: { label: '维权中', color: 'magenta' },
|
||||
abnormal: { label: '异常', color: 'error' },
|
||||
completed: { label: '已完成', color: 'success' },
|
||||
refunded: { label: '已退款', color: 'purple' },
|
||||
cancelled: { label: '已取消', color: 'default' },
|
||||
}
|
||||
|
||||
const SETTLEMENT_STATUS_MAP: Record<string, { label: string; color: string }> = {
|
||||
settled: { label: '已结算', color: 'success' },
|
||||
pending: { label: '待结算', color: 'warning' },
|
||||
unsettled: { label: '未结算', color: 'default' },
|
||||
settling: { label: '结算中', color: 'processing' },
|
||||
disputed: { label: '争议冻结', color: 'magenta' },
|
||||
failed: { label: '结算异常', color: 'error' },
|
||||
}
|
||||
|
||||
function formatGameName(gameName?: string): string {
|
||||
if (!gameName) return ''
|
||||
const lower = gameName.toLowerCase().trim()
|
||||
if (
|
||||
lower === 'delta_force' ||
|
||||
lower === 'deltaforce' ||
|
||||
lower === 'delta' ||
|
||||
lower.includes('delta_force') ||
|
||||
lower.includes('delta') ||
|
||||
gameName.includes('三角洲')
|
||||
) {
|
||||
return '三角洲'
|
||||
}
|
||||
return gameName
|
||||
}
|
||||
|
||||
export default function Dashboard() {
|
||||
const member = useMember()
|
||||
const [sites, setSites] = useState<Site[]>([])
|
||||
@@ -266,23 +306,92 @@ export default function Dashboard() {
|
||||
rowKey="order_id"
|
||||
dataSource={recentOrders}
|
||||
pagination={false}
|
||||
scroll={{ x: 1050 }}
|
||||
columns={[
|
||||
{
|
||||
title: '订单号',
|
||||
dataIndex: 'order_no',
|
||||
width: 170,
|
||||
render: (v: string) => <Typography.Text copyable strong>{v}</Typography.Text>,
|
||||
title: '订单与商品编号',
|
||||
width: 260,
|
||||
render: (_: unknown, row: DistributionOrder) => (
|
||||
<div style={{ whiteSpace: 'nowrap' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', whiteSpace: 'nowrap', marginBottom: 4 }}>
|
||||
<Tag
|
||||
color="default"
|
||||
style={{
|
||||
margin: 0,
|
||||
marginInlineEnd: 6,
|
||||
fontSize: 11,
|
||||
padding: '0 4px',
|
||||
lineHeight: '18px',
|
||||
flexShrink: 0,
|
||||
}}
|
||||
>
|
||||
订单
|
||||
</Tag>
|
||||
<Typography.Text
|
||||
copyable={{ text: row.order_no, tooltips: ['复制订单号', '已复制'] }}
|
||||
strong
|
||||
style={{
|
||||
fontSize: 13,
|
||||
fontFamily: 'monospace',
|
||||
whiteSpace: 'nowrap',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
{row.order_no}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
{row.listing_no ? (
|
||||
<div style={{ display: 'flex', alignItems: 'center', whiteSpace: 'nowrap' }}>
|
||||
<Tag
|
||||
color="blue"
|
||||
style={{
|
||||
margin: 0,
|
||||
marginInlineEnd: 6,
|
||||
fontSize: 11,
|
||||
padding: '0 4px',
|
||||
lineHeight: '18px',
|
||||
flexShrink: 0,
|
||||
}}
|
||||
>
|
||||
商品
|
||||
</Tag>
|
||||
<Typography.Text
|
||||
copyable={{ text: row.listing_no, tooltips: ['复制商品编号', '已复制'] }}
|
||||
style={{
|
||||
fontSize: 13,
|
||||
color: '#1677ff',
|
||||
fontWeight: 600,
|
||||
fontFamily: 'monospace',
|
||||
whiteSpace: 'nowrap',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
{row.listing_no}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '租赁账号与游戏',
|
||||
minWidth: 180,
|
||||
width: 240,
|
||||
render: (_: unknown, row: DistributionOrder) => (
|
||||
<div>
|
||||
<Typography.Text strong style={{ display: 'block' }}>
|
||||
<Typography.Text
|
||||
strong
|
||||
style={{ display: 'block', fontSize: 14, lineHeight: '20px' }}
|
||||
ellipsis={{ tooltip: row.title }}
|
||||
>
|
||||
{row.title || (row.listing_no ? `商品 #${row.listing_no}` : `订单 #${row.order_id}`)}
|
||||
</Typography.Text>
|
||||
{row.game_name && <Tag color="blue" style={{ marginTop: 2 }}>{row.game_name}</Tag>}
|
||||
{row.server_region && <Tag>{row.server_region}</Tag>}
|
||||
<Space size={4} style={{ marginTop: 4 }} wrap>
|
||||
{row.game_name && <Tag color="blue">{formatGameName(row.game_name)}</Tag>}
|
||||
{row.server_region && <Tag>{row.server_region}</Tag>}
|
||||
{row.login_platform && <Tag color="cyan">{row.login_platform}</Tag>}
|
||||
</Space>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
@@ -290,16 +399,16 @@ export default function Dashboard() {
|
||||
title: '实付金额',
|
||||
width: 120,
|
||||
render: (_: unknown, row: DistributionOrder) => (
|
||||
<Typography.Text strong style={{ color: '#1677ff' }}>
|
||||
<Typography.Text strong style={{ color: '#1677ff', fontSize: 15, whiteSpace: 'nowrap' }}>
|
||||
{formatMoney(row.net_paid_amount_cent || row.gross_paid_amount_cent || 0)}
|
||||
</Typography.Text>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '本站净收益',
|
||||
width: 140,
|
||||
width: 130,
|
||||
render: (_: unknown, row: DistributionOrder) => (
|
||||
<Typography.Text strong style={{ color: '#389e0d', fontSize: 15 }}>
|
||||
<Typography.Text strong style={{ color: '#389e0d', fontSize: 15, whiteSpace: 'nowrap' }}>
|
||||
+{formatMoney(row.distributor_earning_cent || 0)}
|
||||
</Typography.Text>
|
||||
),
|
||||
@@ -308,20 +417,26 @@ export default function Dashboard() {
|
||||
title: '订单状态',
|
||||
dataIndex: 'status',
|
||||
width: 110,
|
||||
render: (v: string) => <Tag color={v === 'completed' || v === 'renting' ? 'green' : 'default'}>{v}</Tag>,
|
||||
render: (v: string) => {
|
||||
const conf = ORDER_STATUS_MAP[v] || { label: v, color: 'default' }
|
||||
return <Tag color={conf.color}>{conf.label}</Tag>
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '结算状态',
|
||||
dataIndex: 'settlement_status',
|
||||
width: 110,
|
||||
render: (v: string) => <Tag color={v === 'settled' ? 'success' : 'warning'}>{v === 'settled' ? '已结算' : '待结算'}</Tag>,
|
||||
render: (v: string) => {
|
||||
const conf = SETTLEMENT_STATUS_MAP[v] || { label: v, color: 'default' }
|
||||
return <Tag color={conf.color}>{conf.label}</Tag>
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '下单时间',
|
||||
dataIndex: 'created_at',
|
||||
width: 160,
|
||||
render: (v: string) => (
|
||||
<span style={{ fontSize: 12, color: '#8c8c8c' }}>
|
||||
<span style={{ fontSize: 12, color: '#8c8c8c', whiteSpace: 'nowrap' }}>
|
||||
{v ? new Date(v).toLocaleString('zh-CN', { hour12: false }) : '-'}
|
||||
</span>
|
||||
),
|
||||
|
||||
@@ -110,7 +110,7 @@ export default function Payments() {
|
||||
columns={[
|
||||
{ title: '商户配置 ID', dataIndex: 'config_id' },
|
||||
{ title: '优先级', dataIndex: 'priority' },
|
||||
{ title: '状态', dataIndex: 'status', render: (v: string) => <Tag color={v === 'active' ? 'green' : 'default'}>{v}</Tag> },
|
||||
{ title: '状态', dataIndex: 'status', render: (v: string) => <Tag color={v === 'active' ? 'green' : 'default'}>{v === 'active' ? '正常生效' : (v || '已停用')}</Tag> },
|
||||
{
|
||||
title: '操作',
|
||||
render: (_: unknown, row: PaymentChannel) => <a onClick={() => handleUnbind(row.id)}>解绑</a>,
|
||||
|
||||
@@ -47,10 +47,12 @@ const STATUS_LABELS: Record<string, { label: string; color: string }> = {
|
||||
}
|
||||
|
||||
const PARTY_ROLE_LABELS: Record<string, string> = {
|
||||
seller: '卖出提成分账 (40%)',
|
||||
distributor_b: '卖出提成分账 (40%)',
|
||||
receiver: '收号提成分账 (35%)',
|
||||
distributor_a: '收号提成分账 (35%)',
|
||||
seller: '渠道代销分润 (40%)',
|
||||
distributor_sell: '渠道代销分润 (40%)',
|
||||
distributor_b: '渠道代销分润 (40%)',
|
||||
receiver: '号源出租分润 (35%)',
|
||||
distributor_receive: '号源出租分润 (35%)',
|
||||
distributor_a: '号源出租分润 (35%)',
|
||||
two_party_distributor: '分销商分润',
|
||||
platform: '平台服务费',
|
||||
}
|
||||
@@ -212,6 +214,7 @@ export default function Settlements() {
|
||||
loading={loading}
|
||||
dataSource={batches}
|
||||
pagination={false}
|
||||
scroll={{ x: 1000 }}
|
||||
locale={{
|
||||
emptyText: (
|
||||
<Empty
|
||||
|
||||
@@ -35,6 +35,22 @@ import {
|
||||
type PublicDistributionListing,
|
||||
} from '../api'
|
||||
|
||||
function formatGameName(gameName?: string): string {
|
||||
if (!gameName) return ''
|
||||
const lower = gameName.toLowerCase().trim()
|
||||
if (
|
||||
lower === 'delta_force' ||
|
||||
lower === 'deltaforce' ||
|
||||
lower === 'delta' ||
|
||||
lower.includes('delta_force') ||
|
||||
lower.includes('delta') ||
|
||||
gameName.includes('三角洲')
|
||||
) {
|
||||
return '三角洲'
|
||||
}
|
||||
return gameName
|
||||
}
|
||||
|
||||
export default function Storefront() {
|
||||
const { siteCode = 'demo' } = useParams<{ siteCode: string }>()
|
||||
const [loading, setLoading] = useState(true)
|
||||
@@ -247,7 +263,7 @@ export default function Storefront() {
|
||||
buttonStyle="solid"
|
||||
>
|
||||
<Radio.Button value="all">全部游戏</Radio.Button>
|
||||
<Radio.Button value="delta_force">三角洲行动</Radio.Button>
|
||||
<Radio.Button value="delta_force">三角洲</Radio.Button>
|
||||
<Radio.Button value="honor_of_kings">王者荣耀</Radio.Button>
|
||||
</Radio.Group>
|
||||
|
||||
@@ -345,7 +361,7 @@ export default function Storefront() {
|
||||
{/* 标签属性 */}
|
||||
<Space wrap size={4} style={{ marginBottom: 12 }}>
|
||||
<Tag color="blue" style={{ margin: 0 }}>
|
||||
{item.game_name === 'delta_force' ? '三角洲行动' : item.game_name}
|
||||
{formatGameName(item.game_name)}
|
||||
</Tag>
|
||||
{item.server_region && (
|
||||
<Tag style={{ margin: 0, background: 'rgba(255,255,255,0.06)', color: '#cbd5e1', border: 'none' }}>
|
||||
@@ -446,7 +462,7 @@ export default function Storefront() {
|
||||
|
||||
<Descriptions column={2} bordered size="small">
|
||||
<Descriptions.Item label="所属游戏">
|
||||
{selectedListing.game_name === 'delta_force' ? '三角洲行动' : selectedListing.game_name}
|
||||
{formatGameName(selectedListing.game_name)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="游戏大区">{selectedListing.server_region || '全区通用'}</Descriptions.Item>
|
||||
<Descriptions.Item label="登录平台">{selectedListing.login_platform || 'PC端'}</Descriptions.Item>
|
||||
|
||||
@@ -251,12 +251,29 @@ export default function Wallet() {
|
||||
showTotal: (tot) => `共 ${tot} 条提现记录`,
|
||||
onChange: (p) => void loadData(p),
|
||||
}}
|
||||
scroll={{ x: 1100 }}
|
||||
columns={[
|
||||
{
|
||||
title: '提现单号',
|
||||
dataIndex: 'withdraw_no',
|
||||
width: 170,
|
||||
render: (v: string) => <Typography.Text copyable strong>{v}</Typography.Text>,
|
||||
width: 200,
|
||||
render: (v: string) => (
|
||||
<div style={{ whiteSpace: 'nowrap' }}>
|
||||
<Typography.Text
|
||||
copyable={{ text: v, tooltips: ['复制单号', '已复制'] }}
|
||||
strong
|
||||
style={{
|
||||
fontFamily: 'monospace',
|
||||
fontSize: 13,
|
||||
whiteSpace: 'nowrap',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
{v}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '提现金额',
|
||||
@@ -325,14 +342,20 @@ export default function Wallet() {
|
||||
title: '申请时间',
|
||||
dataIndex: 'created_at',
|
||||
width: 160,
|
||||
render: (v: string) => <span style={{ fontSize: 12, color: '#666' }}>{v}</span>,
|
||||
render: (v: string) => (
|
||||
<span style={{ fontSize: 12, color: '#666', whiteSpace: 'nowrap' }}>
|
||||
{v ? new Date(v).toLocaleString('zh-CN', { hour12: false }) : '-'}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '打款时间',
|
||||
dataIndex: 'paid_at',
|
||||
width: 160,
|
||||
render: (v: string | undefined) => (
|
||||
<span style={{ fontSize: 12, color: v ? '#52c41a' : '#999' }}>{v || '待打款'}</span>
|
||||
<span style={{ fontSize: 12, color: v ? '#52c41a' : '#999', whiteSpace: 'nowrap' }}>
|
||||
{v ? new Date(v).toLocaleString('zh-CN', { hour12: false }) : '待打款'}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
]}
|
||||
|
||||
Reference in New Issue
Block a user