Files
BMS/bms-front/src/views/monitor/orderSource/components/OrderSourceSyncLogDrawer.vue
T
2026-10-20 13:55:55 +08:00

203 lines
6.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<el-drawer v-model="visible" size="860px" :title="'操作记录'" append-to-body destroy-on-close>
<basic-table
v-if="visible"
:columns="columns"
:search-columns="searchColumns"
:query="queryList"
row-key="docId"
:page-size="10"
:selection="false"
:show-add="false"
>
<template #col-actionName="{ row }">
{{ actionLabel(row) }}
</template>
<template #col-status="{ row }">
<el-tag size="small" :type="row.status === 'FAIL' ? 'danger' : 'success'">{{ row.status === 'FAIL' ? '失败' : '成功' }}</el-tag>
</template>
<template #col-action="{ row }">
<el-button link type="primary" icon="View" @click="handleView(row)">查看</el-button>
</template>
</basic-table>
<el-drawer v-model="detailOpen" size="640px" :title="'操作详情'" append-to-body destroy-on-close>
<div v-loading="detailLoading">
<el-empty v-if="!detail" description="暂无详情" />
<div v-else>
<el-descriptions :column="2" border size="small" class="mb12">
<el-descriptions-item label="业务ID">{{ detail.bizId || '-' }}</el-descriptions-item>
<el-descriptions-item label="状态">
<el-tag size="small" :type="detail.status === 'FAIL' ? 'danger' : 'success'">{{ detail.status === 'FAIL' ? '失败' : '成功' }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="写入时间" :span="2">{{ detail.updateTime || '-' }}</el-descriptions-item>
<el-descriptions-item v-if="detail.errorMessage" label="错误信息" :span="2">
<span class="err-text">{{ detail.errorMessage }}</span>
</el-descriptions-item>
</el-descriptions>
<div v-if="failRows.length" class="json-panel">
<div class="json-panel__head"><span>失败明细(共 {{ failRows.length }} 单)</span></div>
<el-table :data="failRows" border size="small" max-height="280" class="fail-table">
<el-table-column label="订单号" prop="orderId" min-width="160" show-overflow-tooltip />
<el-table-column label="转单号" prop="transferOrderId" min-width="140" show-overflow-tooltip />
<el-table-column label="错误信息" prop="errorMessage" min-width="220" show-overflow-tooltip />
</el-table>
</div>
<div class="json-panel">
<div class="json-panel__head"><span>请求报文</span></div>
<pre class="code-pre">{{ formatJson(detail.requestJson) }}</pre>
</div>
<div class="json-panel">
<div class="json-panel__head"><span>返回报文</span></div>
<pre class="code-pre">{{ formatJson(detail.responseJson) }}</pre>
</div>
</div>
</div>
</el-drawer>
</el-drawer>
</template>
<script setup>
import { listOrderSourceSyncLog, getOrderSourceSyncLog } from '@/api/monitor/orderSource'
const visible = ref(false)
const detailOpen = ref(false)
const detailLoading = ref(false)
const detail = ref(null)
const searchColumns = [
{ label: '业务ID', prop: 'bizId', component: 'input', placeholder: '业务ID', width: '220px' },
{
label: '状态',
prop: 'status',
component: 'select',
options: [
{ label: '成功', value: 'SUCCESS' },
{ label: '失败', value: 'FAIL' }
],
placeholder: '请选择',
width: '140px',
props: { clearable: true }
}
]
const columns = [
{ label: '操作', prop: 'actionName', width: 150, slot: 'actionName' },
{ label: '业务ID', prop: 'bizId', minWidth: 180, showOverflowTooltip: true },
{ label: '状态', prop: 'status', align: 'center', width: 90, slot: 'status' },
{ label: '写入时间', prop: 'updateTime', align: 'center', width: 170 },
{ label: '操作', prop: 'action', align: 'center', width: 80, fixed: 'right', slot: 'action', showInToolbar: false }
]
function parseReq(row) {
if (!row || !row.requestJson) return {}
try {
return typeof row.requestJson === 'object' ? row.requestJson : JSON.parse(row.requestJson)
} catch (e) {
return {}
}
}
function actionLabel(row) {
const action = parseReq(row).action
if (action === 'FILTER') return '筛选同步'
if (action === 'FILTER_DONE') {
return row.status === 'FAIL' ? '筛选完成(有失败)' : '筛选完成'
}
if (action === 'SELECTED') {
return row.status === 'FAIL' ? '同步选中(有失败)' : '同步选中'
}
if (action === 'ONE') return '单条同步'
if (action === 'ONE_FAIL') return '同步失败'
if (action === 'COMPARE') return '订单比对'
if (action === 'COMPARE_DONE') {
return row.status === 'FAIL' ? '比对完成(失败)' : '比对完成'
}
return action || '-'
}
const failRows = computed(() => {
if (!detail.value) return []
const resp = parseResp(detail.value)
if (Array.isArray(resp.failDetails) && resp.failDetails.length) {
return resp.failDetails
}
if (Array.isArray(resp.details) && resp.details.length) {
return resp.details.filter(d => {
const st = d && d.successStatus
return st && String(st).toUpperCase() !== 'SUCCESS'
})
}
return []
})
function parseResp(row) {
if (!row || !row.responseJson) return {}
try {
return typeof row.responseJson === 'object' ? row.responseJson : JSON.parse(row.responseJson)
} catch (e) {
return {}
}
}
function queryList(params) {
return listOrderSourceSyncLog(params)
}
function formatJson(raw) {
if (raw == null || raw === '') return '-'
try {
const obj = typeof raw === 'string' ? JSON.parse(raw) : raw
return JSON.stringify(obj, null, 2)
} catch (e) {
return String(raw)
}
}
function handleView(row) {
detailOpen.value = true
detail.value = null
detailLoading.value = true
getOrderSourceSyncLog(row.docId).then(res => {
detail.value = res.data || row
}).finally(() => {
detailLoading.value = false
})
}
function open() {
visible.value = true
}
defineExpose({ open })
</script>
<style scoped>
.err-text {
color: #f56c6c;
word-break: break-all;
}
.json-panel {
margin-top: 12px;
}
.json-panel__head {
margin-bottom: 6px;
font-weight: 600;
}
.fail-table {
margin-top: 6px;
}
.code-pre {
margin: 0;
padding: 10px 12px;
max-height: 240px;
overflow: auto;
background: #f5f7fa;
border-radius: 4px;
font-size: 12px;
line-height: 1.5;
white-space: pre-wrap;
word-break: break-all;
}
</style>