/** * 自助开台页面 */ import { View, Text, Image } from '@tarojs/components' import Taro, { useLoad, useRouter } from '@tarojs/taro' import { useState } from 'react' import { observer } from 'mobx-react' import { Stepper } from '@taroify/core' import { depositStart, balanceStart, invokeWechatPay, PayType, getTableInfo, pollCheckOpenStatus } from '../../api/startDevice' import { closeOrder } from '../../api/order' import { userStore, tableStore } from '../../store' import './index.scss' // 使用本地图片资源 const phoneIcon = require('../startTable/images/phone.png') const SelfStart = observer(() => { const router = useRouter() const scanInfo = tableStore.scanInfo const priceInfo = scanInfo?.price const defaultDeposit = priceInfo?.deposit || 100 const [deposit, setDeposit] = useState(defaultDeposit) // 押金金额 const [paymentMethod, setPaymentMethod] = useState<'微信支付' | '余额支付'>('微信支付') // 支付方式 const [loading, setLoading] = useState(false) // 加载状态 // 从路由参数获取设备信息,如果没有则从 store 获取 const grpSn = tableStore.getGrpSn(router.params.grpSn) // 门店余额从 userStore 获取 const storeBalance = userStore.balance || 0 useLoad(() => { console.log('自助开台页面加载, 设备编码:', grpSn) if (grpSn) { tableStore.setCurrentGrpSn(grpSn) } setTimeout(() => { Taro.showToast({ title: '开台后需要手动进行关台哦!', icon: 'none', duration: 2000 }) }, 300) }) // 拨打电话 const handlePhoneCall = () => { Taro.makePhoneCall({ phoneNumber: '100-666-XXXX', }).catch((err) => { console.error('拨打电话失败:', err) }) } // 押金变化 const handleDepositChange = (value: number) => { setDeposit(value) } const pricePerHour = priceInfo?.currentPrice || priceInfo?.standard || 0 // 根据押金和实际价格计算预计时长 const calculateDuration = () => { if (!pricePerHour) return '-' const hours = Math.floor(deposit / pricePerHour) const minutes = Math.round((deposit / pricePerHour - hours) * 60) return `约${hours}小时${minutes}分钟` } // 选择支付方式 const handleSelectPayment = () => { // 判断余额是否充足 if (storeBalance >= deposit) { Taro.showActionSheet({ itemList: ['微信支付', '余额支付'], success: (res) => { if (res.tapIndex === 0) { setPaymentMethod('微信支付') } else if (res.tapIndex === 1) { setPaymentMethod('余额支付') } } }) } else { Taro.showToast({ title: '余额不足,仅支持微信支付', icon: 'none', duration: 2000 }) } } // 去充值 const handleRecharge = () => { console.log('去充值') Taro.showToast({ title: '功能开发中', icon: 'none', duration: 2000 }) } // 立即开台 const handleConfirmStart = async () => { if (loading) return // 获取用户 openId const openId = userStore.userInfo?.wxOpenId || Taro.getStorageSync('openId') if (!openId) { Taro.showToast({ title: '请先登录', icon: 'none', duration: 2000 }) return } if (!grpSn) { Taro.showToast({ title: '设备信息异常,请重新扫码', icon: 'none', duration: 2000 }) return } setLoading(true) try { console.log('立即开台,押金:', deposit, '设备编码:', grpSn, '支付方式:', paymentMethod) // 根据支付方式选择接口 let result if (paymentMethod === '余额支付') { // 余额开台 result = await balanceStart(grpSn, openId, deposit) } else { // 押金开台(微信支付) result = await depositStart(grpSn, openId, deposit, PayType.WechatPay) } console.log('开台接口返回:', result) // 保存操作记录ID到 store if (result.data.consumptionId) { tableStore.setCurrentOperationId(result.data.consumptionId) } const consumptionId = result.data.consumptionId const outTradeNo = result.data.paymentResponseDto?.outTradeNo // 判断是否需要支付 if (result.data.paymentResponseDto?.payParameters) { // 调起微信支付 try { await invokeWechatPay(result.data.paymentResponseDto.payParameters) // 轮询台子是否真正开启(check-open-status),解决付款后仍显示 open 的问题 Taro.showLoading({ title: '开台确认中...', mask: true }) const openResult = await pollCheckOpenStatus(outTradeNo!) Taro.hideLoading() if (openResult?.isOpened) { // 用接口返回的 operationId(比 consumptionId 更准确) const confirmedOperationId = openResult.operationId || consumptionId // 刷新 scanInfo,关台页 opInfo 有真实数据 try { const openId2 = userStore.userInfo?.wxOpenId || Taro.getStorageSync('openId') const freshInfo = await getTableInfo(grpSn, openId2) tableStore.setScanInfo(freshInfo.data) } catch (_) {} Taro.showToast({ title: '开台成功', icon: 'success', duration: 2000 }) setTimeout(() => { Taro.redirectTo({ url: `/pageScan/closeTable/index?grpSn=${grpSn}&operationId=${confirmedOperationId}` }) }, 2000) } else { Taro.showModal({ title: '开台确认中', content: '台桌正在启动,请稍后重新扫码进入关台页,如有疑问请联系店长。', showCancel: false, confirmText: '知道了', }) } } catch (payError: any) { console.log('支付错误:', payError) // 关闭服务端未支付订单,避免产生悬挂订单 if (outTradeNo) closeOrder(outTradeNo).catch(() => {}) if (payError.errMsg?.includes('cancel')) { Taro.showToast({ title: '已取消支付', icon: 'none', duration: 2000 }) } else { Taro.showToast({ title: payError.errMsg || '支付失败', icon: 'none', duration: 2000 }) } } } else { // 无需支付(余额支付等场景) try { const openId2 = userStore.userInfo?.wxOpenId || Taro.getStorageSync('openId') const freshInfo = await getTableInfo(grpSn, openId2) tableStore.setScanInfo(freshInfo.data) } catch (_) { // 刷新失败不阻断流程 } Taro.showToast({ title: '开台成功', icon: 'success', duration: 2000 }) setTimeout(() => { Taro.redirectTo({ url: `/pageScan/closeTable/index?grpSn=${grpSn}&operationId=${consumptionId}` }) }, 2000) } } catch (error: any) { console.error('开台失败:', error) // 错误提示由 request 拦截器处理 } finally { setLoading(false) } } return ( {/* 内容区域 */} {/* 台球桌信息卡片 */} {/* 顶部:店名和电话 */} {scanInfo?.shopName || '--'} 联系店长 {/* 台球桌标题 */} {scanInfo?.tableInfo?.name || '--'} {/* 价格信息 */} ¥{pricePerHour > 0 ? pricePerHour.toFixed(2) : '--'} /小时 押金 ¥{priceInfo ? priceInfo.deposit.toFixed(2) : '--'} {/* 价格时段 */} 价格时段:{priceInfo?.pricePeriod || '--'} {/* 押金卡片 */} {/* 押金输入 */} 押金(元) {/* 押金说明 */} 押金不小于100元,手动关台自动退剩余押金 {/* 分割线 */} {/* 续费时长 */} 续费时长 {calculateDuration()} {/* 支付方式 */} 支付方式 {paymentMethod} {/* */} {/* 门店余额 */} 门店余额 {storeBalance.toFixed(2)} 去充值 {/* 底部固定区域 */} 需支付 {deposit.toFixed(2)} 立即开台 ) }) export default SelfStart