feat(m5): add failure reason tagging and batch retry

This commit is contained in:
2026-05-25 14:52:06 +08:00
parent 6522f02b54
commit 0ae3987fb2
2 changed files with 40 additions and 3 deletions
@@ -62,6 +62,14 @@
<div v-if="isPending" class="status-row">
<el-button v-permission="'callback:process'" type="success" :loading="patchingStatus" @click="setStatus('PROCESSED')">标为已处理</el-button>
<el-button v-permission="'callback:process'" type="danger" :loading="patchingStatus" @click="setStatus('FAILED')">标为失败</el-button>
<el-select v-model="failureReason" clearable placeholder="失败原因" style="width: 180px">
<el-option label="SN未关联合同" value="SN_NOT_LINKED" />
<el-option label="网络超时" value="NETWORK_TIMEOUT" />
<el-option label="SN已吊销" value="SN_REVOKED" />
<el-option label="设备指纹不匹配" value="DEVICE_MISMATCH" />
<el-option label="比特接口错误" value="BITANSWER_ERROR" />
<el-option label="其他" value="OTHER" />
</el-select>
<el-button v-permission="'callback:process'" type="info" :loading="patchingStatus" @click="setStatus('IGNORED')">忽略</el-button>
</div>
@@ -109,6 +117,7 @@ const loading = ref(false);
const patchingStatus = ref(false);
const replaying = ref(false);
const savingLink = ref(false);
const failureReason = ref("");
const row = ref(null);
const webhookDeliveryStatus = ref(null);
const webhookDeliveryLoading = ref(false);
@@ -238,7 +247,13 @@ async function setStatus(status) {
}
patchingStatus.value = true;
try {
await patchCallbackInboxStatus(id, { status });
const body = { status };
if (status === "FAILED" && failureReason.value) {
body.failureReason = failureReason.value;
body.operatorNote = failureReason.value;
}
await patchCallbackInboxStatus(id, body);
failureReason.value = "";
ElMessage.success("状态已更新");
await load();
} catch (e) {
@@ -14,11 +14,13 @@
<el-input v-model="filterSnCode" clearable placeholder="SN 编码" class="filter" style="width: 140px" @keyup.enter="load" />
<el-input v-model="filterProjectId" clearable placeholder="项目 ID" class="filter" style="width: 120px" @keyup.enter="load" />
<el-button type="primary" :loading="loading" @click="load">查询</el-button>
<el-button @click="handleBatchRetry" :disabled="selectedCallbacks.length === 0">批量重试</el-button>
</div>
</div>
</template>
<el-table v-loading="loading" :data="rows" stripe style="width: 100%">
<el-table v-loading="loading" :data="rows" stripe style="width: 100%" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column prop="sourceSystem" label="来源" width="120" show-overflow-tooltip />
<el-table-column prop="externalMessageId" label="外部消息 ID" min-width="160" show-overflow-tooltip />
<el-table-column prop="eventType" label="事件类型" min-width="140" show-overflow-tooltip />
@@ -58,7 +60,7 @@ import { ref, onMounted } from "vue";
import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import { useAuthStore } from "../stores/auth";
import { listCallbackInbox } from "../api/platform";
import { listCallbackInbox, replayCallbackWebhookDelivery } from "../api/platform";
import { apiErrorMessage } from "../utils/apiErrorMessage";
const auth = useAuthStore();
@@ -73,6 +75,26 @@ const filterStatus = ref("");
const filterEventType = ref("");
const filterSnCode = ref("");
const filterProjectId = ref("");
const selectedCallbacks = ref([]);
function handleSelectionChange(val) {
selectedCallbacks.value = val;
}
async function handleBatchRetry() {
let success = 0;
let fail = 0;
for (const cb of selectedCallbacks.value) {
try {
await replayCallbackWebhookDelivery(cb.id);
success++;
} catch {
fail++;
}
}
ElMessage.success(`重试完成: ${success} 成功, ${fail} 失败`);
load();
}
onMounted(async () => {
auth.restoreAxiosAuth();