接入多发货平台与电子凭证

This commit is contained in:
yml2213
2026-07-07 12:06:19 +08:00
parent c101b5f359
commit ddfa6c278f
35 changed files with 2627 additions and 365 deletions
-3
View File
@@ -17,7 +17,6 @@ declare module 'vue' {
ElAlert: typeof import('element-plus/es')['ElAlert']
ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCol: typeof import('element-plus/es')['ElCol']
ElCollapse: typeof import('element-plus/es')['ElCollapse']
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
@@ -32,7 +31,6 @@ declare module 'vue' {
ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElImage: typeof import('element-plus/es')['ElImage']
ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElMenu: typeof import('element-plus/es')['ElMenu']
@@ -45,7 +43,6 @@ declare module 'vue' {
ElRow: typeof import('element-plus/es')['ElRow']
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
ElSpace: typeof import('element-plus/es')['ElSpace']
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import('element-plus/es')['ElTable']
+20 -1
View File
@@ -135,15 +135,34 @@ export interface ClaimKuaishouCloudFlowInfo {
}
}
export interface ClaimKuaishouFeifeiFlowInfo {
flowType: 'kuaishou_feifei'
productCode: string
productName: string
platformOrderNo: string
orderNo: string
rechargeStatus: number
rechargeStatusLabel: string
rechargeResultMessage: string
claimUrl: string
consumeStatus: string
h5: {
entryUrl: string
rechargeUrl: string
}
lastSyncedAt: string | null
}
export interface ClaimDetailData {
tokenStatus: ClaimTokenStatus
claimUrl: string
flowType: 'kuaishou_cloud' | 'kuaishou_ct_assisted' | (string & {})
flowType: 'kuaishou_cloud' | 'kuaishou_ct_assisted' | 'kuaishou_feifei' | (string & {})
task: ClaimTaskInfo
order: ClaimOrderInfo
orderItem: ClaimOrderItemInfo
product: ClaimProductInfo
session: unknown | null
kuaishouCloudFulfillment: ClaimKuaishouCloudFlowInfo | null
kuaishouFeifei: ClaimKuaishouFeifeiFlowInfo | null
result: ClaimResultInfo | null
}
@@ -34,6 +34,42 @@ const claim = useKuaishouCloudClaim(() => props.token)
<p>{{ claim.errorMessage.value }}</p>
</div>
<template v-else-if="claim.detail.value?.flowType === 'kuaishou_feifei' && claim.feifei.value">
<section class="content-card feifei-card">
<div class="feifei-main">
<p class="feifei-label">kuaishou-feifei</p>
<h2>{{ claim.product.value?.title || claim.orderItem.value?.skuName || '商品领取' }}</h2>
<p class="feifei-status">
{{ claim.feifei.value.rechargeStatusLabel || '待领取' }}
</p>
</div>
<dl class="feifei-meta">
<div>
<dt>订单号</dt>
<dd>{{ claim.order.value?.platformOrderId || '-' }}</dd>
</div>
<div>
<dt>平台单号</dt>
<dd>{{ claim.feifei.value.orderNo || claim.feifei.value.platformOrderNo || '-' }}</dd>
</div>
</dl>
<el-button
type="primary"
size="large"
:disabled="!claim.feifei.value.h5.rechargeUrl && !claim.feifei.value.h5.entryUrl"
@click="claim.openFeifeiUrl(false)"
>
打开领取链接
</el-button>
<p v-if="claim.task.value?.lastError" class="feifei-error">
{{ claim.task.value.lastError }}
</p>
</section>
</template>
<template v-else-if="claim.detail.value && claim.flow.value">
<ClaimTicketStep
v-if="claim.currentStep.value === 1"
@@ -145,6 +181,60 @@ const claim = useKuaishouCloudClaim(() => props.token)
color: #dc2626;
}
.feifei-card {
gap: 22px;
}
.feifei-main {
display: grid;
gap: 8px;
}
.feifei-label {
margin: 0;
color: #64748b;
font-size: 13px;
}
.feifei-main h2 {
margin: 0;
font-size: 22px;
color: #0f172a;
}
.feifei-status {
margin: 0;
color: #2563eb;
font-weight: 600;
}
.feifei-meta {
margin: 0;
display: grid;
gap: 12px;
}
.feifei-meta div {
display: grid;
gap: 4px;
}
.feifei-meta dt {
color: #64748b;
font-size: 13px;
}
.feifei-meta dd {
margin: 0;
color: #0f172a;
word-break: break-all;
}
.feifei-error {
margin: 0;
color: #b45309;
}
.spinning {
animation: spin 1s linear infinite;
}
@@ -46,6 +46,7 @@ export function useKuaishouCloudClaim(token: () => string) {
// ── derived data ────────────────────────────────────────
const flow = computed(() => detail.value?.kuaishouCloudFulfillment || null)
const feifei = computed(() => detail.value?.kuaishouFeifei || null)
const order = computed(() => detail.value?.order || null)
const orderItem = computed(() => detail.value?.orderItem || null)
const product = computed(() => detail.value?.product || null)
@@ -55,6 +56,7 @@ export function useKuaishouCloudClaim(token: () => string) {
const roleName = computed(() => flow.value?.role.name || flow.value?.binding.roleName || '')
const roleId = computed(() => flow.value?.role.rid || flow.value?.binding.roleId || '')
const isFeifeiFlow = computed(() => detail.value?.flowType === 'kuaishou_feifei')
const isTicketVerified = computed(() => flow.value?.ticket.status === 'verified')
const isBindUrlExpired = computed(() => {
@@ -125,6 +127,9 @@ export function useKuaishouCloudClaim(token: () => string) {
)
const currentStep = computed(() => {
if (isFeifeiFlow.value) {
return isCompleted.value ? 4 : 2
}
if (hasRedeemResult.value) {
return 4
}
@@ -138,6 +143,9 @@ export function useKuaishouCloudClaim(token: () => string) {
})
const progressText = computed(() => {
if (isFeifeiFlow.value) {
return feifei.value?.rechargeStatusLabel || '请打开领取链接'
}
if (hasRedeemResult.value) {
return '兑换结果已生成'
}
@@ -365,6 +373,19 @@ export function useKuaishouCloudClaim(token: () => string) {
window.open(bindUrl, '_blank', 'noopener,noreferrer')
}
function openFeifeiUrl(useCurrentPage = false) {
const url = String(feifei.value?.h5.rechargeUrl || feifei.value?.h5.entryUrl || '').trim()
if (!url) {
showError('领取链接还没准备好,请稍后刷新')
return
}
if (useCurrentPage) {
window.location.assign(url)
return
}
window.open(url, '_blank', 'noopener,noreferrer')
}
// ── polling ─────────────────────────────────────────────
function stopPolling() {
@@ -457,6 +478,7 @@ export function useKuaishouCloudClaim(token: () => string) {
qrCodeDataUrl,
// derived data
flow,
feifei,
order,
orderItem,
product,
@@ -464,6 +486,7 @@ export function useKuaishouCloudClaim(token: () => string) {
// computed status
roleName,
roleId,
isFeifeiFlow,
isTicketVerified,
isBindUrlExpired,
isBindingPrepared,
@@ -493,6 +516,7 @@ export function useKuaishouCloudClaim(token: () => string) {
rebindRole,
confirmRedeem,
openBindUrl,
openFeifeiUrl,
// utility
formatAdminDateTime,
}