feat(m5): add simulated callback event delivery for testing

This commit is contained in:
2026-05-25 15:04:03 +08:00
parent ca1279162b
commit 1cef437fb3
3 changed files with 74 additions and 3 deletions
@@ -280,6 +280,14 @@ export function patchCallbackInboxLink(id, body) {
return axios.patch(`/api/v1/callback-inbox/${id}/link`, body);
}
/**
* M5-F10:模拟投递(仅测试环境)。
* @param {Record<string, unknown>} body
*/
export function simulateCallback(body) {
return axios.post('/api/v1/callback-inbox/simulate', body);
}
/**
* I8:将 Webhook 侧 DEAD 出库按收据 ID 重新入队(需平台配置 LICENSE_WEBHOOK_*)。
* @param {string | number} id — callback inbox id
@@ -15,6 +15,7 @@
<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>
<el-button @click="simDialogVisible = true">模拟投递</el-button>
</div>
</div>
</template>
@@ -52,6 +53,29 @@
@size-change="onSizeChange"
/>
</div>
<el-dialog v-model="simDialogVisible" title="模拟 Callback 投递" width="560px">
<el-form label-width="120px">
<el-form-item label="事件类型" required>
<el-select v-model="simForm.eventType" style="width:100%">
<el-option label="sn:post_activate" value="sn:post_activate" />
<el-option label="sn:pre_activate" value="sn:pre_activate" />
<el-option label="device:post_activate" value="device:post_activate" />
<el-option label="yunbaobao:session_logout" value="yunbaobao:session_logout" />
</el-select>
</el-form-item>
<el-form-item label="SN 编码">
<el-input v-model="simForm.snCode" placeholder="选填" />
</el-form-item>
<el-form-item label="Payload (JSON)">
<el-input v-model="simForm.rawPayload" type="textarea" :rows="6" placeholder='{"key": "value"}' />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="simDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="simulating" @click="handleSimulate">投递</el-button>
</template>
</el-dialog>
</el-card>
</template>
@@ -60,7 +84,7 @@ import { ref, onMounted } from "vue";
import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import { useAuthStore } from "../stores/auth";
import { listCallbackInbox, replayCallbackWebhookDelivery } from "../api/platform";
import { listCallbackInbox, replayCallbackWebhookDelivery, simulateCallback } from "../api/platform";
import { apiErrorMessage } from "../utils/apiErrorMessage";
const auth = useAuthStore();
@@ -76,6 +100,9 @@ const filterEventType = ref("");
const filterSnCode = ref("");
const filterProjectId = ref("");
const selectedCallbacks = ref([]);
const simDialogVisible = ref(false);
const simulating = ref(false);
const simForm = ref({ eventType: 'sn:post_activate', snCode: '', rawPayload: '{}' });
function handleSelectionChange(val) {
selectedCallbacks.value = val;
@@ -150,6 +177,27 @@ async function load() {
}
}
async function handleSimulate() {
simulating.value = true;
try {
await simulateCallback({
sourceSystem: 'SIMULATOR',
externalMessageId: `sim-${Date.now()}`,
schemaVersion: '1.0',
eventType: simForm.value.eventType,
rawPayload: JSON.parse(simForm.value.rawPayload),
receivedAt: new Date().toISOString(),
});
ElMessage.success('模拟事件已投递');
simDialogVisible.value = false;
load();
} catch (e) {
ElMessage.error(apiErrorMessage(e, '模拟投递失败'));
} finally {
simulating.value = false;
}
}
function goDetail(id) {
router.push({ name: "callback-inbox-detail", params: { id: String(id) } });
}