Files
medical-mall/pages/mall/delivery/test/platform-webhook-logs.uvue
not-like-juvenile a5e7afacec 创建数据库表格
2026-02-06 16:56:24 +08:00

251 lines
5.7 KiB
Plaintext
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>
<view class="container">
<view class="header">
<text class="title">Webhook 接收日志</text>
<text class="subtitle">监控推送到达、验签与入库状态</text>
</view>
<view class="stats-bar">
<view class="stat-box">
<text class="stat-val green">99.8%</text>
<text class="stat-lab">成功率</text>
</view>
<view class="stat-box">
<text class="stat-val red">24</text>
<text class="stat-lab">验签失败</text>
</view>
<view class="stat-box">
<text class="stat-val blue">1.2s</text>
<text class="stat-lab">平均延迟</text>
</view>
</view>
<scroll-view class="log-list" scroll-y="true">
<view v-for="(log, index) in logs" :key="index" class="log-item">
<view class="log-header">
<view class="log-status" :class="log.success ? 'bg-success' : 'bg-danger'"></view>
<text class="log-time">{{ log.time }}</text>
<text class="log-carrier">{{ log.carrier }}</text>
</view>
<view class="log-body">
<view class="log-row">
<text class="log-label">单号:</text>
<text class="log-value">{{ log.tracking_no }}</text>
</view>
<view class="log-row">
<text class="log-label">事件:</text>
<text class="log-value">{{ getEventText(log.event_code) }}</text>
</view>
<view class="log-row">
<text class="log-label">状态:</text>
<text class="log-value" :class="log.success ? 'text-success' : 'text-danger'">{{ log.result_text }}</text>
</view>
</view>
<view class="log-actions">
<text class="action-link" @click="viewPayload(log)">查看 Payload</text>
<text class="action-link" @click="reProcess(log)" v-if="!log.success">尝试重新入库</text>
</view>
</view>
</scroll-view>
<!-- Payload 详情抽屉 -->
<view v-if="showPayload" class="drawer-mask" @click="showPayload = false">
<view class="drawer-content" @click.stop>
<view class="drawer-header">
<text>原始报文明细</text>
<text class="close" @click="showPayload = false">×</text>
</view>
<scroll-view class="drawer-body" scroll-y="true">
<view class="payload-box">
<text class="payload-text">{{ currentPayload }}</text>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script setup lang="uts">
import { onShow } from '@dcloudio/uni-app'
import { mockService, MockWebhookLog } from './mock-service.uts'
const logs = ref([] as MockWebhookLog[])
const showPayload = ref(false)
const currentPayload = ref('')
onShow(() => {
logs.value = mockService.getMockWebhookLogs()
})
function viewPayload(log: MockWebhookLog) {
currentPayload.value = JSON.stringify(log.payload, null, 2)
showPayload.value = true
}
function getEventText(code: string) : string {
const maps = {
'SHIPPED': '发货揽收',
'IN_TRANSIT': '运输中',
'ARRIVED_HUB': '中转入库',
'OUT_FOR_DELIVERY': '派件中',
'DELIVERED': '确认签收',
'EXCEPTION': '异常上报'
}
return (maps[code] != null) ? maps[code] : code
}
function reProcess(log: MockWebhookLog) {
uni.showLoading({ title: '重送中...' })
setTimeout(() => {
uni.hideLoading()
uni.showToast({ title: '重试成功: 已重新入库', icon: 'success' })
log.success = true
log.result_text = '成功入库 (手动补录)'
}, 1000)
}
</script>
<style scoped>
.container {
padding: 24rpx;
background-color: #f8f9fa;
min-height: 100vh;
}
.header {
margin-bottom: 30rpx;
}
.title {
font-size: 36rpx;
font-weight: bold;
color: #2c3e50;
}
.subtitle {
font-size: 24rpx;
color: #7f8c8d;
}
.stats-bar {
display: flex;
gap: 20rpx;
margin-bottom: 30rpx;
}
.stat-box {
flex: 1;
background-color: #fff;
border-radius: 12rpx;
padding: 20rpx;
text-align: center;
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.05);
}
.stat-val {
font-size: 32rpx;
font-weight: bold;
display: block;
}
.stat-lab {
font-size: 22rpx;
color: #95a5a6;
}
.green { color: #27ae60; }
.red { color: #e74c3c; }
.blue { color: #3498db; }
.log-item {
background-color: #fff;
border-radius: 12rpx;
padding: 24rpx;
margin-bottom: 16rpx;
border-left: 8rpx solid transparent;
}
.bg-success { background-color: #27ae60; }
.bg-danger { background-color: #e74c3c; }
.log-header {
display: flex;
align-items: center;
margin-bottom: 16rpx;
}
.log-status {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
margin-right: 16rpx;
}
.log-time {
font-size: 24rpx;
color: #7f8c8d;
margin-right: 20rpx;
}
.log-carrier {
font-size: 24rpx;
font-weight: bold;
color: #34495e;
}
.log-row {
display: flex;
margin-bottom: 8rpx;
}
.log-label {
width: 100rpx;
font-size: 24rpx;
color: #95a5a6;
}
.log-value {
flex: 1;
font-size: 24rpx;
color: #34495e;
}
.text-success { color: #27ae60; }
.text-danger { color: #e74c3c; }
.log-actions {
display: flex;
gap: 30rpx;
margin-top: 20rpx;
padding-top: 16rpx;
border-top: 1rpx solid #f1f1f1;
}
.action-link {
font-size: 24rpx;
color: #3498db;
}
.drawer-mask {
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background-color: rgba(0,0,0,0.5);
z-index: 1000;
}
.drawer-content {
position: absolute;
bottom: 0; left: 0; right: 0;
height: 70%;
background-color: #fff;
border-radius: 24rpx 24rpx 0 0;
display: flex;
flex-direction: column;
}
.drawer-header {
padding: 30rpx;
border-bottom: 1rpx solid #eee;
display: flex;
justify-content: space-between;
font-weight: bold;
}
.drawer-body {
flex: 1;
padding: 20rpx;
}
.payload-box {
background-color: #2c3e50;
padding: 20rpx;
border-radius: 8rpx;
}
.payload-text {
color: #ecf0f1;
font-size: 22rpx;
font-family: monospace;
}
</style>