优化快手电子凭证:接口结果按动作内联结构化展示
- 执行后不再强制跳转到接口结果 Tab - 券码/售后操作区直接展示成功失败摘要与关键字段 - 按检查/核销/冲正/发码/售后等接口类型解析展示 - 原始 JSON 折叠保留,可按需打开接口结果页
This commit is contained in:
@@ -10,6 +10,8 @@ import {
|
||||
Alert,
|
||||
Button,
|
||||
Card,
|
||||
Collapse,
|
||||
Descriptions,
|
||||
Input,
|
||||
InputNumber,
|
||||
Select,
|
||||
@@ -57,6 +59,31 @@ import { stringifyDisplayJson } from '@/utils/date-time'
|
||||
|
||||
type DateRangeValue = [Dayjs | null, Dayjs | null] | null
|
||||
type IndustryTab = 'vouchers' | 'refunds' | 'result'
|
||||
type IndustryActionScope = 'vouchers' | 'refunds'
|
||||
type IndustryActionKind =
|
||||
| 'check'
|
||||
| 'consume'
|
||||
| 'reverse'
|
||||
| 'resend'
|
||||
| 'refund-list'
|
||||
| 'refund-approve'
|
||||
| 'refund-disagree'
|
||||
|
||||
type IndustryActionHighlight = {
|
||||
label: string
|
||||
value: string
|
||||
}
|
||||
|
||||
type IndustryActionResultView = {
|
||||
kind: IndustryActionKind
|
||||
scope: IndustryActionScope
|
||||
title: string
|
||||
success: boolean
|
||||
summary: string
|
||||
highlights: IndustryActionHighlight[]
|
||||
raw: unknown
|
||||
executedAt: string
|
||||
}
|
||||
|
||||
type VoucherFilterState = {
|
||||
oid: string
|
||||
@@ -129,8 +156,7 @@ export default function AdminKuaishouIndustryPage() {
|
||||
status: '10',
|
||||
negotiateStatus: '1',
|
||||
})
|
||||
const [lastResultTitle, setLastResultTitle] = useState('接口结果')
|
||||
const [lastResult, setLastResult] = useState<unknown>(null)
|
||||
const [lastActionResult, setLastActionResult] = useState<IndustryActionResultView | null>(null)
|
||||
const [refundRows, setRefundRows] = useState<Array<Record<string, unknown>>>([])
|
||||
const [industryShops, setIndustryShops] = useState<AdminKuaishouIndustryShopConfig[]>([])
|
||||
const refundShopOptions = useMemo(
|
||||
@@ -308,13 +334,13 @@ export default function AdminKuaishouIndustryPage() {
|
||||
}
|
||||
|
||||
async function runCheckAvailable() {
|
||||
await runOpenApiAction('检查电子凭证有效性', 'check', () =>
|
||||
await runOpenApiAction('check', '检查电子凭证有效性', 'check', () =>
|
||||
checkAdminKuaishouIndustryVoucherAvailable(buildVoucherToolPayload()),
|
||||
)
|
||||
}
|
||||
|
||||
async function runReverse() {
|
||||
await runOpenApiAction('电子凭证冲正回调', 'reverse', () =>
|
||||
await runOpenApiAction('reverse', '电子凭证冲正回调', 'reverse', () =>
|
||||
reverseAdminKuaishouIndustryVoucher({
|
||||
...buildVoucherToolPayload(),
|
||||
reason: toolForm.reason || '后台手动冲正',
|
||||
@@ -327,13 +353,20 @@ export default function AdminKuaishouIndustryPage() {
|
||||
setActionLoading('consume')
|
||||
try {
|
||||
const response = await consumeAdminKuaishouIndustryVoucher(buildVoucherToolPayload())
|
||||
setLastResultTitle('手动核销')
|
||||
setLastResult(response.data)
|
||||
setActiveTab('result')
|
||||
publishActionResult(
|
||||
buildIndustryActionResultView('consume', '手动核销', response.data),
|
||||
)
|
||||
showSuccess('手动核销已完成')
|
||||
await loadVouchers()
|
||||
} catch (error) {
|
||||
showError(error instanceof Error ? error.message : '手动核销失败')
|
||||
const message = error instanceof Error ? error.message : '手动核销失败'
|
||||
publishActionResult(
|
||||
buildIndustryActionResultView('consume', '手动核销', {
|
||||
success: false,
|
||||
error: message,
|
||||
}),
|
||||
)
|
||||
showError(message)
|
||||
} finally {
|
||||
setActionLoading('')
|
||||
}
|
||||
@@ -343,9 +376,9 @@ export default function AdminKuaishouIndustryPage() {
|
||||
setActionLoading('resend')
|
||||
try {
|
||||
const response = await resendAdminKuaishouIndustryVoucherCode(buildVoucherToolPayload())
|
||||
setLastResultTitle('重发发码回调')
|
||||
setLastResult(response.data)
|
||||
setActiveTab('result')
|
||||
publishActionResult(
|
||||
buildIndustryActionResultView('resend', '重发发码回调', response.data),
|
||||
)
|
||||
if (response.data.success) {
|
||||
showSuccess('发码回调已重发')
|
||||
} else {
|
||||
@@ -353,7 +386,14 @@ export default function AdminKuaishouIndustryPage() {
|
||||
}
|
||||
await loadVouchers()
|
||||
} catch (error) {
|
||||
showError(error instanceof Error ? error.message : '重发发码回调失败')
|
||||
const message = error instanceof Error ? error.message : '重发发码回调失败'
|
||||
publishActionResult(
|
||||
buildIndustryActionResultView('resend', '重发发码回调', {
|
||||
success: false,
|
||||
error: message,
|
||||
}),
|
||||
)
|
||||
showError(message)
|
||||
} finally {
|
||||
setActionLoading('')
|
||||
}
|
||||
@@ -368,6 +408,7 @@ export default function AdminKuaishouIndustryPage() {
|
||||
}
|
||||
|
||||
await runOpenApiAction(
|
||||
'refund-list',
|
||||
'售后单列表',
|
||||
'refund-list',
|
||||
() =>
|
||||
@@ -380,6 +421,7 @@ export default function AdminKuaishouIndustryPage() {
|
||||
(result) => {
|
||||
const rows = extractRefundRows(result.response)
|
||||
setRefundRows(rows)
|
||||
return { refundCount: rows.length }
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -391,7 +433,7 @@ export default function AdminKuaishouIndustryPage() {
|
||||
return
|
||||
}
|
||||
|
||||
await runOpenApiAction('同意退款', 'refund-approve', () =>
|
||||
await runOpenApiAction('refund-approve', '同意退款', 'refund-approve', () =>
|
||||
approveAdminKuaishouIndustryRefund({
|
||||
...approveForm,
|
||||
sellerId,
|
||||
@@ -407,7 +449,7 @@ export default function AdminKuaishouIndustryPage() {
|
||||
return
|
||||
}
|
||||
|
||||
await runOpenApiAction('不同意退款', 'refund-disagree', () =>
|
||||
await runOpenApiAction('refund-disagree', '不同意退款', 'refund-disagree', () =>
|
||||
disagreeAdminKuaishouIndustryRefund({
|
||||
...disagreeForm,
|
||||
sellerId,
|
||||
@@ -417,30 +459,44 @@ export default function AdminKuaishouIndustryPage() {
|
||||
}
|
||||
|
||||
async function runOpenApiAction(
|
||||
kind: IndustryActionKind,
|
||||
title: string,
|
||||
loadingKey: string,
|
||||
action: () => Promise<{ data: AdminKuaishouIndustryOpenApiResult }>,
|
||||
afterSuccess?: (result: AdminKuaishouIndustryOpenApiResult) => void,
|
||||
afterSuccess?: (
|
||||
result: AdminKuaishouIndustryOpenApiResult,
|
||||
) => { refundCount?: number } | void,
|
||||
) {
|
||||
setActionLoading(loadingKey)
|
||||
try {
|
||||
const response = await action()
|
||||
setLastResultTitle(title)
|
||||
setLastResult(response.data)
|
||||
setActiveTab('result')
|
||||
afterSuccess?.(response.data)
|
||||
const meta = afterSuccess?.(response.data) || undefined
|
||||
publishActionResult(
|
||||
buildIndustryActionResultView(kind, title, response.data, meta || undefined),
|
||||
)
|
||||
if (response.data.success) {
|
||||
showSuccess(`${title}已执行`)
|
||||
} else {
|
||||
showError(response.data.error || `${title}返回失败`)
|
||||
}
|
||||
} catch (error) {
|
||||
showError(error instanceof Error ? error.message : `${title}失败`)
|
||||
const message = error instanceof Error ? error.message : `${title}失败`
|
||||
publishActionResult(
|
||||
buildIndustryActionResultView(kind, title, {
|
||||
success: false,
|
||||
error: message,
|
||||
}),
|
||||
)
|
||||
showError(message)
|
||||
} finally {
|
||||
setActionLoading('')
|
||||
}
|
||||
}
|
||||
|
||||
function publishActionResult(view: IndustryActionResultView) {
|
||||
setLastActionResult(view)
|
||||
}
|
||||
|
||||
function buildVoucherToolPayload(): AdminKuaishouIndustryVoucherToolPayload {
|
||||
const voucherCode = String(toolForm.voucherCode || '').trim()
|
||||
return {
|
||||
@@ -498,7 +554,7 @@ export default function AdminKuaishouIndustryPage() {
|
||||
: []),
|
||||
{
|
||||
key: 'result',
|
||||
label: '接口结果',
|
||||
label: lastActionResult ? `接口结果 · ${lastActionResult.title}` : '接口结果',
|
||||
children: renderResultTab(),
|
||||
},
|
||||
]
|
||||
@@ -697,6 +753,7 @@ export default function AdminKuaishouIndustryPage() {
|
||||
重发发码
|
||||
</Button>
|
||||
</Space>
|
||||
{renderInlineActionResult('vouchers')}
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
@@ -898,39 +955,124 @@ export default function AdminKuaishouIndustryPage() {
|
||||
</Button>
|
||||
</Card>
|
||||
</div>
|
||||
{renderInlineActionResult('refunds')}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function renderInlineActionResult(scope: IndustryActionScope) {
|
||||
if (!lastActionResult || lastActionResult.scope !== scope) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="kuaishou-industry-action-result">
|
||||
{renderActionResultBody(lastActionResult, {
|
||||
compact: true,
|
||||
onOpenRaw: () => setActiveTab('result'),
|
||||
onClear: () => setLastActionResult(null),
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function renderResultTab() {
|
||||
const summary = resolveOpenApiResultSummary(lastResult)
|
||||
|
||||
return (
|
||||
<Card
|
||||
title={lastResultTitle}
|
||||
title={lastActionResult?.title || '接口结果'}
|
||||
extra={
|
||||
<Button icon={<ReloadOutlined />} onClick={() => setLastResult(null)}>
|
||||
清空
|
||||
</Button>
|
||||
lastActionResult ? (
|
||||
<Button icon={<ReloadOutlined />} onClick={() => setLastActionResult(null)}>
|
||||
清空
|
||||
</Button>
|
||||
) : null
|
||||
}
|
||||
>
|
||||
{lastResult ? (
|
||||
<Space direction="vertical" size={12} className="full-width">
|
||||
<Alert
|
||||
type={summary.success ? 'success' : 'error'}
|
||||
showIcon
|
||||
message={summary.title}
|
||||
description={summary.description}
|
||||
/>
|
||||
<pre className="json-preview">{stringifyDisplayJson(lastResult)}</pre>
|
||||
</Space>
|
||||
{lastActionResult ? (
|
||||
renderActionResultBody(lastActionResult, { compact: false })
|
||||
) : (
|
||||
<Alert type="info" showIcon message="暂无接口结果" />
|
||||
<Alert
|
||||
type="info"
|
||||
showIcon
|
||||
message="暂无接口结果"
|
||||
description="在「券码操作」或「售后退款」执行接口后,结果会展示在对应操作区;这里保留完整原始响应。"
|
||||
/>
|
||||
)}
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
function renderActionResultBody(
|
||||
result: IndustryActionResultView,
|
||||
options: {
|
||||
compact?: boolean
|
||||
onOpenRaw?: () => void
|
||||
onClear?: () => void
|
||||
} = {},
|
||||
) {
|
||||
return (
|
||||
<Space direction="vertical" size={12} className="full-width">
|
||||
<Alert
|
||||
type={result.success ? 'success' : 'error'}
|
||||
showIcon
|
||||
message={
|
||||
<Space wrap size={[8, 4]}>
|
||||
<span>{result.title}</span>
|
||||
<Tag color={result.success ? 'success' : 'error'}>
|
||||
{result.success ? '成功' : '失败'}
|
||||
</Tag>
|
||||
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
|
||||
{formatAdminDateTime(result.executedAt)}
|
||||
</Typography.Text>
|
||||
</Space>
|
||||
}
|
||||
description={result.summary}
|
||||
action={
|
||||
options.compact ? (
|
||||
<Space>
|
||||
{options.onOpenRaw ? (
|
||||
<Button size="small" type="link" onClick={options.onOpenRaw}>
|
||||
原始响应
|
||||
</Button>
|
||||
) : null}
|
||||
{options.onClear ? (
|
||||
<Button size="small" type="link" onClick={options.onClear}>
|
||||
关闭
|
||||
</Button>
|
||||
) : null}
|
||||
</Space>
|
||||
) : undefined
|
||||
}
|
||||
/>
|
||||
|
||||
{result.highlights.length > 0 ? (
|
||||
<Descriptions
|
||||
size="small"
|
||||
bordered
|
||||
column={options.compact ? 1 : 2}
|
||||
items={result.highlights.map((item) => ({
|
||||
key: item.label,
|
||||
label: item.label,
|
||||
children: item.value || '-',
|
||||
}))}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<Collapse
|
||||
size="small"
|
||||
items={[
|
||||
{
|
||||
key: 'raw',
|
||||
label: '原始响应 JSON',
|
||||
children: <pre className="json-preview">{stringifyDisplayJson(result.raw)}</pre>,
|
||||
},
|
||||
]}
|
||||
defaultActiveKey={options.compact ? [] : ['raw']}
|
||||
/>
|
||||
</Space>
|
||||
)
|
||||
}
|
||||
|
||||
function updateToolForm(patch: Partial<AdminKuaishouIndustryVoucherToolPayload>) {
|
||||
setToolForm((current) => ({ ...current, ...patch }))
|
||||
}
|
||||
@@ -997,43 +1139,261 @@ function extractRefundRows(
|
||||
: []
|
||||
}
|
||||
|
||||
function resolveOpenApiResultSummary(value: unknown) {
|
||||
const result =
|
||||
value && typeof value === 'object' && !Array.isArray(value)
|
||||
? (value as Record<string, unknown>)
|
||||
: {}
|
||||
const response =
|
||||
result.response && typeof result.response === 'object' && !Array.isArray(result.response)
|
||||
? (result.response as Record<string, unknown>)
|
||||
: null
|
||||
const success = Boolean(result.success)
|
||||
const code = String(response?.code || response?.sub_code || '').trim()
|
||||
const resultCode = String(response?.result || '').trim()
|
||||
const message = String(
|
||||
response?.error_msg ||
|
||||
response?.msg ||
|
||||
response?.sub_msg ||
|
||||
response?.message ||
|
||||
result.error ||
|
||||
'',
|
||||
).trim()
|
||||
const status = Number(result.httpStatus || 0) || 0
|
||||
const durationMs = Number(result.durationMs || 0) || 0
|
||||
const markers = [
|
||||
status ? `HTTP ${status}` : '',
|
||||
resultCode ? `result=${resultCode}` : '',
|
||||
code ? `code=${code}` : '',
|
||||
durationMs ? `${durationMs}ms` : '',
|
||||
].filter(Boolean)
|
||||
function buildIndustryActionResultView(
|
||||
kind: IndustryActionKind,
|
||||
title: string,
|
||||
raw: unknown,
|
||||
meta?: { refundCount?: number },
|
||||
): IndustryActionResultView {
|
||||
const scope: IndustryActionScope = kind.startsWith('refund') ? 'refunds' : 'vouchers'
|
||||
const record = asRecord(raw)
|
||||
const openApi = asOpenApiShape(record)
|
||||
const voucher = asRecord(record.voucher)
|
||||
const task = asRecord(record.task)
|
||||
const response = openApi.response
|
||||
const responseData = asRecord(response?.data)
|
||||
const success = resolveActionSuccess(kind, record, openApi)
|
||||
const platformMessage = pickFirstString([
|
||||
response?.error_msg,
|
||||
response?.msg,
|
||||
response?.sub_msg,
|
||||
response?.message,
|
||||
openApi.error,
|
||||
record.error,
|
||||
])
|
||||
const platformResult = pickFirstString([response?.result, response?.code, response?.sub_code])
|
||||
const highlights: IndustryActionHighlight[] = []
|
||||
|
||||
pushHighlight(highlights, '接口', title)
|
||||
if (openApi.httpStatus) {
|
||||
pushHighlight(highlights, 'HTTP', String(openApi.httpStatus))
|
||||
}
|
||||
if (openApi.durationMs) {
|
||||
pushHighlight(highlights, '耗时', `${openApi.durationMs}ms`)
|
||||
}
|
||||
if (platformResult) {
|
||||
pushHighlight(highlights, '平台 result', platformResult)
|
||||
}
|
||||
if (openApi.skippedReason) {
|
||||
pushHighlight(highlights, '跳过原因', openApi.skippedReason)
|
||||
}
|
||||
|
||||
if (kind === 'check') {
|
||||
const etickets = extractAvailableEtickets(responseData)
|
||||
pushHighlight(highlights, '可核销券数', String(etickets.length || 0))
|
||||
if (etickets[0]) {
|
||||
pushHighlight(
|
||||
highlights,
|
||||
'首张券码',
|
||||
pickFirstString([etickets[0].code, etickets[0].id]) || '-',
|
||||
)
|
||||
pushHighlight(highlights, '首张数量', String(etickets[0].num || 1))
|
||||
}
|
||||
}
|
||||
|
||||
if (kind === 'consume' || kind === 'reverse' || kind === 'resend' || voucher) {
|
||||
if (voucher) {
|
||||
pushHighlight(highlights, '券码', String(voucher.voucherCode || '-'))
|
||||
pushHighlight(
|
||||
highlights,
|
||||
'券状态',
|
||||
getVoucherStatusLabel(String(voucher.status || '')),
|
||||
)
|
||||
if (voucher.consumeSerialNum) {
|
||||
pushHighlight(highlights, '核销序列号', String(voucher.consumeSerialNum))
|
||||
}
|
||||
if (voucher.sendCallbackStatus) {
|
||||
pushHighlight(highlights, '发码状态', String(voucher.sendCallbackStatus))
|
||||
}
|
||||
if (voucher.sendCallbackLastError) {
|
||||
pushHighlight(highlights, '发码错误', String(voucher.sendCallbackLastError))
|
||||
}
|
||||
}
|
||||
if (task) {
|
||||
pushHighlight(highlights, '任务号', String(task.taskNo || task.taskId || '-'))
|
||||
pushHighlight(highlights, '任务状态', String(task.status || '-'))
|
||||
if (task.deliveryStatus) {
|
||||
pushHighlight(highlights, '交付状态', String(task.deliveryStatus))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (kind === 'refund-list') {
|
||||
const count =
|
||||
typeof meta?.refundCount === 'number'
|
||||
? meta.refundCount
|
||||
: extractRefundRows(response).length
|
||||
pushHighlight(highlights, '售后单数量', String(count))
|
||||
const pcursor = pickFirstString([
|
||||
responseData?.pcursor,
|
||||
responseData?.cursor,
|
||||
asRecord(response)?.pcursor,
|
||||
])
|
||||
if (pcursor) {
|
||||
pushHighlight(highlights, '下一页游标', pcursor)
|
||||
}
|
||||
}
|
||||
|
||||
if (kind === 'refund-approve' || kind === 'refund-disagree') {
|
||||
const refundId = pickFirstString([
|
||||
responseData?.refundId,
|
||||
asRecord(openApi.request)?.refundId,
|
||||
])
|
||||
if (refundId) {
|
||||
pushHighlight(highlights, '退款单号', refundId)
|
||||
}
|
||||
}
|
||||
|
||||
if (platformMessage) {
|
||||
pushHighlight(highlights, '平台消息', platformMessage)
|
||||
}
|
||||
|
||||
return {
|
||||
kind,
|
||||
scope,
|
||||
title,
|
||||
success,
|
||||
title: success ? '接口返回成功' : '接口返回失败',
|
||||
description:
|
||||
[markers.join(' / '), message].filter(Boolean).join(',') || '请查看下方原始响应。',
|
||||
summary: buildActionSummary(kind, success, {
|
||||
platformMessage,
|
||||
platformResult,
|
||||
refundCount: meta?.refundCount,
|
||||
voucherStatus: voucher ? getVoucherStatusLabel(String(voucher.status || '')) : '',
|
||||
skippedReason: openApi.skippedReason,
|
||||
}),
|
||||
highlights,
|
||||
raw,
|
||||
executedAt: new Date().toISOString(),
|
||||
}
|
||||
}
|
||||
|
||||
function buildActionSummary(
|
||||
kind: IndustryActionKind,
|
||||
success: boolean,
|
||||
context: {
|
||||
platformMessage: string
|
||||
platformResult: string
|
||||
refundCount?: number
|
||||
voucherStatus: string
|
||||
skippedReason: string
|
||||
},
|
||||
) {
|
||||
if (context.skippedReason) {
|
||||
return `请求被跳过:${context.skippedReason}${context.platformMessage ? `,${context.platformMessage}` : ''}`
|
||||
}
|
||||
|
||||
if (kind === 'check') {
|
||||
return success
|
||||
? context.platformMessage || '平台返回券码有效,可继续核销。'
|
||||
: context.platformMessage || '检查失败,请核对卖家、券码与电子凭证类型。'
|
||||
}
|
||||
|
||||
if (kind === 'consume') {
|
||||
return success
|
||||
? `核销成功${context.voucherStatus ? `,券状态:${context.voucherStatus}` : ''}。`
|
||||
: context.platformMessage || '核销失败。'
|
||||
}
|
||||
|
||||
if (kind === 'reverse') {
|
||||
return success
|
||||
? `冲正成功${context.voucherStatus ? `,券状态已回写为 ${context.voucherStatus}` : ''}。`
|
||||
: context.platformMessage || '冲正失败。'
|
||||
}
|
||||
|
||||
if (kind === 'resend') {
|
||||
return success
|
||||
? '发码回调已重发,请确认发码状态是否更新为 success。'
|
||||
: context.platformMessage || '重发发码失败。'
|
||||
}
|
||||
|
||||
if (kind === 'refund-list') {
|
||||
return success
|
||||
? `查询成功,共 ${context.refundCount ?? 0} 条售后单,已填充列表。`
|
||||
: context.platformMessage || '查询售后单失败。'
|
||||
}
|
||||
|
||||
if (kind === 'refund-approve') {
|
||||
return success
|
||||
? context.platformMessage || '同意退款已提交。'
|
||||
: context.platformMessage || '同意退款失败。'
|
||||
}
|
||||
|
||||
if (kind === 'refund-disagree') {
|
||||
return success
|
||||
? context.platformMessage || '不同意退款已提交。'
|
||||
: context.platformMessage || '不同意退款失败。'
|
||||
}
|
||||
|
||||
return (
|
||||
context.platformMessage ||
|
||||
(success ? '接口执行成功。' : '接口执行失败。') +
|
||||
(context.platformResult ? `(result=${context.platformResult})` : '')
|
||||
)
|
||||
}
|
||||
|
||||
function resolveActionSuccess(
|
||||
kind: IndustryActionKind,
|
||||
record: Record<string, unknown>,
|
||||
openApi: ReturnType<typeof asOpenApiShape>,
|
||||
) {
|
||||
if (typeof record.success === 'boolean') {
|
||||
return record.success
|
||||
}
|
||||
if (kind === 'consume') {
|
||||
return Boolean(record.voucher)
|
||||
}
|
||||
return openApi.success
|
||||
}
|
||||
|
||||
function asOpenApiShape(record: Record<string, unknown>) {
|
||||
const response = asRecord(record.response)
|
||||
return {
|
||||
success: Boolean(record.success),
|
||||
error: String(record.error || '').trim(),
|
||||
response,
|
||||
request: asRecord(record.request),
|
||||
durationMs: Number(record.durationMs || 0) || 0,
|
||||
httpStatus: Number(record.httpStatus || 0) || 0,
|
||||
skippedReason: String(record.skippedReason || '').trim(),
|
||||
}
|
||||
}
|
||||
|
||||
function extractAvailableEtickets(data: Record<string, unknown> | null) {
|
||||
const candidates = [data?.etickets, data?.eTicketList, data?.eticketList, data?.list]
|
||||
for (const candidate of candidates) {
|
||||
if (!Array.isArray(candidate)) {
|
||||
continue
|
||||
}
|
||||
return candidate
|
||||
.map((item) => asRecord(item))
|
||||
.filter((item): item is Record<string, unknown> => Boolean(item))
|
||||
}
|
||||
return [] as Array<Record<string, unknown>>
|
||||
}
|
||||
|
||||
function asRecord(value: unknown): Record<string, unknown> | null {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
||||
return null
|
||||
}
|
||||
return value as Record<string, unknown>
|
||||
}
|
||||
|
||||
function pickFirstString(values: unknown[]) {
|
||||
for (const value of values) {
|
||||
const text = String(value ?? '').trim()
|
||||
if (text) {
|
||||
return text
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
function pushHighlight(list: IndustryActionHighlight[], label: string, value: string) {
|
||||
if (!value || value === '-') {
|
||||
return
|
||||
}
|
||||
list.push({ label, value })
|
||||
}
|
||||
|
||||
function getVoucherStatusColor(status: string) {
|
||||
const normalized = String(status || '').toUpperCase()
|
||||
if (normalized === 'CONSUMED') return 'green'
|
||||
|
||||
@@ -324,6 +324,16 @@ select {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.kuaishou-industry-action-result {
|
||||
margin-top: 14px;
|
||||
padding-top: 14px;
|
||||
border-top: 1px solid #edf0f5;
|
||||
}
|
||||
|
||||
.kuaishou-industry-action-result .json-preview {
|
||||
max-height: 280px;
|
||||
}
|
||||
|
||||
.task-action-hint {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
|
||||
Reference in New Issue
Block a user