回滚代码
This commit is contained in:
@@ -1,31 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function listPrcOrder(query) {
|
||||
return request({
|
||||
url: '/monitor/prcOrder/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
export function getPrcOrder(orderId) {
|
||||
return request({
|
||||
url: '/monitor/prcOrder/' + orderId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function retryPrcOrder(orderId) {
|
||||
return request({
|
||||
url: '/monitor/prcOrder/retry/' + orderId,
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function retryPrcOrderBatch(orderIds) {
|
||||
return request({
|
||||
url: '/monitor/prcOrder/retry',
|
||||
method: 'post',
|
||||
data: orderIds
|
||||
})
|
||||
}
|
||||
@@ -5,47 +5,65 @@
|
||||
<template v-else>
|
||||
<div class="detail-header">
|
||||
<el-tag :type="statusTag(detail.successStatus)" effect="light">{{ statusLabel(detail.successStatus) }}</el-tag>
|
||||
<span class="detail-header-time">计费时间:{{ detail.bizDate || '-' }}</span>
|
||||
<span class="detail-header-type">{{ billTypeLabel(detail.billType) }}</span>
|
||||
<span class="detail-header-time">计费时间:{{ detail.billTime || '-' }}</span>
|
||||
</div>
|
||||
<el-descriptions :column="1" border size="small" class="detail-desc">
|
||||
<el-descriptions-item label="订单ID">{{ detail.orderId }}</el-descriptions-item>
|
||||
<el-descriptions-item label="任务ID">{{ detail.taskId }}</el-descriptions-item>
|
||||
<el-descriptions-item label="客户代码">{{ detail.customerCode || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="订单号">{{ detail.orderNo || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="运单号">{{ detail.trackingNo || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="转单号">{{ detail.transferNo || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="产品代码">{{ detail.productCode || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="计费订单ID">{{ detail.billId || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="失败码">{{ detail.failCode || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ detail.createTime || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="更新时间">{{ detail.updateTime || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div v-if="detail.errorMessage" class="err-block">
|
||||
<div class="err-block-head">
|
||||
<span class="err-block-title">失败原因</span>
|
||||
<el-button link type="primary" size="small" icon="CopyDocument" @click="copyError">复制</el-button>
|
||||
</div>
|
||||
<div class="err-block-body">{{ detail.errorMessage }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { getPrcOrder } from '@/api/monitor/prcOrder'
|
||||
import { statusLabel, statusTag } from './billingTaskOptions'
|
||||
import { getBillingTask } from '@/api/monitor/billingTask'
|
||||
import { billTypeLabel, statusLabel, statusTag } from './billingTaskOptions'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const open = ref(false)
|
||||
const loading = ref(false)
|
||||
const detail = ref(null)
|
||||
const drawerTitle = ref('订单计费详情')
|
||||
const drawerTitle = ref('计费任务详情')
|
||||
|
||||
function openDrawer(row) {
|
||||
if (!row || !row.orderId) return
|
||||
drawerTitle.value = '订单 ' + (row.transferNo || row.orderId)
|
||||
if (!row || !row.taskId) return
|
||||
drawerTitle.value = '计费任务 #' + row.taskId
|
||||
open.value = true
|
||||
loading.value = true
|
||||
detail.value = null
|
||||
getPrcOrder(row.orderId).then(res => {
|
||||
getBillingTask(row.taskId).then(res => {
|
||||
detail.value = res.data || row
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function copyError() {
|
||||
const text = detail.value?.errorMessage || ''
|
||||
if (!text) return
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
proxy.$modal.msgSuccess('已复制')
|
||||
}).catch(() => {
|
||||
proxy.$modal.msgError('复制失败')
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({ open: openDrawer })
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,15 +1,38 @@
|
||||
<template>
|
||||
<div class="app-container billing-task-page">
|
||||
<div v-if="retryFloatVisible" class="retry-status-float">
|
||||
<el-tooltip :content="retryFloatTooltip" placement="bottom">
|
||||
<el-button class="retry-status-button" type="primary" plain size="small" @click="filterRetryRef.open()">
|
||||
<span class="retry-progress-ring" :style="{ '--retry-progress': retryProgressDegree + 'deg' }" aria-hidden="true">
|
||||
<span class="retry-progress-value">{{ retryProgressText }}</span>
|
||||
</span>
|
||||
<span class="retry-status-text">
|
||||
<strong>{{ retryFloatTitle }}</strong>
|
||||
<small>{{ retryFloatSummary }}</small>
|
||||
</span>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
<basic-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:search-columns="searchColumns"
|
||||
:query="queryList"
|
||||
:default-params="defaultParams"
|
||||
row-key="orderId"
|
||||
row-key="taskId"
|
||||
selection
|
||||
>
|
||||
<template #toolbar="{ ids }">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="Refresh"
|
||||
v-hasPermi="['monitor:billingTask:retry']"
|
||||
@click="filterRetryRef.open()"
|
||||
>批量重新同步</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
@@ -22,16 +45,22 @@
|
||||
>同步选中</el-button>
|
||||
</el-col>
|
||||
</template>
|
||||
<template #col-billType="{ row }">
|
||||
<el-tag size="small">{{ billTypeLabel(row.billType) }}</el-tag>
|
||||
</template>
|
||||
<template #col-successStatus="{ row }">
|
||||
<el-tag size="small" :type="statusTag(row.successStatus)">{{ statusLabel(row.successStatus) }}</el-tag>
|
||||
</template>
|
||||
<template #col-errorMessage="{ row }">
|
||||
<span class="err-text" :title="row.errorMessage || ''">{{ row.errorMessage || '-' }}</span>
|
||||
</template>
|
||||
<template #col-action="{ row }">
|
||||
<el-button link type="primary" icon="View" @click="detailRef.open(row)" v-hasPermi="['monitor:billingTask:list']">查看</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="warning"
|
||||
icon="Refresh"
|
||||
:loading="retryingId === row.orderId"
|
||||
:loading="retryingId === row.taskId"
|
||||
v-hasPermi="['monitor:billingTask:retry']"
|
||||
@click="handleRetry(row)"
|
||||
>重新同步</el-button>
|
||||
@@ -39,15 +68,23 @@
|
||||
</basic-table>
|
||||
|
||||
<billing-task-detail-drawer ref="detailRef" />
|
||||
<billing-task-filter-retry-dialog
|
||||
ref="filterRetryRef"
|
||||
@progress="onFilterRetryProgress"
|
||||
@success="onFilterRetrySuccess"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="BillingTaskMonitor">
|
||||
import { listPrcOrder, retryPrcOrder, retryPrcOrderBatch } from '@/api/monitor/prcOrder'
|
||||
import { listBillingTask, retryBillingTask, retryBillingTaskBatch } from '@/api/monitor/billingTask'
|
||||
import BillingTaskDetailDrawer from './components/BillingTaskDetailDrawer.vue'
|
||||
import BillingTaskFilterRetryDialog from './components/BillingTaskFilterRetryDialog.vue'
|
||||
import {
|
||||
statusOptions,
|
||||
billTypeOptions,
|
||||
failCodeOptions,
|
||||
billTypeLabel,
|
||||
statusLabel,
|
||||
statusTag
|
||||
} from './components/billingTaskOptions'
|
||||
@@ -55,13 +92,16 @@ import {
|
||||
const { proxy } = getCurrentInstance()
|
||||
const tableRef = ref()
|
||||
const detailRef = ref()
|
||||
const filterRetryRef = ref()
|
||||
const retryingId = ref(null)
|
||||
const batchLoading = ref(false)
|
||||
const retryFloat = ref(null)
|
||||
|
||||
const defaultParams = { successStatus: 'FAILED' }
|
||||
|
||||
const searchColumns = [
|
||||
{ label: '状态', prop: 'successStatus', component: 'select', options: statusOptions, placeholder: '请选择状态', width: '140px', props: { clearable: true } },
|
||||
{ label: '计费类型', prop: 'billType', component: 'select', options: billTypeOptions, placeholder: '请选择类型', width: '140px', props: { clearable: true } },
|
||||
{ label: '失败码', prop: 'failCode', component: 'select', options: failCodeOptions, placeholder: '请选择失败码', width: '220px', props: { clearable: true, filterable: true } },
|
||||
{ label: '客户代码', prop: 'customerCode', component: 'input', placeholder: '客户代码', width: '160px' },
|
||||
{ label: '订单号', prop: 'orderNo', component: 'input', placeholder: '订单号', width: '180px' },
|
||||
@@ -71,34 +111,70 @@ const searchColumns = [
|
||||
]
|
||||
|
||||
const columns = [
|
||||
{ label: '任务ID', prop: 'taskId', align: 'center', width: 100 },
|
||||
{ label: '客户代码', prop: 'customerCode', minWidth: 120, showOverflowTooltip: true },
|
||||
{ label: '订单号', prop: 'orderNo', minWidth: 160, showOverflowTooltip: true },
|
||||
{ label: '运单号', prop: 'trackingNo', minWidth: 150, showOverflowTooltip: true },
|
||||
{ label: '转单号', prop: 'transferNo', minWidth: 160, showOverflowTooltip: true },
|
||||
{ label: '产品', prop: 'productCode', minWidth: 120, showOverflowTooltip: true },
|
||||
{ label: '计费类型', prop: 'billType', align: 'center', width: 100, slot: 'billType' },
|
||||
{ label: '状态', prop: 'successStatus', align: 'center', width: 100, slot: 'successStatus' },
|
||||
{ label: '计费时间', prop: 'bizDate', align: 'center', width: 170 },
|
||||
{ label: '计费时间', prop: 'billTime', align: 'center', width: 170 },
|
||||
{ label: '失败原因', prop: 'errorMessage', minWidth: 220, slot: 'errorMessage', showOverflowTooltip: true },
|
||||
{ label: '失败码', prop: 'failCode', align: 'center', width: 180, showOverflowTooltip: true },
|
||||
{ label: '创建时间', prop: 'createTime', align: 'center', width: 170 },
|
||||
{ label: '操作', prop: 'action', align: 'center', width: 180, fixed: 'right', slot: 'action', showInToolbar: false }
|
||||
]
|
||||
|
||||
const retryFloatVisible = computed(() => {
|
||||
const p = retryFloat.value
|
||||
return !!(p && (p.loading || p.finished))
|
||||
})
|
||||
const retryProgressDegree = computed(() => Math.round(((retryFloat.value?.percent || 0) / 100) * 360))
|
||||
const retryProgressText = computed(() => (retryFloat.value?.percent || 0) + '%')
|
||||
const retryFloatTitle = computed(() => {
|
||||
const st = (retryFloat.value?.status || '').toUpperCase()
|
||||
if (retryFloat.value?.loading) return '异步重新计费中'
|
||||
if (st === 'SUCCESS') return '重新计费完成'
|
||||
if (st === 'FAIL') return '重新计费失败'
|
||||
return '异步重新计费'
|
||||
})
|
||||
const retryFloatSummary = computed(() => {
|
||||
const p = retryFloat.value || {}
|
||||
return '成功 ' + (p.ok || 0) + ' / 失败 ' + (p.fail || 0) + ' / 总数 ' + (p.total || 0)
|
||||
})
|
||||
const retryFloatTooltip = computed(() => retryFloat.value?.message || '点击查看详情')
|
||||
|
||||
function queryList(params) {
|
||||
const p = proxy.addDateRange({ ...params }, params.dateRange)
|
||||
delete p.dateRange
|
||||
return listPrcOrder(p)
|
||||
return listBillingTask(p)
|
||||
}
|
||||
|
||||
function onFilterRetryProgress(payload) {
|
||||
retryFloat.value = payload
|
||||
if (payload && payload.finished && !payload.loading) {
|
||||
window.setTimeout(() => {
|
||||
if (retryFloat.value && retryFloat.value.finished && !retryFloat.value.loading) {
|
||||
retryFloat.value = null
|
||||
}
|
||||
}, 8000)
|
||||
}
|
||||
}
|
||||
|
||||
function onFilterRetrySuccess() {
|
||||
tableRef.value?.refresh()
|
||||
}
|
||||
|
||||
function handleRetry(row) {
|
||||
proxy.$modal.confirm('确认重新同步转单号 ' + (row.transferNo || row.orderId) + ' ?').then(() => {
|
||||
retryingId.value = row.orderId
|
||||
return retryPrcOrder(row.orderId)
|
||||
proxy.$modal.confirm('确认重新同步任务 #' + row.taskId + ' ?').then(() => {
|
||||
retryingId.value = row.taskId
|
||||
return retryBillingTask(row.taskId)
|
||||
}).then(res => {
|
||||
const order = res.data || {}
|
||||
if (order.successStatus === 'SUCCESS') {
|
||||
const task = res.data || {}
|
||||
if (task.successStatus === 'SUCCESS') {
|
||||
proxy.$modal.msgSuccess('同步成功')
|
||||
} else {
|
||||
proxy.$modal.msgError(order.failCode || '同步失败')
|
||||
proxy.$modal.msgError(task.errorMessage || '同步失败')
|
||||
}
|
||||
tableRef.value.refresh()
|
||||
}).catch(() => {}).finally(() => {
|
||||
@@ -108,9 +184,9 @@ function handleRetry(row) {
|
||||
|
||||
function handleBatchRetry(ids) {
|
||||
if (!ids || !ids.length) return
|
||||
proxy.$modal.confirm('确认同步选中的 ' + ids.length + ' 条订单?').then(() => {
|
||||
proxy.$modal.confirm('确认同步选中的 ' + ids.length + ' 条任务?').then(() => {
|
||||
batchLoading.value = true
|
||||
return retryPrcOrderBatch(ids)
|
||||
return retryBillingTaskBatch(ids)
|
||||
}).then(res => {
|
||||
const data = res.data || {}
|
||||
proxy.$modal.msgSuccess('完成:成功 ' + (data.ok || 0) + ' / 失败 ' + (data.fail || 0))
|
||||
@@ -122,4 +198,76 @@ function handleBatchRetry(ids) {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.err-text {
|
||||
color: #f56c6c;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.billing-task-page .retry-status-float {
|
||||
position: fixed;
|
||||
top: 92px;
|
||||
right: 24px;
|
||||
z-index: 3001;
|
||||
}
|
||||
|
||||
.billing-task-page .retry-status-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
min-width: 200px;
|
||||
min-height: 68px;
|
||||
padding: 6px 16px 6px 7px;
|
||||
border-radius: 36px;
|
||||
}
|
||||
|
||||
.billing-task-page .retry-progress-ring {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 0 0 54px;
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
border-radius: 50%;
|
||||
background: conic-gradient(
|
||||
var(--el-color-primary) 0deg var(--retry-progress, 45deg),
|
||||
var(--el-color-primary-light-8) var(--retry-progress, 45deg) 360deg
|
||||
);
|
||||
}
|
||||
|
||||
.billing-task-page .retry-progress-ring::after {
|
||||
position: absolute;
|
||||
inset: 5px;
|
||||
content: '';
|
||||
border-radius: 50%;
|
||||
background: var(--el-bg-color);
|
||||
}
|
||||
|
||||
.billing-task-page .retry-progress-value {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
color: var(--el-color-primary);
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.billing-task-page .retry-status-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 3px;
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.billing-task-page .retry-status-text strong {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.billing-task-page .retry-status-text small {
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 11px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user