import { useState } from 'react'; import { Button, Drawer, Form, Input, Select, Table, Tag, Typography } from 'antd'; import type { ColumnsType } from 'antd/es/table'; import { REDEEM_CHANNEL_LABELS, type RedeemChannel } from '@dukang/shared-types'; import RedeemRecordDetailDescriptions from '../components/RedeemRecordDetailDescriptions'; import { request } from '../lib/api'; import { fmtTime } from '../lib/constants'; import { useAdminList } from '../lib/useAdminList'; type Row = { id: string; redeemNo: string; amount: number; settleAmount: number; channel?: RedeemChannel; createdAt: string; user?: { userNo: string; phone: string | null; nickname?: string | null }; store?: { name: string; cityName: string }; coupon?: { couponNo: string }; }; function maskPhone(phone: string | null | undefined) { if (!phone || phone.length < 7) return phone ?? '—'; return `${phone.slice(0, 3)}****${phone.slice(-4)}`; } export default function RedeemRecordsPage() { const [form] = Form.useForm(); const [filters, setFilters] = useState>({}); const { data, loading, page, pageSize, setPage, setPageSize } = useAdminList( '/admin/redeem-records', () => { const qs = new URLSearchParams(); if (filters.redeemNo) qs.set('redeemNo', filters.redeemNo); if (filters.storeId) qs.set('storeId', filters.storeId); if (filters.channel) qs.set('channel', filters.channel); return qs; }, [filters], ); const [detail, setDetail] = useState | null>(null); const [drawerOpen, setDrawerOpen] = useState(false); const [detailLoading, setDetailLoading] = useState(false); async function openDetail(id: string) { setDetailLoading(true); setDrawerOpen(true); try { setDetail(await request(`/admin/redeem-records/${id}`)); } finally { setDetailLoading(false); } } const columns: ColumnsType = [ { title: '核销号', dataIndex: 'redeemNo', width: 180 }, { title: '方式', dataIndex: 'channel', width: 110, render: (v: RedeemChannel | undefined) => { const channel = v === 'PHONE' ? 'PHONE' : 'SCAN'; return ( {REDEEM_CHANNEL_LABELS[channel]} ); }, }, { title: '用户编号', dataIndex: ['user', 'userNo'], width: 110 }, { title: '用户昵称', dataIndex: ['user', 'nickname'], width: 100, render: (v: string | null | undefined) => v || '—', }, { title: '用户手机', dataIndex: ['user', 'phone'], width: 120, render: (v: string | null | undefined) => maskPhone(v), }, { title: '门店', dataIndex: ['store', 'name'] }, { title: '核销额', dataIndex: 'amount', width: 90, render: (v) => `¥${v}` }, { title: '结算额', dataIndex: 'settleAmount', width: 90, render: (v) => `¥${v}` }, { title: '券号', dataIndex: ['coupon', 'couponNo'], width: 160 }, { title: '时间', dataIndex: 'createdAt', width: 160, render: fmtTime }, { title: '操作', width: 80, render: (_, row) => ( ), }, ]; return (
核销记录
{ setFilters(v); setPage(1); }} >