lock.uvue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <script setup lang='ts'>
  2. import { type PropType } from 'vue'
  3. import { dict } from '@/.cool/store'
  4. import { wechatPay, wechatPayRequest, wechatPayQuery, wechatPayCancel } from '@/services/user'
  5. import { type SubjectCourseResult, fetchSubjectCourseApp } from '@/services/subject/course'
  6. import { user } from '@/.cool'
  7. import { ref } from 'vue'
  8. const emit = defineEmits(['close'])
  9. const props = defineProps({
  10. record: {
  11. type: Object,
  12. default: () => ({})
  13. },
  14. type: {
  15. type: String as PropType<'vip' | 'course' | 'test'>,
  16. default: 'vip'
  17. },
  18. finish: {
  19. type: Boolean,
  20. default: true
  21. },
  22. studyUnitLock: {
  23. type: Boolean,
  24. default: false
  25. }
  26. })
  27. const visible = ref(false)
  28. const visible2 = ref(false)
  29. const visible3 = ref(false)
  30. const visible4 = ref(false)
  31. const visible5 = ref(false)
  32. const msg = ref('')
  33. function handleOpen() {
  34. console.log(1)
  35. switch (props.type) {
  36. case 'course':
  37. if (!props.record.payFlag) {
  38. visible.value = true
  39. return
  40. }
  41. fetchSubjectCourseApp({
  42. id: props.record.id
  43. }).then(res => {
  44. if (res.studyUnitLock) {
  45. visible4.value = true
  46. msg.value = res.msg
  47. }
  48. })
  49. break;
  50. case 'vip':
  51. visible3.value = true
  52. break;
  53. case 'test':
  54. visible5.value = true
  55. break;
  56. }
  57. }
  58. async function getPayStatus(outTradeNo: string) {
  59. const res = await wechatPayQuery({
  60. outTradeNo
  61. })
  62. if (res.code !== 1000) {
  63. getPayStatus(outTradeNo)
  64. } else {
  65. emit('close', true)
  66. await user.get()
  67. }
  68. }
  69. const handlePay = async () => {
  70. try {
  71. const { prepayId, outTradeNo } = await wechatPay({
  72. subjectId: props.type === 'course' ? props.record.subjectId : dict.getValueByLabelMapByType('index_subject_id')['物理'],
  73. })
  74. const { signature, timestamp, nonceStr } = await wechatPayRequest({
  75. prepayId, outTradeNo
  76. })
  77. console.log(signature)
  78. uni.requestPayment({
  79. provider: "wxpay",
  80. timeStamp: timestamp,
  81. nonceStr: nonceStr,
  82. package: "prepay_id=" + prepayId,
  83. paySign: signature,
  84. signType: "RSA",
  85. success: (res) => {
  86. console.log('res: ', res)
  87. uni.showToast({
  88. title: "支付成功",
  89. icon: 'success'
  90. });
  91. // 支付成功后,查询支付结果
  92. getPayStatus(outTradeNo)
  93. },
  94. fail: (err) => {
  95. console.error("err", err);
  96. uni.hideLoading();
  97. // 支付失败后,取消订单
  98. wechatPayCancel({
  99. outTradeNo
  100. }).then(res => {
  101. if (res.code === 200) {
  102. uni.showToast({
  103. title: "订单已取消",
  104. icon: 'success'
  105. });
  106. emit('close', false)
  107. }
  108. })
  109. }
  110. });
  111. } catch (err: any) {
  112. uni.showToast({
  113. title: err.message,
  114. icon: 'error'
  115. });
  116. }
  117. }
  118. </script>
  119. <template>
  120. <view class="absolute top-0 left-0 w-full h-full flex items-center justify-center bg1" @tap.stop="handleOpen">
  121. <cl-image src="https://oss.xiaoxiongcode.com/static/home/lock.png" mode="widthFix" width="30%" height="auto" />
  122. </view>
  123. <cl-popup v-model="visible" showClose :size="400" :show-header="false" direction="center">
  124. <view class="p-[40px] ">
  125. <cl-text class="text-center" color="#000" :size="20"> 小朋友,快叫爸爸妈妈帮忙,解锁更多精彩内容吧! </cl-text>
  126. <cl-button class="mt-4" size="large" type="warn" block @tap="handlePay"> 前往购课 </cl-button>
  127. </view>
  128. </cl-popup>
  129. <cl-popup v-model="visible2" showClose :size="400" :show-header="false" direction="center">
  130. <view class="p-[40px] ">
  131. <cl-text class="text-center" color="#000" :size="20"> 请先学习完前面章节再来解锁! </cl-text>
  132. <cl-button class="mt-4" size="large" type="warn" block @tap="visible2 = false"> 返回 </cl-button>
  133. </view>
  134. </cl-popup>
  135. <cl-popup v-model="visible5" showClose :size="400" :show-header="false" direction="center">
  136. <view class="p-[40px] ">
  137. <cl-text class="text-center" color="#000" :size="20"> 请先学习完本章节课程再来解锁! </cl-text>
  138. <cl-button class="mt-4" size="large" type="warn" block @tap="visible5 = false"> 返回 </cl-button>
  139. </view>
  140. </cl-popup>
  141. <cl-popup v-model="visible3" showClose :size="400" :show-header="false" direction="center">
  142. <view class="p-[40px] ">
  143. <cl-text class="text-center" color="#000" :size="20"> 小朋友,快叫爸爸妈妈帮忙成为会员,解锁更多精彩内容吧! </cl-text>
  144. <cl-text class="text-center" color="#666" :size="14"> 购买物理AI课后自动成为会员</cl-text>
  145. <cl-button class="mt-4" size="large" type="warn" block @tap="handlePay"> 前往购课 </cl-button>
  146. </view>
  147. </cl-popup>
  148. <cl-popup v-model="visible4" showClose :size="400" :show-header="false" direction="center">
  149. <view class="p-[40px] ">
  150. <cl-text class="text-center" color="#000" :size="20"> {{ msg }} </cl-text>
  151. <cl-button class="mt-4" size="large" type="warn" block @tap="visible4 = false"> 返回 </cl-button>
  152. </view>
  153. </cl-popup>
  154. </template>
  155. <style lang="scss" scoped>
  156. .bg1 {
  157. background-color: rgba(255, 255, 255, 0.5);
  158. }
  159. </style>