124 lines
3.9 KiB
TypeScript
124 lines
3.9 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
import { Card, Table, Typography, Space, Select, Tag, InputNumber, Button, message } from 'antd'
|
|
import { bindPaymentChannel, listPaymentChannels, listSites, unbindPaymentChannel, getMe, type PaymentChannel, type Site } from '../api'
|
|
import { useMember } from '../MemberContext'
|
|
|
|
export default function Payments() {
|
|
const member = useMember()
|
|
const [sites, setSites] = useState<Site[]>([])
|
|
const [siteID, setSiteID] = useState<number | undefined>(member?.site_id)
|
|
const [channels, setChannels] = useState<PaymentChannel[]>([])
|
|
const [configID, setConfigID] = useState<number | null>(null)
|
|
const [priority, setPriority] = useState<number>(0)
|
|
const [loading, setLoading] = useState(false)
|
|
|
|
async function load(id: number) {
|
|
setLoading(true)
|
|
try {
|
|
setChannels(await listPaymentChannels(id))
|
|
} catch {
|
|
message.error('支付通道加载失败')
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
async function init() {
|
|
let currentMember = member
|
|
if (!currentMember) {
|
|
try {
|
|
currentMember = await getMe()
|
|
} catch {
|
|
// ignore
|
|
}
|
|
}
|
|
const activeSiteID = currentMember?.site_id
|
|
if (activeSiteID) {
|
|
setSiteID(activeSiteID)
|
|
void load(activeSiteID)
|
|
}
|
|
|
|
if (currentMember?.is_superadmin) {
|
|
try {
|
|
const rows = await listSites()
|
|
setSites(rows)
|
|
if (!activeSiteID && rows.length > 0) {
|
|
setSiteID(rows[0].id)
|
|
void load(rows[0].id)
|
|
}
|
|
} catch {
|
|
// ignore
|
|
}
|
|
}
|
|
}
|
|
void init()
|
|
}, [member])
|
|
|
|
async function handleBind() {
|
|
if (!siteID || !configID) {
|
|
message.warning('请选择站点并填写商户配置 ID')
|
|
return
|
|
}
|
|
try {
|
|
await bindPaymentChannel(siteID, configID, priority)
|
|
message.success('支付通道已绑定')
|
|
setConfigID(null)
|
|
void load(siteID)
|
|
} catch (error: unknown) {
|
|
const respMessage = (error as { response?: { data?: { message?: string } } })?.response?.data?.message
|
|
message.error(respMessage ?? '绑定失败')
|
|
}
|
|
}
|
|
|
|
async function handleUnbind(id: number) {
|
|
try {
|
|
await unbindPaymentChannel(id)
|
|
message.success('已解绑')
|
|
if (siteID) void load(siteID)
|
|
} catch {
|
|
message.error('解绑失败')
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Space direction="vertical" className="page">
|
|
<Typography.Title level={3}>支付通道</Typography.Title>
|
|
<Space>
|
|
{member?.is_superadmin && sites.length > 1 && (
|
|
<Select
|
|
placeholder="分销网站"
|
|
style={{ width: 200 }}
|
|
value={siteID}
|
|
options={sites.map((site) => ({ label: site.site_name, value: site.id }))}
|
|
onChange={(value) => {
|
|
setSiteID(value)
|
|
void load(value)
|
|
}}
|
|
/>
|
|
)}
|
|
<InputNumber min={1} placeholder="商户配置 ID" value={configID ?? undefined} onChange={(v) => setConfigID(v ?? null)} />
|
|
<InputNumber min={0} placeholder="优先级" value={priority} onChange={(v) => setPriority(v ?? 0)} />
|
|
<Button type="primary" onClick={handleBind}>绑定</Button>
|
|
</Space>
|
|
<Card>
|
|
<Table
|
|
rowKey="id"
|
|
loading={loading}
|
|
dataSource={channels}
|
|
pagination={false}
|
|
columns={[
|
|
{ title: '商户配置 ID', dataIndex: 'config_id' },
|
|
{ title: '优先级', dataIndex: 'priority' },
|
|
{ title: '状态', dataIndex: 'status', render: (v: string) => <Tag color={v === 'active' ? 'green' : 'default'}>{v}</Tag> },
|
|
{
|
|
title: '操作',
|
|
render: (_: unknown, row: PaymentChannel) => <a onClick={() => handleUnbind(row.id)}>解绑</a>,
|
|
},
|
|
]}
|
|
/>
|
|
</Card>
|
|
</Space>
|
|
)
|
|
}
|