shinnosuke
2026-08-06 c7511f1e1a70b8e53775d462bf4a05a2d3bdaf32
fix(merchant): 扫码后进入二次确认页 (bug #24135)
1个文件已添加
2个文件已修改
106 ■■■■■ 已修改文件
rencaika_merchant/pages.json 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rencaika_merchant/pages/scan/scan.uvue 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rencaika_merchant/pages/verification-confirm/verification-confirm.uvue 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rencaika_merchant/pages.json
@@ -156,6 +156,14 @@
            }
        },
        {
            "path": "pages/verification-confirm/verification-confirm",
            "style": {
                "navigationStyle": "custom",
                "backgroundColor": "#F6F5F2",
                "disableScroll": true
            }
        },
        {
            "path": "pages/consume-input/consume-input",
            "style": {
                "navigationStyle": "custom",
rencaika_merchant/pages/scan/scan.uvue
@@ -51,6 +51,7 @@
    let lastScanResult = ''
    let currentVerificationId = ''
    let openedManualConsumption = false
    let openedConfirmation = false
    let cancelVerificationRequest: (() => void) | null = null
    const cancelPendingRequest = () => {
@@ -94,16 +95,15 @@
                uni.navigateTo({ url: '/pages/consume-input/consume-input?verificationId=' + encodeURIComponent(result.verificationId) })
                return
            }
            scanState.value = 'success'
            statusTitle.value = '待确认核销'
            statusMessage.value = result.message
            credentialLabel.value = credentialTypeLabel(result.credentialType)
            customerName.value = result.customerName.length > 0 ? result.customerName : '持卡人'
            customerMobile.value = result.customerMobile
            cardLevel.value = result.cardLevel
            orderNo.value = result.orderNo
            currentVerificationId = result.verificationId
            verificationConfirmed.value = false
            openedConfirmation = true
            uni.navigateTo({
                url: '/pages/verification-confirm/verification-confirm?verificationId=' + encodeURIComponent(result.verificationId)
                    + '&credentialType=' + encodeURIComponent(result.credentialType)
                    + '&customerName=' + encodeURIComponent(result.customerName)
                    + '&customerMobile=' + encodeURIComponent(result.customerMobile)
                    + '&cardLevel=' + encodeURIComponent(result.cardLevel)
                    + '&orderNo=' + encodeURIComponent(result.orderNo)
            })
        }, showVerificationError)
    }
@@ -214,8 +214,9 @@
    })
    onShow(() => {
        if (!openedManualConsumption) return
        if (!openedManualConsumption && !openedConfirmation) return
        openedManualConsumption = false
        openedConfirmation = false
        resetScanning()
    })
</script>
rencaika_merchant/pages/verification-confirm/verification-confirm.uvue
New file
@@ -0,0 +1,75 @@
<template>
    <view class="page">
        <view class="navigation-bar"><view class="back-button" @tap="goBack"><image class="back-icon" src="/static/icons/lucide/chevron-right.svg" mode="aspectFit"></image></view><text class="navigation-title">确认核销</text></view>
        <view class="content">
            <view class="notice-card"><text class="notice-title">请确认核销信息</text><text class="notice-desc">确认后将完成本次权益核销,请仔细核对。</text></view>
            <view class="credential-card"><view class="credential-head"><text class="credential-title">{{credentialLabel}}</text><text class="card-level">{{cardLevel}}</text></view><text class="customer-name">{{customerName}}</text><text class="customer-mobile">{{displayMobile(customerMobile)}}</text><view v-if="orderNo.length > 0" class="info-row"><text>订单号</text><text>{{orderNo}}</text></view></view>
        </view>
        <view class="bottom-bar"><view class="confirm-button" :class="submitting ? 'button-disabled' : ''" @tap="confirm"><text>{{submitting ? '核销中…' : '确认核销'}}</text></view></view>
    </view>
