增加异常订单功能
This commit is contained in:
+114
@@ -0,0 +1,114 @@
|
|||||||
|
package com.ruoyi.web.controller.monitor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
import com.ruoyi.price.domain.PrcBillingTask;
|
||||||
|
import com.ruoyi.price.enums.BillTaskSuccessStatus;
|
||||||
|
import com.ruoyi.price.service.IPrcBillingTaskService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Monitor: failed / waiting prc_billing_task list and manual resync.
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/monitor/billingTask")
|
||||||
|
public class BillingTaskMonitorController extends BaseController
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private IPrcBillingTaskService billingTaskService;
|
||||||
|
|
||||||
|
/** Default list = FAILED abnormal tasks. */
|
||||||
|
@PreAuthorize("@ss.hasPermi('monitor:billingTask:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(PrcBillingTask query)
|
||||||
|
{
|
||||||
|
if (query.getSuccessStatus() == null || query.getSuccessStatus().isEmpty())
|
||||||
|
{
|
||||||
|
query.setSuccessStatus(BillTaskSuccessStatus.FAILED.getCode());
|
||||||
|
}
|
||||||
|
else if ("ALL".equalsIgnoreCase(query.getSuccessStatus()))
|
||||||
|
{
|
||||||
|
query.setSuccessStatus(null);
|
||||||
|
}
|
||||||
|
startPage();
|
||||||
|
List<PrcBillingTask> list = billingTaskService.selectList(query);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('monitor:billingTask:list')")
|
||||||
|
@GetMapping("/{taskId}")
|
||||||
|
public AjaxResult getInfo(@PathVariable("taskId") Long taskId)
|
||||||
|
{
|
||||||
|
return success(billingTaskService.getById(taskId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Manual resync one task (reset WAITING then process). */
|
||||||
|
@PreAuthorize("@ss.hasPermi('monitor:billingTask:retry')")
|
||||||
|
@Log(title = "billing task retry", businessType = BusinessType.UPDATE)
|
||||||
|
@PostMapping("/retry/{taskId}")
|
||||||
|
public AjaxResult retry(@PathVariable("taskId") Long taskId)
|
||||||
|
{
|
||||||
|
return success(billingTaskService.retryTask(taskId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Manual resync selected tasks. */
|
||||||
|
@PreAuthorize("@ss.hasPermi('monitor:billingTask:retry')")
|
||||||
|
@Log(title = "billing task batch retry", businessType = BusinessType.UPDATE)
|
||||||
|
@PostMapping("/retry")
|
||||||
|
public AjaxResult retryBatch(@RequestBody Long[] taskIds)
|
||||||
|
{
|
||||||
|
if (taskIds == null || taskIds.length == 0)
|
||||||
|
{
|
||||||
|
return error("taskIds required");
|
||||||
|
}
|
||||||
|
int ok = 0;
|
||||||
|
int fail = 0;
|
||||||
|
List<Map<String, Object>> details = new ArrayList<Map<String, Object>>();
|
||||||
|
for (Long taskId : taskIds)
|
||||||
|
{
|
||||||
|
Map<String, Object> row = new HashMap<String, Object>();
|
||||||
|
row.put("taskId", taskId);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PrcBillingTask task = billingTaskService.retryTask(taskId);
|
||||||
|
row.put("successStatus", task == null ? null : task.getSuccessStatus());
|
||||||
|
row.put("errorMessage", task == null ? null : task.getErrorMessage());
|
||||||
|
if (task != null && BillTaskSuccessStatus.SUCCESS.getCode().equals(task.getSuccessStatus()))
|
||||||
|
{
|
||||||
|
ok++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fail++;
|
||||||
|
}
|
||||||
|
details.add(row);
|
||||||
|
}
|
||||||
|
catch (RuntimeException e)
|
||||||
|
{
|
||||||
|
fail++;
|
||||||
|
row.put("successStatus", "ERROR");
|
||||||
|
row.put("errorMessage", e.getMessage());
|
||||||
|
details.add(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Map<String, Object> data = new HashMap<String, Object>();
|
||||||
|
data.put("ok", Integer.valueOf(ok));
|
||||||
|
data.put("fail", Integer.valueOf(fail));
|
||||||
|
data.put("details", details);
|
||||||
|
return success(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -1,5 +1,6 @@
|
|||||||
package com.ruoyi.price.service;
|
package com.ruoyi.price.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import com.ruoyi.price.domain.PrcBillingTask;
|
import com.ruoyi.price.domain.PrcBillingTask;
|
||||||
import com.ruoyi.price.domain.vo.BillingTaskSubmitRequest;
|
import com.ruoyi.price.domain.vo.BillingTaskSubmitRequest;
|
||||||
|
|
||||||
@@ -12,4 +13,13 @@ public interface IPrcBillingTaskService
|
|||||||
void processTask(Long taskId);
|
void processTask(Long taskId);
|
||||||
|
|
||||||
PrcBillingTask getById(Long taskId);
|
PrcBillingTask getById(Long taskId);
|
||||||
|
|
||||||
|
/** Admin list (failed / waiting / filter). */
|
||||||
|
List<PrcBillingTask> selectList(PrcBillingTask query);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manual resync: reset to WAITING then process again.
|
||||||
|
* @return task after retry
|
||||||
|
*/
|
||||||
|
PrcBillingTask retryTask(Long taskId);
|
||||||
}
|
}
|
||||||
|
|||||||
+36
@@ -2,6 +2,7 @@ package com.ruoyi.price.service.impl;
|
|||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -255,6 +256,41 @@ public class PrcBillingTaskServiceImpl implements IPrcBillingTaskService
|
|||||||
return billingTaskMapper.selectPrcBillingTaskById(taskId);
|
return billingTaskMapper.selectPrcBillingTaskById(taskId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PrcBillingTask> selectList(PrcBillingTask query)
|
||||||
|
{
|
||||||
|
return billingTaskMapper.selectPrcBillingTaskList(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PrcBillingTask retryTask(Long taskId)
|
||||||
|
{
|
||||||
|
if (taskId == null)
|
||||||
|
{
|
||||||
|
throw new ServiceException("taskId required");
|
||||||
|
}
|
||||||
|
PrcBillingTask task = billingTaskMapper.selectPrcBillingTaskById(taskId);
|
||||||
|
if (task == null)
|
||||||
|
{
|
||||||
|
throw new ServiceException("billing task not found");
|
||||||
|
}
|
||||||
|
String st = task.getSuccessStatus();
|
||||||
|
if (BillTaskSuccessStatus.SUCCESS.getCode().equals(st))
|
||||||
|
{
|
||||||
|
throw new ServiceException("SUCCESS task cannot retry");
|
||||||
|
}
|
||||||
|
// Reset to WAITING so UI reflects re-queue; then sync process (admin expects immediate result).
|
||||||
|
PrcBillingTask reset = new PrcBillingTask();
|
||||||
|
reset.setTaskId(taskId);
|
||||||
|
reset.setSuccessStatus(BillTaskSuccessStatus.WAITING.getCode());
|
||||||
|
reset.setBillId(null);
|
||||||
|
reset.setErrorMessage(null);
|
||||||
|
billingTaskMapper.updateBillingResult(reset);
|
||||||
|
|
||||||
|
processTask(taskId);
|
||||||
|
return billingTaskMapper.selectPrcBillingTaskById(taskId);
|
||||||
|
}
|
||||||
|
|
||||||
private BillTaskType resolveAutoType(String transferNo, String trackingNo, String orderNo)
|
private BillTaskType resolveAutoType(String transferNo, String trackingNo, String orderNo)
|
||||||
{
|
{
|
||||||
PrcOrderBill existed = null;
|
PrcOrderBill existed = null;
|
||||||
|
|||||||
@@ -35,13 +35,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<include refid="selectPrcBillingTaskVo"/>
|
<include refid="selectPrcBillingTaskVo"/>
|
||||||
<where>
|
<where>
|
||||||
<if test="transferNo != null and transferNo != ''">
|
<if test="transferNo != null and transferNo != ''">
|
||||||
AND transfer_no = #{transferNo}
|
AND transfer_no like concat('%', #{transferNo}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="trackingNo != null and trackingNo != ''">
|
<if test="trackingNo != null and trackingNo != ''">
|
||||||
AND tracking_no = #{trackingNo}
|
AND tracking_no like concat('%', #{trackingNo}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="orderNo != null and orderNo != ''">
|
<if test="orderNo != null and orderNo != ''">
|
||||||
AND order_no = #{orderNo}
|
AND order_no like concat('%', #{orderNo}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="billType != null and billType != ''">
|
<if test="billType != null and billType != ''">
|
||||||
AND bill_type = #{billType}
|
AND bill_type = #{billType}
|
||||||
@@ -49,6 +49,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="successStatus != null and successStatus != ''">
|
<if test="successStatus != null and successStatus != ''">
|
||||||
AND success_status = #{successStatus}
|
AND success_status = #{successStatus}
|
||||||
</if>
|
</if>
|
||||||
|
<if test="params.beginTime != null and params.beginTime != ''">
|
||||||
|
AND create_time >= #{params.beginTime}
|
||||||
|
</if>
|
||||||
|
<if test="params.endTime != null and params.endTime != ''">
|
||||||
|
AND create_time <= #{params.endTime}
|
||||||
|
</if>
|
||||||
</where>
|
</where>
|
||||||
order by task_id desc
|
order by task_id desc
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
-- Billing task abnormal list under system monitor (parent_id = 2)
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
|
||||||
|
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||||
|
SELECT 2322, N'计费任务异常', 2, 8, 'billingTask', 'monitor/billingTask/index', '', 'BillingTaskMonitor', 1, 0, 'C', '0', '0', 'monitor:billingTask:list', 'bug', 'admin', sysdate(), N'prc_billing_task异常订单,支持手工重新同步'
|
||||||
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2322 OR perms = 'monitor:billingTask:list');
|
||||||
|
|
||||||
|
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time)
|
||||||
|
SELECT 2323, N'查询', 2322, 1, '', NULL, 1, 0, 'F', '0', '0', 'monitor:billingTask:list', '#', 'admin', sysdate()
|
||||||
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2323);
|
||||||
|
|
||||||
|
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||||
|
SELECT 2324, N'重新同步', 2322, 2, '', NULL, 1, 0, 'F', '0', '0', 'monitor:billingTask:retry', '#', 'admin', sysdate(), N'手工重试计费任务'
|
||||||
|
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2324 OR perms = 'monitor:billingTask:retry');
|
||||||
|
|
||||||
|
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||||
|
SELECT 1, m.menu_id FROM (SELECT 2322 AS menu_id UNION SELECT 2323 UNION SELECT 2324) m
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM sys_role_menu rm WHERE rm.role_id = 1 AND rm.menu_id = m.menu_id);
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
export function listBillingTask(query) {
|
||||||
|
return request({
|
||||||
|
url: '/monitor/billingTask/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBillingTask(taskId) {
|
||||||
|
return request({
|
||||||
|
url: '/monitor/billingTask/' + taskId,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function retryBillingTask(taskId) {
|
||||||
|
return request({
|
||||||
|
url: '/monitor/billingTask/retry/' + taskId,
|
||||||
|
method: 'post'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function retryBillingTaskBatch(taskIds) {
|
||||||
|
return request({
|
||||||
|
url: '/monitor/billingTask/retry',
|
||||||
|
method: 'post',
|
||||||
|
data: taskIds
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,277 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<basic-table
|
||||||
|
ref="tableRef"
|
||||||
|
:columns="columns"
|
||||||
|
:search-columns="searchColumns"
|
||||||
|
:query="queryList"
|
||||||
|
:default-params="defaultParams"
|
||||||
|
row-key="taskId"
|
||||||
|
selection
|
||||||
|
>
|
||||||
|
<template #toolbar="{ ids }">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="Refresh"
|
||||||
|
:disabled="!ids.length"
|
||||||
|
:loading="batchLoading"
|
||||||
|
v-hasPermi="['monitor:billingTask:retry']"
|
||||||
|
@click="handleBatchRetry(ids)"
|
||||||
|
>批量重新同步</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="handleView(row)" v-hasPermi="['monitor:billingTask:list']">查看</el-button>
|
||||||
|
<el-button
|
||||||
|
link
|
||||||
|
type="warning"
|
||||||
|
icon="Refresh"
|
||||||
|
:disabled="row.successStatus === 'SUCCESS'"
|
||||||
|
:loading="retryingId === row.taskId"
|
||||||
|
v-hasPermi="['monitor:billingTask:retry']"
|
||||||
|
@click="handleRetry(row)"
|
||||||
|
>重新同步</el-button>
|
||||||
|
</template>
|
||||||
|
</basic-table>
|
||||||
|
|
||||||
|
<el-drawer v-model="open" size="600px" :title="drawerTitle" append-to-body destroy-on-close class="billing-task-drawer">
|
||||||
|
<div v-loading="loading" class="detail-wrap">
|
||||||
|
<el-empty v-if="!detail" description="暂无详情" />
|
||||||
|
<template v-else>
|
||||||
|
<div class="detail-header">
|
||||||
|
<el-tag :type="statusTag(detail.successStatus)" effect="light">{{ statusLabel(detail.successStatus) }}</el-tag>
|
||||||
|
<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.taskId }}</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="计费订单ID">{{ detail.billId || '-' }}</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>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="BillingTaskMonitor">
|
||||||
|
import { listBillingTask, getBillingTask, retryBillingTask, retryBillingTaskBatch } from '@/api/monitor/billingTask'
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
|
const tableRef = ref()
|
||||||
|
const open = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const detail = ref(null)
|
||||||
|
const drawerTitle = ref('计费任务详情')
|
||||||
|
const retryingId = ref(null)
|
||||||
|
const batchLoading = ref(false)
|
||||||
|
|
||||||
|
const defaultParams = { successStatus: 'FAILED' }
|
||||||
|
|
||||||
|
const statusOptions = [
|
||||||
|
{ label: '失败', value: 'FAILED' },
|
||||||
|
{ label: '待处理', value: 'WAITING' },
|
||||||
|
{ label: '成功', value: 'SUCCESS' },
|
||||||
|
{ label: '全部', value: 'ALL' }
|
||||||
|
]
|
||||||
|
|
||||||
|
const billTypeOptions = [
|
||||||
|
{ label: '待计费', value: 'PENDING' },
|
||||||
|
{ label: '重计费', value: 'REBILL' },
|
||||||
|
{ label: '退费', value: 'REFUND' }
|
||||||
|
]
|
||||||
|
|
||||||
|
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: 'orderNo', component: 'input', placeholder: '订单号', width: '180px' },
|
||||||
|
{ label: '运单号', prop: 'trackingNo', component: 'input', placeholder: '运单号', width: '180px' },
|
||||||
|
{ label: '转单号', prop: 'transferNo', component: 'input', placeholder: '转单号', width: '180px' }
|
||||||
|
]
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{ label: '任务ID', prop: 'taskId', align: 'center', width: 100 },
|
||||||
|
{ label: '订单号', prop: 'orderNo', minWidth: 160, showOverflowTooltip: true },
|
||||||
|
{ label: '运单号', prop: 'trackingNo', minWidth: 150, showOverflowTooltip: true },
|
||||||
|
{ label: '转单号', prop: 'transferNo', minWidth: 160, showOverflowTooltip: true },
|
||||||
|
{ label: '计费类型', prop: 'billType', align: 'center', width: 100, slot: 'billType' },
|
||||||
|
{ label: '状态', prop: 'successStatus', align: 'center', width: 100, slot: 'successStatus' },
|
||||||
|
{ label: '计费时间', prop: 'billTime', align: 'center', width: 170 },
|
||||||
|
{ label: '失败原因', prop: 'errorMessage', minWidth: 220, slot: 'errorMessage', showOverflowTooltip: true },
|
||||||
|
{ label: '创建时间', prop: 'createTime', align: 'center', width: 170 },
|
||||||
|
{ label: '操作', prop: 'action', align: 'center', width: 180, fixed: 'right', slot: 'action', showInToolbar: false }
|
||||||
|
]
|
||||||
|
|
||||||
|
function queryList(params) {
|
||||||
|
return listBillingTask(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
function billTypeLabel(type) {
|
||||||
|
const found = billTypeOptions.find(item => item.value === type)
|
||||||
|
return found ? found.label : (type || '-')
|
||||||
|
}
|
||||||
|
|
||||||
|
function statusLabel(status) {
|
||||||
|
const found = statusOptions.find(item => item.value === status)
|
||||||
|
return found ? found.label : (status || '-')
|
||||||
|
}
|
||||||
|
|
||||||
|
function statusTag(status) {
|
||||||
|
if (status === 'SUCCESS') return 'success'
|
||||||
|
if (status === 'FAILED') return 'danger'
|
||||||
|
if (status === 'WAITING') return 'warning'
|
||||||
|
return 'info'
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleView(row) {
|
||||||
|
drawerTitle.value = '计费任务 #' + row.taskId
|
||||||
|
open.value = true
|
||||||
|
loading.value = true
|
||||||
|
detail.value = null
|
||||||
|
getBillingTask(row.taskId).then(res => {
|
||||||
|
detail.value = res.data || row
|
||||||
|
}).finally(() => {
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleRetry(row) {
|
||||||
|
proxy.$modal.confirm('确认重新同步任务 #' + row.taskId + ' ?').then(() => {
|
||||||
|
retryingId.value = row.taskId
|
||||||
|
return retryBillingTask(row.taskId)
|
||||||
|
}).then(res => {
|
||||||
|
const task = res.data || {}
|
||||||
|
if (task.successStatus === 'SUCCESS') {
|
||||||
|
proxy.$modal.msgSuccess('同步成功')
|
||||||
|
} else {
|
||||||
|
proxy.$modal.msgError(task.errorMessage || '同步失败')
|
||||||
|
}
|
||||||
|
tableRef.value.refresh()
|
||||||
|
}).catch(() => {}).finally(() => {
|
||||||
|
retryingId.value = null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyError() {
|
||||||
|
const text = detail.value?.errorMessage || ''
|
||||||
|
if (!text) return
|
||||||
|
navigator.clipboard.writeText(text).then(() => {
|
||||||
|
proxy.$modal.msgSuccess('已复制')
|
||||||
|
}).catch(() => {
|
||||||
|
proxy.$modal.msgError('复制失败')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBatchRetry(ids) {
|
||||||
|
if (!ids || !ids.length) return
|
||||||
|
proxy.$modal.confirm('确认批量重新同步选中的 ' + ids.length + ' 条任务?').then(() => {
|
||||||
|
batchLoading.value = true
|
||||||
|
return retryBillingTaskBatch(ids)
|
||||||
|
}).then(res => {
|
||||||
|
const data = res.data || {}
|
||||||
|
proxy.$modal.msgSuccess('完成:成功 ' + (data.ok || 0) + ' / 失败 ' + (data.fail || 0))
|
||||||
|
tableRef.value.refresh()
|
||||||
|
}).catch(() => {}).finally(() => {
|
||||||
|
batchLoading.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.err-text {
|
||||||
|
color: #f56c6c;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-wrap {
|
||||||
|
padding: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
background: #f8f9fb;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-header-type {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-header-time {
|
||||||
|
margin-left: auto;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-desc :deep(.el-descriptions__label) {
|
||||||
|
width: 96px;
|
||||||
|
min-width: 96px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-desc :deep(.el-descriptions__content) {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.err-block {
|
||||||
|
margin-top: 16px;
|
||||||
|
border: 1px solid #fde2e2;
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.err-block-head {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 6px 12px;
|
||||||
|
background: #fef0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.err-block-title {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.err-block-body {
|
||||||
|
max-height: 260px;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 10px 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: Consolas, Monaco, monospace;
|
||||||
|
line-height: 1.7;
|
||||||
|
color: #c45656;
|
||||||
|
word-break: break-all;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user