index.tsx 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  1. import ColProtocol from '@/components/col-protocol'
  2. import { Button, Cell, CellGroup, Dialog, Popup, Toast } from 'vant'
  3. import ColPopup from '@/components/col-popup'
  4. import { defineComponent } from 'vue'
  5. import { postMessage } from '@/helpers/native-message'
  6. import styles from './index.module.less'
  7. import UserAuth from './userAuth'
  8. import request from '@/helpers/request'
  9. import qs from 'query-string'
  10. // 调用原生支付
  11. // postMessage({ api: 'paymentOrder', content: { orderNo: 0 } })
  12. // listenerMessage({ api: 'paymentResult', callback: (res: any) => {
  13. // status: 'success | fail'
  14. // }})
  15. // import iconTips from '@common/images/icon_tips.png'
  16. import Payment from './payment'
  17. import UrlPayment from '../adapay/payment'
  18. import ColHeader from '@/components/col-header'
  19. import { setLogin, state } from '@/state'
  20. import {
  21. beforeSubmit,
  22. orderInfos,
  23. orderStatus,
  24. orderTenantInfos,
  25. resestState
  26. } from './orderStatus'
  27. import OrderVideo from './order-video'
  28. import OrderLive from './order-live'
  29. import OrderPractice from './order-practice'
  30. import OrderVip from './order-vip'
  31. import OrderMusic from './order-music'
  32. import { moneyFormat } from '@/helpers/utils'
  33. import OrderPinao from './order-pinao'
  34. import { getMusicDetail } from '@/student/trade/tradeOrder'
  35. import OrderActive from './order-active'
  36. import UseCoupon, { couponToOrderTypeEnum } from './use-coupons'
  37. import OrderAlbum from './order-album'
  38. import { useRect } from '@vant/use'
  39. import QrcodePayment from './qrcode-payment'
  40. import OrderTennatAlbum from './order-tennat-album'
  41. import OrderDiscount from './order-discount'
  42. import OrderVipCourse from './order-vip-course'
  43. import AddDiscount from './add-discount'
  44. /** 保留两位小数向上取整 */
  45. export const numberToTwoUp = (num: number | string) => {
  46. num = Number(num)
  47. return Math.ceil(Number((num * 100).toFixed(1))) / 100
  48. }
  49. /** 保留两位小数向下取整 */
  50. export const numberToTwoDown = (num: number | string) => {
  51. num = Number(num)
  52. return Math.floor(Number((num * 100).toFixed(1))) / 100
  53. }
  54. export default defineComponent({
  55. name: 'order-detail',
  56. data() {
  57. const query = this.$route.query
  58. return {
  59. loading: false, // 是否加载中,为了处理0元订单()
  60. dialogVisible: false,
  61. dialogContent: '',
  62. dialogBtnText: '确定',
  63. dialogType: 'back' as 'back' | 'refresh',
  64. orderType: query.orderType as string,
  65. orderGoodsType: [] as any[],
  66. recomUserId: query.recomUserId, // 推荐人id
  67. activityId: query.activityId, // 活动编号
  68. id: query.id,
  69. agreeStatus: false,
  70. popupShow: false,
  71. paymentStatus: false,
  72. orderAmount: 0, // 订单金额,用于使用优惠券,余额,优惠等
  73. orderPrice: 0, // 支付金额,最后支付金额
  74. dataLoading: true,
  75. disabledCoupon: false, // 是否禁用优惠券
  76. exists: false, // 是否签署过用户注册协议
  77. bottomHeight: 0,
  78. paymentVendor: '', //支付厂商
  79. paymentVersion: 'V1', // 支付版本,可用值:V1 老版,V2 新版
  80. paymentChannels: [] as any, // 可以选择的支付类型
  81. showQrcode: false,
  82. orderTimer: null as any,
  83. qrCodeUrl: '',
  84. selectGoods: [] as any, // 用于先中的其它商品
  85. pay_channel: '',
  86. orderInfo: {} as any,
  87. config: {} as any, // 支付信息
  88. orderNo: '' //
  89. }
  90. },
  91. unmounted() {
  92. // 销毁时解绑监听
  93. orderStatus.orderInfo = {
  94. orderNo: '',
  95. actualPrice: 0,
  96. payStatus: false
  97. }
  98. },
  99. computed: {
  100. orderList() {
  101. // 商品列表
  102. const orderObject = orderStatus.orderObject
  103. return orderObject.orderList || []
  104. },
  105. goodsNum() {
  106. const orderList = orderStatus.orderObject.orderList || []
  107. let num = 0
  108. orderList.forEach((item: any) => {
  109. if (item.num) {
  110. num += item.num
  111. } else {
  112. num += 1
  113. }
  114. })
  115. return num
  116. },
  117. countDiscountPrice() {
  118. const orderObject = orderStatus.orderObject
  119. return (
  120. orderObject.couponAmount ||
  121. numberToTwoDown(
  122. orderObject.couponDiscountPrice +
  123. orderObject.discountPrice +
  124. orderObject.discountCardPrice
  125. )
  126. )
  127. }
  128. },
  129. async mounted() {
  130. // await this.getUserRegisterProtocol()
  131. // 判断是否是曲目购买(只有智能陪练才会有入口),其它地方不会有入口
  132. this.dataLoading = true
  133. if (this.orderType == 'MUSIC' && this.id) {
  134. try {
  135. const item = await getMusicDetail(this.id)
  136. orderStatus.orderObject.orderType = 'MUSIC'
  137. orderStatus.orderObject.orderName = item.musicSheetName
  138. orderStatus.orderObject.orderDesc = item.musicSheetName
  139. orderStatus.orderObject.actualPrice = item.musicPrice
  140. orderStatus.orderObject.recomUserId = this.recomUserId
  141. orderStatus.orderObject.activityId = this.activityId
  142. // 判断当前订单是否在支付中
  143. if (['WAIT_PAY', 'PAYING'].includes(item.orderStatus)) {
  144. orderStatus.orderObject.orderNo = item.orderNo
  145. } else if (['PAID', 'CLOSE', 'FAIL'].includes(item.orderStatus)) {
  146. // 判断订单是否是其它状态
  147. Toast('订单有误')
  148. postMessage({ api: 'back', content: {} })
  149. }
  150. orderStatus.orderObject.orderList = [
  151. {
  152. orderType: 'MUSIC',
  153. goodsName: item.musicSheetName,
  154. actualPrice: item.musicPrice,
  155. price: item.musicPrice,
  156. ...item
  157. }
  158. ]
  159. } catch {
  160. //
  161. }
  162. }
  163. // 初始化所有商品的类型
  164. const orderList = orderStatus.orderObject.orderList || []
  165. const tempGoodsType: any = []
  166. orderList.forEach((order: any) => {
  167. tempGoodsType.push({
  168. orderType: order.orderType,
  169. basePrice: order.price || 0,
  170. price: order.price || 0
  171. })
  172. })
  173. this.orderGoodsType = tempGoodsType
  174. await this.getOrderPayType()
  175. this.orderAmount = orderStatus.orderObject.actualPrice || 0
  176. this.orderPrice = orderStatus.orderObject.actualPrice || 0
  177. this.disabledCoupon = orderStatus.orderObject.orderNo ? true : false
  178. this.dataLoading = false
  179. // 0元支付特别处理
  180. if (this.orderPrice === 0 && orderStatus.orderObject.orderType) {
  181. this.loading = true
  182. this.onSubmit()
  183. }
  184. this.$nextTick(() => {
  185. // paymentButton
  186. // 处理超过一屏显示
  187. const { height } = useRect((this as any).$refs.paymentButton)
  188. this.bottomHeight = height + 10
  189. })
  190. if (!orderStatus.orderObject.orderType) {
  191. this.dialogVisible = true
  192. this.dialogContent = '产品信息已更新,请重新选择'
  193. this.dialogBtnText = '确定'
  194. this.dialogType = 'back'
  195. return
  196. }
  197. },
  198. methods: {
  199. async getUserRegisterProtocol() {
  200. // 获取是否签署过《用户注册协议》
  201. try {
  202. const res = await request.get(
  203. state.platformApi + '/sysUserContractRecord/checkContractSign',
  204. {
  205. params: {
  206. contractType: 'REGISTER'
  207. }
  208. }
  209. )
  210. this.exists = res.data
  211. } catch {
  212. //
  213. }
  214. },
  215. /** 查询支付类型 */
  216. async getOrderPayType() {
  217. try {
  218. const orderObject = orderStatus.orderObject
  219. // 单独处理其它支付类型下面用的bizId
  220. const orderItem = orderObject.orderList.find(
  221. (item: any) => item.orderType === this.orderType
  222. )
  223. let bizId = orderItem ? orderItem.id : ''
  224. if (orderObject.orderType === 'PRACTICE') {
  225. const orderItem = orderObject.orderList.find(
  226. (item: any) => item.orderType === 'PRACTICE'
  227. )
  228. bizId = orderItem ? orderItem.teacherId : ''
  229. }
  230. if (
  231. orderObject.orderType === 'LIVE' ||
  232. orderObject.orderType === 'VIDEO'
  233. ) {
  234. const orderItem = orderObject.orderList.find(
  235. (item: any) =>
  236. item.orderType === 'VIDEO' || item.orderType === 'LIVE'
  237. )
  238. bizId = orderItem ? orderItem.courseGroupId : ''
  239. }
  240. const { data } = await request.post(
  241. state.platformApi + '/userOrder/orderPayType',
  242. {
  243. data: {
  244. goodType: orderObject.orderType,
  245. bizId,
  246. recomUserId: orderObject.recomUserId
  247. ? orderObject.recomUserId
  248. : null
  249. }
  250. }
  251. )
  252. // 判断是否已经有支付方式了
  253. const paymentConfig = orderStatus.orderObject.paymentConfig || {}
  254. if (paymentConfig.paymentVersion && orderStatus.orderObject.orderNo) {
  255. this.paymentVersion = paymentConfig.paymentVersion || 'V1'
  256. this.paymentVendor = paymentConfig.paymentVendor
  257. } else {
  258. this.paymentVersion = data.paymentVersion || 'V1'
  259. this.paymentVendor = data.paymentVendor
  260. }
  261. this.paymentChannels = data.paymentChannels // 可以选择的支付类型
  262. } catch {
  263. //
  264. }
  265. },
  266. async onAuthSuccess() {
  267. this.popupShow = false
  268. await this.getUserRegisterProtocol()
  269. this.onSubmit() // 实名成功后自动支付
  270. },
  271. async onSubmit() {
  272. // console.log(this.orderInfos)
  273. if (this.orderPrice > 0) {
  274. if (!this.agreeStatus) {
  275. Toast('请先阅读并同意《酷乐秀平台服务协议》')
  276. return
  277. }
  278. const users = state.user.data
  279. // 判断是否需要实名认证, 姓名,卡号,是否签协议 || !this.exists
  280. if (!users?.realName || !users?.idCardNo) {
  281. this.popupShow = true
  282. return
  283. }
  284. }
  285. // 判断是否有订单号
  286. if (orderStatus.orderObject.orderNo) {
  287. if (this.paymentVersion === 'V1') {
  288. this.paymentStatus = true
  289. } else {
  290. this.orderInfo = orderStatus.orderObject.paymentConfig || {}
  291. console.log(orderStatus.orderObject, 'orderStatus.orderObject')
  292. this.orderNo = orderStatus.orderObject.orderNo
  293. const paymentChannel = this.orderInfo.paymentConfig.paymentChannel
  294. console.log(this.orderInfo, 'this.orderInfo.paymentConfig')
  295. // 判断是否为原生支付
  296. if (
  297. this.orderInfo.paymentVendor?.indexOf('wxpay') > -1 ||
  298. this.orderInfo.paymentVendor?.indexOf('alipay') > -1
  299. ) {
  300. this.paymentStatus = true
  301. } else {
  302. if (paymentChannel) {
  303. const payCode = beforeSubmit(paymentChannel)
  304. this.onConfirm({
  305. payCode,
  306. pay_channel: paymentChannel
  307. })
  308. } else {
  309. this.paymentStatus = true
  310. }
  311. }
  312. }
  313. return
  314. }
  315. // 正常支付
  316. try {
  317. const orderObject = orderStatus.orderObject
  318. if (this.paymentVersion === 'V1') {
  319. const url =
  320. state.platformType === 'TEACHER'
  321. ? '/api-teacher/userOrder/executeOrder'
  322. : '/api-student/userOrder/executeOrder'
  323. const res = await request.post(url, {
  324. data: {
  325. orderName: orderObject.orderName,
  326. orderDesc: orderObject.orderDesc,
  327. orderType: orderObject.orderType,
  328. actualPrice: this.orderPrice || 0,
  329. recomUserId: orderObject.recomUserId,
  330. activityId: orderObject.activityId,
  331. couponId: orderObject.couponId,
  332. orderInfos: [...orderInfos()]
  333. }
  334. })
  335. const result = res.data || {}
  336. if (res.code === 998 || res.code === 999) {
  337. this.dialogVisible = true
  338. this.dialogContent = res.msg
  339. this.dialogBtnText = '刷新'
  340. this.dialogType = 'back'
  341. return
  342. }
  343. // 支付成功
  344. if (result.status == 'PAID') {
  345. this.$router.replace({
  346. path: '/tradeDetail',
  347. query: {
  348. orderNo: result.orderNo
  349. }
  350. })
  351. return
  352. }
  353. // 拉起支付方式
  354. orderStatus.orderObject.orderNo = result.orderNo
  355. orderStatus.orderObject.actualPrice = result.actualPrice
  356. } else {
  357. const url =
  358. state.platformType === 'TEACHER'
  359. ? '/api-teacher/userOrder/executeOrder/v2'
  360. : '/api-student/userOrder/executeOrder/v2'
  361. const goods: any = orderTenantInfos()
  362. if (this.selectGoods && this.selectGoods.length > 0) {
  363. goods.push(...orderTenantInfos(this.selectGoods))
  364. }
  365. const res = await request.post(url, {
  366. data: {
  367. activityId:
  368. orderObject.activityId > 0 ? orderObject.activityId : null,
  369. couponIds: orderObject.couponId,
  370. goodsInfos: goods,
  371. orderDesc: orderObject.orderDesc,
  372. orderName: orderObject.orderName,
  373. orderType: orderObject.orderType,
  374. paymentCashAmount: this.orderPrice || 0,
  375. paymentType: this.paymentVendor,
  376. recomUserId: orderObject.recomUserId || null
  377. }
  378. })
  379. const result = res.data || {}
  380. // 支付成功
  381. if (res.code === 999 || res.code === 998) {
  382. this.dialogVisible = true
  383. this.dialogContent = res.msg
  384. this.dialogBtnText = '确定'
  385. this.dialogType = 'back'
  386. return
  387. }
  388. if (result.status == 'PAID') {
  389. this.$router.replace({
  390. path: '/tradeDetail',
  391. query: {
  392. orderNo: result.orderNo
  393. }
  394. })
  395. return
  396. }
  397. orderStatus.orderObject.paymentConfig = result || {}
  398. // orderStatus.orderObject.paymentConfig.actualPrice = result.paymentConfig.price
  399. orderStatus.orderObject.actualPrice = result.paymentConfig.price
  400. orderStatus.orderObject.orderNo = result?.orderNo
  401. this.orderInfo = result
  402. this.orderNo = result.orderNo
  403. }
  404. // console.log(orderStatus.orderObject, orderStatus.orderObject.paymentConfig, '111')
  405. this.paymentStatus = true
  406. } catch {
  407. this.loading = false
  408. if (this.orderPrice === 0) {
  409. Dialog.alert({
  410. title: '提示',
  411. message: '支付失败,请稍后重试!',
  412. confirmButtonText: '确定',
  413. confirmButtonColor: '#2dc7aa'
  414. })
  415. }
  416. }
  417. },
  418. async onDialogConfirm() {
  419. this.dialogVisible = false
  420. if (this.dialogType === 'back') {
  421. this.$router.back()
  422. } else if (this.dialogType === 'refresh') {
  423. // 更新会员天数
  424. const userInfo = await request.get(
  425. state.platformType === 'TEACHER'
  426. ? '/api-teacher/teacher/queryUserInfo'
  427. : '/api-student/student/queryUserInfo'
  428. )
  429. setLogin(userInfo.data)
  430. const vipEndDays = userInfo.data.userVip.vipEndDays || 0
  431. orderStatus.orderObject.orderList.forEach((item: any) => {
  432. item.vipEndDays = vipEndDays
  433. })
  434. }
  435. },
  436. onBackOut() {
  437. // 关闭订单后需要重置数据
  438. resestState()
  439. },
  440. onCouponSelect(item: any) {
  441. let discountCount = 0
  442. let universalCount = 0
  443. const tempPrice: any = {}
  444. this.orderGoodsType.forEach((type: any) => {
  445. tempPrice[type.orderType] = type.price
  446. })
  447. ;(item || []).forEach((child: any) => {
  448. if(child.couponCategory === 'UNIVERSAL') {
  449. universalCount += Number(child.discountPrice)
  450. } else {
  451. const tempCoupon = couponToOrderTypeEnum[child.couponCategory]
  452. let price = tempPrice[tempCoupon] - Number(child.discountPrice)
  453. // 折扣金额
  454. if(price >= 0) {
  455. discountCount += Number(child.discountPrice)
  456. } else {
  457. discountCount += Number(tempPrice[tempCoupon])
  458. }
  459. tempPrice[tempCoupon] = price >= 0 ? price : 0
  460. }
  461. })
  462. // 获取金额
  463. let tempAllAmount = 0
  464. for(let i in tempPrice) {
  465. tempAllAmount += tempPrice[i]
  466. }
  467. // 判断 通用券的金额是否大于订单的金额
  468. if(universalCount >= tempAllAmount) {
  469. universalCount = tempAllAmount
  470. }
  471. const lastAmount = Number(
  472. numberToTwoUp(tempAllAmount - Number(universalCount)
  473. )
  474. )
  475. this.orderPrice = lastAmount >= 0 ? lastAmount : 0
  476. // 设置优惠券编号
  477. const couponIds = (item || []).map((item: any) => {
  478. return item.couponIssueId
  479. })
  480. orderStatus.orderObject.couponId = couponIds.join(',') || ''
  481. orderStatus.orderObject.couponDiscountPrice = discountCount + universalCount
  482. },
  483. onConfirm(val: any) {
  484. // debugger
  485. const config: any = this.orderInfo.paymentConfig || {}
  486. this.pay_channel = val.pay_channel
  487. const params = qs.stringify({
  488. pay_channel: val.pay_channel,
  489. wxAppId: config.wxAppId,
  490. alipayAppId: config.alipayAppId,
  491. paymentType: this.orderInfo.paymentType,
  492. body: config.body,
  493. price: config.price,
  494. orderNo: config.merOrderNo,
  495. userId: config.userId
  496. })
  497. orderStatus.orderObject.paymentConfig.paymentConfig.paymentChannel = val.pay_channel
  498. console.log(params, 'params ---', config)
  499. if (val.payCode === 'payResult') {
  500. window.location.href =
  501. window.location.origin + state.payBackPath + '#/payResult?' + params
  502. } else {
  503. this.qrCodeUrl =
  504. window.location.origin + state.payBackPath + '#/payDefine?' + params
  505. this.showQrcode = true
  506. this.paymentStatus = false
  507. setTimeout(() => {
  508. this.getPaymentOrderStatus()
  509. }, 300)
  510. }
  511. },
  512. // 轮询查询订单状态
  513. async getPaymentOrderStatus() {
  514. // 循环查询订单
  515. // const orderNo = state.orderNo
  516. const orderTimer = setInterval(async () => {
  517. // 判断是否在当前路由,如果不是则清除定时器
  518. if (this.$route.name != 'orderDetail') {
  519. clearInterval(orderTimer)
  520. return
  521. }
  522. this.orderTimer = orderTimer
  523. try {
  524. const urlFix =
  525. state.platformType === 'TEACHER' ? '/api-teacher' : '/api-student'
  526. const { data } = await request.get(
  527. `${urlFix}/userOrder/detailByOrderNo/${this.orderNo}`,
  528. {
  529. hideLoading: true
  530. }
  531. )
  532. if (data.status !== 'WAIT_PAY' && data.status !== 'PAYING') {
  533. // 默认关闭支付二维码弹窗
  534. this.showQrcode = false
  535. clearInterval(this.orderTimer)
  536. setTimeout(() => {
  537. this.$router.replace({
  538. path: '/tradeDetail',
  539. query: {
  540. orderNo: this.orderNo
  541. }
  542. })
  543. }, 100)
  544. }
  545. } catch (e: any) {
  546. //
  547. console.log(e, 'error')
  548. clearInterval(this.orderTimer)
  549. }
  550. }, 5000)
  551. }
  552. },
  553. beforeUnmount() {
  554. resestState()
  555. },
  556. render() {
  557. return (
  558. <div
  559. class={styles['order-detail']}
  560. style={{
  561. paddingBottom: this.bottomHeight + 'px'
  562. }}
  563. >
  564. <ColHeader />
  565. {!this.loading && (
  566. <>
  567. {this.orderList.map((item: any) => {
  568. if (item.orderType === 'VIDEO') {
  569. return <OrderVideo item={item} />
  570. } else if (item.orderType === 'LIVE') {
  571. return <OrderLive item={item} />
  572. } else if (item.orderType === 'PRACTICE') {
  573. return <OrderPractice item={item} />
  574. } else if (item.orderType === 'VIP_COURSE') {
  575. return <OrderVipCourse item={item} />
  576. } else if (
  577. item.orderType === 'VIP' ||
  578. item.orderType === 'SVIP'
  579. ) {
  580. return (
  581. <OrderVip
  582. item={item}
  583. disabled={this.disabledCoupon}
  584. onPriceChange={(price: number) => {
  585. // 畅学卡变更状态时需要重新选择优惠券
  586. orderStatus.orderObject.couponId = ''
  587. orderStatus.orderObject.couponDiscountPrice = 0
  588. // 重置金额
  589. this.orderAmount = Number(price)
  590. const lastAmount = Number(
  591. numberToTwoUp(
  592. Number(this.orderAmount) -
  593. Number(orderStatus.orderObject.couponDiscountPrice)
  594. )
  595. )
  596. this.orderPrice = lastAmount >= 0 ? lastAmount : 0
  597. this.orderGoodsType.forEach((child: any) => {
  598. if (child.orderType === item.orderType) {
  599. child.price = Number(price)
  600. }
  601. })
  602. // 更新优惠券列表
  603. const useCouponRef: any = this.$refs.useCouponRef
  604. if (useCouponRef) {
  605. useCouponRef.resetCouponList()
  606. }
  607. }}
  608. />
  609. )
  610. } else if (item.orderType === 'MUSIC') {
  611. return <OrderMusic item={item} />
  612. } else if (item.orderType === 'PIANO_ROOM') {
  613. return <OrderPinao item={item} />
  614. } else if (item.orderType === 'ACTI_REGIST') {
  615. return <OrderActive item={item} />
  616. } else if (item.orderType === 'ALBUM') {
  617. return <OrderAlbum item={item} />
  618. } else if (item.orderType === 'TENANT_ALBUM') {
  619. return <OrderTennatAlbum item={item} />
  620. } else if (item.orderType === 'DISCOUNT') {
  621. return (
  622. <OrderDiscount
  623. disabled={this.disabledCoupon}
  624. item={item}
  625. onPriceChange={(price: number) => {
  626. // 畅学卡变更状态时需要重新选择优惠券
  627. orderStatus.orderObject.couponId = ''
  628. orderStatus.orderObject.couponDiscountPrice = 0
  629. // 重置金额
  630. this.orderAmount = Number(price)
  631. const lastAmount = Number(
  632. numberToTwoUp(
  633. Number(this.orderAmount) -
  634. Number(orderStatus.orderObject.couponDiscountPrice)
  635. )
  636. )
  637. this.orderPrice = lastAmount >= 0 ? lastAmount : 0
  638. this.orderGoodsType.forEach((child: any) => {
  639. if (child.orderType === item.orderType) {
  640. child.price = Number(price)
  641. }
  642. })
  643. // 更新优惠券列表
  644. const useCouponRef: any = this.$refs.useCouponRef
  645. if (useCouponRef) {
  646. useCouponRef.resetCouponList()
  647. }
  648. }}
  649. />
  650. )
  651. }
  652. })}
  653. {/* 畅学卡 - 目前只有学生端支持 */}
  654. {state.platformType === 'STUDENT' &&
  655. !this.dataLoading &&
  656. !this.disabledCoupon ? (
  657. <AddDiscount
  658. actualPrice={this.orderAmount}
  659. orderType={this.orderType}
  660. orderGoodsType={this.orderGoodsType}
  661. onConfirmOnlyDiscount={(item: {
  662. checked: boolean
  663. id: number | null
  664. salePrice: number
  665. discountRate: number
  666. discountPrice: number | string
  667. vipType: string
  668. }) => {
  669. orderStatus.orderObject.discountCardPrice = Number(
  670. item.discountPrice
  671. )
  672. this.orderGoodsType.forEach((child: any) => {
  673. if (child.orderType !== 'DISCOUNT') {
  674. child.price = numberToTwoUp(
  675. child.price - Number(item.discountPrice)
  676. )
  677. }
  678. })
  679. // 更新优惠券列表
  680. const useCouponRef: any = this.$refs.useCouponRef
  681. if (useCouponRef) {
  682. useCouponRef.resetCouponList()
  683. }
  684. this.orderPrice = Number(
  685. numberToTwoUp(
  686. Number(this.orderAmount) -
  687. Number(item.discountPrice) -
  688. Number(orderStatus.orderObject.couponDiscountPrice)
  689. )
  690. )
  691. }}
  692. onConfirm={(item: {
  693. checked: boolean
  694. id: number | null
  695. salePrice: number
  696. discountRate: number
  697. discountPrice: number | string
  698. vipType: string
  699. }) => {
  700. // 畅学卡变更状态时需要重新选择优惠券
  701. orderStatus.orderObject.couponId = ''
  702. orderStatus.orderObject.couponDiscountPrice = 0
  703. // 是否选中畅学卡
  704. const index = this.selectGoods?.findIndex(
  705. (child: any) => child.id === item.id
  706. )
  707. const tempType = this.orderGoodsType
  708. if (item.checked) {
  709. orderStatus.orderObject.discountCardPrice = Number(
  710. item.discountPrice
  711. )
  712. this.orderGoodsType.forEach((child: any) => {
  713. if (child.orderType !== 'DISCOUNT') {
  714. child.price = numberToTwoUp(
  715. child.price - Number(item.discountPrice)
  716. )
  717. }
  718. })
  719. if (index === -1) {
  720. this.orderAmount = this.orderAmount + item.salePrice
  721. this.selectGoods.push({
  722. orderType: item.vipType,
  723. goodsName: '畅学卡',
  724. num: 1,
  725. id: item.id
  726. })
  727. const typeIndex = tempType.findIndex(
  728. (child: any) => child.orderType === item.vipType
  729. )
  730. if (typeIndex === -1) {
  731. tempType.push({
  732. orderType: item.vipType,
  733. price: item.salePrice
  734. })
  735. }
  736. }
  737. } else {
  738. orderStatus.orderObject.discountCardPrice = 0
  739. if (index !== -1) {
  740. this.selectGoods.splice(index, 1)
  741. this.orderAmount = this.orderAmount - item.salePrice
  742. this.orderGoodsType.forEach((child: any) => {
  743. if (child.orderType !== 'DISCOUNT') {
  744. child.price = child.basePrice
  745. }
  746. })
  747. const typeIndex = tempType.findIndex(
  748. (child: any) => child.orderType === item.vipType
  749. )
  750. if (typeIndex !== -1) {
  751. tempType.splice(typeIndex, 1)
  752. }
  753. }
  754. }
  755. this.orderGoodsType = tempType
  756. // 更新优惠券列表
  757. const useCouponRef: any = this.$refs.useCouponRef
  758. if (useCouponRef) {
  759. // console.log(useCouponRef, 'useCouponRef')
  760. useCouponRef.resetCouponList()
  761. }
  762. this.orderPrice = Number(
  763. numberToTwoUp(
  764. Number(this.orderAmount) -
  765. Number(item.discountPrice) -
  766. Number(orderStatus.orderObject.couponDiscountPrice)
  767. )
  768. )
  769. this.$forceUpdate()
  770. }}
  771. />
  772. ) : (
  773. ''
  774. )}
  775. {/* 只做显示用 - 不参与逻辑 */}
  776. {state.platformType === 'STUDENT' &&
  777. !this.dataLoading &&
  778. this.disabledCoupon &&
  779. orderStatus.orderObject.discountCardPrice > 0 ? (
  780. <CellGroup class={['mb12', styles.cellGroup]} border={false}>
  781. <Cell
  782. center
  783. v-slots={{
  784. title: () => (
  785. <div class={styles.timerCell}>
  786. <div class={styles.timerTitle}>
  787. <span>畅学卡优惠</span>
  788. </div>
  789. <div class={styles.timer}>
  790. -¥
  791. {(this as any).$filters.moneyFormat(
  792. orderStatus.orderObject.discountCardPrice
  793. )}
  794. </div>
  795. </div>
  796. )
  797. }}
  798. />
  799. </CellGroup>
  800. ) : (
  801. ''
  802. )}
  803. {/* 优惠券使用 */}
  804. {!this.dataLoading && (
  805. <UseCoupon
  806. ref="useCouponRef"
  807. couponId={orderStatus.orderObject.couponId}
  808. discountPrice={orderStatus.orderObject.discountPrice}
  809. orderType={this.orderType}
  810. orderGoodsType={this.orderGoodsType}
  811. orderAmount={
  812. this.orderAmount - orderStatus.orderObject.discountCardPrice
  813. }
  814. onCouponSelect={this.onCouponSelect}
  815. disabled={this.disabledCoupon}
  816. />
  817. )}
  818. <div class={styles.paymentInfo} ref="paymentButton">
  819. {this.orderPrice > 0 && (
  820. <div
  821. class={[
  822. styles.protocol,
  823. state.projectType === 'tenant' && styles.protocolTenant
  824. ]}
  825. >
  826. <ColProtocol
  827. v-model={this.agreeStatus}
  828. showHeader
  829. style={{ paddingLeft: 0, paddingRight: 0 }}
  830. onProtocolExists={(val: any) => {
  831. this.exists = val
  832. }}
  833. />
  834. </div>
  835. )}
  836. <div class={styles.btnGroup}>
  837. <div class={styles.priceSection}>
  838. <span class={styles.goodsNum}>共{this.goodsNum || 1}件</span>
  839. <div>
  840. <div>
  841. 合计:
  842. <div class={styles.price}>
  843. <span class={styles.priceUnit}>¥</span>
  844. <span class={styles.priceNum}>
  845. {moneyFormat(this.orderPrice)}
  846. </span>
  847. </div>
  848. </div>
  849. {this.countDiscountPrice > 0 ? (
  850. <div class={styles.isDiscountPrice}>
  851. 已优惠 ¥{moneyFormat(this.countDiscountPrice)}
  852. </div>
  853. ) : (
  854. ''
  855. )}
  856. </div>
  857. </div>
  858. <Button
  859. type="primary"
  860. round
  861. class={[
  862. styles.btn,
  863. state.projectType === 'tenant' && styles.btnTenant
  864. ]}
  865. onClick={this.onSubmit}
  866. >
  867. 立即支付
  868. </Button>
  869. </div>
  870. </div>
  871. </>
  872. )}
  873. <ColPopup v-model={this.popupShow}>
  874. <UserAuth exists={this.exists} onSuccess={this.onAuthSuccess} />
  875. </ColPopup>
  876. <Popup
  877. show={this.paymentStatus}
  878. closeOnClickOverlay={false}
  879. position="bottom"
  880. round
  881. closeOnPopstate
  882. safeAreaInsetBottom
  883. style={{ minHeight: '30%' }}
  884. >
  885. {/* 判断类型使用什么去支付 */}
  886. {this.paymentVersion === 'V1' ? (
  887. <Payment
  888. v-model={this.paymentStatus}
  889. orderInfo={orderStatus.orderObject}
  890. onBackOut={this.onBackOut}
  891. />
  892. ) : (
  893. <UrlPayment
  894. paymentConfig={{
  895. ...orderStatus.orderObject,
  896. orderNo: this.orderNo
  897. }}
  898. // paymentVersion={this.paymentVersion}
  899. paymentVendor={this.paymentVendor}
  900. paymentChannels={this.paymentChannels}
  901. onClose={() => (this.paymentStatus = false)}
  902. onBackOut={this.onBackOut}
  903. onConfirm={(val: any) => this.onConfirm(val)}
  904. />
  905. )}
  906. </Popup>
  907. <Popup
  908. v-model:show={this.showQrcode}
  909. round
  910. class={styles.qrcodePopup}
  911. onClose={() => {
  912. // 二维码关闭时清除定时器
  913. clearInterval(this.orderTimer)
  914. }}
  915. >
  916. <QrcodePayment
  917. url={this.qrCodeUrl}
  918. pay_channel={this.pay_channel}
  919. // orderType={orderType.value}
  920. />
  921. </Popup>
  922. <Popup
  923. v-model:show={this.dialogVisible}
  924. style={{ background: 'transparent' }}
  925. closeOnClickOverlay={false}
  926. >
  927. <div class={styles.dialogContainer}>
  928. <div class={styles.dialogTitle}>提示</div>
  929. <div class={styles.dialogContent}>{this.dialogContent}</div>
  930. <div class={styles.dialogBtnGroup}>
  931. <Button
  932. round
  933. type="primary"
  934. block
  935. class={styles.dialogBtn}
  936. onClick={this.onDialogConfirm}
  937. >
  938. {this.dialogBtnText}
  939. </Button>
  940. </div>
  941. </div>
  942. </Popup>
  943. </div>
  944. )
  945. }
  946. })