优化 UID 履约闸门、运营可见性与一键兑换
lewan 发货强制 expectedUid 并取消无 UID 旧路径回落;任务详情展示 UID 匹配态;领取页匹配后可一键兑换;补充 identity 单测并收口短链说明。
This commit is contained in:
@@ -681,13 +681,57 @@ function FulfillmentOverviewPanel({
|
||||
}) {
|
||||
const executor = resolveTaskExecutorDisplay(detail.task.executorKey)
|
||||
const steps = buildFulfillmentOverviewSteps(detail, claimUrl, claimLinkInvalid)
|
||||
const currentBlocker = resolveTaskBlocker(detail.task, claimUrl, claimLinkInvalid)
|
||||
const claimIdentity = detail.claimIdentity
|
||||
const currentBlocker = resolveTaskBlocker(
|
||||
detail.task,
|
||||
claimUrl,
|
||||
claimLinkInvalid,
|
||||
claimIdentity,
|
||||
)
|
||||
const uidMatchTag =
|
||||
claimIdentity?.uidMatched === true
|
||||
? { color: 'success' as const, text: 'UID 已匹配' }
|
||||
: claimIdentity?.uidMatched === false
|
||||
? { color: 'error' as const, text: 'UID 不一致' }
|
||||
: claimIdentity?.ready
|
||||
? { color: 'processing' as const, text: '已填 UID' }
|
||||
: { color: 'warning' as const, text: '未填 UID' }
|
||||
|
||||
return (
|
||||
<Card
|
||||
title="履约链路总览"
|
||||
extra={<Tag color={executor.color}>{executor.label}</Tag>}
|
||||
>
|
||||
<Descriptions
|
||||
size="small"
|
||||
column={{ xs: 1, sm: 2, md: 3 }}
|
||||
className="platform-section-gap"
|
||||
style={{ marginBottom: 12 }}
|
||||
>
|
||||
<Descriptions.Item label="填写 UID">
|
||||
{claimIdentity?.expectedUid || (
|
||||
<Typography.Text type="warning">未提交</Typography.Text>
|
||||
)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="绑定角色 ID">
|
||||
{claimIdentity?.boundUid || detail.task.roleId || '-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="绑定角色名">
|
||||
{claimIdentity?.boundRoleName || detail.task.roleName || '-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="匹配状态">
|
||||
<Tag color={uidMatchTag.color}>{uidMatchTag.text}</Tag>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="兼容模式">
|
||||
{claimIdentity?.compatibilityMode === 'legacy_no_uid' ? '旧单无 UID' : 'UID 闸门'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="说明" span={3}>
|
||||
<Typography.Text type="secondary">
|
||||
{claimIdentity?.note || '暂无 UID 信息'}
|
||||
</Typography.Text>
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
|
||||
<div className="fulfillment-overview-grid">
|
||||
{steps.map((step) => (
|
||||
<div key={step.key} className="fulfillment-step-card">
|
||||
@@ -791,6 +835,7 @@ function resolveTaskBlocker(
|
||||
task: AdminTaskDetail['task'],
|
||||
claimUrl: string,
|
||||
claimLinkInvalid: boolean,
|
||||
claimIdentity?: AdminTaskDetail['claimIdentity'],
|
||||
): { level: 'success' | 'info' | 'warning' | 'error'; title: string; detail: string } {
|
||||
if (['completed', 'redeemed', 'delivered'].includes(task.status) || task.deliveryStatus === 'delivered') {
|
||||
return {
|
||||
@@ -808,6 +853,29 @@ function resolveTaskBlocker(
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
task.executorKey === 'kuaishou_ct_assisted' &&
|
||||
claimIdentity &&
|
||||
!claimIdentity.ready
|
||||
) {
|
||||
return {
|
||||
level: 'warning',
|
||||
title: '等待用户填写 UID',
|
||||
detail: '旧单或新单均需用户打开领取页提交游戏 UID,否则禁止自动发货。',
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
task.executorKey === 'kuaishou_ct_assisted' &&
|
||||
claimIdentity?.uidMatched === false
|
||||
) {
|
||||
return {
|
||||
level: 'error',
|
||||
title: 'UID 与绑定角色不一致',
|
||||
detail: `填写 ${claimIdentity.expectedUid || '-'},绑定 ${claimIdentity.boundUid || '-'},请用户换绑或更正 UID。`,
|
||||
}
|
||||
}
|
||||
|
||||
if (claimLinkInvalid) {
|
||||
return {
|
||||
level: 'warning',
|
||||
|
||||
@@ -521,6 +521,7 @@ function createClaimSnapshot(
|
||||
hasRedeemResult,
|
||||
isRoleConfirmed,
|
||||
isFeifeiFlow,
|
||||
isUidMatched,
|
||||
})
|
||||
const progressText = resolveProgressText({
|
||||
feifei,
|
||||
@@ -613,6 +614,7 @@ function resolveCurrentStep(options: {
|
||||
hasRedeemResult: boolean
|
||||
isRoleConfirmed: boolean
|
||||
isFeifeiFlow: boolean
|
||||
isUidMatched?: boolean
|
||||
}) {
|
||||
if (!options.hasExpectedUid) {
|
||||
return 1
|
||||
@@ -620,6 +622,10 @@ function resolveCurrentStep(options: {
|
||||
if (options.hasRedeemResult) {
|
||||
return 4
|
||||
}
|
||||
// UID 匹配后仍停留在绑定步,提供一键兑换;已 ROLE_CONFIRMED 走确认页
|
||||
if (!options.isFeifeiFlow && options.isRoleConfirmed && !options.isUidMatched) {
|
||||
return 3
|
||||
}
|
||||
if (!options.isFeifeiFlow && options.isRoleConfirmed) {
|
||||
return 3
|
||||
}
|
||||
@@ -857,10 +863,12 @@ function KuaishouCloudClaimSteps({
|
||||
refreshingRole={refreshingRole}
|
||||
confirmingRole={confirmingRole}
|
||||
rebindingRole={rebindingRole}
|
||||
redeeming={redeeming}
|
||||
onOpenBindUrl={onOpenBindUrl}
|
||||
onRefreshRole={onRefreshRole}
|
||||
onRebindRole={onRebindRole}
|
||||
onConfirmRole={onConfirmRole}
|
||||
onConfirmRedeem={onConfirmRedeem}
|
||||
uidInput={uidInput}
|
||||
submittingUid={submittingUid}
|
||||
onUidChange={onUidChange}
|
||||
@@ -875,10 +883,12 @@ function ClaimBindingStep({
|
||||
refreshingRole,
|
||||
confirmingRole,
|
||||
rebindingRole,
|
||||
redeeming,
|
||||
onOpenBindUrl,
|
||||
onRefreshRole,
|
||||
onRebindRole,
|
||||
onConfirmRole,
|
||||
onConfirmRedeem,
|
||||
uidInput,
|
||||
submittingUid,
|
||||
onUidChange,
|
||||
@@ -889,10 +899,12 @@ function ClaimBindingStep({
|
||||
refreshingRole: boolean
|
||||
confirmingRole: boolean
|
||||
rebindingRole: boolean
|
||||
redeeming: boolean
|
||||
onOpenBindUrl: (useCurrentPage?: boolean) => void
|
||||
onRefreshRole: () => void
|
||||
onRebindRole: () => void
|
||||
onConfirmRole: () => void
|
||||
onConfirmRedeem: () => void
|
||||
uidInput: string
|
||||
submittingUid: boolean
|
||||
onUidChange: (value: string) => void
|
||||
@@ -962,25 +974,39 @@ function ClaimBindingStep({
|
||||
size="large"
|
||||
icon={<SwapOutlined />}
|
||||
loading={rebindingRole}
|
||||
disabled={confirmingRole}
|
||||
disabled={confirmingRole || redeeming}
|
||||
onClick={onRebindRole}
|
||||
>
|
||||
换绑角色
|
||||
</Button>
|
||||
<Tooltip title={snapshot.confirmRoleDisabledReason || undefined}>
|
||||
<span className="claim-action-tooltip-wrap">
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
icon={<CheckCircleOutlined />}
|
||||
loading={confirmingRole}
|
||||
disabled={Boolean(snapshot.confirmRoleDisabledReason)}
|
||||
onClick={onConfirmRole}
|
||||
>
|
||||
UID 已匹配,下一步
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
{snapshot.isUidMatched ? (
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
danger
|
||||
icon={<CheckCircleOutlined />}
|
||||
loading={redeeming}
|
||||
disabled={rebindingRole}
|
||||
onClick={onConfirmRedeem}
|
||||
>
|
||||
UID 已匹配,确认兑换
|
||||
</Button>
|
||||
) : (
|
||||
<Tooltip title={snapshot.confirmRoleDisabledReason || undefined}>
|
||||
<span className="claim-action-tooltip-wrap">
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
icon={<CheckCircleOutlined />}
|
||||
loading={confirmingRole}
|
||||
disabled={Boolean(snapshot.confirmRoleDisabledReason)}
|
||||
onClick={onConfirmRole}
|
||||
>
|
||||
刷新后重试匹配
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Space>
|
||||
|
||||
<div className="claim-meta-footer">
|
||||
|
||||
Reference in New Issue
Block a user