feat(frontend): extract task cloud panel
This commit is contained in:
@@ -1,9 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
|
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
import AdminStatusTag from '@/components/admin/AdminStatusTag.vue'
|
import AdminStatusTag from '@/components/admin/AdminStatusTag.vue'
|
||||||
import { showConfirm, showError, showSuccess } from '@/lib/feedback'
|
import { showConfirm, showError, showSuccess } from '@/lib/feedback'
|
||||||
|
|
||||||
|
import AdminTaskKuaishouCloudPanel from './components/AdminTaskKuaishouCloudPanel.vue'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
closeAdminTask,
|
closeAdminTask,
|
||||||
confirmAdminTaskAssistedRole,
|
confirmAdminTaskAssistedRole,
|
||||||
@@ -52,7 +54,6 @@ const canViewSensitiveTaskData = computed(() =>
|
|||||||
)
|
)
|
||||||
const kuaishouCloudFlow = computed(() => detail.value?.kuaishouCloudFulfillment || null)
|
const kuaishouCloudFlow = computed(() => detail.value?.kuaishouCloudFulfillment || null)
|
||||||
const kuaishouCloudRole = computed(() => kuaishouCloudFlow.value?.role || null)
|
const kuaishouCloudRole = computed(() => kuaishouCloudFlow.value?.role || null)
|
||||||
const kuaishouCloudCollapsePanels = ref(['claim', 'ticket', 'cloud'])
|
|
||||||
const isKuaishouCloudTask = computed(
|
const isKuaishouCloudTask = computed(
|
||||||
() => detail.value?.task.executorKey === 'kuaishou_ct_assisted',
|
() => detail.value?.task.executorKey === 'kuaishou_ct_assisted',
|
||||||
)
|
)
|
||||||
@@ -394,7 +395,8 @@ onBeforeUnmount(clearScreenshotPreview)
|
|||||||
<h2>{{ detail.task.taskNo }}</h2>
|
<h2>{{ detail.task.taskNo }}</h2>
|
||||||
<p>
|
<p>
|
||||||
订单 {{ detail.order?.platformOrderId || '-' }} · 商品
|
订单 {{ detail.order?.platformOrderId || '-' }} · 商品
|
||||||
{{ detail.orderItem?.skuName || detail.orderItem?.skuCode || '-' }} · 店铺
|
{{ detail.orderItem?.skuName || detail.orderItem?.skuCode || '-' }}
|
||||||
|
· 店铺
|
||||||
{{ detail.order?.shopName || detail.order?.shopId || '-' }}
|
{{ detail.order?.shopName || detail.order?.shopId || '-' }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -439,7 +441,10 @@ onBeforeUnmount(clearScreenshotPreview)
|
|||||||
系统绑定:<AdminStatusTag :status="detail.task.systemBindingStatus" /> ·
|
系统绑定:<AdminStatusTag :status="detail.task.systemBindingStatus" /> ·
|
||||||
完整绑定:<AdminStatusTag :status="detail.task.userBindingStatus" />
|
完整绑定:<AdminStatusTag :status="detail.task.userBindingStatus" />
|
||||||
</p>
|
</p>
|
||||||
<p>角色:{{ detail.task.roleName || '-' }} / {{ detail.task.roleId || '-' }}</p>
|
<p>
|
||||||
|
角色:{{ detail.task.roleName || '-' }} /
|
||||||
|
{{ detail.task.roleId || '-' }}
|
||||||
|
</p>
|
||||||
<p>最后错误:{{ detail.task.lastError || '-' }}</p>
|
<p>最后错误:{{ detail.task.lastError || '-' }}</p>
|
||||||
<p v-if="claimUrl">
|
<p v-if="claimUrl">
|
||||||
领取链接:
|
领取链接:
|
||||||
@@ -607,7 +612,9 @@ onBeforeUnmount(clearScreenshotPreview)
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>履约状态</th>
|
<th>履约状态</th>
|
||||||
<td><AdminStatusTag :status="detail.task.deliveryStatus || ''" /></td>
|
<td>
|
||||||
|
<AdminStatusTag :status="detail.task.deliveryStatus || ''" />
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>结果代码</th>
|
<th>结果代码</th>
|
||||||
@@ -627,7 +634,9 @@ onBeforeUnmount(clearScreenshotPreview)
|
|||||||
</tr>
|
</tr>
|
||||||
<tr v-if="canViewSensitiveTaskData">
|
<tr v-if="canViewSensitiveTaskData">
|
||||||
<th>库存状态</th>
|
<th>库存状态</th>
|
||||||
<td><AdminStatusTag :status="detail.inventory?.status || ''" /></td>
|
<td>
|
||||||
|
<AdminStatusTag :status="detail.inventory?.status || ''" />
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-if="canViewSensitiveTaskData">
|
<tr v-if="canViewSensitiveTaskData">
|
||||||
<th>Claim Token</th>
|
<th>Claim Token</th>
|
||||||
@@ -639,7 +648,9 @@ onBeforeUnmount(clearScreenshotPreview)
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Token 状态</th>
|
<th>Token 状态</th>
|
||||||
<td><AdminStatusTag :status="detail.claimToken?.status || ''" /></td>
|
<td>
|
||||||
|
<AdminStatusTag :status="detail.claimToken?.status || ''" />
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Token 过期</th>
|
<th>Token 过期</th>
|
||||||
@@ -684,301 +695,18 @@ onBeforeUnmount(clearScreenshotPreview)
|
|||||||
</table>
|
</table>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section v-if="isKuaishouCloudTask && kuaishouCloudFlow" class="info-card flow-card">
|
<AdminTaskKuaishouCloudPanel
|
||||||
<div class="flow-card-head">
|
v-if="isKuaishouCloudTask && kuaishouCloudFlow"
|
||||||
<div>
|
:detail="detail"
|
||||||
<h3>快手 Cloud 履约面板</h3>
|
:flow="kuaishouCloudFlow"
|
||||||
<p class="section-copy">
|
:role-info-entries="kuaishouRoleInfoEntries"
|
||||||
这是一套独立的快手 Cloud
|
:checklist="kuaishouCloudChecklist"
|
||||||
任务面板,优先展示角色信息与当前履约推进点,次级明细可按需展开。
|
:claim-url="claimUrl"
|
||||||
</p>
|
:action-loading="actionLoading"
|
||||||
</div>
|
@refresh-role="submitKuaishouCloudRefreshRoleInfo"
|
||||||
<div class="flow-head-actions">
|
@copy-bind-url="copyText($event, '绑定链接已复制')"
|
||||||
<el-button
|
@open-bind-url="openExternalLink"
|
||||||
v-if="detail.operations.canRefreshKuaishouCloudRoleInfo"
|
/>
|
||||||
:loading="actionLoading"
|
|
||||||
round
|
|
||||||
@click="submitKuaishouCloudRefreshRoleInfo"
|
|
||||||
>
|
|
||||||
刷新角色信息
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
v-if="kuaishouCloudFlow.binding.bindUrl"
|
|
||||||
round
|
|
||||||
@click="copyText(kuaishouCloudFlow.binding.bindUrl, '绑定链接已复制')"
|
|
||||||
>
|
|
||||||
复制绑定链接
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
v-if="kuaishouCloudFlow.binding.bindUrl"
|
|
||||||
round
|
|
||||||
type="primary"
|
|
||||||
plain
|
|
||||||
@click="openExternalLink(kuaishouCloudFlow.binding.bindUrl)"
|
|
||||||
>
|
|
||||||
打开绑定页
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="redeem-summary-grid">
|
|
||||||
<article class="redeem-summary-card">
|
|
||||||
<span>准备状态</span>
|
|
||||||
<div class="auto-delivery-tag-line">
|
|
||||||
<AdminStatusTag :status="kuaishouCloudFlow.binding.prepareStatus" />
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
<article class="redeem-summary-card">
|
|
||||||
<span>发货状态</span>
|
|
||||||
<div class="auto-delivery-tag-line">
|
|
||||||
<AdminStatusTag :status="kuaishouCloudFlow.dispatch.status" />
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
<article class="redeem-summary-card">
|
|
||||||
<span>退号状态</span>
|
|
||||||
<div class="auto-delivery-tag-line">
|
|
||||||
<AdminStatusTag :status="kuaishouCloudFlow.returnNumber.status" />
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
<article class="redeem-summary-card">
|
|
||||||
<span>当前任务状态</span>
|
|
||||||
<div class="auto-delivery-tag-line">
|
|
||||||
<AdminStatusTag :status="detail.task.status" />
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="kuaishou-focus-grid">
|
|
||||||
<article class="flow-block flow-block--spotlight">
|
|
||||||
<div class="spotlight-head">
|
|
||||||
<div>
|
|
||||||
<h4>角色信息</h4>
|
|
||||||
<p class="flow-copy">
|
|
||||||
角色信息来自 cloudtentacles 的 `vn/bind_info`,客服可在客户绑定后手动刷新。
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="spotlight-actions">
|
|
||||||
<AdminStatusTag :status="kuaishouCloudRole?.status || 'pending'" />
|
|
||||||
<el-button
|
|
||||||
v-if="detail.operations.canRefreshKuaishouCloudRoleInfo"
|
|
||||||
:loading="actionLoading"
|
|
||||||
round
|
|
||||||
size="small"
|
|
||||||
@click="submitKuaishouCloudRefreshRoleInfo"
|
|
||||||
>
|
|
||||||
刷新
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="role-hero">
|
|
||||||
<div>
|
|
||||||
<span>角色名</span>
|
|
||||||
<strong>{{ kuaishouCloudRole?.name || detail.task.roleName || '等待识别' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>角色 ID</span>
|
|
||||||
<strong>{{ kuaishouCloudRole?.rid || detail.task.roleId || '等待识别' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>最近刷新</span>
|
|
||||||
<strong>{{ formatAdminDateTime(kuaishouCloudRole?.refreshedAt) }}</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p v-if="kuaishouCloudRole?.errorMessage" class="role-warning">
|
|
||||||
{{ kuaishouCloudRole.errorMessage }}
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
v-if="kuaishouRoleInfoEntries.length > 0"
|
|
||||||
class="flow-meta-list flow-meta-list--dense"
|
|
||||||
>
|
|
||||||
<div v-for="entry in kuaishouRoleInfoEntries" :key="entry.key">
|
|
||||||
<span>{{ entry.label }}</span>
|
|
||||||
<strong>{{ entry.value }}</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
|
|
||||||
<article class="flow-block flow-block--checklist">
|
|
||||||
<h4>流程检查</h4>
|
|
||||||
<p class="flow-copy">
|
|
||||||
客服可以先看这里,快速判断卡在哪一步,再决定是刷新角色、准备资源、发货还是退号。
|
|
||||||
</p>
|
|
||||||
<div class="checklist-grid">
|
|
||||||
<div v-for="item in kuaishouCloudChecklist" :key="item.key" class="checklist-item">
|
|
||||||
<div class="checklist-item-head">
|
|
||||||
<span>{{ item.label }}</span>
|
|
||||||
<AdminStatusTag :status="item.status" />
|
|
||||||
</div>
|
|
||||||
<strong>{{ item.detail }}</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-collapse v-model="kuaishouCloudCollapsePanels" class="flow-collapse">
|
|
||||||
<el-collapse-item name="claim" title="客户领取与绑定">
|
|
||||||
<div class="flow-meta-list flow-meta-list--two-column">
|
|
||||||
<div>
|
|
||||||
<span>客户链接</span><strong>{{ claimUrl || '-' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>绑定链接</span><strong>{{ kuaishouCloudFlow.binding.bindUrl || '-' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>Token 状态</span><strong>{{ detail.claimToken?.status || '-' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>准备时间</span
|
|
||||||
><strong>{{
|
|
||||||
formatAdminDateTime(kuaishouCloudFlow.binding.bindPreparedAt)
|
|
||||||
}}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>首次提交</span
|
|
||||||
><strong>{{ formatAdminDateTime(kuaishouCloudFlow.ticket.capturedAt) }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>校验时间</span
|
|
||||||
><strong>{{ formatAdminDateTime(kuaishouCloudFlow.ticket.verifiedAt) }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>虚拟号 ID</span><strong>{{ kuaishouCloudFlow.binding.vnId || '-' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>虚拟号码</span><strong>{{ kuaishouCloudFlow.binding.vnPhone || '-' }}</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p class="manual-hint">
|
|
||||||
客户会先在领取页查看图文指引并提交核销码,只有校验通过后才会自动跳转绑定链接。
|
|
||||||
</p>
|
|
||||||
</el-collapse-item>
|
|
||||||
|
|
||||||
<el-collapse-item name="ticket" title="核销与商品信息">
|
|
||||||
<div class="flow-meta-list flow-meta-list--two-column">
|
|
||||||
<div>
|
|
||||||
<span>核销码</span><strong>{{ kuaishouCloudFlow.ticket.code || '-' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>校验状态</span><strong>{{ kuaishouCloudFlow.ticket.status || '-' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>商品标题</span
|
|
||||||
><strong>{{ kuaishouCloudFlow.ticket.goodsTitle || '-' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>剩余次数</span><strong>{{ kuaishouCloudFlow.ticket.leftCount || 0 }}</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p class="manual-hint">
|
|
||||||
"确认绑定完成并发货"已经合并为一个按钮,只有核销码通过校验后才能继续。
|
|
||||||
</p>
|
|
||||||
</el-collapse-item>
|
|
||||||
|
|
||||||
<el-collapse-item name="cloud" title="Cloud 资源与发货">
|
|
||||||
<div class="flow-meta-list flow-meta-list--two-column">
|
|
||||||
<div>
|
|
||||||
<span>cloudSourceKey</span
|
|
||||||
><strong>{{ kuaishouCloudFlow.binding.cloudSourceKey || '-' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>cloud SKU</span
|
|
||||||
><strong>{{
|
|
||||||
kuaishouCloudFlow.binding.skuId
|
|
||||||
? `${kuaishouCloudFlow.binding.skuId} / ${kuaishouCloudFlow.binding.skuName || '-'}`
|
|
||||||
: '-'
|
|
||||||
}}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>VN Key</span><strong>{{ kuaishouCloudFlow.binding.vnKey || '-' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>自动购买</span
|
|
||||||
><strong>{{ kuaishouCloudFlow.purchase.autoBuyEnabled ? '开启' : '关闭' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>背包命中</span
|
|
||||||
><strong>{{ kuaishouCloudFlow.purchase.usedKnapsack ? '是' : '否' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>触发购买</span
|
|
||||||
><strong>{{ kuaishouCloudFlow.purchase.purchaseTriggered ? '是' : '否' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>购买时间</span
|
|
||||||
><strong>{{ formatAdminDateTime(kuaishouCloudFlow.purchase.purchaseAt) }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>发货时间</span
|
|
||||||
><strong>{{ formatAdminDateTime(kuaishouCloudFlow.dispatch.dispatchAt) }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>发送类型</span
|
|
||||||
><strong>{{ kuaishouCloudFlow.dispatch.sendType || '-' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>结果说明</span
|
|
||||||
><strong>{{
|
|
||||||
kuaishouCloudFlow.dispatch.note || detail.task.resultMessage || '-'
|
|
||||||
}}</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-collapse-item>
|
|
||||||
|
|
||||||
<el-collapse-item name="closure" title="流程收口">
|
|
||||||
<div class="flow-meta-list flow-meta-list--two-column">
|
|
||||||
<div>
|
|
||||||
<span>退号时间</span
|
|
||||||
><strong>{{
|
|
||||||
formatAdminDateTime(kuaishouCloudFlow.returnNumber.returnedAt)
|
|
||||||
}}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>自动退号</span
|
|
||||||
><strong>{{
|
|
||||||
kuaishouCloudFlow.returnNumber.autoReturnEnabled ? '开启' : '关闭'
|
|
||||||
}}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>自动核销</span
|
|
||||||
><strong>{{
|
|
||||||
kuaishouCloudFlow.consume.autoConsumeEnabled ? '开启' : '关闭'
|
|
||||||
}}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>核销店铺</span><strong>{{ kuaishouCloudFlow.consume.shopId || '-' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>核销店铺名</span
|
|
||||||
><strong>{{ kuaishouCloudFlow.consume.shopName || '-' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>核销时间</span
|
|
||||||
><strong>{{ formatAdminDateTime(kuaishouCloudFlow.consume.consumedAt) }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>核销异常</span
|
|
||||||
><strong>{{ kuaishouCloudFlow.consume.errorMessage || '-' }}</strong>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>备注</span><strong>{{ kuaishouCloudFlow.notes || '-' }}</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-collapse-item>
|
|
||||||
|
|
||||||
<el-collapse-item
|
|
||||||
v-if="kuaishouRoleInfoEntries.length > 0"
|
|
||||||
name="raw"
|
|
||||||
title="角色原始字段"
|
|
||||||
>
|
|
||||||
<div class="flow-meta-list flow-meta-list--two-column">
|
|
||||||
<div v-for="entry in kuaishouRoleInfoEntries" :key="`raw-${entry.key}`">
|
|
||||||
<span>{{ entry.label }}</span>
|
|
||||||
<strong>{{ entry.value }}</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-collapse-item>
|
|
||||||
</el-collapse>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section
|
<section
|
||||||
v-if="detail.order?.provider === 'agiso' && detail.order?.platform === 'xianyu'"
|
v-if="detail.order?.provider === 'agiso' && detail.order?.platform === 'xianyu'"
|
||||||
@@ -1086,7 +814,9 @@ onBeforeUnmount(clearScreenshotPreview)
|
|||||||
<strong>{{ attempt.resultCode || '-' }}</strong>
|
<strong>{{ attempt.resultCode || '-' }}</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="redeem-attempt-copy">{{ attempt.resultMessage || '-' }}</p>
|
<p class="redeem-attempt-copy">
|
||||||
|
{{ attempt.resultMessage || '-' }}
|
||||||
|
</p>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -1125,7 +855,8 @@ onBeforeUnmount(clearScreenshotPreview)
|
|||||||
<div>ID {{ binding.inventoryItemId }}</div>
|
<div>ID {{ binding.inventoryItemId }}</div>
|
||||||
<div>{{ binding.skuCode || '-' }}</div>
|
<div>{{ binding.skuCode || '-' }}</div>
|
||||||
<div class="binding-meta">
|
<div class="binding-meta">
|
||||||
{{ binding.credentialType || '-' }} · {{ binding.batchNo || '无批次' }}
|
{{ binding.credentialType || '-' }} ·
|
||||||
|
{{ binding.batchNo || '无批次' }}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -1143,7 +874,9 @@ onBeforeUnmount(clearScreenshotPreview)
|
|||||||
}}:{{ binding.invalidReason }}
|
}}:{{ binding.invalidReason }}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ canViewSensitiveTaskData ? binding.displayValue || '-' : '客服不可见' }}</td>
|
<td>
|
||||||
|
{{ canViewSensitiveTaskData ? binding.displayValue || '-' : '客服不可见' }}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>绑定 {{ formatAdminDateTime(binding.createdAt) }}</div>
|
<div>绑定 {{ formatAdminDateTime(binding.createdAt) }}</div>
|
||||||
<div class="binding-meta">消费 {{ formatAdminDateTime(binding.consumedAt) }}</div>
|
<div class="binding-meta">消费 {{ formatAdminDateTime(binding.consumedAt) }}</div>
|
||||||
@@ -1159,7 +892,9 @@ onBeforeUnmount(clearScreenshotPreview)
|
|||||||
() =>
|
() =>
|
||||||
releaseAdminTaskInventoryBinding(detail!.task.taskId, binding.bindingId),
|
releaseAdminTaskInventoryBinding(detail!.task.taskId, binding.bindingId),
|
||||||
'库存绑定已释放',
|
'库存绑定已释放',
|
||||||
`确认释放绑定 #${binding.bindingId} 对应的库存项 ${binding.displayValue || binding.inventoryItemId} 吗?`,
|
`确认释放绑定 #${binding.bindingId} 对应的库存项 ${
|
||||||
|
binding.displayValue || binding.inventoryItemId
|
||||||
|
} 吗?`,
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
@@ -1232,8 +967,12 @@ onBeforeUnmount(clearScreenshotPreview)
|
|||||||
<tr v-for="event in detail.events" :key="event.eventId">
|
<tr v-for="event in detail.events" :key="event.eventId">
|
||||||
<th>{{ formatTaskEventType(event.eventType) }}</th>
|
<th>{{ formatTaskEventType(event.eventType) }}</th>
|
||||||
<td>
|
<td>
|
||||||
<div class="event-copy">{{ formatTaskEventPayload(event.payload) }}</div>
|
<div class="event-copy">
|
||||||
<div class="event-time">{{ formatAdminDateTime(event.createdAt) }}</div>
|
{{ formatTaskEventPayload(event.payload) }}
|
||||||
|
</div>
|
||||||
|
<div class="event-time">
|
||||||
|
{{ formatAdminDateTime(event.createdAt) }}
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -0,0 +1,308 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import AdminStatusTag from '@/components/admin/AdminStatusTag.vue'
|
||||||
|
import type { AdminTaskDetail } from '@/types/admin'
|
||||||
|
import { formatAdminDateTime } from '@/utils/admin-time'
|
||||||
|
|
||||||
|
type KuaishouCloudFlow = NonNullable<AdminTaskDetail['kuaishouCloudFulfillment']>
|
||||||
|
type RoleInfoEntry = {
|
||||||
|
key: string
|
||||||
|
label: string
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
type ChecklistItem = {
|
||||||
|
key: string
|
||||||
|
label: string
|
||||||
|
status: string
|
||||||
|
detail: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
detail: AdminTaskDetail
|
||||||
|
flow: KuaishouCloudFlow
|
||||||
|
roleInfoEntries: RoleInfoEntry[]
|
||||||
|
checklist: ChecklistItem[]
|
||||||
|
claimUrl: string
|
||||||
|
actionLoading: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
defineProps<Props>()
|
||||||
|
|
||||||
|
const collapsePanels = ['claim', 'ticket', 'cloud']
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
refreshRole: []
|
||||||
|
copyBindUrl: [url: string]
|
||||||
|
openBindUrl: [url: string]
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<section class="info-card flow-card">
|
||||||
|
<div class="flow-card-head">
|
||||||
|
<div>
|
||||||
|
<h3>快手 Cloud 履约面板</h3>
|
||||||
|
<p class="section-copy">
|
||||||
|
这是一套独立的快手 Cloud 任务面板,优先展示角色信息与当前履约推进点,次级明细可按需展开。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="flow-head-actions">
|
||||||
|
<el-button
|
||||||
|
v-if="detail.operations.canRefreshKuaishouCloudRoleInfo"
|
||||||
|
:loading="actionLoading"
|
||||||
|
round
|
||||||
|
@click="emit('refreshRole')"
|
||||||
|
>
|
||||||
|
刷新角色信息
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-if="flow.binding.bindUrl"
|
||||||
|
round
|
||||||
|
@click="emit('copyBindUrl', flow.binding.bindUrl)"
|
||||||
|
>
|
||||||
|
复制绑定链接
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-if="flow.binding.bindUrl"
|
||||||
|
round
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
@click="emit('openBindUrl', flow.binding.bindUrl)"
|
||||||
|
>
|
||||||
|
打开绑定页
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="redeem-summary-grid">
|
||||||
|
<article class="redeem-summary-card">
|
||||||
|
<span>准备状态</span>
|
||||||
|
<div class="auto-delivery-tag-line">
|
||||||
|
<AdminStatusTag :status="flow.binding.prepareStatus" />
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
<article class="redeem-summary-card">
|
||||||
|
<span>发货状态</span>
|
||||||
|
<div class="auto-delivery-tag-line">
|
||||||
|
<AdminStatusTag :status="flow.dispatch.status" />
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
<article class="redeem-summary-card">
|
||||||
|
<span>退号状态</span>
|
||||||
|
<div class="auto-delivery-tag-line">
|
||||||
|
<AdminStatusTag :status="flow.returnNumber.status" />
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
<article class="redeem-summary-card">
|
||||||
|
<span>当前任务状态</span>
|
||||||
|
<div class="auto-delivery-tag-line">
|
||||||
|
<AdminStatusTag :status="detail.task.status" />
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kuaishou-focus-grid">
|
||||||
|
<article class="flow-block flow-block--spotlight">
|
||||||
|
<div class="spotlight-head">
|
||||||
|
<div>
|
||||||
|
<h4>角色信息</h4>
|
||||||
|
<p class="flow-copy">
|
||||||
|
角色信息来自 cloudtentacles 的 `vn/bind_info`,客服可在客户绑定后手动刷新。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="spotlight-actions">
|
||||||
|
<AdminStatusTag :status="flow.role?.status || 'pending'" />
|
||||||
|
<el-button
|
||||||
|
v-if="detail.operations.canRefreshKuaishouCloudRoleInfo"
|
||||||
|
:loading="actionLoading"
|
||||||
|
round
|
||||||
|
size="small"
|
||||||
|
@click="emit('refreshRole')"
|
||||||
|
>
|
||||||
|
刷新
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="role-hero">
|
||||||
|
<div>
|
||||||
|
<span>角色名</span>
|
||||||
|
<strong>{{ flow.role?.name || detail.task.roleName || '等待识别' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>角色 ID</span>
|
||||||
|
<strong>{{ flow.role?.rid || detail.task.roleId || '等待识别' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>最近刷新</span>
|
||||||
|
<strong>{{ formatAdminDateTime(flow.role?.refreshedAt) }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p v-if="flow.role?.errorMessage" class="role-warning">
|
||||||
|
{{ flow.role.errorMessage }}
|
||||||
|
</p>
|
||||||
|
<div v-if="roleInfoEntries.length > 0" class="flow-meta-list flow-meta-list--dense">
|
||||||
|
<div v-for="entry in roleInfoEntries" :key="entry.key">
|
||||||
|
<span>{{ entry.label }}</span>
|
||||||
|
<strong>{{ entry.value }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="flow-block flow-block--checklist">
|
||||||
|
<h4>流程检查</h4>
|
||||||
|
<p class="flow-copy">
|
||||||
|
客服可以先看这里,快速判断卡在哪一步,再决定是刷新角色、准备资源、发货还是退号。
|
||||||
|
</p>
|
||||||
|
<div class="checklist-grid">
|
||||||
|
<div v-for="item in checklist" :key="item.key" class="checklist-item">
|
||||||
|
<div class="checklist-item-head">
|
||||||
|
<span>{{ item.label }}</span>
|
||||||
|
<AdminStatusTag :status="item.status" />
|
||||||
|
</div>
|
||||||
|
<strong>{{ item.detail }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-collapse :model-value="collapsePanels" class="flow-collapse">
|
||||||
|
<el-collapse-item name="claim" title="客户领取与绑定">
|
||||||
|
<div class="flow-meta-list flow-meta-list--two-column">
|
||||||
|
<div>
|
||||||
|
<span>客户链接</span><strong>{{ claimUrl || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>绑定链接</span><strong>{{ flow.binding.bindUrl || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>Token 状态</span><strong>{{ detail.claimToken?.status || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>准备时间</span
|
||||||
|
><strong>{{ formatAdminDateTime(flow.binding.bindPreparedAt) }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>首次提交</span><strong>{{ formatAdminDateTime(flow.ticket.capturedAt) }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>校验时间</span><strong>{{ formatAdminDateTime(flow.ticket.verifiedAt) }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>虚拟号 ID</span><strong>{{ flow.binding.vnId || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>虚拟号码</span><strong>{{ flow.binding.vnPhone || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="manual-hint">
|
||||||
|
客户会先在领取页查看图文指引并提交核销码,只有校验通过后才会自动跳转绑定链接。
|
||||||
|
</p>
|
||||||
|
</el-collapse-item>
|
||||||
|
|
||||||
|
<el-collapse-item name="ticket" title="核销与商品信息">
|
||||||
|
<div class="flow-meta-list flow-meta-list--two-column">
|
||||||
|
<div>
|
||||||
|
<span>核销码</span><strong>{{ flow.ticket.code || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>校验状态</span><strong>{{ flow.ticket.status || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>商品标题</span><strong>{{ flow.ticket.goodsTitle || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>剩余次数</span><strong>{{ flow.ticket.leftCount || 0 }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="manual-hint">
|
||||||
|
"确认绑定完成并发货"已经合并为一个按钮,只有核销码通过校验后才能继续。
|
||||||
|
</p>
|
||||||
|
</el-collapse-item>
|
||||||
|
|
||||||
|
<el-collapse-item name="cloud" title="Cloud 资源与发货">
|
||||||
|
<div class="flow-meta-list flow-meta-list--two-column">
|
||||||
|
<div>
|
||||||
|
<span>cloudSourceKey</span><strong>{{ flow.binding.cloudSourceKey || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>cloud SKU</span>
|
||||||
|
<strong>{{
|
||||||
|
flow.binding.skuId ? `${flow.binding.skuId} / ${flow.binding.skuName || '-'}` : '-'
|
||||||
|
}}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>VN Key</span><strong>{{ flow.binding.vnKey || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>自动购买</span
|
||||||
|
><strong>{{ flow.purchase.autoBuyEnabled ? '开启' : '关闭' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>背包命中</span><strong>{{ flow.purchase.usedKnapsack ? '是' : '否' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>触发购买</span
|
||||||
|
><strong>{{ flow.purchase.purchaseTriggered ? '是' : '否' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>购买时间</span
|
||||||
|
><strong>{{ formatAdminDateTime(flow.purchase.purchaseAt) }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>发货时间</span
|
||||||
|
><strong>{{ formatAdminDateTime(flow.dispatch.dispatchAt) }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>发送类型</span><strong>{{ flow.dispatch.sendType || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>结果说明</span
|
||||||
|
><strong>{{ flow.dispatch.note || detail.task.resultMessage || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-collapse-item>
|
||||||
|
|
||||||
|
<el-collapse-item name="closure" title="流程收口">
|
||||||
|
<div class="flow-meta-list flow-meta-list--two-column">
|
||||||
|
<div>
|
||||||
|
<span>退号时间</span
|
||||||
|
><strong>{{ formatAdminDateTime(flow.returnNumber.returnedAt) }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>自动退号</span
|
||||||
|
><strong>{{ flow.returnNumber.autoReturnEnabled ? '开启' : '关闭' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>自动核销</span
|
||||||
|
><strong>{{ flow.consume.autoConsumeEnabled ? '开启' : '关闭' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>核销店铺</span><strong>{{ flow.consume.shopId || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>核销店铺名</span><strong>{{ flow.consume.shopName || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>核销时间</span><strong>{{ formatAdminDateTime(flow.consume.consumedAt) }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>核销异常</span><strong>{{ flow.consume.errorMessage || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>备注</span><strong>{{ flow.notes || '-' }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-collapse-item>
|
||||||
|
|
||||||
|
<el-collapse-item v-if="roleInfoEntries.length > 0" name="raw" title="角色原始字段">
|
||||||
|
<div class="flow-meta-list flow-meta-list--two-column">
|
||||||
|
<div v-for="entry in roleInfoEntries" :key="`raw-${entry.key}`">
|
||||||
|
<span>{{ entry.label }}</span>
|
||||||
|
<strong>{{ entry.value }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-collapse-item>
|
||||||
|
</el-collapse>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped src="../AdminTaskDetail.css"></style>
|
||||||
Reference in New Issue
Block a user