PayrollManagementSystem/frontend/src/views/system/tplus/BatchDetailDialog.vue
liuwenxin 0ca1734523 refactor(前端): 清理 T+ 页面展示细节
详情对话框:异常明细补充后端已支持的范围筛选,执行时间行
在批次未开始时隐藏(原先显示「— → —」);核验结果提示与
页首警告统一 show-icon;删除已声明未消费的 receipt_line_kinds
类型字段(方向信息已在 receipt_kinds 名称内)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-30 09:58:08 +08:00

87 lines
4.7 KiB
Vue

<script setup lang="ts">
import { ref, watch } from 'vue'
import * as api from '@/api/tplus'
import AppPagination from '@/components/table/AppPagination.vue'
import { usePagedList } from '@/composables/usePagedList'
import { handledError } from '@/utils/error'
import { formatDateTime } from '@/utils/format'
import AuditResult from './AuditResult.vue'
import { entities, scopeLabel, statuses } from './labels'
const number = defineModel<string | null>({ required: true })
const detail = ref<api.TPlusDetail | null>(null)
const loading = ref(false)
const failed = ref(false)
const errorEntityType = ref<api.EntityType>()
let sequence = 0
const { records, total, pageNum, pageSize, loading: errorsLoading, search, onPageChange, onSizeChange } =
usePagedList<api.TPlusError, api.ErrorQuery>(
(query) => api.listErrors(number.value!, query),
() => ({ entity_type: errorEntityType.value }),
)
async function load(): Promise<void> {
const current = ++sequence
const key = number.value
if (!key) return
detail.value = null
loading.value = true
failed.value = false
try {
const result = await api.getBatch(key)
if (current !== sequence) return
detail.value = result
if (result.failed_record_count) await search()
} catch (error) {
handledError(error)
if (current === sequence) failed.value = true
} finally { if (current === sequence) loading.value = false }
}
watch(number, (value) => { if (value) void load(); else sequence++ })
</script>
<template>
<el-dialog :model-value="!!number" title="T+ 任务详情" width="min(880px, 96vw)" @update:model-value="number = null">
<div v-loading="loading" class="detail-body">
<el-alert v-if="failed" type="error" title="详情加载失败,请重试" :closable="false"><el-button link @click="load">重新加载</el-button></el-alert>
<template v-if="detail">
<p class="cell-code batch-number">{{ detail.batch_no }}</p>
<el-descriptions :column="1" border>
<el-descriptions-item label="状态">{{ statuses[detail.status] }}</el-descriptions-item>
<el-descriptions-item label="范围">{{ scopeLabel(detail) }}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ formatDateTime(detail.create_time) }}</el-descriptions-item>
<el-descriptions-item v-if="detail.started_at" label="执行时间">{{ formatDateTime(detail.started_at) }} → {{ formatDateTime(detail.finished_at) }}</el-descriptions-item>
<el-descriptions-item v-if="detail.parent_batch_no" label="原批次">{{ detail.parent_batch_no }}</el-descriptions-item>
<el-descriptions-item label="数量">源记录 {{ detail.source_record_count.toLocaleString() }},新增 {{ detail.staged_record_count.toLocaleString() }},重复跳过 {{ detail.skipped_record_count.toLocaleString() }},异常 {{ detail.failed_record_count.toLocaleString() }}</el-descriptions-item>
</el-descriptions>
<p v-if="detail.status === 'QUEUED'" role="status">任务等待读取服务处理,可稍后刷新查看。</p>
<p v-if="detail.error_summary" role="alert">{{ detail.error_summary }}</p>
<AuditResult v-if="detail.audit_result" :report="detail.audit_result" />
<section v-if="detail.failed_record_count" class="errors-section" aria-label="异常明细">
<h3>异常明细</h3>
<el-select v-model="errorEntityType" clearable placeholder="全部范围" aria-label="异常范围" @change="search">
<el-option v-for="item in entities" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-table v-loading="errorsLoading" :data="records" empty-text="暂无异常记录">
<el-table-column label="范围" width="100"><template #default="{ row }">{{ entities.find((item) => item.value === row.entity_type)?.label ?? '任务' }}</template></el-table-column>
<el-table-column prop="source_id" label="源 ID" width="90" />
<el-table-column prop="error_message" label="异常说明" min-width="240" />
<el-table-column prop="retry_count" label="已重试" width="80" />
</el-table>
<div class="pager-scroll"><AppPagination :total="total" :page-num="pageNum" :page-size="pageSize" @page-change="onPageChange" @size-change="onSizeChange" /></div>
</section>
</template>
</div>
<template #footer><el-button @click="number = null">关闭</el-button><el-button :loading="loading" @click="load">刷新详情</el-button></template>
</el-dialog>
</template>
<style scoped>
.detail-body { min-height: 120px; }
.batch-number { overflow-wrap: anywhere; }
.errors-section { margin-top: 24px; }
.errors-section .el-select { width: 160px; margin-bottom: 12px; }
h3 { font-size: 14px; }
.pager-scroll { overflow-x: auto; }
</style>