live-detail.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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 UserList from '@/business-components/user-list'
  5. import ColResult from '@/components/col-result'
  6. import ColShare from '@/components/col-share'
  7. import ColSticky from '@/components/col-sticky'
  8. import { postMessage } from '@/helpers/native-message'
  9. import request from '@/helpers/request'
  10. import { state } from '@/state'
  11. import LiveItem from '@/views/live-class/live-item'
  12. import dayjs from 'dayjs'
  13. import { Button, Popup, Sticky, Tab, Tabs, Toast } from 'vant'
  14. import { defineComponent } from 'vue'
  15. import styles from './live-detail.module.less'
  16. import ColHeader from '@/components/col-header'
  17. import TheSticky from '@/components/the-sticky'
  18. interface IProps {
  19. courseTime: string
  20. coursePlan: string
  21. videoPosterUrl?: string
  22. roomUid?: string
  23. liveState?: number
  24. id?: number | string
  25. }
  26. export default defineComponent({
  27. name: 'LiveDetail',
  28. data() {
  29. const query = this.$route.query
  30. return {
  31. share: query.share,
  32. joinRoom: query.joinRoom, // 原生传递过来的参数,判断是否进入直播间
  33. groupId: query.groupId,
  34. courseId: query.classId,
  35. live: {} as any,
  36. shareStatus: false,
  37. shareUrl: '',
  38. myself: false
  39. }
  40. },
  41. computed: {
  42. userInfo() {
  43. const live = this.live as any
  44. const planList = live.planList || []
  45. const startTime = planList[0]?.startTime || new Date()
  46. // const endTime = planList[0]?.endTime || new Date()
  47. return {
  48. headUrl: live.avatar,
  49. avatar: live.avatar,
  50. username: live.userName,
  51. id: live.teacherId,
  52. startTime:
  53. `${dayjs(startTime).format('YYYY-MM-DD')} ${dayjs(startTime).format(
  54. 'HH:mm'
  55. )}` || '',
  56. courseStartTime: dayjs(live.courseStartTime).format('YYYY-MM-DD HH:mm'),
  57. lessonPrice: live.coursePrice,
  58. buyNum: live.studentCount || 0,
  59. type: 'live',
  60. lessonId: live.courseGroupId,
  61. completeCourseNum: live.completeCourseNum, // 已上课时
  62. isShowCourse: live.status !== 'APPLY', // 是否显示课程
  63. lessonNum: live.courseNum || 0, // 课时数
  64. lessonDesc: live.courseIntroduce,
  65. lessonCoverUrl: live.backgroundPic || live.backgroundPicTemplate,
  66. lessonName: live.courseGroupName,
  67. subjectName: live.subjectName,
  68. auditVersion: live.auditVersion || 0,
  69. isDegree: live.degreeFlag ? true : false,
  70. isTeacher: live.teacherFlag ? true : false
  71. }
  72. },
  73. courseInfo() {
  74. const tempArr = [] as IProps[]
  75. const coursePlanList = this.live.planList || []
  76. coursePlanList.forEach((item: any) => {
  77. const startTime = item.startTime || new Date()
  78. const endTime = item.endTime || new Date()
  79. tempArr.push({
  80. courseTime: `${dayjs(startTime).format('YYYY-MM-DD')} ${dayjs(
  81. startTime
  82. ).format('HH:mm')}~${dayjs(endTime).format('HH:mm')}`,
  83. coursePlan: item.plan,
  84. roomUid: item.roomUid,
  85. liveState: item.liveState,
  86. id: item.courseId
  87. })
  88. })
  89. return tempArr || []
  90. },
  91. liveStatus() {
  92. const coursePlanList = this.live.planList || []
  93. const tempObj = {
  94. status: false,
  95. liveStatus: 0,
  96. roomUid: ''
  97. }
  98. coursePlanList.forEach((item: any) => {
  99. if (item.courseId === Number(this.courseId)) {
  100. tempObj.status = true
  101. tempObj.liveStatus = item.liveStatus
  102. tempObj.roomUid = item.roomUid
  103. }
  104. })
  105. return tempObj
  106. },
  107. studentList() {
  108. const live = this.live as any
  109. return live.studentList || []
  110. },
  111. courseOffStatus() {
  112. const live = this.live as any
  113. let status = false
  114. if (
  115. (live.status === 'APPLY' && live.studentList.length === 0) ||
  116. live.status === 'NOT_SALE'
  117. ) {
  118. status = true
  119. }
  120. return status
  121. }
  122. },
  123. async mounted() {
  124. try {
  125. const res = await request.get(
  126. '/api-teacher/courseGroup/queryLiveCourseInfo',
  127. {
  128. params: {
  129. groupId: this.groupId
  130. }
  131. }
  132. )
  133. this.live = res.data || {}
  134. if (state.platformType === 'TEACHER') {
  135. this.myself = !res.data.myself
  136. }
  137. this.shareUrl = `${location.origin}/teacher/#/shareLive?recomUserId=${state.user.data?.userId}&groupId=${this.groupId}&p=tenant`
  138. // console.log(this.live)
  139. } catch {
  140. //
  141. }
  142. },
  143. methods: {
  144. async onJoinRoom() {
  145. try {
  146. const res = await request.get(
  147. '/api-teacher/courseGroup/queryLiveCourseInfo',
  148. {
  149. params: {
  150. groupId: this.groupId
  151. }
  152. }
  153. )
  154. const result = res.data || {}
  155. const coursePlanList = result.planList || []
  156. let tempObj: any = {}
  157. coursePlanList.forEach((item: any) => {
  158. if (item.courseId === Number(this.courseId)) {
  159. tempObj = item
  160. }
  161. })
  162. if (tempObj && tempObj.liveState === 1) {
  163. postMessage({
  164. api: 'joinLiveRoom',
  165. content: {
  166. roomId: tempObj.roomUid,
  167. teacherId: this.live.teacherId
  168. }
  169. })
  170. } else if (tempObj && tempObj.liveState === 2) {
  171. setTimeout(() => {
  172. Toast('课程已结束')
  173. }, 100)
  174. } else {
  175. setTimeout(() => {
  176. Toast('课程尚未开始,请耐心等候')
  177. }, 100)
  178. }
  179. } catch {
  180. //
  181. }
  182. },
  183. async cancelCourseGroup() {
  184. try {
  185. await request.get('/api-teacher/courseGroup/cancelCourseGroup', {
  186. params: {
  187. groupId: this.groupId
  188. }
  189. })
  190. Toast('取消课程成功')
  191. setTimeout(() => {
  192. postMessage({ api: 'back', content: {} })
  193. }, 500)
  194. } catch {
  195. //
  196. }
  197. }
  198. },
  199. render() {
  200. return (
  201. <div class={[styles['live-detail'], 'mb12']}>
  202. <ColHeader />
  203. <UserDetail userInfo={this.userInfo} />
  204. <SectionDetail border>
  205. <p class={styles.introduction}>{this.userInfo.lessonDesc}</p>
  206. </SectionDetail>
  207. {this.myself ? (
  208. <SectionDetail title="课程列表" icon="courseList" border={true}>
  209. <CoursePlanStep
  210. courseInfo={this.courseInfo}
  211. courseId={Number(this.courseId) || 0}
  212. />
  213. </SectionDetail>
  214. ) : (
  215. <SectionDetail
  216. title="课程列表"
  217. icon="courseList"
  218. titleShow={false}
  219. contentStyle={{ paddingTop: '0' }}
  220. >
  221. <Tabs color="var(--van-primary)" lineWidth={20} sticky>
  222. <Tab title="课程列表" titleClass="van-hairline--bottom">
  223. <CoursePlanStep
  224. showState={
  225. this.joinRoom == '1' && this.liveStatus.liveStatus !== 2
  226. }
  227. courseInfo={this.courseInfo}
  228. courseId={Number(this.courseId) || 0}
  229. />
  230. </Tab>
  231. <Tab title="上课学员" titleClass="van-hairline--bottom">
  232. {this.studentList.map((item: any) => (
  233. <UserList
  234. class="mb16"
  235. users={{
  236. avatar: item.avatar,
  237. studentId: item.studentId,
  238. studentName: item.userName,
  239. createTime: item.createTime
  240. }}
  241. />
  242. ))}
  243. {this.studentList.length === 0 && (
  244. <ColResult
  245. tips="暂无购买学员"
  246. classImgSize="SMALL"
  247. btnStatus={false}
  248. />
  249. )}
  250. </Tab>
  251. </Tabs>
  252. </SectionDetail>
  253. )}
  254. {this.live.status !== 'OUT_SALE' && (
  255. <>
  256. {this.courseOffStatus && (
  257. <TheSticky position="bottom">
  258. <div
  259. class={['btnGroup']}
  260. style={{ paddingTop: '10px', background: '#fff' }}
  261. >
  262. <Button
  263. block
  264. round
  265. type="primary"
  266. onClick={this.cancelCourseGroup}
  267. >
  268. 取消课程
  269. </Button>
  270. </div>
  271. </TheSticky>
  272. )}
  273. {this.joinRoom == '1' && this.liveStatus.liveStatus !== 2 && (
  274. <TheSticky position="bottom">
  275. <div
  276. class={['btnGroup']}
  277. style={{ paddingTop: '10px', background: '#fff' }}
  278. >
  279. <Button block round type="primary" onClick={this.onJoinRoom}>
  280. 进入直播间
  281. </Button>
  282. </div>
  283. </TheSticky>
  284. )}
  285. {this.share == '1' && this.courseInfo.length > 0 && (
  286. <TheSticky position="bottom">
  287. <div
  288. class={['btnGroup']}
  289. style={{ paddingTop: '10px', background: '#fff' }}
  290. >
  291. <Button
  292. block
  293. round
  294. type="primary"
  295. onClick={() => {
  296. this.shareStatus = true
  297. }}
  298. >
  299. 分享
  300. </Button>
  301. </div>
  302. </TheSticky>
  303. )}
  304. </>
  305. )}
  306. <Popup
  307. v-model:show={this.shareStatus}
  308. style={{ background: 'transparent' }}
  309. >
  310. <ColShare
  311. teacherId={this.userInfo.id}
  312. shareUrl={this.shareUrl}
  313. shareType="live"
  314. >
  315. <LiveItem
  316. class={styles.shareCourse}
  317. liveInfo={{
  318. backgroundPic: this.userInfo.lessonCoverUrl,
  319. courseGroupId: this.userInfo.lessonId,
  320. courseGroupName: this.userInfo.lessonName,
  321. courseNum: this.userInfo.lessonNum,
  322. coursePrice: this.userInfo.lessonPrice,
  323. teacherName: this.userInfo.username,
  324. teacherId: this.userInfo.id,
  325. avatar: this.userInfo.avatar,
  326. studentCount: this.userInfo.buyNum,
  327. courseStartTime: this.userInfo.courseStartTime,
  328. existBuy: 0,
  329. subjectName: this.userInfo.subjectName
  330. }}
  331. />
  332. </ColShare>
  333. </Popup>
  334. </div>
  335. )
  336. }
  337. })