import { useState } from 'react' import { useQuery, useQueryClient } from '@tanstack/react-query' import { Alert, App, Button, Modal, Radio, Space, Tag, Typography, type TableColumnsType } from 'antd' import { EyeOutlined, ReloadOutlined } from '@ant-design/icons' import { approveAdminRefund, fetchPendingRefundOrders, rejectAdminRefund } from '@/features/admin/api' import { AdminOrderDetailDrawer } from '@/features/admin/AdminOrderDetailDrawer' import { AdminPageHeader } from '@/features/admin/components/AdminPageHeader' import { DataTable } from '@/features/admin/components/DataTable' import { StatusTag } from '@/features/admin/components/StatusTag' import { handoffStatusMeta, orderStatusMap, readStatusMeta, } from '@/features/admin/labels' import type { AdminOrderDetail } from '@/features/admin/types' import { useAdminSessionStore } from '@/stores/adminSession' import { formatDateTime, formatMoney, formatText } from '@/shared/utils/format' type RejectMode = 'restore' | 'close' function buildColumns( onDetail: (row: AdminOrderDetail) => void, onApprove: (row: AdminOrderDetail) => void, onReject: (row: AdminOrderDetail) => void, canClose: boolean, canView: boolean ): TableColumnsType { return [ { title: '订单', dataIndex: 'order_no', width: 220, fixed: 'left', render: (_, row) => (
{canView ? ( ) : ( {row.order_no} )} {row.title} 商品 {formatText(row.listing_no)}
), }, { title: '交易双方', key: 'parties', width: 180, render: (_, row) => (
租客 {formatText(row.renter_phone)} 号主 {formatText(row.owner_phone)}
), }, { title: '退款金额', dataIndex: 'refund_amount_cent', width: 140, align: 'right', render: (_, row) => (
{formatMoney(row.refund_amount_cent)} 订单 {formatMoney(row.display_amount_cent)} 押金 {formatMoney(row.deposit_amount_cent)}
), }, { title: '订单状态', key: 'status', width: 170, render: (_, row) => (
), }, { title: '申请时间', dataIndex: 'updated_at', width: 170, render: value => formatDateTime(value), }, { title: '操作', key: 'actions', width: 190, fixed: 'right', render: (_, row) => ( {canView ? ( ) : null} {canClose ? ( <> ) : null} ), }, ] } export function AdminRefundReviewPage() { const { message, modal } = App.useApp() const queryClient = useQueryClient() const permissions = useAdminSessionStore(state => state.admin?.permissions) const can = (code: string) => Boolean(permissions?.includes('*') || permissions?.includes(code)) const canClose = can('order:close') const canView = can('order:view') const [detailId, setDetailId] = useState(null) const [detailOpen, setDetailOpen] = useState(false) const [rejectOrder, setRejectOrder] = useState(null) const [rejectMode, setRejectMode] = useState('restore') const [submitting, setSubmitting] = useState(false) const query = useQuery({ queryKey: ['admin-refund-pending'], queryFn: fetchPendingRefundOrders, }) const items = query.data ?? [] const refreshAll = async () => { await query.refetch() await queryClient.invalidateQueries({ queryKey: ['admin-orders'] }) await queryClient.invalidateQueries({ queryKey: ['admin-dashboard'] }) } const openDetail = (row: AdminOrderDetail) => { setDetailId(row.id) setDetailOpen(true) } const approve = (row: AdminOrderDetail) => { modal.confirm({ title: '通过退款申请?', content: `订单 ${row.order_no} 将原路退款 ${formatMoney(row.refund_amount_cent)},订单随后取消。`, okText: '通过退款', cancelText: '再核对一下', okButtonProps: { danger: true }, onOk: async () => { try { await approveAdminRefund(row.id) message.success('退款已通过并发起') await refreshAll() } catch (error) { message.error(error instanceof Error ? error.message : '退款审核失败') } }, }) } const openReject = (row: AdminOrderDetail) => { setRejectOrder(row) setRejectMode('restore') } const submitReject = async () => { if (!rejectOrder) return setSubmitting(true) try { await rejectAdminRefund(rejectOrder.id, rejectMode) message.success(rejectMode === 'restore' ? '退款已驳回,订单恢复待交接' : '退款已驳回,订单已关闭') setRejectOrder(null) await refreshAll() } catch (error) { message.error(error instanceof Error ? error.message : '驳回退款失败') } finally { setSubmitting(false) } } const columns = buildColumns(openDetail, approve, openReject, canClose, canView) const errorText = query.error instanceof Error ? query.error.message : '请稍后重试或重新登录后台。' return (
待审核 {items.length} 单 {query.isFetching ? 正在更新 : null} } extra={ } /> {!canClose ? ( ) : null} {query.isError ? ( void query.refetch()}> 重试 } /> ) : null} title={待审核退款} extra={ {query.isPending ? '加载中' : `共 ${items.length} 单`} } rowKey="id" columns={columns} dataSource={items} loading={query.isFetching} emptyDescription="当前没有待审核退款" onRowClick={canView ? row => openDetail(row) : undefined} /> {canView ? ( setDetailOpen(false)} /> ) : null} void submitReject()} onCancel={() => { if (!submitting) setRejectOrder(null) }} > 订单 {rejectOrder?.order_no},退款金额 {formatMoney(rejectOrder?.refund_amount_cent)}。 请选择驳回后的订单处理方式。 setRejectMode(event.target.value as RejectMode)} style={{ display: 'flex', flexDirection: 'column', gap: 12 }} > 恢复订单至待交接 仅驳回退款,订单继续流转,商品保持占用。 驳回退款并关闭订单 关闭订单并归档商品,后续不可再操作。
) }