</template>
<script setup lang="uts">
    import { confirmVerificationCode } from '../../services/verification.uts'
    const verificationId = ref('')
    const credentialType = ref('')
    const customerName = ref('持卡人')
    const customerMobile = ref('')
    const cardLevel = ref('人才卡')
    const orderNo = ref('')
    const submitting = ref(false)
    const credentialLabel = computed((): string => {
        if (credentialType.value == 'ORDER_CODE') return '订单核销码'
        if (credentialType.value == 'FREE_STAY_CODE') return '免费入住核销码'
        return '人才码'
    })
    const displayMobile = (mobile: string): string => mobile.length < 7 ? mobile : mobile.substring(0, 3) + '***' + mobile.substring(mobile.length - 4)
    const goBack = () => uni.navigateBack()
    const textOption = (options: any, name: string, fallback: string): string => options != null && options[name] != null && ('' + options[name]).length > 0 ? decodeURIComponent('' + options[name]) : fallback
    const confirm = () => {
        if (submitting.value || verificationId.value.length == 0) return
        submitting.value = true
        confirmVerificationCode(verificationId.value, 'merchant-verify-' + verificationId.value + '-' + Date.now(), (result: any, _traceId: string) => {
            submitting.value = false
            uni.showToast({ title: result.message != null ? result.message : '核销成功', icon: 'success' })
            setTimeout(() => uni.navigateBack({ delta: 2 }), 1000)
        }, (error: any) => {
            submitting.value = false
            uni.showToast({ title: error.message != null ? error.message : '核销失败,请重试', icon: 'none' })
        })
    }
    onLoad((options: any) => {
        verificationId.value = textOption(options, 'verificationId', '')
        credentialType.value = textOption(options, 'credentialType', '')
        customerName.value = textOption(options, 'customerName', '持卡人')
        customerMobile.value = textOption(options, 'customerMobile', '')
        cardLevel.value = textOption(options, 'cardLevel', '人才卡')
        orderNo.value = textOption(options, 'orderNo', '')
    })
</script>
<style>
    page { background-color: #F6F5F2; }
    .page { display: flex; width: 100%; height: 100vh; flex-direction: column; background-color: #F6F5F2; }
    .navigation-bar { display: flex; height: 176rpx; flex: none; justify-content: center; align-items: flex-end; padding-bottom: 26rpx; box-sizing: border-box; background-color: #FFFFFF; position: relative; }
    .navigation-title { color: #293344; font-size: 34rpx; line-height: 48rpx; font-weight: 700; }
    .back-button { display: flex; width: 72rpx; height: 72rpx; justify-content: center; align-items: center; position: absolute; left: 24rpx; bottom: 14rpx; }
    .back-icon { width: 38rpx; height: 38rpx; transform: rotate(180deg); }
    .content { flex: 1; padding: 34rpx 32rpx; box-sizing: border-box; }
    .notice-card, .credential-card { border-radius: 28rpx; background-color: #FFFFFF; box-shadow: 0 12rpx 28rpx rgba(62, 69, 80, 0.06); box-sizing: border-box; }
    .notice-card { padding: 30rpx; }
    .notice-title { display: block; color: #263043; font-size: 32rpx; line-height: 45rpx; font-weight: 700; }
    .notice-desc { display: block; margin-top: 12rpx; color: #87909E; font-size: 25rpx; line-height: 36rpx; }
    .credential-card { padding: 32rpx; margin-top: 26rpx; border-width: 1rpx; border-style: solid; border-color: #E4BE59; background-image: linear-gradient(135deg, #C99D32 0%, #F7E69D 55%, #E5BD4E 100%); }
    .credential-head { display: flex; flex-direction: row; justify-content: space-between; align-items: center; }
    .credential-title, .customer-name, .customer-mobile { color: #FFFFFF; }
    .credential-title { font-size: 27rpx; line-height: 38rpx; font-weight: 600; }
    .card-level { padding: 8rpx 18rpx; border-radius: 22rpx; color: #FFFFFF; font-size: 21rpx; line-height: 30rpx; background-color: rgba(149, 104, 22, 0.46); }
    .customer-name { display: block; margin-top: 34rpx; font-size: 40rpx; line-height: 56rpx; font-weight: 700; }
    .customer-mobile { display: block; margin-top: 11rpx; font-size: 28rpx; line-height: 40rpx; }
    .info-row { display: flex; padding-top: 25rpx; margin-top: 25rpx; border-top-width: 1rpx; border-top-style: solid; border-top-color: rgba(255, 255, 255, 0.35); flex-direction: row; justify-content: space-between; color: #FFFFFF; font-size: 24rpx; line-height: 34rpx; }
    .bottom-bar { display: flex; height: 148rpx; padding: 20rpx 84rpx 30rpx; flex: none; background-color: #FFFFFF; box-sizing: border-box; }
    .confirm-button { display: flex; flex: 1; height: 92rpx; justify-content: center; align-items: center; border-radius: 46rpx; color: #FFFFFF; font-size: 29rpx; line-height: 41rpx; font-weight: 700; background-image: linear-gradient(90deg, #FF7428 0%, #FF9630 100%); }
    .button-disabled { opacity: 0.62; }
</style>