fix(admin): 修复恢复启用订单兑换时 orderId 闭包失效及 H5 页面重试机制
- 修复任务详情页和订单详情页中 statusMutation 闭包提前捕获空 orderId 导致恢复启用请求未发出的问题,改为动态从 query.data 解析最新的 orderId - 订单详情页统一切换为 App.useApp 提供的 modal/message 实例,保证异步弹窗与提示稳定渲染 - H5 买家领取页面在暂停或关闭等异常状态卡片中增加【重新检测状态】按钮,客服恢复启用后买家可一键重新加载最新状态 - 验证方式:前端类型检查(0 error)、单测 132 项全通及前端 Vite 重新构建成功
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
|||||||
} from '@ant-design/icons'
|
} from '@ant-design/icons'
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
|
App,
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
Descriptions,
|
Descriptions,
|
||||||
@@ -17,7 +18,6 @@ import {
|
|||||||
Table,
|
Table,
|
||||||
Tag,
|
Tag,
|
||||||
Typography,
|
Typography,
|
||||||
message,
|
|
||||||
} from 'antd'
|
} from 'antd'
|
||||||
import type { TableColumnsType } from 'antd'
|
import type { TableColumnsType } from 'antd'
|
||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||||
@@ -34,6 +34,7 @@ import { formatAdminDateTime } from '@/utils/admin-time'
|
|||||||
export default function AdminOrderDetailPage() {
|
export default function AdminOrderDetailPage() {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
|
const { message, modal } = App.useApp()
|
||||||
const { orderId = '' } = useParams()
|
const { orderId = '' } = useParams()
|
||||||
const [statusModalVisible, setStatusModalVisible] = useState(false)
|
const [statusModalVisible, setStatusModalVisible] = useState(false)
|
||||||
const [targetStatus, setTargetStatus] = useState<'active' | 'paused' | 'closed'>('active')
|
const [targetStatus, setTargetStatus] = useState<'active' | 'paused' | 'closed'>('active')
|
||||||
@@ -47,8 +48,11 @@ export default function AdminOrderDetailPage() {
|
|||||||
const detail = query.data?.data
|
const detail = query.data?.data
|
||||||
|
|
||||||
const statusMutation = useMutation({
|
const statusMutation = useMutation({
|
||||||
mutationFn: (data: { status: 'active' | 'paused' | 'closed'; reason?: string }) =>
|
mutationFn: async (data: { status: 'active' | 'paused' | 'closed'; reason?: string }) => {
|
||||||
updateAdminOrderClaimStatus(orderId, data),
|
const targetOrderId = orderId || detail?.order?.orderId
|
||||||
|
if (!targetOrderId) throw new Error('订单 ID 缺失')
|
||||||
|
return updateAdminOrderClaimStatus(targetOrderId, data)
|
||||||
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
message.success('订单兑换状态已更新')
|
message.success('订单兑换状态已更新')
|
||||||
setStatusModalVisible(false)
|
setStatusModalVisible(false)
|
||||||
@@ -71,10 +75,12 @@ export default function AdminOrderDetailPage() {
|
|||||||
|
|
||||||
const openStatusModal = (status: 'active' | 'paused' | 'closed') => {
|
const openStatusModal = (status: 'active' | 'paused' | 'closed') => {
|
||||||
if (status === 'active') {
|
if (status === 'active') {
|
||||||
Modal.confirm({
|
modal.confirm({
|
||||||
title: '恢复启用订单兑换',
|
title: '恢复启用订单兑换',
|
||||||
content: '恢复后,买家可正常进入 H5 页面提交 UID 领取,确认恢复吗?',
|
content: '恢复后,买家可正常进入 H5 页面提交 UID 领取,确认恢复吗?',
|
||||||
onOk: () => statusMutation.mutateAsync({ status: 'active', reason: '管理员恢复启用' }),
|
onOk: async () => {
|
||||||
|
await statusMutation.mutateAsync({ status: 'active', reason: '管理员恢复启用' })
|
||||||
|
},
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,9 +89,10 @@ export default function AdminTaskDetailPage() {
|
|||||||
const orderId = detail?.order?.orderId ? String(detail.order.orderId) : ''
|
const orderId = detail?.order?.orderId ? String(detail.order.orderId) : ''
|
||||||
|
|
||||||
const statusMutation = useMutation({
|
const statusMutation = useMutation({
|
||||||
mutationFn: (data: { status: 'active' | 'paused' | 'closed'; reason?: string }) => {
|
mutationFn: async (data: { status: 'active' | 'paused' | 'closed'; reason?: string }) => {
|
||||||
if (!orderId) throw new Error('当前任务无关联订单信息')
|
const resolvedOrderId = query.data?.data?.order?.orderId || detail?.order?.orderId
|
||||||
return updateAdminOrderClaimStatus(orderId, data)
|
if (!resolvedOrderId) throw new Error('当前任务无关联订单信息')
|
||||||
|
return updateAdminOrderClaimStatus(resolvedOrderId, data)
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
message.success('订单兑换状态已更新')
|
message.success('订单兑换状态已更新')
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import {
|
import {
|
||||||
ExclamationCircleOutlined,
|
ExclamationCircleOutlined,
|
||||||
LoadingOutlined,
|
LoadingOutlined,
|
||||||
|
ReloadOutlined,
|
||||||
StopOutlined,
|
StopOutlined,
|
||||||
WarningOutlined,
|
WarningOutlined,
|
||||||
} from '@ant-design/icons'
|
} from '@ant-design/icons'
|
||||||
import { Card, Empty, Spin } from 'antd'
|
import { Button, Card, Empty, Spin } from 'antd'
|
||||||
import QRCode from 'qrcode'
|
import QRCode from 'qrcode'
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import { useParams } from 'react-router'
|
import { useParams } from 'react-router'
|
||||||
@@ -255,17 +256,39 @@ export default function ClaimPage() {
|
|||||||
<WarningOutlined style={{ fontSize: 48, color: '#faad14' }} />
|
<WarningOutlined style={{ fontSize: 48, color: '#faad14' }} />
|
||||||
<h3 style={{ marginTop: 16 }}>订单兑换已暂停</h3>
|
<h3 style={{ marginTop: 16 }}>订单兑换已暂停</h3>
|
||||||
<p style={{ color: '#64748b' }}>{errorMessage}</p>
|
<p style={{ color: '#64748b' }}>{errorMessage}</p>
|
||||||
|
<Button
|
||||||
|
icon={<ReloadOutlined />}
|
||||||
|
style={{ marginTop: 16 }}
|
||||||
|
onClick={() => void loadDetail()}
|
||||||
|
>
|
||||||
|
重新检测状态
|
||||||
|
</Button>
|
||||||
</>
|
</>
|
||||||
) : errorMessage.includes('关闭') || errorMessage.includes('退款') ? (
|
) : errorMessage.includes('关闭') || errorMessage.includes('退款') ? (
|
||||||
<>
|
<>
|
||||||
<StopOutlined style={{ fontSize: 48, color: '#94a3b8' }} />
|
<StopOutlined style={{ fontSize: 48, color: '#94a3b8' }} />
|
||||||
<h3 style={{ marginTop: 16 }}>订单不可兑换</h3>
|
<h3 style={{ marginTop: 16 }}>订单不可兑换</h3>
|
||||||
<p style={{ color: '#64748b' }}>{errorMessage}</p>
|
<p style={{ color: '#64748b' }}>{errorMessage}</p>
|
||||||
|
<Button
|
||||||
|
icon={<ReloadOutlined />}
|
||||||
|
style={{ marginTop: 16 }}
|
||||||
|
onClick={() => void loadDetail()}
|
||||||
|
>
|
||||||
|
重新检测状态
|
||||||
|
</Button>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<ExclamationCircleOutlined className="claim-large-icon claim-icon-error" />
|
<ExclamationCircleOutlined className="claim-large-icon claim-icon-error" />
|
||||||
<p>{errorMessage}</p>
|
<p>{errorMessage}</p>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<ReloadOutlined />}
|
||||||
|
style={{ marginTop: 16 }}
|
||||||
|
onClick={() => void loadDetail()}
|
||||||
|
>
|
||||||
|
重新加载
|
||||||
|
</Button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
Reference in New Issue
Block a user