feat(web-admin): add public pound QR page by inventory id
Drivers can open a standalone link that renders the shared weighbridge QR card. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
d7dec04cb3
commit
5b4c1bc991
3 files changed
+162
No files matched your search
@@ -19,8 +19,23 @@ export interface PublicInventoryPage {
|
||||
voided: boolean
|
||||
}
|
||||
|
||||
export interface PublicPoundQr {
|
||||
id: string
|
||||
date?: string
|
||||
businessType: string
|
||||
vehicleNo: string
|
||||
partnerCompany: string
|
||||
product: string
|
||||
specification?: string
|
||||
quantity: number
|
||||
quantityUnit?: string
|
||||
remarks?: string
|
||||
}
|
||||
|
||||
export const publicInventoryApi = {
|
||||
getPage: (token: string) => publicPlGet<PublicInventoryPage>(`/public/db/inventory/${token}`),
|
||||
getPoundQr: (inventoryId: string) =>
|
||||
publicPlGet<PublicPoundQr>(`/public/db/inventory/${inventoryId}/pound-qr`),
|
||||
saveFeedback: (
|
||||
token: string,
|
||||
data: { siteFeedbackRemark?: string; siteFeedbackImages?: string[] }
|
||||
|
||||
@@ -111,6 +111,12 @@ export const staticRoutes: AppRouteRecordRaw[] = [
|
||||
component: () => import('@views/public/pl/outbound/index.vue'),
|
||||
meta: { title: '出库单', isHideTab: true, isPublicMobile: true }
|
||||
},
|
||||
{
|
||||
path: '/public/pl/pound-qrcode/:inventoryId',
|
||||
name: 'PublicPlPoundQrcode',
|
||||
component: () => import('@views/public/pl/pound-qrcode/index.vue'),
|
||||
meta: { title: '磅单二维码', isHideTab: true, isPublicMobile: true }
|
||||
},
|
||||
{
|
||||
path: '/public/db/inventory/:token',
|
||||
name: 'PublicDbInventorySite',
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<PublicMobileShell>
|
||||
<div class="public-pl-pound-qrcode-page">
|
||||
<van-loading v-if="loading" vertical class="page-loading">加载中...</van-loading>
|
||||
<van-empty v-else-if="errorMessage" :description="errorMessage" />
|
||||
<div v-else-if="row && qrObjectUrl" class="qr-stage">
|
||||
<div class="qr-dialog-title">{{ pageTitle }}</div>
|
||||
<PoundSlipQrcodeView
|
||||
:vehicle-no="row.vehicleNo"
|
||||
:partner-company="row.partnerCompany"
|
||||
:product-line="productLine"
|
||||
:remarks="row.remarks || ''"
|
||||
:date-text="row.date || ''"
|
||||
:business-type="row.businessType"
|
||||
:inventory-id="row.id"
|
||||
:qr-object-url="qrObjectUrl"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</PublicMobileShell>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { publicInventoryApi, type PublicPoundQr } from '@/api/db/public-inventory'
|
||||
import PoundSlipQrcodeView from '@/components/business/db/PoundSlipQrcodeView.vue'
|
||||
import PublicMobileShell from '@/layouts/PublicMobileShell.vue'
|
||||
|
||||
import 'vant/es/toast/style'
|
||||
import 'vant/es/empty/style'
|
||||
import '@/styles/public-mobile-vant.scss'
|
||||
|
||||
const route = useRoute()
|
||||
const inventoryId = computed(() => String(route.params.inventoryId || ''))
|
||||
|
||||
const loading = ref(true)
|
||||
const errorMessage = ref('')
|
||||
const row = ref<PublicPoundQr | null>(null)
|
||||
const qrObjectUrl = ref('')
|
||||
|
||||
const pageTitle = computed(() => {
|
||||
if (!row.value) return '磅单二维码'
|
||||
return row.value.businessType === '出库' ? '出库磅单二维码' : '入库磅单二维码'
|
||||
})
|
||||
|
||||
const quantityUnitLabel = computed(() => (row.value?.quantityUnit || '').trim() || '吨')
|
||||
|
||||
function formatQrcodeProductLabel(item: PublicPoundQr) {
|
||||
const product = (item.product || '').trim()
|
||||
const specification = (item.specification || '').trim()
|
||||
if (!specification) return product
|
||||
if (product.endsWith(specification)) {
|
||||
const base = product.slice(0, -specification.length).trimEnd()
|
||||
return base ? `${base} ${specification}` : specification
|
||||
}
|
||||
return `${product} ${specification}`
|
||||
}
|
||||
|
||||
const productLine = computed(() => {
|
||||
if (!row.value) return ''
|
||||
return `${formatQrcodeProductLabel(row.value)}(${row.value.quantity} ${quantityUnitLabel.value})`
|
||||
})
|
||||
|
||||
function getQrImageUrl(id: string) {
|
||||
return `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(id)}`
|
||||
}
|
||||
|
||||
function revokeQrObjectUrl() {
|
||||
if (qrObjectUrl.value) {
|
||||
URL.revokeObjectURL(qrObjectUrl.value)
|
||||
qrObjectUrl.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
async function loadPage() {
|
||||
loading.value = true
|
||||
errorMessage.value = ''
|
||||
row.value = null
|
||||
revokeQrObjectUrl()
|
||||
const id = inventoryId.value
|
||||
if (!id) {
|
||||
errorMessage.value = '链接无效或单据不存在'
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
try {
|
||||
// publicPlGet 已解包 data;与其它公共页一致直接使用返回值
|
||||
const data = await publicInventoryApi.getPoundQr(id)
|
||||
row.value = data
|
||||
const fetchRes = await fetch(getQrImageUrl(data.id), { mode: 'cors' })
|
||||
if (!fetchRes.ok) throw new Error('二维码图片加载失败')
|
||||
const blob = await fetchRes.blob()
|
||||
qrObjectUrl.value = URL.createObjectURL(blob)
|
||||
} catch (e: any) {
|
||||
errorMessage.value = e?.message || '链接无效或单据不存在'
|
||||
row.value = null
|
||||
revokeQrObjectUrl()
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(loadPage)
|
||||
onBeforeUnmount(revokeQrObjectUrl)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.public-pl-pound-qrcode-page {
|
||||
min-height: 100vh;
|
||||
background: rgba(0, 0, 0, 0.92);
|
||||
}
|
||||
|
||||
.page-loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 48px 0;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.qr-stage {
|
||||
padding: 18px 14px 22px;
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.qr-dialog-title {
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
margin: 0 0 10px;
|
||||
padding: 2px 10px 0;
|
||||
}
|
||||
|
||||
:deep(.van-empty) {
|
||||
padding-top: 80px;
|
||||
}
|
||||
|
||||
:deep(.van-empty__description) {
|
||||
color: #94a3b8;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user