feat: 券详情页接入实时核销码(/voucher/checkCode,60秒滚动刷新)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
571afb0673
commit
5d253c60a8
@@ -19,11 +19,11 @@
|
||||
<block v-else-if="status === 2">
|
||||
<view class="qrbox">
|
||||
<view class="qr-badge">有效</view>
|
||||
<!-- 石油返回图片URL时直接展示 -->
|
||||
<image v-if="isQrImage" class="qr-img" :src="voucher.voucherCode" mode="widthFix" />
|
||||
<!-- 返回码字符串时用 qrcodejs 渲染 -->
|
||||
<!-- 核销码为图片URL时直接展示 -->
|
||||
<image v-if="isQrImage" class="qr-img" :src="qrText" mode="widthFix" />
|
||||
<!-- 核销码为字符串时前端渲染二维码(每60秒向服务端换取新码) -->
|
||||
<view v-else id="petrol-qr" class="qr-canvas"></view>
|
||||
<view class="qr-tip">到店出示此二维码,收银员以“中石油汽油券”通道扫码核销</view>
|
||||
<view class="qr-tip">核销码每 60 秒自动刷新,请到店后出示给收银员扫码</view>
|
||||
</view>
|
||||
|
||||
<view class="card">
|
||||
@@ -93,8 +93,10 @@ export default {
|
||||
phone: '',
|
||||
voucher: {},
|
||||
status: null, // null=加载中;含义对齐后端 statusCode
|
||||
qrText: '', // xuchao: 实时核销码(60 秒滚动,来自 /voucher/checkCode)
|
||||
pollTimer: null,
|
||||
pollLeft: 3,
|
||||
checkTimer: null,
|
||||
voucherName: VOUCHER_NAME,
|
||||
voucherRule: VOUCHER_RULE,
|
||||
useRules: VOUCHER_USE_RULES,
|
||||
@@ -107,7 +109,7 @@ export default {
|
||||
return f ? (f / 100).toFixed(2) : ''
|
||||
},
|
||||
isQrImage() {
|
||||
return typeof this.voucher.voucherCode === 'string' && /^https?:\/\//i.test(this.voucher.voucherCode)
|
||||
return typeof this.qrText === 'string' && /^https?:\/\//i.test(this.qrText)
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
@@ -121,6 +123,7 @@ export default {
|
||||
},
|
||||
onUnload() {
|
||||
this.stopPoll()
|
||||
this.stopCheckTimer()
|
||||
},
|
||||
methods: {
|
||||
refresh(first) {
|
||||
@@ -143,7 +146,11 @@ export default {
|
||||
} else {
|
||||
this.stopPoll()
|
||||
}
|
||||
if (this.status === 2) this.$nextTick(() => this.renderQr())
|
||||
if (this.status === 2) {
|
||||
this.loadCheckCode()
|
||||
} else {
|
||||
this.stopCheckTimer()
|
||||
}
|
||||
}).catch(() => {
|
||||
if (first) uni.showToast({ title: '网络异常,请稍后重试', icon: 'none' })
|
||||
})
|
||||
@@ -159,18 +166,37 @@ export default {
|
||||
stopPoll() {
|
||||
if (this.pollTimer) { clearInterval(this.pollTimer); this.pollTimer = null }
|
||||
},
|
||||
// xuchao: 码字符串→二维码渲染;qrcode.min.js 为本地静态资源(static/js/),动态注入一次
|
||||
// xuchao: 取实时核销码并渲染;CNPC 侧 60 秒滚动,前端每 55 秒预取刷新
|
||||
loadCheckCode() {
|
||||
const orderNo = this.voucher.orderNo || this.orderNo
|
||||
if (!orderNo) return
|
||||
this.$u.api.voucherCheckCode({ orderNo, phone: this.phone }).then(res => {
|
||||
if (!bizOk(res)) { uni.showToast({ title: bizMsg(res) || '获取核销码失败', icon: 'none' }); return }
|
||||
const d = bizData(res)
|
||||
this.qrText = d.checkCode || ''
|
||||
this.$nextTick(() => this.renderQr())
|
||||
this.startCheckTimer()
|
||||
}).catch(() => {})
|
||||
},
|
||||
startCheckTimer() {
|
||||
this.stopCheckTimer()
|
||||
this.checkTimer = setInterval(() => this.loadCheckCode(), 55000)
|
||||
},
|
||||
stopCheckTimer() {
|
||||
if (this.checkTimer) { clearInterval(this.checkTimer); this.checkTimer = null }
|
||||
},
|
||||
// xuchao: 核销码字符串→二维码渲染;qrcode.min.js 为本地静态资源(static/js/),动态注入一次
|
||||
renderQr() {
|
||||
if (this.isQrImage) return
|
||||
if (!this.qrText) return
|
||||
const draw = () => {
|
||||
if (typeof document === 'undefined' || typeof window.QRCode === 'undefined') return
|
||||
const el = document.getElementById('petrol-qr')
|
||||
if (!el || el.hasChildNodes()) {
|
||||
if (el && this.voucher.voucherCode) { el.innerHTML = ''; } else { return }
|
||||
}
|
||||
if (!el) return
|
||||
el.innerHTML = ''
|
||||
// eslint-disable-next-line no-new
|
||||
new window.QRCode(el, {
|
||||
text: this.voucher.voucherCode,
|
||||
text: this.qrText,
|
||||
width: 200, height: 200, colorDark: '#1a1818', colorLight: '#ffffff',
|
||||
correctLevel: window.QRCode.CorrectLevel.H
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user