index.tsx 37 KB

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