数据库分析和对应不同角色页面
This commit is contained in:
291
pages/mall/delivery/test/api-simulator.uvue
Normal file
291
pages/mall/delivery/test/api-simulator.uvue
Normal file
@@ -0,0 +1,291 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="header">
|
||||
<text class="title">第三方物流 API 模拟发送器</text>
|
||||
<text class="subtitle">模拟外部物流平台向后端推送 Webhook 轨迹数据</text>
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<text class="section-title">1. 选择目标订单 (已发货)</text>
|
||||
<scroll-view class="order-list" direction="horizontal">
|
||||
<view v-for="(item, index) in shippedOrders" :key="index"
|
||||
:class="['order-card', selectedOrderIndex == index ? 'active' : '']"
|
||||
@click="selectOrder(index)">
|
||||
<text class="order-no">{{ item.order_no }}</text>
|
||||
<text class="tracking-no">{{ item.carrier }}: {{ item.tracking_no }}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<text class="section-title">2. 构造回调数据 (JSON Payload)</text>
|
||||
<view class="form-group">
|
||||
<text class="label">运单号:</text>
|
||||
<input class="input" v-model="form.tracking_no" placeholder="请输入运单号" />
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<text class="label">快递公司:</text>
|
||||
<input class="input" v-model="form.carrier" placeholder="请输入快递公司" />
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<text class="label">物流状态:</text>
|
||||
<picker :range="statusOptions" range-key="label" @change="onStatusChange">
|
||||
<view class="picker-val">{{ currentStatusLabel }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<text class="label">轨迹描述文字:</text>
|
||||
<textarea class="textarea" v-model="form.event_text" placeholder="描述当前的物流位置或状态..." />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="payload-preview">
|
||||
<text class="preview-title">接口发送原始数据预览:</text>
|
||||
<view class="code-block">
|
||||
<text class="code-text">{{ jsonString }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<button class="btn-send" type="primary" @click="sendWebhook">立即推送 API 数据</button>
|
||||
|
||||
<view class="footer-links">
|
||||
<text class="link" @click="goToLogs">查看接收日志 (Webhook Logs)</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { mockService, MockOrder } from './mock-service.uts'
|
||||
|
||||
const shippedOrders = computed((): MockOrder[] => {
|
||||
return mockService.getMockOrders().filter((o: MockOrder): boolean => o.status !== 'PENDING' && o.tracking_no !== '')
|
||||
})
|
||||
|
||||
const selectedOrderIndex = ref(-1)
|
||||
|
||||
const form = reactive({
|
||||
tracking_no: '',
|
||||
carrier: '',
|
||||
status_code: 'IN_TRANSIT',
|
||||
event_text: '快件已到达【XX转运中心】,准备发往下一站'
|
||||
})
|
||||
|
||||
const statusOptions = [
|
||||
{ label: '在途中 (IN_TRANSIT)', value: 'IN_TRANSIT' },
|
||||
{ label: '派送中 (OUT_FOR_DELIVERY)', value: 'OUT_FOR_DELIVERY' },
|
||||
{ label: '已签收 (DELIVERED)', value: 'DELIVERED' },
|
||||
{ label: '异常 (EXCEPTION)', value: 'EXCEPTION' }
|
||||
]
|
||||
|
||||
const currentStatusLabel = computed(() => {
|
||||
const opt = statusOptions.find(o => o.value === form.status_code)
|
||||
return opt ? opt.label : '请选择'
|
||||
})
|
||||
|
||||
const jsonString = computed(() => {
|
||||
return JSON.stringify(form, null, 2)
|
||||
})
|
||||
|
||||
function selectOrder(index: number) {
|
||||
selectedOrderIndex.value = index
|
||||
const order = shippedOrders.value[index]
|
||||
form.tracking_no = order.tracking_no
|
||||
form.carrier = order.carrier
|
||||
|
||||
// 根据订单当前状态智能预设
|
||||
if (order.status === 'SHIPPED') {
|
||||
form.status_code = 'IN_TRANSIT'
|
||||
form.event_text = '快件已揽收,正发往城市中心'
|
||||
} else if (order.status === 'IN_TRANSIT') {
|
||||
form.status_code = 'OUT_FOR_DELIVERY'
|
||||
form.event_text = '派送员王师傅(13700008888)正在派件'
|
||||
}
|
||||
}
|
||||
|
||||
function onStatusChange(e: UniPickerChangeEvent) {
|
||||
const idx = e.detail.value as number
|
||||
form.status_code = statusOptions[idx].value as string
|
||||
}
|
||||
|
||||
function sendWebhook() {
|
||||
if (!form.tracking_no) {
|
||||
uni.showToast({ title: '请先填写运单号', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
// 执行模拟推送 (转换为普通对象以兼容 UTS)
|
||||
const payload = {
|
||||
tracking_no: form.tracking_no,
|
||||
carrier: form.carrier,
|
||||
status_code: form.status_code,
|
||||
event_text: form.event_text
|
||||
} as UTSJSONObject
|
||||
|
||||
const success = mockService.pushWebhookData(payload)
|
||||
|
||||
if (success) {
|
||||
uni.showToast({ title: 'API 发送成功!', icon: 'success' })
|
||||
// 可选:跳转到详情或日志预览
|
||||
} else {
|
||||
uni.showModal({
|
||||
title: '发送失败',
|
||||
content: '系统未找到该运单号,后端拒绝接收该数据。',
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function goToLogs() {
|
||||
uni.navigateTo({ url: '/pages/mall/delivery/test/webhook-logs' })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
padding: 20px;
|
||||
background-color: #f8f9fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
margin-top: 5px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 25px;
|
||||
background: #fff;
|
||||
padding: 15px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #444;
|
||||
margin-bottom: 12px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.order-list {
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.order-card {
|
||||
display: inline-block;
|
||||
width: 160px;
|
||||
padding: 12px;
|
||||
background: #f0f4f8;
|
||||
border: 1.5px solid transparent;
|
||||
border-radius: 8px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.order-card.active {
|
||||
border-color: #007aff;
|
||||
background: #eef6ff;
|
||||
}
|
||||
|
||||
.order-no {
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tracking-no {
|
||||
font-size: 11px;
|
||||
color: #888;
|
||||
margin-top: 4px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
margin-bottom: 5px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.input {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
.picker-val {
|
||||
font-size: 14px;
|
||||
color: #007aff;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
background: #fafafa;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.payload-preview {
|
||||
background: #2d2d2d;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.preview-title {
|
||||
color: #aaa;
|
||||
font-size: 12px;
|
||||
margin-bottom: 10px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.code-block {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.code-text {
|
||||
color: #69f0ae;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.btn-send {
|
||||
margin-top: 10px;
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.footer-links {
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #007aff;
|
||||
font-size: 14px;
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user