创建数据库表格
This commit is contained in:
@@ -18,24 +18,24 @@
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<text class="section-title">2. 构造回调数据 (JSON Payload)</text>
|
||||
<text class="section-title">2. 构造圆通协议数据 (YTO Protocol)</text>
|
||||
<view class="form-group">
|
||||
<text class="label">运单号:</text>
|
||||
<input class="input" v-model="form.tracking_no" placeholder="请输入运单号" />
|
||||
<text class="label">物流单号 (mailNo):</text>
|
||||
<input class="input" v-model="form.mailNo" placeholder="请输入运单号" />
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<text class="label">快递公司:</text>
|
||||
<input class="input" v-model="form.carrier" placeholder="请输入快递公司" />
|
||||
<text class="label">订单号 (txLogisticId):</text>
|
||||
<input class="input" v-model="form.txLogisticId" placeholder="请输入关联订单号" />
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<text class="label">物流状态:</text>
|
||||
<text class="label">事件状态 (infoContent):</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="描述当前的物流位置或状态..." />
|
||||
<text class="label">轨迹描述 (remark):</text>
|
||||
<textarea class="textarea" v-model="form.remark" placeholder="描述当前的物流位置或状态..." />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -64,61 +64,77 @@
|
||||
const selectedOrderIndex = ref(-1)
|
||||
|
||||
const form = reactive({
|
||||
tracking_no: '',
|
||||
carrier: '',
|
||||
status_code: 'IN_TRANSIT',
|
||||
event_text: '快件已到达【XX转运中心】,准备发往下一站'
|
||||
mailNo: '',
|
||||
txLogisticId: '',
|
||||
infoContent: 'SEND',
|
||||
remark: '快件已到达【XX分拨中心】,准备发往下一站',
|
||||
acceptTime: '',
|
||||
carrier: '圆通速递'
|
||||
})
|
||||
|
||||
const statusOptions = [
|
||||
{ label: '在途中 (IN_TRANSIT)', value: 'IN_TRANSIT' },
|
||||
{ label: '派送中 (OUT_FOR_DELIVERY)', value: 'OUT_FOR_DELIVERY' },
|
||||
{ label: '已签收 (DELIVERED)', value: 'DELIVERED' },
|
||||
{ label: '异常 (EXCEPTION)', value: 'EXCEPTION' }
|
||||
{ label: '揽收 (GOT)', value: 'GOT' },
|
||||
{ label: '运输中 (SEND)', value: 'SEND' },
|
||||
{ label: '派送中 (SENT)', value: 'SENT' },
|
||||
{ label: '已签收 (SIGNED)', value: 'SIGNED' },
|
||||
{ label: '异常 (FAILED)', value: 'FAILED' }
|
||||
]
|
||||
|
||||
const currentStatusLabel = computed(() => {
|
||||
const opt = statusOptions.find(o => o.value === form.status_code)
|
||||
return opt ? opt.label : '请选择'
|
||||
const currentStatusLabel = computed((): string => {
|
||||
const opt = statusOptions.find((o: UTSJSONObject): boolean => o['value'] === form.infoContent)
|
||||
return (opt != null) ? opt['label'] as string : '请选择'
|
||||
})
|
||||
|
||||
const jsonString = computed(() => {
|
||||
const jsonString = computed((): string => {
|
||||
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
|
||||
form.mailNo = order.tracking_no
|
||||
form.txLogisticId = order.order_no
|
||||
form.carrier = order.carrier + '速递'
|
||||
|
||||
// 根据订单当前状态智能预设
|
||||
if (order.status === 'SHIPPED') {
|
||||
form.status_code = 'IN_TRANSIT'
|
||||
form.event_text = '快件已揽收,正发往城市中心'
|
||||
form.infoContent = 'SEND'
|
||||
form.remark = '快件已到达北京分拨中心'
|
||||
} else if (order.status === 'IN_TRANSIT') {
|
||||
form.status_code = 'OUT_FOR_DELIVERY'
|
||||
form.event_text = '派送员王师傅(13700008888)正在派件'
|
||||
form.infoContent = 'SENT'
|
||||
form.remark = '派送员王师傅(13700008888)正在派件'
|
||||
}
|
||||
}
|
||||
|
||||
function onStatusChange(e: UniPickerChangeEvent) {
|
||||
const idx = e.detail.value as number
|
||||
form.status_code = statusOptions[idx].value as string
|
||||
form.infoContent = statusOptions[idx].value
|
||||
}
|
||||
|
||||
function sendWebhook() {
|
||||
if (!form.tracking_no) {
|
||||
if (!form.mailNo) {
|
||||
uni.showToast({ title: '请先填写运单号', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
// 获取当前时间戳作为圆通要求的 acceptTime
|
||||
const now = new Date()
|
||||
const Y = now.getFullYear()
|
||||
const M = (now.getMonth() + 1).toString().padStart(2, '0')
|
||||
const D = now.getDate().toString().padStart(2, '0')
|
||||
const h = now.getHours().toString().padStart(2, '0')
|
||||
const m = now.getMinutes().toString().padStart(2, '0')
|
||||
const s = now.getSeconds().toString().padStart(2, '0')
|
||||
form.acceptTime = `${Y}-${M}-${D} ${h}:${m}:${s}`
|
||||
|
||||
// 执行模拟推送 (转换为普通对象以兼容 UTS)
|
||||
const payload = {
|
||||
tracking_no: form.tracking_no,
|
||||
carrier: form.carrier,
|
||||
status_code: form.status_code,
|
||||
event_text: form.event_text
|
||||
mailNo: form.mailNo,
|
||||
txLogisticId: form.txLogisticId,
|
||||
infoContent: form.infoContent,
|
||||
remark: form.remark,
|
||||
acceptTime: form.acceptTime,
|
||||
carrier: form.carrier
|
||||
} as UTSJSONObject
|
||||
|
||||
const success = mockService.pushWebhookData(payload)
|
||||
|
||||
@@ -135,7 +135,8 @@
|
||||
},
|
||||
getStatusText(status: string): string {
|
||||
const maps = {
|
||||
'SHIPPED': '运输中',
|
||||
'SHIPPED': '已发货',
|
||||
'IN_TRANSIT': '运输中',
|
||||
'DELIVERED': '已签收',
|
||||
'OUT_FOR_DELIVERY': '派送中',
|
||||
'PENDING': '待揽收',
|
||||
|
||||
@@ -71,7 +71,8 @@
|
||||
},
|
||||
getStatusText(status: string): string {
|
||||
const maps = {
|
||||
'SHIPPED': '运输中',
|
||||
'SHIPPED': '已发货',
|
||||
'IN_TRANSIT': '运输中',
|
||||
'DELIVERED': '已签收',
|
||||
'OUT_FOR_DELIVERY': '派送中',
|
||||
'PENDING': '待揽收',
|
||||
|
||||
@@ -113,7 +113,14 @@
|
||||
this.statusHistory = mockService.getMockTracking(this.orderNo)
|
||||
},
|
||||
getStatusText(status: string) : string {
|
||||
const maps = { 'PENDING': '待发货', 'SHIPPED': '待签收', 'DELIVERED': '已签收', 'EXCEPTION': '异常' }
|
||||
const maps = {
|
||||
'PENDING': '待发货',
|
||||
'SHIPPED': '已发货',
|
||||
'IN_TRANSIT': '运输中',
|
||||
'DELIVERED': '已签收',
|
||||
'OUT_FOR_DELIVERY': '派送中',
|
||||
'EXCEPTION': '异常'
|
||||
}
|
||||
return (maps[status] != null) ? maps[status] : status
|
||||
},
|
||||
async refreshLogistics() {
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<view class="modal-body">
|
||||
<view class="form-item">
|
||||
<text class="label">选择承运商</text>
|
||||
<picker :range="carriers" @change="onCarrierChange">
|
||||
<picker :range="carriers" range-key="label" @change="onCarrierChange">
|
||||
<view class="picker-val">{{ currentCarrier || '请选择' }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
@@ -83,8 +83,14 @@
|
||||
orders: [] as MockOrder[],
|
||||
showShipModal: false,
|
||||
selectedOrder: null as MockOrder | null,
|
||||
carriers: ['YUNDA', 'YTO', 'ZTO', 'STO', 'SF'],
|
||||
currentCarrier: '',
|
||||
carriers: [
|
||||
{ label: '韵达快递', value: '韵达' },
|
||||
{ label: '圆通速递', value: '圆通' },
|
||||
{ label: '中通快递', value: '中通' },
|
||||
{ label: '申通快递', value: '申通' },
|
||||
{ label: '顺丰速运', value: '顺丰' }
|
||||
],
|
||||
currentCarrier: '韵达',
|
||||
trackingNo: ''
|
||||
}
|
||||
},
|
||||
@@ -117,6 +123,7 @@
|
||||
const maps = {
|
||||
'PENDING': '待发货',
|
||||
'SHIPPED': '已发货',
|
||||
'IN_TRANSIT': '运输中',
|
||||
'DELIVERED': '已签收',
|
||||
'OUT_FOR_DELIVERY': '派送中',
|
||||
'EXCEPTION': '包裹异常'
|
||||
@@ -131,7 +138,7 @@
|
||||
},
|
||||
onCarrierChange(e: any) {
|
||||
const index = e.detail.value as number
|
||||
this.currentCarrier = this.carriers[index]
|
||||
this.currentCarrier = this.carriers[index].value
|
||||
},
|
||||
async confirmShip() {
|
||||
if (!this.trackingNo) {
|
||||
|
||||
@@ -436,14 +436,24 @@ class MockService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心功能:模拟第三方回调接口
|
||||
* 模拟外部物流平台向本系统发送轨迹更新 API
|
||||
* 核心功能:模拟第三方回调接口 (适配圆通推送协议)
|
||||
* 对应字段: txLogisticId(订单号), mailNo(票号), infoContent(状态), remark(描述)
|
||||
*/
|
||||
pushWebhookData(payload: UTSJSONObject): boolean {
|
||||
const tracking_no = payload['tracking_no'] as string
|
||||
const status_code = payload['status_code'] as string
|
||||
const event_text = payload['event_text'] as string
|
||||
const carrier = payload['carrier'] as string || '顺丰'
|
||||
// 兼容圆通协议字段
|
||||
const tracking_no = (payload['mailNo'] != null) ? payload['mailNo'] as string : (payload['tracking_no'] as string)
|
||||
const yto_status = (payload['infoContent'] != null) ? payload['infoContent'] as string : (payload['status_code'] as string)
|
||||
const event_text = (payload['remark'] != null) ? payload['remark'] as string : (payload['event_text'] as string)
|
||||
const order_id = payload['txLogisticId'] as string || ''
|
||||
const carrier = payload['carrier'] as string || '圆通速递'
|
||||
|
||||
// 状态映射:圆通状态 -> 本系统状态
|
||||
let status_code = 'IN_TRANSIT'
|
||||
if (yto_status === 'GOT' || yto_status === 'SEND') status_code = 'IN_TRANSIT'
|
||||
else if (yto_status === 'SENT') status_code = 'OUT_FOR_DELIVERY'
|
||||
else if (yto_status === 'SIGNED') status_code = 'DELIVERED'
|
||||
else if (yto_status === 'FAILED') status_code = 'EXCEPTION'
|
||||
else status_code = yto_status
|
||||
|
||||
// 1. 记录原始日志
|
||||
const now = new Date()
|
||||
@@ -451,7 +461,7 @@ class MockService {
|
||||
time: this.formatDate(now).split(' ')[1],
|
||||
carrier: carrier,
|
||||
tracking_no: tracking_no,
|
||||
event_code: status_code,
|
||||
event_code: yto_status, // 保留圆通原始代码
|
||||
success: true,
|
||||
result_text: '接收成功',
|
||||
payload: payload
|
||||
@@ -459,16 +469,16 @@ class MockService {
|
||||
this.webhookLogs.unshift(log)
|
||||
|
||||
// 2. 更新系统内部轨迹
|
||||
const order = this.orders.find(o => o.tracking_no === tracking_no)
|
||||
const order = this.orders.find(o => o.tracking_no === tracking_no || o.order_no === order_id)
|
||||
if (order != null) {
|
||||
if (!this.trackingHistory.has(order.order_no)) {
|
||||
this.trackingHistory.set(order.order_no, [])
|
||||
}
|
||||
const history = this.trackingHistory.get(order.order_no)!
|
||||
history.unshift({
|
||||
event_id: 'wb_' + Date.now(),
|
||||
event_time: this.formatDate(now),
|
||||
event_code: status_code,
|
||||
event_id: 'yto_' + Date.now(),
|
||||
event_time: payload['acceptTime'] as string || this.formatDate(now),
|
||||
event_code: yto_status,
|
||||
event_text: event_text,
|
||||
status_code: status_code,
|
||||
evidence_urls: []
|
||||
@@ -479,7 +489,7 @@ class MockService {
|
||||
}
|
||||
|
||||
log.success = false
|
||||
log.result_text = '未找到对应的运单号'
|
||||
log.result_text = '未找到对应的运单或订单号'
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">当前状态:</text>
|
||||
<text class="value">{{ waybillInfo.status }}</text>
|
||||
<text class="value">{{ getStatusText(waybillInfo.status) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -44,8 +44,8 @@
|
||||
<view class="event-main-col">
|
||||
<text class="event-text">{{ event.event_text }}</text>
|
||||
<view class="event-meta">
|
||||
<text class="meta-tag blue">CODE: {{ event.event_code }}</text>
|
||||
<text class="meta-tag orange">MAP: {{ event.status_code }}</text>
|
||||
<text class="meta-tag blue">代码: {{ event.event_code }}</text>
|
||||
<text class="meta-tag orange">映射状态: {{ getStatusMapping(event.status_code) }}</text>
|
||||
</view>
|
||||
<view class="raw-box" v-if="showRaw[index]">
|
||||
<text class="raw-text">{{ JSON.stringify(event.raw_payload, null, 2) }}</text>
|
||||
@@ -116,6 +116,28 @@
|
||||
const current = this.showRaw[index]
|
||||
this.showRaw[index] = !current
|
||||
},
|
||||
getStatusText(status: string) : string {
|
||||
const maps = {
|
||||
'PENDING': '待发货',
|
||||
'SHIPPED': '已发货',
|
||||
'IN_TRANSIT': '运输中',
|
||||
'DELIVERED': '已签收',
|
||||
'OUT_FOR_DELIVERY': '派送中',
|
||||
'EXCEPTION': '异常'
|
||||
}
|
||||
return (maps[status] != null) ? maps[status] : status
|
||||
},
|
||||
getStatusMapping(code: string) : string {
|
||||
const maps = {
|
||||
'SHIPPED': '已揽收',
|
||||
'IN_TRANSIT': '运输中',
|
||||
'ARRIVED_HUB': '到达分拨中心',
|
||||
'OUT_FOR_DELIVERY': '正在派送',
|
||||
'DELIVERED': '已签收',
|
||||
'EXCEPTION': '包裹异常'
|
||||
}
|
||||
return (maps[code] != null) ? maps[code] : code
|
||||
},
|
||||
runScenario(type: string) {
|
||||
if (this.waybillInfo == null) return
|
||||
uni.showModal({
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
</view>
|
||||
<view class="log-row">
|
||||
<text class="log-label">事件:</text>
|
||||
<text class="log-value">{{ log.event_code }}</text>
|
||||
<text class="log-value">{{ getEventText(log.event_code) }}</text>
|
||||
</view>
|
||||
<view class="log-row">
|
||||
<text class="log-label">状态:</text>
|
||||
@@ -84,6 +84,18 @@
|
||||
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(() => {
|
||||
|
||||
Reference in New Issue
Block a user