live-detail.tsx 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. import CoursePlanStep from '@/business-components/course-plan-step'
  2. import SectionDetail from '@/business-components/section-detail'
  3. import UserDetail from '@/business-components/user-detail'
  4. import request from '@/helpers/request'
  5. import dayjs from 'dayjs'
  6. import { Icon, Sticky, Button, Dialog, Toast } from 'vant'
  7. import { defineComponent } from 'vue'
  8. import styles from './live-detail.module.less'
  9. import iconTips from '@common/images/icon_tips.png'
  10. import { orderStatus } from '@/views/order-detail/orderStatus'
  11. import ColHeader from '@/components/col-header'
  12. import { postMessage } from '@/helpers/native-message'
  13. interface IProps {
  14. courseTime: string
  15. coursePlan: string
  16. videoPosterUrl?: string
  17. id?: number | string
  18. }
  19. export default defineComponent({
  20. name: 'LiveDetail',
  21. data() {
  22. const query = this.$route.query
  23. return {
  24. joinRoom: query.joinRoom, // 原生传递过来的参数,判断是否进入直播间
  25. groupId: query.groupId,
  26. courseId: query.classId,
  27. live: {} as any
  28. }
  29. },
  30. computed: {
  31. userInfo() {
  32. const live = this.live as any
  33. const planList = live.planList || []
  34. const startTime = planList[0]?.startTime || new Date()
  35. const endTime = planList[0]?.endTime || new Date()
  36. return {
  37. headUrl: live.avatar,
  38. username: live.userName || `游客${live.teacherId || ''}`,
  39. startTime:
  40. `${dayjs(startTime).format('YYYY-MM-DD')} ${dayjs(startTime).format(
  41. 'HH:mm'
  42. )}~${dayjs(endTime).format('HH:mm')}` || '',
  43. buyNum: live.studentCount,
  44. lessonPrice: live.coursePrice,
  45. lessonNum: live.courseNum,
  46. lessonDesc: live.courseIntroduce,
  47. lessonCoverUrl: live.backgroundPic || live.backgroundPicTemplate,
  48. lessonName: live.courseGroupName
  49. }
  50. },
  51. courseInfo() {
  52. let tempArr = [] as IProps[]
  53. const coursePlanList = this.live.planList || []
  54. coursePlanList.forEach((item: any) => {
  55. const startTime = item.startTime || new Date()
  56. const endTime = item.endTime || new Date()
  57. tempArr.push({
  58. courseTime: `${dayjs(startTime).format('YYYY-MM-DD')} ${dayjs(
  59. startTime
  60. ).format('HH:mm')}~${dayjs(endTime).format('HH:mm')}`,
  61. coursePlan: item.plan,
  62. id: item.courseId
  63. })
  64. })
  65. return tempArr || []
  66. },
  67. salesEndDate() {
  68. const live = this.live as any
  69. return dayjs(live.salesEndDate || new Date()).format('YYYY-MM-DD')
  70. },
  71. liveStatus() {
  72. const coursePlanList = this.live.planList || []
  73. const tempObj = {
  74. status: false,
  75. liveStatus: 0,
  76. roomUid: ''
  77. }
  78. coursePlanList.forEach((item: any) => {
  79. if (item.courseId === Number(this.courseId)) {
  80. tempObj.status = true
  81. tempObj.liveStatus = item.liveStatus
  82. tempObj.roomUid = item.roomUid
  83. }
  84. })
  85. return tempObj
  86. }
  87. },
  88. async mounted() {
  89. try {
  90. const res = await request.get(
  91. '/api-student/courseGroup/queryLiveCourseInfo',
  92. {
  93. params: {
  94. groupId: this.groupId
  95. }
  96. }
  97. )
  98. this.live = res.data || {}
  99. } catch {}
  100. },
  101. methods: {
  102. async onJoinRoom() {
  103. try {
  104. const res = await request.get(
  105. '/api-student/courseGroup/queryLiveCourseInfo',
  106. {
  107. params: {
  108. groupId: this.groupId
  109. }
  110. }
  111. )
  112. const result = res.data || {}
  113. const coursePlanList = result.planList || []
  114. let tempObj: any = {}
  115. coursePlanList.forEach((item: any) => {
  116. if (item.courseId === Number(this.courseId)) {
  117. tempObj = item
  118. }
  119. })
  120. if (tempObj && tempObj.liveState === 1) {
  121. postMessage({
  122. api: 'joinLiveRoom',
  123. content: {
  124. roomId: this.liveStatus.roomUid,
  125. teacherId: this.live.teacherId
  126. }
  127. })
  128. } else {
  129. setTimeout(() => {
  130. Toast('课程尚未开始,请耐心等候')
  131. }, 100)
  132. }
  133. } catch {}
  134. },
  135. async onBuy() {
  136. try {
  137. const res = await request.post(
  138. '/api-student/userOrder/getPendingOrder',
  139. {
  140. data: {
  141. goodType: 'LIVE',
  142. bizId: this.groupId
  143. }
  144. }
  145. )
  146. const live = this.live
  147. orderStatus.orderObject.orderType = 'LIVE'
  148. orderStatus.orderObject.orderName = '直播课购买'
  149. orderStatus.orderObject.orderDesc = '直播课购买'
  150. orderStatus.orderObject.actualPrice = live.coursePrice
  151. orderStatus.orderObject.orderNo = ''
  152. orderStatus.orderObject.orderList = [
  153. {
  154. orderType: 'LIVE',
  155. goodsName: '直播课购买',
  156. courseGroupId: live.courseGroupId,
  157. courseGroupName: live.courseGroupName,
  158. coursePrice: live.coursePrice,
  159. teacherName: live.teacherName || `游客${live.teacherId || ''}`,
  160. teacherId: live.teacherId,
  161. avatar: live.avatar,
  162. courseInfo: this.courseInfo
  163. }
  164. ]
  165. const result = res.data
  166. if (result) {
  167. Dialog.confirm({
  168. title: '提示',
  169. message: '您有一个未支付的订单,是否继续支付?',
  170. confirmButtonColor: '#269a93',
  171. cancelButtonText: '取消订单',
  172. confirmButtonText: '继续支付'
  173. })
  174. .then(async () => {
  175. orderStatus.orderObject.orderNo = result.orderNo
  176. orderStatus.orderObject.actualPrice = result.actualPrice
  177. this.routerTo()
  178. })
  179. .catch(() => {
  180. Dialog.close()
  181. // 只用取消订单,不用做其它处理
  182. this.cancelPayment(result.orderNo)
  183. })
  184. } else {
  185. this.routerTo()
  186. }
  187. } catch {}
  188. },
  189. routerTo() {
  190. const live = this.live
  191. this.$router.push({
  192. path: '/orderDetail',
  193. query: {
  194. orderType: 'LIVE',
  195. courseGroupId: live.courseGroupId
  196. }
  197. })
  198. },
  199. async cancelPayment(orderNo: string) {
  200. try {
  201. await request.post('/api-student/userOrder/orderCancel', {
  202. data: {
  203. orderNo
  204. }
  205. })
  206. // this.routerTo()
  207. } catch {}
  208. }
  209. },
  210. render() {
  211. return (
  212. <div class={[styles['live-detail'], 'mb12']}>
  213. <ColHeader />
  214. <UserDetail userInfo={this.userInfo} showBuy={false} />
  215. <SectionDetail>
  216. <p class={styles.introduction}>{this.userInfo.lessonDesc}</p>
  217. </SectionDetail>
  218. <SectionDetail
  219. title="课程列表"
  220. icon="courseList"
  221. contentStyle={{ paddingTop: '0' }}
  222. >
  223. {this.courseInfo.length > 0 && (
  224. <CoursePlanStep
  225. courseInfo={this.courseInfo}
  226. courseId={Number(this.courseId) || 0}
  227. />
  228. )}
  229. </SectionDetail>
  230. <div class={styles.tips}>
  231. <h3>
  232. <Icon name={iconTips} size={15} />
  233. 温馨提示
  234. </h3>
  235. <p>
  236. 1、该直播课程销售截止后,报名人数若少于
  237. {this.live.mixStudentNum || 0}
  238. 人将取消开课,已购买学员付费金额将自动返还,请您放心购买;
  239. <br />
  240. 2、直播课教学计划中的上课时间为老师预计时间,实际上课时间以老师开启直播时间为准;
  241. <br />
  242. 3、若您错过老师直播,可通过视频回放观看完整课程。
  243. </p>
  244. </div>
  245. {this.courseInfo.length > 0 && this.live.existBuy !== 1 && (
  246. <Sticky offsetBottom={0} position="bottom">
  247. <div class={['btnGroup', styles.btnMore]}>
  248. <Button block round type="primary" onClick={this.onBuy}>
  249. 立即购买
  250. </Button>
  251. </div>
  252. </Sticky>
  253. )}
  254. {this.joinRoom == '1' && this.liveStatus.liveStatus !== 2 && (
  255. <Sticky offsetBottom={0} position="bottom">
  256. <div class={['btnGroup']} style={{ paddingTop: '12px' }}>
  257. <Button block round type="primary" onClick={this.onJoinRoom}>
  258. 进入直播间
  259. </Button>
  260. </div>
  261. </Sticky>
  262. )}
  263. </div>
  264. )
  265. }
  266. })