<template>
|
<view class="page">
|
<view class="navigation-bar">
|
<view class="back-button" @tap.stop="goBack"><image class="back-icon" src="/static/icons/lucide/back-left.svg" mode="aspectFit"></image></view>
|
<text class="navigation-title">手输核销码</text>
|
</view>
|
<view class="content">
|
<text class="hint">请输入顾客屏幕上的 6 位数字核销码</text>
|
<view class="input-shell" :class="errorText.length > 0 ? 'field-invalid' : ''">
|
<input class="code-input" type="number" maxlength="6" :value="code" placeholder="6 位数字"
|
placeholder-class="code-placeholder" @input="onCodeInput" @confirm="submit" />
|
</view>
|
<text v-if="errorText.length > 0" class="field-error">{{errorText}}</text>
|
<text class="tip">连续输错会短暂锁定,锁定期间请改用扫码核销。</text>
|
</view>
|
<view class="bottom-bar">
|
<view class="submit-button" :class="submitting || !codeReady() ? 'submit-disabled' : ''" hover-class="submit-active" @tap="submit">
|
<text>{{submitting ? '核验中...' : '核验并核销'}}</text>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<script setup lang="uts">
|
import { scanVerificationCode, VerificationScanResult } from '../../services/verification.uts'
|
|
const code = ref('')
|
const errorText = ref('')
|
const submitting = ref(false)
|
|
const goBack = () => uni.navigateBack()
|
const codeReady = () : boolean => code.value.length == 6
|
|
// 只留数字:数字键盘上仍然可能粘进空格或其它字符。
|
const onCodeInput = (event: any) : void => {
|
const raw = event != null && event.detail != null && event.detail.value != null ? '' + event.detail.value : ''
|
code.value = raw.replace(/[^0-9]/g, '').substring(0, 6)
|
if (errorText.value.length > 0) errorText.value = ''
|
}
|
|
const submit = () : void => {
|
if (submitting.value || !codeReady()) return
|
submitting.value = true
|
errorText.value = ''
|
scanVerificationCode(code.value, (result: VerificationScanResult, _traceId: string) => {
|
submitting.value = false
|
if (!result.canVerify) {
|
errorText.value = result.message.length > 0 ? result.message : '核销码无效,请核对后重新输入'
|
return
|
}
|
// 确认核销放在承接页上(与扫码同一条动线):那里会再把金额、权益与顾客信息摆一次让商户确认。
|
// 数字码这条路服务端不返回订单号,所以带 numeric=1 让确认页走按扫码尝试确认的接口。
|
uni.navigateTo({
|
url: '/pages/verification-confirm/verification-confirm?numeric=1'
|
+ '&verificationId=' + encodeURIComponent(result.verificationId)
|
+ '&credentialType=' + encodeURIComponent(result.credentialType)
|
+ '&customerName=' + encodeURIComponent(result.customerName)
|
+ '&customerMobile=' + encodeURIComponent(result.customerMobile)
|
+ '&cardLevel=' + encodeURIComponent(result.cardLevel)
|
})
|
}, (error: any) => {
|
submitting.value = false
|
errorText.value = error != null && error.message != null ? '' + error.message : '核验失败,请重试'
|
})
|
}
|
|
onLoad(() => {})
|
</script>
|
|
<style>
|
page { background-color: #F7F7F7; }
|
.page { display: flex; width: 100%; height: 100vh; flex-direction: column; background-color: #F7F7F7; }
|
.navigation-bar { display: flex; height: 174rpx; flex: none; position: relative; align-items: center; justify-content: center; }
|
.back-button { display: flex; width: 72rpx; height: 72rpx; justify-content: center; align-items: center; position: absolute; left: 28rpx; bottom: 22rpx; }
|
.back-icon { width: 40rpx; height: 40rpx; }
|
.navigation-title { margin-top: 60rpx; color: #181A1E; font-size: 36rpx; font-weight: 700; }
|
.content { display: flex; padding: 24rpx 44rpx 0; flex-direction: column; }
|
.hint { color: #4A5261; font-size: 28rpx; line-height: 42rpx; }
|
.input-shell { display: flex; height: 104rpx; margin-top: 26rpx; padding: 0 30rpx; border-width: 1rpx; border-style: solid; border-color: #E0E5EC; border-radius: 30rpx; background-color: #FFFEFD; box-sizing: border-box; align-items: center; }
|
.field-invalid { border-color: #FF633A; }
|
.code-input { width: 100%; height: 100%; color: #1F2530; font-size: 40rpx; font-weight: 700; letter-spacing: 12rpx; }
|
.code-placeholder { color: #B4BAC4; font-size: 30rpx; font-weight: 400; letter-spacing: 0; }
|
.field-error { margin-top: 16rpx; color: #FF633A; font-size: 25rpx; line-height: 36rpx; }
|
.tip { margin-top: 18rpx; color: #97A0AE; font-size: 23rpx; line-height: 34rpx; }
|
/* 必须显式写 flex-direction: row:uvue 里 flex 容器默认是 column,那样按钮的 flex: 1 会作用在高度上
|
(flex-basis 0 压过 height),按钮被压成一行字那么高,只剩一条细橙条。 */
|
.bottom-bar { display: flex; flex-direction: row; padding: 24rpx 44rpx; padding-bottom: calc(24rpx + env(safe-area-inset-bottom)); margin-top: auto; }
|
.submit-button { display: flex; flex: 1; height: 92rpx; justify-content: center; align-items: center; border-radius: 46rpx; background-image: linear-gradient(90deg, #FF7625 0%, #FF962F 100%); }
|
.submit-button text { color: #FFFFFF; font-size: 29rpx; font-weight: 700; }
|
.submit-disabled { opacity: .55; }
|
.submit-active { opacity: .82; }
|
</style>
|