import ColProtocol from '@/components/col-protocol' import { Button, Cell, CellGroup, Dialog, Popup, Toast } from 'vant' import ColPopup from '@/components/col-popup' import { defineComponent } from 'vue' import { postMessage, listenerMessage } from '@/helpers/native-message' import styles from './index.module.less' import UserAuth from './userAuth' import request from '@/helpers/request' import qs from 'query-string' // 调用原生支付 // postMessage({ api: 'paymentOrder', content: { orderNo: 0 } }) // listenerMessage({ api: 'paymentResult', callback: (res: any) => { // status: 'success | fail' // }}) // import iconTips from '@common/images/icon_tips.png' import Payment from './payment' import UrlPayment from '../adapay/payment' import ColHeader from '@/components/col-header' import { setLogin, state } from '@/state' import { beforeSubmit, orderInfos, orderStatus, orderTenantInfos, resestState } from './orderStatus' import OrderVideo from './order-video' import OrderLive from './order-live' import OrderPractice from './order-practice' import OrderVip from './order-vip' import OrderMusic from './order-music' import { getHttpOrigin, moneyFormat } from '@/helpers/utils' import OrderPinao from './order-pinao' import { getMusicDetail } from '@/student/trade/tradeOrder' import OrderActive from './order-active' import UseCoupon, { couponToOrderTypeEnum } from './use-coupons' import OrderAlbum from './order-album' import { useRect } from '@vant/use' import QrcodePayment from './qrcode-payment' import OrderTennatAlbum from './order-tennat-album' import OrderDiscount from './order-discount' import OrderVipCourse from './order-vip-course' import AddDiscount from './add-discount' import { orderType } from '@/constant'; import OrderGroup from './order-group' /** 保留两位小数向上取整 */ export const numberToTwoUp = (num: number | string) => { num = Number(num) return Math.ceil(Number((num * 100).toFixed(1))) / 100 } /** 保留两位小数向下取整 */ export const numberToTwoDown = (num: number | string) => { num = Number(num) return Math.floor(Number((num * 100).toFixed(1))) / 100 } export default defineComponent({ name: 'order-detail', data() { const query = this.$route.query return { loading: false, // 是否加载中,为了处理0元订单() dialogVisible: false, dialogContent: '', dialogBtnText: '确定', dialogType: 'back' as 'back' | 'refresh', orderType: query.orderType as string, orderGoodsType: [] as any[], recomUserId: query.recomUserId, // 推荐人id activityId: query.activityId, // 活动编号 id: query.id, agreeStatus: false, popupShow: false, paymentStatus: false, orderAmount: 0, // 订单金额,用于使用优惠券,余额,优惠等 orderPrice: 0, // 支付金额,最后支付金额 dataLoading: true, disabledCoupon: false, // 是否禁用优惠券 exists: false, // 是否签署过用户注册协议 bottomHeight: 0, paymentVendor: '', //支付厂商 paymentVersion: 'V1', // 支付版本,可用值:V1 老版,V2 新版 paymentChannels: [] as any, // 可以选择的支付类型 showQrcode: false, orderTimer: null as any, qrCodeUrl: '', selectGoods: [] as any, // 用于先中的其它商品 pay_channel: '', orderInfo: {} as any, config: {} as any, // 支付信息 orderNo: '' // } }, unmounted() { // 销毁时解绑监听 orderStatus.orderInfo = { orderNo: '', actualPrice: 0, payStatus: false } }, computed: { orderList() { // 商品列表 const orderObject = orderStatus.orderObject return orderObject.orderList || [] }, goodsNum() { const orderList = orderStatus.orderObject.orderList || [] let num = 0 orderList.forEach((item: any) => { if (item.num) { num += item.num } else { num += 1 } }) return num }, countDiscountPrice() { const orderObject = orderStatus.orderObject return ( orderObject.couponAmount || numberToTwoDown( orderObject.couponDiscountPrice + orderObject.discountPrice + orderObject.discountCardPrice ) ) } }, async mounted() { // await this.getUserRegisterProtocol() // 判断是否是曲目购买(只有智能陪练才会有入口),其它地方不会有入口 this.dataLoading = true if (this.orderType == 'MUSIC' && this.id) { try { const item = await getMusicDetail(this.id) orderStatus.orderObject.orderType = 'MUSIC' orderStatus.orderObject.orderName = item.musicSheetName orderStatus.orderObject.orderDesc = item.musicSheetName orderStatus.orderObject.actualPrice = item.musicPrice orderStatus.orderObject.recomUserId = this.recomUserId orderStatus.orderObject.activityId = this.activityId // 判断当前订单是否在支付中 if (['WAIT_PAY', 'PAYING'].includes(item.orderStatus)) { orderStatus.orderObject.orderNo = item.orderNo } else if (['PAID', 'CLOSE', 'FAIL'].includes(item.orderStatus)) { // 判断订单是否是其它状态 Toast('订单有误') postMessage({ api: 'back', content: {} }) } orderStatus.orderObject.orderList = [ { orderType: 'MUSIC', goodsName: item.musicSheetName, actualPrice: item.musicPrice, price: item.musicPrice, ...item } ] } catch { // } } // 初始化所有商品的类型 const orderList = orderStatus.orderObject.orderList || [] const tempGoodsType: any = [] orderList.forEach((order: any) => { tempGoodsType.push({ orderType: order.orderType, basePrice: order.price || 0, price: order.price || 0 }) }) this.orderGoodsType = tempGoodsType await this.getOrderPayType() this.orderAmount = orderStatus.orderObject.actualPrice || 0 this.orderPrice = orderStatus.orderObject.actualPrice || 0 this.disabledCoupon = orderStatus.orderObject.orderNo ? true : false // 0元支付特别处理 // if (this.orderPrice === 0 && orderStatus.orderObject.orderType) { // this.loading = true // this.onSubmit() // } this.dataLoading = false this.$nextTick(() => { // paymentButton // 处理超过一屏显示 const { height } = useRect((this as any).$refs.paymentButton) this.bottomHeight = height + 10 }) if (!orderStatus.orderObject.orderType) { this.dialogVisible = true this.dialogContent = '产品信息已更新,请重新选择' this.dialogBtnText = '确定' this.dialogType = 'back' return } }, methods: { async getUserRegisterProtocol() { // 获取是否签署过《用户注册协议》 try { const res = await request.get( state.platformApi + '/sysUserContractRecord/checkContractSign', { params: { contractType: 'REGISTER' } } ) this.exists = res.data } catch { // } }, /** 查询支付类型 */ async getOrderPayType() { try { const orderObject = orderStatus.orderObject // 单独处理其它支付类型下面用的bizId const orderItem = orderObject.orderList.find( (item: any) => item.orderType === this.orderType ) let bizId = orderItem ? orderItem.id : '' if (orderObject.orderType === 'PRACTICE' || orderObject.orderType === 'VIP_COURSE') { const orderItem = orderObject.orderList.find( (item: any) => item.orderType === orderObject.orderType ) bizId = orderItem ? orderItem.teacherId : '' } if ( orderObject.orderType === 'LIVE' || orderObject.orderType === "GROUP" || orderObject.orderType === 'VIDEO' ) { const orderItem = orderObject.orderList.find( (item: any) => item.orderType === 'VIDEO' || item.orderType === 'LIVE' || item.orderType === "GROUP" ) bizId = orderItem ? orderItem.courseGroupId : '' } const { data } = await request.post( state.platformApi + '/userOrder/orderPayType', { data: { goodType: orderObject.orderType, bizId, recomUserId: orderObject.recomUserId ? orderObject.recomUserId : null } } ) // 判断是否已经有支付方式了 const paymentConfig = orderStatus.orderObject.paymentConfig || {} if (paymentConfig.paymentVersion && orderStatus.orderObject.orderNo) { this.paymentVersion = paymentConfig.paymentVersion || 'V1' this.paymentVendor = paymentConfig.paymentVendor } else { this.paymentVersion = data.paymentVersion || 'V1' this.paymentVendor = data.paymentVendor } this.paymentChannels = data.paymentChannels // 可以选择的支付类型 } catch { // } }, async onAuthSuccess() { this.popupShow = false await this.getUserRegisterProtocol() this.onSubmit() // 实名成功后自动支付 }, // 支付方式,使用原生支付 async submitNativePay() { // 支付... try { const orderInfo = this.orderInfo.paymentConfig const params = { // orderNo: props.paymentConfig.orderNo, merOrderNo: orderInfo.merOrderNo, paymentChannel: orderInfo.paymentChannel, paymentVendor: orderInfo.paymentVendor } const res = await request.post( state.platformApi + '/userOrder/executePayment/v2', { data: { ...params } } ) const payChannel = orderInfo.paymentChannel; postMessage({ api: 'paymentOrder', content: { orderNo: this.orderNo, payChannel, payInfo: res.data.reqParams.body || JSON.stringify(res.data.reqParams) } }) Toast.loading({ message: '支付中...', forbidClick: true, duration: 3000, loadingType: 'spinner' }) Toast.clear() // 唤起支付时状态 listenerMessage('paymentOperation', result => { console.log(result, 'init paymentOperation') this.paymentOperation(result?.content) }) } catch (e: any) { console.log(e) } }, paymentOperation(res: any) { console.log(res, 'paymentOperation') // 支付状态 // paymentOperation 支付成功:success 支付失败:error 支付取消:cancel 未安装:fail // error 只有安卓端有 if (res.status === 'success' || res.status === 'error') { Toast.clear() this.$router.replace({ path: '/tradeDetail', query: { orderNo: this.orderNo } }) } else if (res.status === 'cancel') { Toast.clear() } else if (res.status === 'fail') { const orderInfo = this.orderInfo // const message = // state.payType === 'zfb' ? '您尚未安装支付宝' : '您尚未安装微信' const message = orderInfo.paymentChannel.indexOf('wxpay') !== -1 ? '您尚未安装微信' : '您尚未安装支付宝'; Dialog.alert({ title: '提示', message }).then(() => { Toast.clear() }) } }, async onSubmit() { // console.log(this.orderInfos) if (this.orderPrice > 0) { if (!this.agreeStatus) { Toast('请先阅读并同意《酷乐秀平台服务协议》') return } const users = state.user.data // 判断是否需要实名认证, 姓名,卡号,是否签协议 || !this.exists if (!users?.realName || !users?.idCardNo) { this.popupShow = true return } } // 判断是否有订单号 if (orderStatus.orderObject.orderNo) { if (this.paymentVersion === 'V1') { this.paymentStatus = true } else { this.orderInfo = orderStatus.orderObject.paymentConfig || {} this.orderNo = orderStatus.orderObject.orderNo const paymentChannel = this.orderInfo.paymentConfig.paymentChannel if (paymentChannel) { // 判断是否为原生支付 if ( this.orderInfo.paymentVendor?.indexOf('wxpay') > -1 || this.orderInfo.paymentVendor?.indexOf('alipay') > -1 ) { this.submitNativePay() } else { const payCode = beforeSubmit(paymentChannel) this.onConfirm({ payCode, pay_channel: paymentChannel }) } } else { this.paymentStatus = true } } return } // 正常支付 try { const orderObject = orderStatus.orderObject if (this.paymentVersion === 'V1') { const url = state.platformType === 'TEACHER' ? '/api-teacher/userOrder/executeOrder' : '/api-student/userOrder/executeOrder' const res = await request.post(url, { data: { orderName: orderObject.orderName, orderDesc: orderObject.orderDesc, orderType: orderObject.orderType, actualPrice: this.orderPrice || 0, recomUserId: orderObject.recomUserId, activityId: orderObject.activityId, couponId: orderObject.couponId, orderInfos: [...orderInfos()] } }) const result = res.data || {} if (res.code === 998 || res.code === 999) { this.dialogVisible = true this.dialogContent = res.msg this.dialogBtnText = '刷新' this.dialogType = 'back' return } // 支付成功 if (result.status == 'PAID') { this.$router.replace({ path: '/tradeDetail', query: { orderNo: result.orderNo } }) return } // 拉起支付方式 orderStatus.orderObject.orderNo = result.orderNo orderStatus.orderObject.actualPrice = result.actualPrice } else { const url = state.platformType === 'TEACHER' ? '/api-teacher/userOrder/executeOrder/v2' : '/api-student/userOrder/executeOrder/v2' const goods: any = orderTenantInfos() if (this.selectGoods && this.selectGoods.length > 0) { goods.push(...orderTenantInfos(this.selectGoods)) } const res = await request.post(url, { data: { activityId: orderObject.activityId > 0 ? orderObject.activityId : null, couponIds: orderObject.couponId, goodsInfos: goods, orderDesc: orderObject.orderDesc, orderName: orderObject.orderName, orderType: orderObject.orderType, paymentCashAmount: this.orderPrice || 0, paymentType: this.paymentVendor, recomUserId: orderObject.recomUserId || null } }) const result = res.data || {} // 支付成功 if (res.code === 999 || res.code === 998) { this.dialogVisible = true this.dialogContent = res.msg this.dialogBtnText = '确定' this.dialogType = 'back' return } if (result.status == 'PAID') { this.$router.replace({ path: '/tradeDetail', query: { orderNo: result.orderNo } }) return } orderStatus.orderObject.paymentConfig = result || {} // orderStatus.orderObject.paymentConfig.actualPrice = result.paymentConfig.price orderStatus.orderObject.actualPrice = result.paymentConfig.price orderStatus.orderObject.orderNo = result?.orderNo this.orderInfo = result this.orderNo = result.orderNo } // console.log(orderStatus.orderObject, orderStatus.orderObject.paymentConfig, '111') this.paymentStatus = true } catch { this.loading = false if (this.orderPrice === 0) { Dialog.alert({ title: '提示', message: '支付失败,请稍后重试!', confirmButtonText: '确定', confirmButtonColor: '#2dc7aa' }) } } }, async onDialogConfirm() { this.dialogVisible = false if (this.dialogType === 'back') { this.$router.back() } else if (this.dialogType === 'refresh') { // 更新会员天数 const userInfo = await request.get( state.platformType === 'TEACHER' ? '/api-teacher/teacher/queryUserInfo' : '/api-student/student/queryUserInfo' ) setLogin(userInfo.data) const vipEndDays = userInfo.data.userVip.vipEndDays || 0 orderStatus.orderObject.orderList.forEach((item: any) => { item.vipEndDays = vipEndDays }) } }, onBackOut() { // 关闭订单后需要重置数据 resestState() }, onCouponSelect(item: any) { let discountCount = 0 let universalCount = 0 const tempPrice: any = {} this.orderGoodsType.forEach((type: any) => { tempPrice[type.orderType] = type.price }) ;(item || []).forEach((child: any) => { if(child.couponCategory === 'UNIVERSAL') { universalCount += Number(child.discountPrice) } else { const tempCoupon = couponToOrderTypeEnum[child.couponCategory] let price = tempPrice[tempCoupon] - Number(child.discountPrice) // 折扣金额 if(price >= 0) { discountCount += Number(child.discountPrice) } else { discountCount += Number(tempPrice[tempCoupon]) } tempPrice[tempCoupon] = price >= 0 ? price : 0 } }) // 获取金额 let tempAllAmount = 0 for(let i in tempPrice) { tempAllAmount += tempPrice[i] } // 判断 通用券的金额是否大于订单的金额 if(universalCount >= tempAllAmount) { universalCount = tempAllAmount } const lastAmount = Number( numberToTwoUp(tempAllAmount - Number(universalCount) ) ) this.orderPrice = lastAmount >= 0 ? lastAmount : 0 // 设置优惠券编号 const couponIds = (item || []).map((item: any) => { return item.couponIssueId }) orderStatus.orderObject.couponId = couponIds.join(',') || '' orderStatus.orderObject.couponDiscountPrice = discountCount + universalCount }, onConfirm(val: any) { // debugger const config: any = this.orderInfo.paymentConfig || {} this.pay_channel = val.pay_channel const params = qs.stringify({ pay_channel: val.pay_channel, wxAppId: config.wxAppId, alipayAppId: config.alipayAppId, paymentType: this.orderInfo.paymentType, body: config.body, price: config.price, orderNo: config.merOrderNo, userId: config.userId }) orderStatus.orderObject.paymentConfig.paymentConfig.paymentChannel = val.pay_channel console.log(params, 'params ---', config) if (val.payCode === 'payResult') { window.location.href = getHttpOrigin() + state.payBackPath + '#/payResult?' + params } else { this.qrCodeUrl = getHttpOrigin() + state.payBackPath + '#/payDefine?' + params this.showQrcode = true this.paymentStatus = false setTimeout(() => { this.getPaymentOrderStatus() }, 300) } }, // 轮询查询订单状态 async getPaymentOrderStatus() { // 循环查询订单 // const orderNo = state.orderNo const orderTimer = setInterval(async () => { // 判断是否在当前路由,如果不是则清除定时器 if (this.$route.name != 'orderDetail') { clearInterval(orderTimer) return } this.orderTimer = orderTimer try { const urlFix = state.platformType === 'TEACHER' ? '/api-teacher' : '/api-student' const { data } = await request.get( `${urlFix}/userOrder/detailByOrderNo/${this.orderNo}`, { hideLoading: true } ) if (data.status !== 'WAIT_PAY' && data.status !== 'PAYING') { // 默认关闭支付二维码弹窗 this.showQrcode = false clearInterval(this.orderTimer) setTimeout(() => { this.$router.replace({ path: '/tradeDetail', query: { orderNo: this.orderNo } }) }, 100) } } catch (e: any) { // console.log(e, 'error') clearInterval(this.orderTimer) } }, 5000) } }, beforeUnmount() { resestState() }, render() { return (
{!this.loading && ( <> {this.orderList.map((item: any) => { if (item.orderType === 'VIDEO') { return } else if(item.orderType === "GROUP") { return } else if (item.orderType === 'LIVE') { return } else if (item.orderType === 'PRACTICE') { return } else if (item.orderType === 'VIP_COURSE') { return } else if ( item.orderType === 'VIP' || item.orderType === 'SVIP' ) { return ( { // 畅学卡变更状态时需要重新选择优惠券 orderStatus.orderObject.couponId = '' orderStatus.orderObject.couponDiscountPrice = 0 // 重置金额 this.orderAmount = Number(price) const lastAmount = Number( numberToTwoUp( Number(this.orderAmount) - Number(orderStatus.orderObject.couponDiscountPrice) ) ) this.orderPrice = lastAmount >= 0 ? lastAmount : 0 this.orderGoodsType.forEach((child: any) => { if (child.orderType === item.orderType) { child.price = Number(price) } }) // 更新优惠券列表 const useCouponRef: any = this.$refs.useCouponRef if (useCouponRef) { useCouponRef.resetCouponList() } }} /> ) } else if (item.orderType === 'MUSIC') { return } else if (item.orderType === 'PIANO_ROOM') { return } else if (item.orderType === 'ACTI_REGIST') { return } else if (item.orderType === 'ALBUM') { return } else if (item.orderType === 'TENANT_ALBUM') { return } else if (item.orderType === 'DISCOUNT') { return ( { // 畅学卡变更状态时需要重新选择优惠券 orderStatus.orderObject.couponId = '' orderStatus.orderObject.couponDiscountPrice = 0 // 重置金额 this.orderAmount = Number(price) const lastAmount = Number( numberToTwoUp( Number(this.orderAmount) - Number(orderStatus.orderObject.couponDiscountPrice) ) ) this.orderPrice = lastAmount >= 0 ? lastAmount : 0 this.orderGoodsType.forEach((child: any) => { if (child.orderType === item.orderType) { child.price = Number(price) } }) // 更新优惠券列表 const useCouponRef: any = this.$refs.useCouponRef if (useCouponRef) { useCouponRef.resetCouponList() } }} /> ) } })} {/* 畅学卡 - 目前只有学生端支持 */} {state.platformType === 'STUDENT' && !this.dataLoading && !this.disabledCoupon ? ( { orderStatus.orderObject.discountCardPrice = Number( item.discountPrice ) this.orderGoodsType.forEach((child: any) => { if (child.orderType !== 'DISCOUNT') { child.price = numberToTwoUp( child.price - Number(item.discountPrice) ) } }) // 更新优惠券列表 const useCouponRef: any = this.$refs.useCouponRef if (useCouponRef) { useCouponRef.resetCouponList() } this.orderPrice = Number( numberToTwoUp( Number(this.orderAmount) - Number(item.discountPrice) - Number(orderStatus.orderObject.couponDiscountPrice) ) ) }} onConfirm={(item: { checked: boolean id: number | null salePrice: number discountRate: number discountPrice: number | string vipType: string }) => { // 畅学卡变更状态时需要重新选择优惠券 orderStatus.orderObject.couponId = '' orderStatus.orderObject.couponDiscountPrice = 0 // 是否选中畅学卡 const index = this.selectGoods?.findIndex( (child: any) => child.id === item.id ) const tempType = this.orderGoodsType if (item.checked) { orderStatus.orderObject.discountCardPrice = Number( item.discountPrice ) this.orderGoodsType.forEach((child: any) => { if (child.orderType !== 'DISCOUNT') { child.price = numberToTwoUp( child.price - Number(item.discountPrice) ) } }) if (index === -1) { this.orderAmount = this.orderAmount + item.salePrice this.selectGoods.push({ orderType: item.vipType, goodsName: '畅学卡', num: 1, id: item.id }) const typeIndex = tempType.findIndex( (child: any) => child.orderType === item.vipType ) if (typeIndex === -1) { tempType.push({ orderType: item.vipType, price: item.salePrice }) } } } else { orderStatus.orderObject.discountCardPrice = 0 if (index !== -1) { this.selectGoods.splice(index, 1) this.orderAmount = this.orderAmount - item.salePrice this.orderGoodsType.forEach((child: any) => { if (child.orderType !== 'DISCOUNT') { child.price = child.basePrice } }) const typeIndex = tempType.findIndex( (child: any) => child.orderType === item.vipType ) if (typeIndex !== -1) { tempType.splice(typeIndex, 1) } } } this.orderGoodsType = tempType // 更新优惠券列表 const useCouponRef: any = this.$refs.useCouponRef if (useCouponRef) { // console.log(useCouponRef, 'useCouponRef') useCouponRef.resetCouponList() } this.orderPrice = Number( numberToTwoUp( Number(this.orderAmount) - Number(item.discountPrice) - Number(orderStatus.orderObject.couponDiscountPrice) ) ) this.$forceUpdate() }} /> ) : ( '' )} {/* 只做显示用 - 不参与逻辑 */} {state.platformType === 'STUDENT' && !this.dataLoading && this.disabledCoupon && orderStatus.orderObject.discountCardPrice > 0 ? ( (
畅学卡优惠
-¥ {(this as any).$filters.moneyFormat( orderStatus.orderObject.discountCardPrice )}
) }} />
) : ( '' )} {/* 优惠券使用 */} {!this.dataLoading && ( )}
{this.orderPrice > 0 && (
{ this.exists = val }} />
)}
共{this.goodsNum || 1}件
合计:
{moneyFormat(this.orderPrice)}
{this.countDiscountPrice > 0 ? (
已优惠 ¥{moneyFormat(this.countDiscountPrice)}
) : ( '' )}
)} {/* 判断类型使用什么去支付 */} {this.paymentVersion === 'V1' ? ( ) : ( (this.paymentStatus = false)} onBackOut={this.onBackOut} onConfirm={(val: any) => this.onConfirm(val)} /> )} { // 二维码关闭时清除定时器 clearInterval(this.orderTimer) }} >
提示
{this.dialogContent}
) } })