import { useState } from 'react'; import { Button, Descriptions, Drawer, Form, Input, InputNumber, Modal, Popconfirm, Select, Table, Tag, Typography, message, } from 'antd'; import type { ColumnsType } from 'antd/es/table'; import type { AdminBenefitGrantRequest } from '@dukang/shared-types'; import { request } from '../lib/api'; import { COUPON_STATUS_LABELS, fmtTime } from '../lib/constants'; import { useAdminList } from '../lib/useAdminList'; type Row = { id: string; couponNo: string; totalAmount: number; balance: number; usedAmount: number; status: string; sourceProduct: string; createdAt: string; user?: { userNo: string; phone: string | null }; order?: { orderNo: string } | null; }; export default function BenefitCouponsPage() { const [form] = Form.useForm(); const [grantForm] = Form.useForm(); const [filters, setFilters] = useState>({}); const [grantOpen, setGrantOpen] = useState(false); const [granting, setGranting] = useState(false); const { data, loading, page, pageSize, setPage, setPageSize, reload } = useAdminList( '/admin/benefit/coupons', () => { const qs = new URLSearchParams(); if (filters.couponNo) qs.set('couponNo', filters.couponNo); if (filters.status) qs.set('status', filters.status); if (filters.userId) qs.set('userId', filters.userId); return qs; }, [filters], ); const [detail, setDetail] = useState | null>(null); const [drawerOpen, setDrawerOpen] = useState(false); const columns: ColumnsType = [ { title: '券号', dataIndex: 'couponNo', width: 200, ellipsis: false }, { title: '用户', dataIndex: ['user', 'userNo'], width: 120, ellipsis: false }, { title: '手机号', dataIndex: ['user', 'phone'], width: 120, render: (v) => v || '—' }, { title: '订单', dataIndex: ['order', 'orderNo'], width: 180, ellipsis: false, render: (v) => v || '—', }, { title: '总额', dataIndex: 'totalAmount', width: 80, render: (v) => `¥${v}` }, { title: '余额', dataIndex: 'balance', width: 80, render: (v) => `¥${v}` }, { title: '状态', dataIndex: 'status', width: 90, render: (s) => {COUPON_STATUS_LABELS[s] || s} }, { title: '来源', dataIndex: 'sourceProduct', ellipsis: true }, { title: '创建', dataIndex: 'createdAt', width: 160, render: fmtTime }, { title: '操作', width: 80, render: (_, row) => ( ), }, ]; async function handleGrant(values: AdminBenefitGrantRequest) { setGranting(true); try { await request('/admin/benefit/coupons/grant', { method: 'POST', body: JSON.stringify({ phone: values.phone.trim(), amount: values.amount, remark: values.remark?.trim() || undefined, }), }); message.success('权益已发放'); setGrantOpen(false); grantForm.resetFields(); void reload(); } catch (e) { message.error(e instanceof Error ? e.message : '发放失败'); } finally { setGranting(false); } } return (
好客权益券
{ setFilters(v); setPage(1); }}>
setDrawerOpen(false)} extra={ detail && detail.status !== 'VOID' && ( { await request(`/admin/benefit/coupons/${detail.id}/void`, { method: 'POST' }); message.success('已作废'); setDrawerOpen(false); void reload(); }} > ) } > {detail && ( {String(detail.couponNo)} {String((detail.user as { userNo?: string } | undefined)?.userNo ?? '—')} {String((detail.user as { phone?: string } | undefined)?.phone ?? '—')} {String((detail.order as { orderNo?: string } | null | undefined)?.orderNo ?? '—')} ¥{String(detail.totalAmount)} ¥{String(detail.balance)} {COUPON_STATUS_LABELS[String(detail.status)] || String(detail.status)} {String(detail.sourceProduct)} )}
); }