diff --git a/pages/goods-vr-ticket-order/goods-vr-ticket-order.css b/pages/goods-vr-ticket-order/goods-vr-ticket-order.css index 0d00323d..b50767d8 100644 --- a/pages/goods-vr-ticket-order/goods-vr-ticket-order.css +++ b/pages/goods-vr-ticket-order/goods-vr-ticket-order.css @@ -439,4 +439,109 @@ .cp { cursor: pointer; +} + +/* =========== 观影人信息卡片 =========== */ +.viewer-card { + margin-top: 20rpx; +} + +.viewer-card .section-header { + display: flex; + align-items: center; + justify-content: space-between; +} + +.viewer-card .required-hint { + font-size: 24rpx; + color: #ff4d4f; + font-weight: 500; +} + +/* 表单项 */ +.viewer-card .form-item { + margin-top: 24rpx; +} + +.viewer-card .form-label { + display: flex; + align-items: center; + margin-bottom: 12rpx; +} + +.viewer-card .label-text { + font-size: 28rpx; + color: #333; + font-weight: 500; +} + +.viewer-card .required-star { + color: #ff4d4f; + margin-left: 4rpx; + font-size: 28rpx; +} + +.viewer-card .form-content { + display: flex; + align-items: center; + gap: 16rpx; +} + +.viewer-card .form-input { + flex: 1; + height: 80rpx; + padding: 0 24rpx; + background: #f5f5f5; + border-radius: 8rpx; + font-size: 28rpx; + border: 1px solid transparent; + transition: all 0.2s; +} + +.viewer-card .form-input:focus { + background: #fff; + border-color: #1677ff; +} + +/* 快速授权按钮 */ +.viewer-card .quick-fill-btn { + padding: 0 24rpx; + height: 64rpx; + line-height: 64rpx; + background: #07c160; + color: #fff; + font-size: 24rpx; + border-radius: 8rpx; + border: none; + display: flex; + align-items: center; + justify-content: center; + white-space: nowrap; + transition: all 0.2s; +} + +.viewer-card .quick-fill-btn::after { + border: none; +} + +.viewer-card .quick-fill-btn:active { + opacity: 0.8; +} + +/* 提示信息 */ +.viewer-card .viewer-tip { + display: flex; + align-items: center; + gap: 8rpx; + margin-top: 24rpx; + padding: 16rpx; + background: #f9f9f9; + border-radius: 8rpx; +} + +.viewer-card .tip-text { + flex: 1; + font-size: 24rpx; + color: #999; + line-height: 1.5; } \ No newline at end of file diff --git a/pages/goods-vr-ticket-order/goods-vr-ticket-order.vue b/pages/goods-vr-ticket-order/goods-vr-ticket-order.vue index ff61525c..dc922440 100644 --- a/pages/goods-vr-ticket-order/goods-vr-ticket-order.vue +++ b/pages/goods-vr-ticket-order/goods-vr-ticket-order.vue @@ -67,6 +67,82 @@ + + + + 观影人信息 + *必填 + + + + + + 手机号 + * + + + + + + + + + + + + + + 姓名 + * + + + + + + + + + + + 身份证号 + * + + + + + + + + + + + 请确保观影人信息准确,订单支付后无法修改 + + + @@ -243,6 +319,22 @@ export default { // 场馆地址 venueAddress: '', + // ===== 观影人信息 ===== + // 观影人配置(从 URL 参数获取) + viewerConfig: { + require_viewer: false, + require_viewer_per_seat: 0, + require_viewer_mobile: 0, + require_viewer_name: 0, + require_viewer_idcard: 0 + }, + // 观影人表单数据 + viewerName: '', + viewerMobile: '', + viewerIdcard: '', + // 微信手机号授权中 + isGettingPhone: false, + // ===== Buy 页面相关数据 ===== // 提交按钮禁用状态 buy_submit_disabled_status: false, @@ -396,6 +488,26 @@ export default { this.venueAddress = decodeURIComponent(params.venueAddress); } + // 解析观影人配置 + if (params.viewerConfig) { + try { + this.viewerConfig = JSON.parse(decodeURIComponent(params.viewerConfig)); + console.log('[Order] viewerConfig loaded:', this.viewerConfig); + } catch (e) { + console.error('[Order] Failed to parse viewerConfig:', e); + this.viewerConfig = { require_viewer: false }; + } + } + + // 自动填充观影人信息 + if (this.viewerConfig.require_viewer) { + // 尝试从用户信息自动填充手机号 + if (this.userInfo && this.userInfo.mobile) { + this.viewerMobile = this.userInfo.mobile; + console.log('[Order] Auto-filled mobile from user:', this.viewerMobile); + } + } + // 记录来源页面 const pages = getCurrentPages(); if (pages.length > 1) { @@ -431,6 +543,102 @@ export default { } }, + // ===== 观影人信息相关方法 ===== + + // 微信小程序一键获取手机号 + onGetPhoneNumber(e) { + const { encryptedData, iv, code, errMsg } = e.detail; + + // 用户拒绝授权 + if (!encryptedData && !code) { + this.app.globalData.showToast('请手动填写手机号'); + return; + } + + this.isGettingPhone = true; + + const user = this.app.globalData.get_login_cache_info() || {}; + const clientType = this.app.globalData.application_client_type(); + + uni.request({ + url: this.app.globalData.get_request_url('onekeyusermobilebind', 'user'), + method: 'POST', + data: { + encrypted_data: encryptedData || '', + iv: iv || '', + code: code || '', + openid: user[clientType + '_openid'] || '', + }, + success: (res) => { + if (res.data.code == 0) { + this.viewerMobile = res.data.data.mobile || ''; + this.app.globalData.showToast('授权成功', 'success'); + } else { + this.app.globalData.showToast(res.data.msg || '授权失败,请手动填写'); + } + }, + fail: () => { + this.app.globalData.showToast('网络错误,请手动填写'); + }, + complete: () => { + this.isGettingPhone = false; + } + }); + }, + + // 前端表单校验 + validateViewerForm() { + const config = this.viewerConfig; + + // 手机号校验 + if (config.require_viewer_mobile) { + if (!this.viewerMobile) { + this.app.globalData.showToast('请填写手机号'); + return false; + } + if (!/^1[3-9]\d{9}$/.test(this.viewerMobile)) { + this.app.globalData.showToast('手机号格式不正确'); + return false; + } + } + + // 姓名校验 + if (config.require_viewer_name) { + if (!this.viewerName || !this.viewerName.trim()) { + this.app.globalData.showToast('请填写观影人姓名'); + return false; + } + } + + // 身份证号校验(预留) + if (config.require_viewer_idcard) { + if (!this.viewerIdcard) { + this.app.globalData.showToast('请填写身份证号'); + return false; + } + if (!/^\d{17}[\dXx]$/.test(this.viewerIdcard)) { + this.app.globalData.showToast('身份证号格式不正确'); + return false; + } + } + + return true; + }, + + // 组装观影人数据 + getViewerData() { + // 如果不需要观影人,返回 null + if (!this.viewerConfig.require_viewer) { + return null; + } + + return [{ + name: this.viewerName || '', + mobile: this.viewerMobile || '', + idcard: this.viewerIdcard || '' + }]; + }, + // 构建购买参数 buildParams() { // 组装规格数据 @@ -686,6 +894,13 @@ export default { } } + // 观影人信息校验 + if (this.viewerConfig.require_viewer) { + if (!this.validateViewerForm()) { + return; + } + } + this.setData({ buy_submit_disabled_status: true, }); @@ -703,6 +918,12 @@ export default { site_model: 3, // 虚拟商品模式 }; + // 添加观影人数据 + const viewerData = this.getViewerData(); + if (viewerData) { + data.viewer_data = viewerData; + } + console.log('[Order Confirm] Submit order with data:', JSON.stringify(data)); var self = this; diff --git a/pages/goods-vr-ticket/goods-vr-ticket.vue b/pages/goods-vr-ticket/goods-vr-ticket.vue index ad7ef73d..caf03bb6 100644 --- a/pages/goods-vr-ticket/goods-vr-ticket.vue +++ b/pages/goods-vr-ticket/goods-vr-ticket.vue @@ -300,16 +300,9 @@ export default { this.goodsId = params.id; } - // 尝试从缓存获取商品数据 - var goods = app.globalData.goods_data_cache_handle(this.goodsId); - if (goods != null) { - console.log('[VR Ticket] goods from cache:', goods); - this.handleGoodsData(goods); - this.loadTreeData(); - } else { - // 请求 API 获取商品详情 - this.loadGoodsDetail(); - } + // 始终从 API 获取最新数据,避免缓存导致收藏状态不一致 + // 请求 API 获取商品详情 + this.loadGoodsDetail(); }, // 加载商品详情 @@ -325,8 +318,6 @@ export default { var goods = res.data.data.goods; console.log('[VR Ticket] goods from API:', goods); self.handleGoodsData(goods); - // 更新商品缓存,确保 user_is_favor 等字段同步 - self.app.globalData.goods_data_cache_handle(goods.id, goods); self.loadTreeData(); } } @@ -391,6 +382,20 @@ export default { console.log('[VR Ticket] detailContent loaded:', this.detailContent); } + // 提取并存储完整的 vr_goods_config 数组 + if (apiData.goods && apiData.goods.vr_goods_config) { + try { + this.vrConfig = typeof apiData.goods.vr_goods_config === 'string' + ? JSON.parse(apiData.goods.vr_goods_config) + : apiData.goods.vr_goods_config; + + console.log('[VR Ticket] vrConfig loaded:', this.vrConfig); + } catch (e) { + console.error('[VR Ticket] Failed to parse vr_goods_config:', e); + this.vrConfig = []; + } + } + // 提取场馆数据 const venuesMap = {}; Object.values(apiData.seat_templates || {}).forEach(template => { @@ -406,9 +411,22 @@ export default { // 找出距离最近的场馆 findClosestVenue() { - // 模拟当前用户坐标 (例如: 北京市朝阳区) - // 在实际项目中,可以使用 uni.getLocation 获取真实经纬度 - const currentLoc = { lat: 39.9042, lng: 116.4074 }; + // 使用 ShopXO 全局位置选择器获取真实用户位置 + const userLocation = this.app.globalData.choice_user_location_init(); + + // 构建当前位置坐标(带兜底策略:默认北京天安门) + const currentLoc = { + lat: parseFloat(userLocation.lat) || 39.9042, + lng: parseFloat(userLocation.lng) || 116.4074 + }; + + // 日志记录(便于调试) + console.log('[VR Ticket] User location:', { + status: userLocation.status, + name: userLocation.name, + lat: currentLoc.lat, + lng: currentLoc.lng + }); let closest = this.venues[0]; let minDistance = Infinity; @@ -429,6 +447,9 @@ export default { }); this.currentVenue = closest || this.venues[0]; + + // 日志记录最终选择的场馆 + console.log('[VR Ticket] Selected venue:', this.currentVenue.name, 'Distance:', minDistance.toFixed(0), 'm'); }, // Haversine 距离计算 (单位:米) @@ -495,12 +516,6 @@ export default { if (res.data.code == 0) { // 更新收藏状态 self.collected = res.data.data.status == 1; - // 更新商品缓存,确保数据一致性 - var goods = self.app.globalData.goods_data_cache_handle(self.goodsId); - if (goods) { - goods.user_is_favor = res.data.data.status; - self.app.globalData.goods_data_cache_handle(self.goodsId, goods); - } self.app.globalData.showToast(res.data.msg, 'success'); } else { if (self.app.globalData.is_login_check(res.data, self, 'toggleCollect')) { @@ -579,6 +594,20 @@ export default { posterImg = this.goodsData.images[0] || ''; } + // 根据当前场馆匹配观影人配置 + let viewerConfig = null; + if (this.vrConfig && Array.isArray(this.vrConfig) && this.currentVenue?.name) { + const matchedConfig = this.vrConfig.find(config => + config.template_snapshot?.venue?.name === this.currentVenue.name + ); + if (matchedConfig && matchedConfig.viewer_config) { + viewerConfig = matchedConfig.viewer_config; + console.log('[VR Ticket] Matched viewer config for venue:', this.currentVenue.name, viewerConfig); + } else { + console.log('[VR Ticket] No viewer config found for venue:', this.currentVenue.name); + } + } + // 组装跳转参数 const params = { goodsId: this.goodsId, @@ -589,7 +618,8 @@ export default { batchExpire: this.goodsData.batch_number_expire || '', sessionDatetime: sessionDatetime, posterUrl: posterImg, - venueAddress: this.currentVenue?.address || '' + venueAddress: this.currentVenue?.address || '', + viewerConfig: viewerConfig ? encodeURIComponent(JSON.stringify(viewerConfig)) : '' }; // 拼接 URL 参数 diff --git a/pages/plugins/vr-ticket-wallet/components/ticket-qr-popup/index.vue b/pages/plugins/vr-ticket-wallet/components/ticket-qr-popup/index.vue index 47e35747..5e1082da 100644 --- a/pages/plugins/vr-ticket-wallet/components/ticket-qr-popup/index.vue +++ b/pages/plugins/vr-ticket-wallet/components/ticket-qr-popup/index.vue @@ -147,7 +147,7 @@ export default { getQrcodeOptions: function(ticket) { return { code: ticket.qr_payload || '', - size: 450, + size: 300, bgColor: '#ffffff', }; }, @@ -279,11 +279,13 @@ export default { /* ========== 二维码 ========== */ .qrcode-wrapper { position: relative; - width: 320rpx; - height: 320rpx; + width: 340rpx; + height: 340rpx; background: #ffffff; - border-radius: 16rpx; overflow: hidden; + display: flex; + align-items: center; + justify-content: center; } /* 过期遮罩 */ diff --git a/pages/plugins/vr-ticket-wallet/records/index.vue b/pages/plugins/vr-ticket-wallet/records/index.vue index 2e890aeb..7570cc83 100644 --- a/pages/plugins/vr-ticket-wallet/records/index.vue +++ b/pages/plugins/vr-ticket-wallet/records/index.vue @@ -52,17 +52,44 @@ v-for="(item, idx) in group.list" :key="'record-' + item.id" > - - {{ formatTime(item.created_at) }} - - + + {{ item.goods_title }} - - {{ item.real_name }} · {{ formatSeatShort(item.seat_info) }} - + + {{ formatTime(item.created_at) }} + - - + + + + + 券码 + {{ item.short_code || '-' }} + + + 订单号 + {{ item.order_no || '-' }} + + + 观演人 + + {{ item.real_name || '-' }} + ({{ item.phone }}) + + + + 座位 + {{ formatSeatShort(item.seat_info) || '-' }} + + + 购买人 + {{ item.buyer_name }} + + + + + + 已核销 diff --git a/pages/plugins/vr-ticket-wallet/records/records.css b/pages/plugins/vr-ticket-wallet/records/records.css index 111f4449..8777913a 100644 --- a/pages/plugins/vr-ticket-wallet/records/records.css +++ b/pages/plugins/vr-ticket-wallet/records/records.css @@ -136,70 +136,109 @@ /* ========== 记录卡片 ========== */ .record-card { - display: flex; - align-items: center; - background: #ffffff; - border-radius: 16rpx; - padding: 24rpx; - margin-bottom: 16rpx; - box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04); -} - -.record-time { - width: 100rpx; - font-size: 24rpx; - color: #999; - font-weight: 500; - flex-shrink: 0; -} - -.record-info { - flex: 1; - min-width: 0; display: flex; flex-direction: column; - gap: 8rpx; + background: #ffffff; + border-radius: 20rpx; + padding: 30rpx; + margin-bottom: 24rpx; + box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04); + position: relative; + overflow: hidden; +} + +.card-header-row { + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 2rpx dashed #f5f5f5; + padding-bottom: 20rpx; + margin-bottom: 20rpx; } .record-title { - font-size: 28rpx; - font-weight: 700; - color: #333; + font-size: 30rpx; + font-weight: 800; + color: #1a1a1a; + flex: 1; + margin-right: 20rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -.record-detail { - font-size: 22rpx; - color: #999; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.record-status { - width: 48rpx; - display: flex; - align-items: center; - justify-content: center; +.record-time-badge { + background: #fdf2f4; + padding: 4rpx 14rpx; + border-radius: 8rpx; flex-shrink: 0; } -.status-icon { - width: 40rpx; - height: 40rpx; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - font-size: 20rpx; - color: #ffffff; - font-weight: bold; +.time-text { + font-size: 22rpx; + color: #e94560; + font-weight: 700; + font-family: 'Montserrat', sans-serif; } -.status-icon.success { - background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%); +.card-details-grid { + display: flex; + flex-direction: column; + gap: 12rpx; + padding-right: 120rpx; /* Leave space for the verified stamp */ +} + +.detail-item { + display: flex; + align-items: flex-start; + font-size: 24rpx; + line-height: 1.4; +} + +.detail-label { + width: 110rpx; + color: #999999; + flex-shrink: 0; + font-weight: 500; +} + +.detail-value { + color: #333333; + font-weight: 500; + flex: 1; + word-break: break-all; +} + +.detail-value.highlight-code { + color: #e94560; + font-weight: 700; + font-family: monospace; + letter-spacing: 0.02em; +} + +.phone-sub { + color: #8c8c8c; + font-size: 22rpx; + margin-left: 8rpx; + font-weight: normal; +} + +.success-stamp { + position: absolute; + right: 24rpx; + bottom: 24rpx; + border: 4rpx solid rgba(82, 196, 26, 0.35); + color: #52c41a; + border-radius: 8rpx; + padding: 4rpx 10rpx; + font-size: 20rpx; + font-weight: 900; + transform: rotate(-12deg); + background-color: rgba(82, 196, 26, 0.03); + pointer-events: none; + font-family: 'Montserrat', sans-serif; + letter-spacing: 0.05em; + text-transform: uppercase; } /* ========== 加载更多 ========== */ diff --git a/pages/plugins/vr-ticket-wallet/verify/index.css b/pages/plugins/vr-ticket-wallet/verify/index.css index e86c2574..354893d0 100644 --- a/pages/plugins/vr-ticket-wallet/verify/index.css +++ b/pages/plugins/vr-ticket-wallet/verify/index.css @@ -629,3 +629,192 @@ justify-content: center; border: none; } + +/* ========== H5 手动输入核销 ========== */ +.h5-manual-container { + width: 100%; + display: flex; + flex-direction: column; + gap: 40rpx; + margin-bottom: 20rpx; + z-index: 2; +} + +/* H5 警告提示卡片 */ +.h5-warning-card { + display: flex; + align-items: flex-start; + gap: 20rpx; + padding: 28rpx 32rpx; + background: rgba(233, 69, 96, 0.08); + border: 1px dashed rgba(233, 69, 96, 0.4); + border-radius: 20rpx; + box-shadow: 0 8rpx 32rpx rgba(233, 69, 96, 0.05); +} + +.warning-icon-wrap { + width: 48rpx; + height: 48rpx; + border-radius: 50%; + background: rgba(233, 69, 96, 0.2); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + margin-top: 4rpx; +} + +.warning-icon { + font-size: 28rpx; + color: #ff6b6b; + font-weight: bold; +} + +.warning-text-wrap { + display: flex; + flex-direction: column; + gap: 6rpx; +} + +.warning-title { + font-size: 28rpx; + font-weight: 800; + color: #ff6b6b; +} + +.warning-desc { + font-size: 22rpx; + color: rgba(255, 255, 255, 0.65); + line-height: 1.5; +} + +/* 手动核销输入卡片 */ +.manual-card { + background: rgba(255, 255, 255, 0.03); + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: 32rpx; + padding: 48rpx 40rpx; + box-shadow: 0 20rpx 80rpx rgba(0, 0, 0, 0.3); + backdrop-filter: blur(40rpx); + display: flex; + flex-direction: column; + gap: 36rpx; +} + +.card-header { + display: flex; + flex-direction: column; + gap: 8rpx; +} + +.card-title { + font-size: 34rpx; + font-weight: 900; + color: #ffffff; + letter-spacing: 0.05em; +} + +.card-subtitle { + font-size: 22rpx; + color: rgba(255, 255, 255, 0.45); +} + +/* 输入框包装器 (带渐变边框和发光效果) */ +.input-wrapper { + display: flex; + align-items: center; + height: 110rpx; + padding: 0 32rpx; + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.12); + border-radius: 24rpx; + position: relative; + transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); +} + +.input-wrapper.focused { + background: rgba(255, 255, 255, 0.08); + border-color: rgba(233, 69, 96, 0.8); + box-shadow: 0 0 25rpx rgba(233, 69, 96, 0.3); +} + +.input-icon { + font-size: 36rpx; + color: rgba(255, 255, 255, 0.4); + margin-right: 20rpx; + transition: color 0.3s; +} + +.input-wrapper.focused .input-icon { + color: #e94560; +} + +.premium-input { + flex: 1; + height: 100%; + font-size: 32rpx; + color: #ffffff; + font-weight: 600; + letter-spacing: 0.02em; + background: transparent; + border: none; + outline: none; +} + +.clear-btn { + width: 44rpx; + height: 44rpx; + border-radius: 50%; + background: rgba(255, 255, 255, 0.15); + display: flex; + align-items: center; + justify-content: center; + margin-left: 16rpx; +} + +.clear-btn:active { + background: rgba(255, 255, 255, 0.3); +} + +.clear-icon { + font-size: 28rpx; + color: #ffffff; + line-height: 1; +} + +/* 确认核销按钮 */ +.verify-submit-btn { + width: 100%; + height: 96rpx; + background: linear-gradient(135deg, #e94560 0%, #ff6b6b 100%); + border-radius: 48rpx; + display: flex; + align-items: center; + justify-content: center; + border: none; + box-shadow: 0 8rpx 30rpx rgba(233, 69, 96, 0.35); + transition: all 0.3s; +} + +.verify-submit-btn:active { + transform: scale(0.98); + box-shadow: 0 4rpx 15rpx rgba(233, 69, 96, 0.25); +} + +.verify-submit-btn[disabled] { + background: rgba(255, 255, 255, 0.08); + color: rgba(255, 255, 255, 0.25); + border: 1px solid rgba(255, 255, 255, 0.05); + box-shadow: none; +} + +.verify-submit-btn[disabled] .btn-text { + color: rgba(255, 255, 255, 0.25); +} + +.btn-text { + font-size: 32rpx; + font-weight: 800; + color: #ffffff; + letter-spacing: 0.1em; +} diff --git a/pages/plugins/vr-ticket-wallet/verify/index.vue b/pages/plugins/vr-ticket-wallet/verify/index.vue index baaf3cce..f581b546 100644 --- a/pages/plugins/vr-ticket-wallet/verify/index.vue +++ b/pages/plugins/vr-ticket-wallet/verify/index.vue @@ -41,6 +41,54 @@ + + + + + + + + + + 当前为 H5 预览环境 + 浏览器环境限制无法直接调用摄像头。请使用下方手动核销,或在微信小程序/APP中进行扫码。 + + + + + + + 手动核销券码 + 支持输入 12位短码 或 36位UUID票码 + + + + + + + + × + + + + + + + + + @@ -174,10 +222,18 @@ export default { resultData: {}, // 无权限提示 showNoPermission: false, + // H5 手动输入核销相关 + manualCode: '', + isInputFocused: false, + isH5: false, }; }, onLoad(params) { + // #ifdef H5 + this.isH5 = true; + // #endif + // 记录来源 if (params && params.from) { this.sourceFrom = params.from; @@ -301,7 +357,7 @@ export default { // #ifdef H5 // H5 环境提示使用手机扫码 - app.globalData.showToast('请使用手机端扫码功能'); + app.globalData.showToast('当前非小程序或APP环境,请使用手动核销'); return; // #endif @@ -324,6 +380,15 @@ export default { }); }, + // 手动输入提交核销 + submitManualCode() { + if (!this.manualCode || this.manualCode.trim() === '') { + app.globalData.showToast('请输入有效的票码'); + return; + } + this.processScanResult(this.manualCode.trim()); + }, + // 处理扫码结果 processScanResult(code) { // 提取票码(可能包含URL等前缀) @@ -350,6 +415,9 @@ export default { this.resultData = res.data.data || {}; this.showResult = true; + // 清空 H5 手动输入框 + this.manualCode = ''; + // 震动反馈 uni.vibrateShort();