194 lines
5.4 KiB
Vue
194 lines
5.4 KiB
Vue
|
|
<template>
|
|||
|
|
<section class="card add-data-card">
|
|||
|
|
<div class="card-header">
|
|||
|
|
<div>
|
|||
|
|
<div class="section-title">任务状态</div>
|
|||
|
|
<div class="section-description">创建任务后自动轮询状态,直到任务成功或失败。</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<el-tag v-if="status" :type="statusMeta.type" effect="light">{{ statusMeta.label }}</el-tag>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div v-loading="loading" class="card-body">
|
|||
|
|
<div v-if="status" class="status-content">
|
|||
|
|
<el-descriptions :column="2" border size="small">
|
|||
|
|
<el-descriptions-item label="任务 ID">{{ taskId || status.taskId || '--' }}</el-descriptions-item>
|
|||
|
|
<el-descriptions-item label="当前状态">{{ statusMeta.label }}</el-descriptions-item>
|
|||
|
|
<el-descriptions-item label="当前表名">{{ status.currentTableName || '--' }}</el-descriptions-item>
|
|||
|
|
<el-descriptions-item label="当前批次">{{ status.currentBatchInfo || '--' }}</el-descriptions-item>
|
|||
|
|
<el-descriptions-item label="已写入数量">{{ status.insertedCount }}</el-descriptions-item>
|
|||
|
|
<el-descriptions-item label="已跳过数量">{{ status.skippedCount }}</el-descriptions-item>
|
|||
|
|
<el-descriptions-item label="失败数量">{{ status.failedCount }}</el-descriptions-item>
|
|||
|
|
<el-descriptions-item label="失败原因">
|
|||
|
|
<span class="failure-text">{{ status.failureReason || '--' }}</span>
|
|||
|
|
</el-descriptions-item>
|
|||
|
|
<el-descriptions-item label="开始时间">{{ status.startTime || '--' }}</el-descriptions-item>
|
|||
|
|
<el-descriptions-item label="结束时间">{{ status.endTime || '--' }}</el-descriptions-item>
|
|||
|
|
</el-descriptions>
|
|||
|
|
|
|||
|
|
<div class="hourly-block">
|
|||
|
|
<div class="hourly-title">业务时刻</div>
|
|||
|
|
<div v-if="status.hourlyTimeResults.length" class="hourly-scroll">
|
|||
|
|
<div class="hourly-list">
|
|||
|
|
<el-tag v-for="item in status.hourlyTimeResults" :key="item" effect="plain" type="info">
|
|||
|
|
{{ item }}
|
|||
|
|
</el-tag>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div v-else class="hourly-empty">当前接口未返回业务时刻。</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div v-else class="empty-block">暂无补数任务,创建任务后会在这里持续展示执行进度。</div>
|
|||
|
|
</div>
|
|||
|
|
</section>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup lang="ts">
|
|||
|
|
import { computed } from 'vue'
|
|||
|
|
import type { AddData } from '@/api/tools/addData/interface'
|
|||
|
|
|
|||
|
|
defineOptions({
|
|||
|
|
name: 'AddDataTaskStatusCard'
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
const props = defineProps<{
|
|||
|
|
status: AddData.NormalizedTaskStatus | null
|
|||
|
|
taskId: string
|
|||
|
|
loading: boolean
|
|||
|
|
}>()
|
|||
|
|
|
|||
|
|
const statusMeta = computed(() => {
|
|||
|
|
const status = props.status?.status
|
|||
|
|
|
|||
|
|
if (status === 'SUCCESS') {
|
|||
|
|
return { label: '成功', type: 'success' as const }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (status === 'FAILED') {
|
|||
|
|
return { label: '失败', type: 'danger' as const }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (status === 'RUNNING') {
|
|||
|
|
return { label: '执行中', type: 'warning' as const }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (status === 'WAITING') {
|
|||
|
|
return { label: '等待中', type: 'info' as const }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
label: status || '未知状态',
|
|||
|
|
type: 'info' as const
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped lang="scss">
|
|||
|
|
.add-data-card {
|
|||
|
|
display: flex;
|
|||
|
|
flex: 1;
|
|||
|
|
flex-direction: column;
|
|||
|
|
min-height: 0;
|
|||
|
|
background: var(--el-bg-color);
|
|||
|
|
border: 1px solid var(--el-border-color-light);
|
|||
|
|
border-radius: 4px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-header {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
gap: 16px;
|
|||
|
|
padding: 16px 16px 12px;
|
|||
|
|
border-bottom: 1px solid var(--el-border-color-lighter);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.section-title {
|
|||
|
|
font-size: 15px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: var(--el-text-color-primary);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.section-description {
|
|||
|
|
margin-top: 6px;
|
|||
|
|
font-size: 13px;
|
|||
|
|
line-height: 1.7;
|
|||
|
|
color: var(--el-text-color-regular);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-body {
|
|||
|
|
display: flex;
|
|||
|
|
flex: 1;
|
|||
|
|
min-height: 0;
|
|||
|
|
padding: 16px;
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.status-content {
|
|||
|
|
display: flex;
|
|||
|
|
flex: 1;
|
|||
|
|
flex-direction: column;
|
|||
|
|
gap: 12px;
|
|||
|
|
min-height: 0;
|
|||
|
|
width: 100%;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.failure-text {
|
|||
|
|
word-break: break-all;
|
|||
|
|
color: var(--el-color-danger);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.hourly-block {
|
|||
|
|
display: flex;
|
|||
|
|
flex: 1;
|
|||
|
|
flex-direction: column;
|
|||
|
|
min-height: 0;
|
|||
|
|
padding: 12px;
|
|||
|
|
background: var(--cn-color-canvas-bg);
|
|||
|
|
border: 1px dashed var(--el-border-color);
|
|||
|
|
border-radius: 4px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.hourly-title {
|
|||
|
|
margin-bottom: 10px;
|
|||
|
|
font-size: 13px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: var(--el-text-color-primary);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.hourly-scroll {
|
|||
|
|
flex: 1;
|
|||
|
|
min-height: 0;
|
|||
|
|
overflow-y: auto;
|
|||
|
|
padding-right: 4px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.hourly-list {
|
|||
|
|
display: flex;
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
align-content: flex-start;
|
|||
|
|
gap: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.hourly-empty {
|
|||
|
|
font-size: 12px;
|
|||
|
|
color: var(--el-text-color-secondary);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.empty-block {
|
|||
|
|
display: flex;
|
|||
|
|
flex: 1;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
width: 100%;
|
|||
|
|
min-height: 0;
|
|||
|
|
padding: 16px;
|
|||
|
|
color: var(--el-text-color-secondary);
|
|||
|
|
background: var(--cn-color-canvas-bg);
|
|||
|
|
border: 1px dashed var(--el-border-color);
|
|||
|
|
border-radius: 4px;
|
|||
|
|
text-align: center;
|
|||
|
|
}
|
|||
|
|
</style>
|