gcx/frontend/admin-web/src/views/issuers/IssuerManagementPage.tsx

204 lines
8.2 KiB
TypeScript

import React, { useState } from 'react';
/**
* D2. 发行方管理
*
* 入驻审核列表、发行方详情、券审核列表
*/
interface Issuer {
id: string;
name: string;
creditRating: string;
status: 'pending' | 'approved' | 'rejected';
submittedAt: string;
couponCount: number;
totalVolume: string;
}
const mockIssuers: Issuer[] = [
{ id: 'ISS-001', name: 'Starbucks Inc.', creditRating: 'AAA', status: 'approved', submittedAt: '2026-01-15', couponCount: 12, totalVolume: '$128,450' },
{ id: 'ISS-002', name: 'Amazon Corp.', creditRating: 'AA', status: 'approved', submittedAt: '2026-01-20', couponCount: 8, totalVolume: '$456,000' },
{ id: 'ISS-003', name: 'NewBrand LLC', creditRating: '-', status: 'pending', submittedAt: '2026-02-09', couponCount: 0, totalVolume: '-' },
{ id: 'ISS-004', name: 'Target Corp.', creditRating: 'A', status: 'approved', submittedAt: '2026-01-25', couponCount: 5, totalVolume: '$67,200' },
{ id: 'ISS-005', name: 'FakeStore Inc.', creditRating: '-', status: 'rejected', submittedAt: '2026-02-05', couponCount: 0, totalVolume: '-' },
];
export const IssuerManagementPage: React.FC = () => {
const [tab, setTab] = useState<'all' | 'pending' | 'approved' | 'rejected'>('all');
const filtered = tab === 'all' ? mockIssuers : mockIssuers.filter(i => i.status === tab);
const creditColor = (rating: string) => {
const map: Record<string, string> = {
'AAA': 'var(--color-credit-aaa)',
'AA': 'var(--color-credit-aa)',
'A': 'var(--color-credit-a)',
'BBB': 'var(--color-credit-bbb)',
};
return map[rating] || 'var(--color-text-tertiary)';
};
const statusStyle = (status: string) => {
const map: Record<string, { bg: string; color: string }> = {
pending: { bg: 'var(--color-warning-light)', color: 'var(--color-warning)' },
approved: { bg: 'var(--color-success-light)', color: 'var(--color-success)' },
rejected: { bg: 'var(--color-error-light)', color: 'var(--color-error)' },
};
return map[status] || { bg: 'var(--color-gray-100)', color: 'var(--color-text-tertiary)' };
};
const statusLabel = (status: string) => {
const map: Record<string, string> = { pending: '待审核', approved: '已通过', rejected: '已驳回' };
return map[status] || status;
};
return (
<div>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 24 }}>
<h1 style={{ font: 'var(--text-h1)' }}></h1>
<div style={{ display: 'flex', gap: 8 }}>
<button style={{
padding: '6px 16px',
border: '1px solid var(--color-primary)',
borderRadius: 'var(--radius-full)',
background: 'var(--color-primary-surface)',
color: 'var(--color-primary)',
cursor: 'pointer',
font: 'var(--text-label-sm)',
}}>
AI
</button>
</div>
</div>
{/* Tabs */}
<div style={{ display: 'flex', gap: 4, marginBottom: 20 }}>
{(['all', 'pending', 'approved', 'rejected'] as const).map(t => (
<button
key={t}
onClick={() => setTab(t)}
style={{
padding: '8px 16px',
border: 'none',
borderRadius: 'var(--radius-full)',
background: tab === t ? 'var(--color-primary)' : 'var(--color-gray-50)',
color: tab === t ? 'white' : 'var(--color-text-secondary)',
cursor: 'pointer',
font: 'var(--text-label-sm)',
}}
>
{t === 'all' ? '全部' : statusLabel(t)}
{t === 'pending' && (
<span style={{
marginLeft: 4, padding: '0 5px',
background: 'var(--color-error)',
color: 'white',
borderRadius: 'var(--radius-full)',
fontSize: 10,
}}>
{mockIssuers.filter(i => i.status === 'pending').length}
</span>
)}
</button>
))}
</div>
{/* Table */}
<div style={{
background: 'var(--color-surface)',
borderRadius: 'var(--radius-md)',
border: '1px solid var(--color-border-light)',
overflow: 'hidden',
}}>
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
<thead>
<tr style={{ background: 'var(--color-gray-50)', borderBottom: '1px solid var(--color-border)' }}>
{['ID', '企业名称', '信用评级', '状态', '提交时间', '券数量', '总发行额', '操作'].map(h => (
<th key={h} style={{
font: 'var(--text-label-sm)',
color: 'var(--color-text-tertiary)',
padding: '12px 16px',
textAlign: 'left',
}}>{h}</th>
))}
</tr>
</thead>
<tbody>
{filtered.map(issuer => {
const ss = statusStyle(issuer.status);
return (
<tr key={issuer.id} style={{ borderBottom: '1px solid var(--color-border-light)' }}>
<td style={{ font: 'var(--text-body-sm)', fontFamily: 'var(--font-family-mono)', padding: '12px 16px', color: 'var(--color-text-tertiary)' }}>
{issuer.id}
</td>
<td style={{ font: 'var(--text-label)', padding: '12px 16px' }}>{issuer.name}</td>
<td style={{ padding: '12px 16px' }}>
<span style={{
padding: '2px 8px',
borderRadius: 'var(--radius-full)',
border: `1px solid ${creditColor(issuer.creditRating)}33`,
background: `${creditColor(issuer.creditRating)}11`,
color: creditColor(issuer.creditRating),
font: 'var(--text-label-sm)',
fontWeight: 700,
}}>
{issuer.creditRating}
</span>
</td>
<td style={{ padding: '12px 16px' }}>
<span style={{
padding: '2px 10px',
borderRadius: 'var(--radius-full)',
background: ss.bg,
color: ss.color,
font: 'var(--text-caption)',
fontWeight: 500,
}}>
{statusLabel(issuer.status)}
</span>
</td>
<td style={{ font: 'var(--text-body-sm)', color: 'var(--color-text-tertiary)', padding: '12px 16px' }}>
{issuer.submittedAt}
</td>
<td style={{ font: 'var(--text-body-sm)', padding: '12px 16px' }}>{issuer.couponCount}</td>
<td style={{ font: 'var(--text-label-sm)', color: 'var(--color-primary)', padding: '12px 16px' }}>
{issuer.totalVolume}
</td>
<td style={{ padding: '12px 16px' }}>
<button style={{
padding: '4px 12px',
border: '1px solid var(--color-border)',
borderRadius: 'var(--radius-sm)',
background: 'none',
cursor: 'pointer',
font: 'var(--text-caption)',
color: 'var(--color-primary)',
}}>
</button>
{issuer.status === 'pending' && (
<button style={{
marginLeft: 8,
padding: '4px 12px',
border: 'none',
borderRadius: 'var(--radius-sm)',
background: 'var(--color-primary)',
cursor: 'pointer',
font: 'var(--text-caption)',
color: 'white',
}}>
</button>
)}
</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
);
};