fetch(add): 分配记录,批量分配/回收, 单卡列表, 任务列表, 导入ICCID
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 2m21s

This commit is contained in:
sexygoat
2026-01-24 16:18:30 +08:00
parent c69124a819
commit 0eed8244e5
13 changed files with 2375 additions and 334 deletions

View File

@@ -0,0 +1,178 @@
<template>
<ArtTableFullScreen>
<div class="task-detail-page" id="table-full-screen">
<ElCard shadow="never" class="art-table-card">
<!-- 返回按钮 -->
<div class="back-button-wrapper">
<ElButton @click="goBack" icon="ArrowLeft">返回</ElButton>
</div>
<!-- 任务基本信息 -->
<ElDescriptions title="任务基本信息" :column="3" border class="task-info">
<ElDescriptionsItem label="任务编号">{{ taskDetail?.task_no || '-' }}</ElDescriptionsItem>
<ElDescriptionsItem label="批次号">{{ taskDetail?.batch_no || '-' }}</ElDescriptionsItem>
<ElDescriptionsItem label="运营商">{{ taskDetail?.carrier_name || '-' }}</ElDescriptionsItem>
<ElDescriptionsItem label="文件名">{{ taskDetail?.file_name || '-' }}</ElDescriptionsItem>
<ElDescriptionsItem label="任务状态">
<ElTag :type="getStatusType(taskDetail?.status)" v-if="taskDetail">
{{ taskDetail.status_text }}
</ElTag>
</ElDescriptionsItem>
<ElDescriptionsItem label="创建时间">
{{ taskDetail?.created_at ? formatDateTime(taskDetail.created_at) : '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="开始处理时间">
{{ taskDetail?.started_at ? formatDateTime(taskDetail.started_at) : '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="完成时间">
{{ taskDetail?.completed_at ? formatDateTime(taskDetail.completed_at) : '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="错误信息" v-if="taskDetail?.error_message">
<span class="error-message">{{ taskDetail.error_message }}</span>
</ElDescriptionsItem>
</ElDescriptions>
<!-- 统计信息 -->
<ElDescriptions title="统计信息" :column="4" border class="statistics-info">
<ElDescriptionsItem label="总数">
<span class="count-text">{{ taskDetail?.total_count || 0 }}</span>
</ElDescriptionsItem>
<ElDescriptionsItem label="成功数">
<ElTag type="success">{{ taskDetail?.success_count || 0 }}</ElTag>
</ElDescriptionsItem>
<ElDescriptionsItem label="失败数">
<ElTag type="danger">{{ taskDetail?.fail_count || 0 }}</ElTag>
</ElDescriptionsItem>
<ElDescriptionsItem label="跳过数">
<ElTag type="warning">{{ taskDetail?.skip_count || 0 }}</ElTag>
</ElDescriptionsItem>
</ElDescriptions>
<!-- 失败记录 -->
<div class="failure-section" v-if="taskDetail?.fail_count && taskDetail.fail_count > 0">
<ElDivider content-position="left">
<span class="section-title">失败记录 ({{ taskDetail.fail_count }})</span>
</ElDivider>
<ElTable :data="taskDetail.failed_items" border style="width: 100%">
<ElTableColumn prop="line" label="行号" width="100" />
<ElTableColumn prop="iccid" label="ICCID" min-width="180" />
<ElTableColumn prop="reason" label="失败原因" min-width="300" />
</ElTable>
</div>
<!-- 跳过记录 -->
<div class="skipped-section" v-if="taskDetail?.skip_count && taskDetail.skip_count > 0">
<ElDivider content-position="left">
<span class="section-title">跳过记录 ({{ taskDetail.skip_count }})</span>
</ElDivider>
<ElTable :data="taskDetail.skipped_items" border style="width: 100%">
<ElTableColumn prop="line" label="行号" width="100" />
<ElTableColumn prop="iccid" label="ICCID" min-width="180" />
<ElTableColumn prop="reason" label="跳过原因" min-width="300" />
</ElTable>
</div>
</ElCard>
</div>
</ArtTableFullScreen>
</template>
<script setup lang="ts">
import { useRouter, useRoute } from 'vue-router'
import { CardService } from '@/api/modules'
import { ElMessage, ElTag, ElDescriptions, ElDescriptionsItem, ElDivider, ElTable, ElTableColumn } from 'element-plus'
import { formatDateTime } from '@/utils/business/format'
import type { IotCardImportTaskDetail, IotCardImportTaskStatus } from '@/types/api/card'
defineOptions({ name: 'TaskDetail' })
const router = useRouter()
const route = useRoute()
const taskDetail = ref<IotCardImportTaskDetail | null>(null)
const loading = ref(false)
// 获取状态标签类型
const getStatusType = (status?: IotCardImportTaskStatus) => {
if (!status) return 'info'
switch (status) {
case 1:
return 'info'
case 2:
return 'warning'
case 3:
return 'success'
case 4:
return 'danger'
default:
return 'info'
}
}
// 返回列表
const goBack = () => {
router.back()
}
// 获取任务详情
const getTaskDetail = async () => {
const taskId = route.query.id
if (!taskId) {
ElMessage.error('缺少任务ID参数')
goBack()
return
}
loading.value = true
try {
const res = await CardService.getIotCardImportTaskDetail(Number(taskId))
if (res.code === 0) {
taskDetail.value = res.data
}
} catch (error) {
console.error(error)
ElMessage.error('获取任务详情失败')
} finally {
loading.value = false
}
}
onMounted(() => {
getTaskDetail()
})
</script>
<style lang="scss" scoped>
.task-detail-page {
.back-button-wrapper {
margin-bottom: 20px;
}
.task-info {
margin-bottom: 20px;
}
.statistics-info {
margin-bottom: 20px;
}
.count-text {
font-size: 16px;
font-weight: bold;
color: var(--el-color-primary);
}
.error-message {
color: var(--el-color-danger);
}
.failure-section,
.skipped-section {
margin-top: 20px;
.section-title {
font-size: 16px;
font-weight: bold;
}
}
}
</style>