live-detail.tsx 10 KB

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