56 lines
3.3 KiB
Vue
56 lines
3.3 KiB
Vue
<script setup lang="ts">
|
|
import { ref, watch, onBeforeUnmount } from 'vue'
|
|
import DataTable, { type DataTableColumn } from '@/shared/components/DataTable.vue'
|
|
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
|
|
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
|
|
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
|
|
import { listOverseasFeeRetries, type OverseasFeeRetryRecord } from '../api/overseasFees'
|
|
import { feeTime, retryResultLabels } from '../overseasFeePresentation'
|
|
import { retryFailureReason } from '../overseasFeeRetryPresentation'
|
|
|
|
const props = defineProps<{ feeId: string; refreshKey?: string }>()
|
|
const rows = ref<OverseasFeeRetryRecord[]>([]), loading = ref(false), error = ref<ApiErrorDetails | null>(null)
|
|
const columns: DataTableColumn[] = [
|
|
{ prop: 'requestedAt', label: '重试时间', width: 160, formatter: (row: OverseasFeeRetryRecord) => feeTime(row.requestedAt) },
|
|
{ prop: 'operatorName', label: '操作人', width: 170 },
|
|
{ prop: 'action', label: '重试操作', width: 100 },
|
|
{ prop: 'result', label: '操作结果', width: 110, formatter: (row: OverseasFeeRetryRecord) => retryResultLabels[row.result] || '—' },
|
|
{ key: 'failureReason', label: '失败原因', minWidth: 230, slotName: 'failureReason', singleLine: false, showOverflowTooltip: false },
|
|
]
|
|
let sequence = 0
|
|
async function load(background = false) {
|
|
const current = ++sequence; error.value = null
|
|
if (!background) { rows.value = []; loading.value = true }
|
|
try { const result = await listOverseasFeeRetries(props.feeId); if (current === sequence) rows.value = result }
|
|
catch (failure) { if (current === sequence) error.value = getApiErrorDetails(failure, '重试记录加载失败') }
|
|
finally { if (current === sequence) loading.value = false }
|
|
}
|
|
watch(() => props.feeId, () => load(), { immediate: true })
|
|
// 列表取得新的投递结果时同步刷新记录,不要求关闭再打开详情。
|
|
watch(() => props.refreshKey, () => load(true))
|
|
onBeforeUnmount(() => { sequence++ })
|
|
</script>
|
|
|
|
<template>
|
|
<section class="density-dialog-section" aria-label="重试记录">
|
|
<h3 class="density-dialog-section__title">重试记录</h3>
|
|
<LoadErrorState v-if="error" title="重试记录加载失败" :message="error.message" :loading="loading" @retry="load()"><template #details><ApiErrorMeta :details="error" /></template></LoadErrorState>
|
|
<DataTable v-else :data="rows" :columns="columns" :loading="loading" row-key="requestId" column-settings-mode="hide" empty-text="暂无重试记录">
|
|
<template #failureReason="{ row }">
|
|
<div class="retry-failure-reason">{{ retryFailureReason(row as OverseasFeeRetryRecord) }}</div>
|
|
<details v-if="row.result === 'FAILED' && row.errorMessage" class="retry-failure-details">
|
|
<summary>查看技术详情</summary>
|
|
<pre>{{ row.errorMessage }}</pre>
|
|
</details>
|
|
</template>
|
|
</DataTable>
|
|
</section>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.retry-failure-reason { white-space: normal; overflow-wrap: anywhere; }
|
|
.retry-failure-details { margin-top: 4px; }
|
|
.retry-failure-details summary { color: var(--el-color-primary); cursor: pointer; width: fit-content; }
|
|
.retry-failure-details pre { margin: 6px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; font: inherit; color: var(--el-text-color-secondary); }
|
|
</style>
|