/** * 确认人工履约弹窗(订单列表 / 订单详情共用)。 * * 口径(2026-10-24): * * 渠道与消耗积分在成本中心提前配好,客服不选、不填; * * 固定成本 → 直接确认; * * 成本不固定(消耗积分 = 0)→ 只填本次实际成本; * * 确认后扣对应平台积分/备用金并写成本快照。 * * 原「人工履约待办」页面已下线,入口收敛到订单界面。 */ import { CheckOutlined } from '@ant-design/icons' import { Alert, App, Form, Input, InputNumber, Modal, Select, Space, Statistic, Tag, Typography, } from 'antd' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useEffect, useState } from 'react' import { confirmAdminManualFulfillment, fetchAdminFundAccounts, fetchAdminManualFulfillmentPending, fetchAdminPlatformCreditOwners, } from '@/services/admin' import type { ManualFulfillmentPendingItem } from '@/types/admin' import { getAdminRole, getAdminUserId } from '@/utils/admin-auth' type ConfirmFormValues = { costYuan?: number payeeName?: string note?: string } const PLATFORM_TAG_COLORS: Record = { nanhang: 'blue', lewan: 'purple', rock: 'cyan', fund_cash: 'orange', } export type ManualFulfillmentConfirmModalProps = { open: boolean orderId: number | null initialOrderItemId?: number | null onClose: () => void onConfirmed?: () => void } export function ManualFulfillmentConfirmModal({ open, orderId, initialOrderItemId = null, onClose, onConfirmed, }: ManualFulfillmentConfirmModalProps) { const { message } = App.useApp() const queryClient = useQueryClient() const [form] = Form.useForm() const [selectedId, setSelectedId] = useState(null) const [fundAccountId, setFundAccountId] = useState(null) const [creditOwnerAdminUserId, setCreditOwnerAdminUserId] = useState(null) const role = getAdminRole() const privileged = role !== 'support' const currentUserId = getAdminUserId() const pendingQuery = useQuery({ queryKey: ['admin-manual-fulfillment-pending', 'order', orderId], queryFn: () => fetchAdminManualFulfillmentPending({ orderId: orderId || undefined, status: 'pending', page: 1, pageSize: 20, }), enabled: open && Boolean(orderId), }) const items = pendingQuery.data?.data.items || [] const selected = items.find((item) => item.orderItemId === selectedId) || items.find((item) => item.orderItemId === initialOrderItemId) || items[0] || null const fundAccountsQuery = useQuery({ queryKey: ['admin-manual-confirm-fund-accounts'], queryFn: () => fetchAdminFundAccounts({ page: 1, pageSize: 100 }), enabled: open && privileged && Boolean(selected?.isFundCash), retry: false, }) const creditOwnersQuery = useQuery({ queryKey: ['admin-manual-confirm-credit-owners'], queryFn: () => fetchAdminPlatformCreditOwners(), enabled: open && privileged && Boolean(selected) && !selected?.isFundCash, retry: false, }) useEffect(() => { if (!open) return setSelectedId(initialOrderItemId || null) form.resetFields() }, [open, initialOrderItemId, form]) // 代录时默认选本人账户;客服没有代录权限,不展示选择。 useEffect(() => { if (!open || !privileged) return if (selected?.isFundCash) { const accounts = (fundAccountsQuery.data?.data.items || []).filter( (item) => item.accountType === 'agent' && item.status === 'active', ) const own = accounts.find((item) => item.ownerAdminUserId === currentUserId) setFundAccountId(own?.id ?? null) return } const owners = creditOwnersQuery.data?.data.items || [] const own = owners.find((item) => item.id === currentUserId) setCreditOwnerAdminUserId(own?.id ?? null) }, [ open, privileged, selected?.orderItemId, selected?.isFundCash, currentUserId, fundAccountsQuery.data, creditOwnersQuery.data, ]) const confirmMutation = useMutation({ mutationFn: (values: ConfirmFormValues) => confirmAdminManualFulfillment({ orderItemId: selected?.orderItemId || 0, costFen: values.costYuan === undefined ? undefined : Math.round(values.costYuan * 100), payeeName: values.payeeName || '', note: values.note || '', ...(privileged && selected?.isFundCash && fundAccountId ? { fundAccountId } : {}), ...(privileged && selected && !selected.isFundCash && creditOwnerAdminUserId ? { creditOwnerAdminUserId } : {}), }), onSuccess: (response) => { const result = response.data message.success( `履约已确认,扣 ${result.creditQuantity} 积分,成本 ¥${(result.costFen / 100).toFixed(2)}`, ) void queryClient.invalidateQueries({ queryKey: ['admin-manual-fulfillment-pending'] }) void queryClient.invalidateQueries({ queryKey: ['admin-order-detail'] }) void queryClient.invalidateQueries({ queryKey: ['admin-orders'] }) void queryClient.invalidateQueries({ queryKey: ['admin-fund-my'] }) void queryClient.invalidateQueries({ queryKey: ['admin-fund-accounts'] }) void queryClient.invalidateQueries({ queryKey: ['admin-platform-credit-accounts'] }) void queryClient.invalidateQueries({ queryKey: ['admin-platform-credit-entries'] }) onConfirmed?.() onClose() }, onError: (error) => { message.error(error instanceof Error ? error.message : '确认履约失败') }, }) const showCostInput = selected?.costFen === null return ( , disabled: !selected || (privileged && ((selected.isFundCash && !fundAccountId) || (!selected.isFundCash && !creditOwnerAdminUserId))), }} cancelText="取消" confirmLoading={confirmMutation.isPending} onOk={() => { void form.validateFields().then((values) => confirmMutation.mutate(values)) }} onCancel={onClose} destroyOnHidden width={560} > {pendingQuery.isLoading ? ( 正在读取待履约商品… ) : items.length === 0 ? ( ) : ( {items.length > 1 ? ( setFundAccountId(value)} options={(fundAccountsQuery.data?.data.items || []) .filter((item) => item.accountType === 'agent' && item.status === 'active') .map((item) => ({ value: item.id, label: `${item.ownerName || item.accountNo} · 余额 ¥${(item.balanceFen / 100).toFixed(2)}`, }))} /> ) : (
代录到客服积分账户: )} ) }