This commit is contained in:
Mrx
2026-05-28 15:22:34 +08:00
parent 6e5379080c
commit 0f0cdd67c2
7 changed files with 98 additions and 19 deletions

View File

@@ -18,8 +18,10 @@ const maskedName = computed(() => {
return name.length > 1 ? `${name[0]}${'*'.repeat(name.length - 1)}` : '*'
})
/** 上游天远返回 { result: { status } },少数场景为顶层 status */
const status = computed(() => {
const s = Number(p.value.status)
const raw = p.value
const s = Number(raw?.status ?? raw?.result?.status)
if ([0, -1, -2, -4].includes(s))
return s
return null

View File

@@ -19,7 +19,7 @@ export const VEHICLE_API_TITLES = {
QCXG4I1Z: '车辆过户详版查询',
QCXGGB2Q: '车辆二要素核验 V1',
QCXGP00W: '车辆出险详版查询',
QCXGYTS2: '车辆二要素核验 V2',
QCXGYTS2: '人车核验(详版)',
QCXGGJ3A: '车辆 VIN 码查询号牌简版',
QCXGJJ2A: '车辆 VIN 码查车辆信息详版',
QCXG5F3A: '名下车辆车牌查询 B',

View File

@@ -59,9 +59,7 @@
"navigationBarTitleText": "我的",
"navigationStyle": "default",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"enableShareAppMessage": true,
"enableShareTimeline": true
"navigationBarTextStyle": "black"
}
},
{

View File

@@ -11,9 +11,6 @@ definePage({
navigationStyle: 'default',
navigationBarBackgroundColor: '#ffffff',
navigationBarTextStyle: 'black',
// 微信小程序:允许使用 open-type="share" 与右上角转发
enableShareAppMessage: true,
enableShareTimeline: true,
},
})

View File

@@ -1,5 +1,5 @@
<script setup>
import { onLoad } from '@dcloudio/uni-app'
import { onLoad, onUnload } from '@dcloudio/uni-app'
import { ref } from 'vue'
import { getQueryDetailByOrderId, getQueryDetailByOrderNo } from '@/api'
import VehicleReportShell from '@/components/report/VehicleReportShell.vue'
@@ -18,45 +18,87 @@ definePage({
const orderNo = ref('')
const orderId = ref('')
const loading = ref(true)
const pending = ref(false)
const errText = ref('')
const productName = ref('')
const queryParams = ref({})
const rows = ref(normalizeVehicleQueryData([]))
let pollTimer = null
onLoad((options) => {
orderNo.value = options?.orderNo || ''
orderId.value = options?.orderId || ''
void load()
})
async function load() {
onUnload(() => {
stopPoll()
})
function stopPoll() {
if (pollTimer) {
clearInterval(pollTimer)
pollTimer = null
}
}
function startPoll() {
if (pollTimer)
return
pollTimer = setInterval(() => {
void load({ silent: true })
}, 2000)
}
async function load(opts = {}) {
const silent = opts.silent === true
if (!orderNo.value && !orderId.value) {
loading.value = false
pending.value = false
errText.value = '缺少订单信息'
return
}
if (!silent) {
loading.value = true
errText.value = ''
pending.value = false
}
try {
const res = orderId.value
? await getQueryDetailByOrderId(orderId.value)
: await getQueryDetailByOrderNo(orderNo.value)
? await getQueryDetailByOrderId(orderId.value, { skipLoading: silent })
: await getQueryDetailByOrderNo(orderNo.value, { skipLoading: silent })
const parsed = parseEncryptedQueryReport(res)
productName.value = parsed.productName || '查询报告'
if (parsed.pending) {
pending.value = true
errText.value = parsed.msg || '报告生成中,请稍候…'
rows.value = normalizeVehicleQueryData([])
startPoll()
return
}
stopPoll()
pending.value = false
if (parsed.ok) {
queryParams.value = parsed.queryParams
rows.value = parsed.rows
if (!rows.value.length)
errText.value = '暂无报告模块数据'
errText.value = rows.value.length ? '' : '暂无报告模块数据'
}
else {
rows.value = normalizeVehicleQueryData([])
errText.value = parsed.msg || '加载失败'
}
}
catch {
stopPoll()
pending.value = false
errText.value = '网络异常或未登录'
}
finally {
if (!silent)
loading.value = false
}
}
@@ -64,9 +106,13 @@ async function load() {
<template>
<view class="page-root">
<view v-if="loading" class="state">
<view v-if="loading && !pending" class="state">
加载中
</view>
<view v-else-if="pending" class="state pending">
<view class="spinner" />
<text>{{ errText || '报告生成中,请稍候…' }}</text>
</view>
<view v-else-if="errText && !rows.length" class="state">
{{ errText }}
</view>
@@ -95,6 +141,28 @@ async function load() {
color: #86909c;
}
.state.pending {
display: flex;
flex-direction: column;
align-items: center;
gap: 24rpx;
}
.spinner {
width: 64rpx;
height: 64rpx;
border: 6rpx solid #e5e6eb;
border-top-color: #1768ff;
border-radius: 50%;
animation: spin 0.9s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.content {
padding: 24rpx 24rpx 48rpx;
box-sizing: border-box;

View File

@@ -53,7 +53,8 @@ const maskedName = computed(() => {
// status: 0 一致, -1 不一致, -2 非法姓名, -4 无记录
const status = computed(() => {
const s = props.data?.status;
const raw = props.data || {};
const s = Number(raw.status ?? raw.result?.status);
if (s === 0 || s === -1 || s === -2 || s === -4) return s;
return null;
});

View File

@@ -5,6 +5,9 @@ import { normalizeVehicleQueryData } from './vehicleReportNormalize'
* 解析 /query/example、/query/orderNo 等接口返回体。
* 成功时 data 为 AES 加密字符串,需解密后取 query_data。
*/
/** 与 H5 Report.vue报告生成中轮询 */
const PENDING_API_CODES = new Set([200002, 100005])
export function parseEncryptedQueryReport(apiBody) {
if (!apiBody)
return { ok: false, msg: '无响应数据' }
@@ -12,6 +15,9 @@ export function parseEncryptedQueryReport(apiBody) {
if (apiBody.code === 200003)
return { ok: false, empty: true, msg: apiBody.msg || '暂无示例报告' }
if (PENDING_API_CODES.has(apiBody.code))
return { ok: false, pending: true, msg: apiBody.msg || '报告生成中,请稍候…' }
if (apiBody.code !== 200 || apiBody.data == null || apiBody.data === '')
return { ok: false, msg: apiBody.msg || '加载失败' }
@@ -29,6 +35,12 @@ export function parseEncryptedQueryReport(apiBody) {
if (!payload || typeof payload !== 'object')
return { ok: false, msg: '报告数据格式错误' }
const queryState = String(payload.query_state || '')
if (queryState === 'pending')
return { ok: false, pending: true, msg: '报告生成中,请稍候…' }
if (queryState === 'failed')
return { ok: false, failed: true, msg: '报告生成失败' }
const rows = normalizeVehicleQueryData(payload.query_data || [])
return {
ok: true,
@@ -36,5 +48,6 @@ export function parseEncryptedQueryReport(apiBody) {
queryParams: payload.query_params || {},
rows,
createTime: payload.create_time || null,
queryState,
}
}