video-detail.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. import CourseVideoItem from '@/business-components/course-video-item'
  2. import SectionDetail from '@/business-components/section-detail'
  3. import UserDetail from '@/business-components/user-detail'
  4. import { Sticky, Button, Dialog, Popup, Toast } from 'vant'
  5. import { postMessage } from '@/helpers/native-message'
  6. import { defineComponent } from 'vue'
  7. import styles from './video-detail.module.less'
  8. import request from '@/helpers/request'
  9. import ColHeader from '@/components/col-header'
  10. import { onSubmitZero, orderStatus } from '@/views/order-detail/orderStatus'
  11. import { tradeOrder } from '../trade/tradeOrder'
  12. import ColSticky from '@/components/col-sticky'
  13. import iconShare from '@/views/shop-mall/images/icon-share.svg'
  14. import ColShare from '@/components/col-share'
  15. import LiveItem from '@/views/live-class/live-item'
  16. import { setLogin, state } from '@/state'
  17. import { browser } from '@/helpers/utils'
  18. import { usePageVisibility } from '@vant/use'
  19. export default defineComponent({
  20. name: 'VideoDetail',
  21. data() {
  22. const query = this.$route.query
  23. return {
  24. pageVisibility: 'visible' as any,
  25. userInfo: {} as any,
  26. detailList: [],
  27. recomUserId: query.recomUserId, // 推荐人id
  28. params: {
  29. groupId: query.groupId
  30. },
  31. platform: query.p, // 属于哪个平台,//机构老师 tenant,平台老师 无
  32. shareStatus: false,
  33. shareUrl: ''
  34. }
  35. },
  36. computed: {
  37. platformStatus() {
  38. const userInfo = state.user.data as any
  39. // 是机构学生 并且 是机构老师分享
  40. const query = this.$route.query
  41. return userInfo.tenantId > 0 && query.p == 'tenant'
  42. }
  43. },
  44. async mounted() {
  45. this.pageVisibility = usePageVisibility()
  46. await this._init()
  47. if (/(localhost|192)/g.test(location.origin)) {
  48. this.shareUrl = `https://dev.colexiu.com/teacher#/shareVideo?recomUserId=${state.user.data?.userId}&groupId=${this.params.groupId}&userType=${state.platformType}&p=tenant`
  49. } else {
  50. this.shareUrl = `${location.origin}/teacher#/shareVideo?recomUserId=${state.user.data?.userId}&groupId=${this.params.groupId}&userType=${state.platformType}&p=tenant`
  51. }
  52. },
  53. methods: {
  54. async _init() {
  55. try {
  56. const res = await request.get(
  57. '/api-student/videoLesson/selectVideoLesson',
  58. {
  59. params: {
  60. groupId: this.params.groupId
  61. }
  62. }
  63. )
  64. const result = res.data || {}
  65. const lessonGroup = result.lessonGroup || {}
  66. const teachertTag = result.teachertTag || ''
  67. const userInfo = state.user.data as any
  68. const alreadyBuy =
  69. lessonGroup.payType === 'VIP'
  70. ? result.alreadyBuy || userInfo.userVip?.vipType !== 'NOT_VIP'
  71. ? true
  72. : false
  73. : result.alreadyBuy
  74. this.userInfo = {
  75. alreadyBuy: alreadyBuy,
  76. username:
  77. lessonGroup.username || `游客${lessonGroup.teacherId || ''}`,
  78. headUrl: lessonGroup.avatar,
  79. buyNum: lessonGroup.countStudent,
  80. id: lessonGroup.id,
  81. lessonNum: lessonGroup.lessonCount,
  82. lessonName: lessonGroup.lessonName,
  83. payType: lessonGroup.payType,
  84. type: 'video',
  85. lessonDesc: lessonGroup.lessonDesc,
  86. lessonPrice: lessonGroup.lessonPrice,
  87. relationType: lessonGroup.relationType,
  88. teacherId: lessonGroup.teacherId,
  89. lessonCoverUrl: lessonGroup.lessonCoverUrl,
  90. auditVersion: lessonGroup.auditVersion,
  91. isDegree: result.degreeFlag ? true : false,
  92. isTeacher: result.teacherFlag ? true : false
  93. }
  94. this.detailList = result.detailList || []
  95. } catch {
  96. //
  97. }
  98. },
  99. onPlay(detail: any) {
  100. this.$router.push({
  101. path: '/videoClassDetail',
  102. query: {
  103. groupId: this.params.groupId,
  104. classId: detail.id
  105. }
  106. })
  107. },
  108. async onBuy() {
  109. try {
  110. if (this.userInfo.payType === 'VIP') {
  111. if (browser().isApp) {
  112. postMessage({
  113. api: 'openWebView',
  114. content: {
  115. url: `${location.origin}${location.pathname}#/memberCenter`,
  116. orientation: 1,
  117. isHideTitle: false
  118. }
  119. })
  120. } else {
  121. this.$router.push({
  122. path: '/memberCenter'
  123. })
  124. }
  125. return
  126. }
  127. const userInfo = this.userInfo
  128. // 判断是否是0无订单
  129. if (userInfo.lessonPrice <= 0) {
  130. await onSubmitZero(() => {
  131. Dialog.alert({
  132. message: '领取成功',
  133. confirmButtonText: '确定',
  134. confirmButtonColor: '#2dc7aa'
  135. }).then(() => {
  136. this._init()
  137. })
  138. })
  139. return
  140. }
  141. const res = await request.post(
  142. '/api-student/userOrder/getPendingOrder',
  143. {
  144. data: {
  145. goodType: 'VIDEO',
  146. bizId: this.params.groupId
  147. }
  148. }
  149. )
  150. const result = res.data
  151. if (result) {
  152. Dialog.confirm({
  153. title: '提示',
  154. message: '您有一个未支付的订单,是否继续支付?',
  155. confirmButtonColor: '#269a93',
  156. cancelButtonText: '取消订单',
  157. confirmButtonText: '继续支付'
  158. })
  159. .then(async () => {
  160. tradeOrder(result, this.routerTo)
  161. })
  162. .catch(() => {
  163. Dialog.close()
  164. // 只用取消订单,不用做其它处理
  165. this.cancelPayment(result.orderNo)
  166. })
  167. } else {
  168. orderStatus.orderObject.orderType = 'VIDEO'
  169. orderStatus.orderObject.orderName = '视频课购买'
  170. orderStatus.orderObject.orderDesc = '视频课购买'
  171. orderStatus.orderObject.actualPrice = userInfo.lessonPrice
  172. orderStatus.orderObject.recomUserId = this.recomUserId
  173. orderStatus.orderObject.orderNo = ''
  174. orderStatus.orderObject.orderList = [
  175. {
  176. orderType: 'VIDEO',
  177. goodsName: '视频课购买',
  178. courseGroupId: userInfo.id,
  179. courseGroupName: userInfo.lessonName,
  180. coursePrice: userInfo.lessonPrice,
  181. price: userInfo.lessonPrice,
  182. teacherName: userInfo.username || `游客${userInfo.teacherId || ''}`,
  183. teacherId: userInfo.teacherId,
  184. avatar: userInfo.headUrl,
  185. relationType: this.userInfo.relationType,
  186. courseInfo: this.detailList,
  187. recomUserId: this.recomUserId
  188. }
  189. ]
  190. this.routerTo()
  191. }
  192. } catch {}
  193. },
  194. routerTo() {
  195. this.$router.push({
  196. path: '/orderDetail',
  197. query: {
  198. orderType: 'VIDEO',
  199. courseGroupId: this.params.groupId
  200. }
  201. })
  202. },
  203. async cancelPayment(orderNo: string) {
  204. try {
  205. await request.post('/api-student/userOrder/orderCancel', {
  206. data: {
  207. orderNo
  208. }
  209. })
  210. } catch {}
  211. }
  212. },
  213. watch: {
  214. pageVisibility() {
  215. // 如果不是会员则不用刷新
  216. if (this.userInfo.payType !== 'VIP') {
  217. return
  218. }
  219. request
  220. .get('/api-student/student/queryUserInfo', {
  221. initRequest: true // 初始化接口
  222. })
  223. .then((res: any) => {
  224. setLogin(res.data)
  225. this.userInfo.alreadyBuy = res.data?.isVip ? true : false
  226. })
  227. }
  228. },
  229. render() {
  230. return (
  231. <div class={[styles['video-detail']]}>
  232. <ColHeader
  233. v-slots={{
  234. right: () => (
  235. <img src={iconShare} onClick={() => (this.shareStatus = true)} />
  236. )
  237. }}
  238. />
  239. <UserDetail
  240. userInfo={this.userInfo}
  241. onUserDetail={(item: any) => {
  242. if (browser().isApp && state.platformType === 'STUDENT') {
  243. this.$router.push({
  244. path: '/teacherHome',
  245. query: {
  246. teacherId: item.teacherId,
  247. tabs: 'video'
  248. }
  249. })
  250. }
  251. }}
  252. />
  253. <SectionDetail border={false}>
  254. <p class={styles.introduction}>{this.userInfo.lessonDesc}</p>
  255. </SectionDetail>
  256. <SectionDetail
  257. title="课程列表"
  258. icon="courseList"
  259. class="mb12"
  260. border={false}
  261. >
  262. {this.detailList.map((item: any) => {
  263. const musicAlbumInfos = item.musicAlbumInfos || []
  264. const temp = musicAlbumInfos.map((info: any) => {
  265. return {
  266. relationMusicAlbum: info.relationType,
  267. musicAlbumName: info.name,
  268. musicAlbumId: info.musicAlbumId,
  269. status: info.status, // 是否上架
  270. useRelationType: this.userInfo.relationType
  271. }
  272. })
  273. return (
  274. <CourseVideoItem
  275. musicAlbumInfos={temp}
  276. class={[styles.videoItem]}
  277. detail={{
  278. id: item.id,
  279. title: item.videoTitle,
  280. content: item.videoContent,
  281. imgUrl: item.coverUrl
  282. }}
  283. onPlay={this.onPlay}
  284. onMusicAlbumDetail={(item: any) => {
  285. if (!this.userInfo.alreadyBuy && !item.status) {
  286. Toast('数据正在更新,请稍后再试')
  287. return
  288. }
  289. if (item.relationMusicAlbum === 'MUSIC') {
  290. this.$router.push({
  291. path: '/music-detail',
  292. query: {
  293. id: item.musicAlbumId
  294. }
  295. })
  296. } else if (item.relationMusicAlbum === 'ALBUM') {
  297. this.$router.push({
  298. path: '/music-album-detail/' + item.musicAlbumId
  299. })
  300. }
  301. }}
  302. />
  303. )
  304. })}
  305. </SectionDetail>
  306. {this.userInfo.id && !this.userInfo.alreadyBuy && (
  307. // <Sticky offsetBottom={0} position="bottom">
  308. // <div class={['btnGroup', styles.btnMore]}>
  309. // <Button block round type="primary" onClick={this.onBuy}>
  310. // {this.userInfo.lessonPrice <= 0 ? '免费领取' : `立即购买`}
  311. // </Button>
  312. // </div>
  313. // </Sticky>
  314. <ColSticky position="bottom" background="white">
  315. <div class={['btnGroup', styles.btnMore]}>
  316. <Button
  317. block
  318. round
  319. type="primary"
  320. onClick={this.onBuy}
  321. disabled={this.platformStatus}
  322. >
  323. {this.userInfo.payType === 'VIP'
  324. ? '开通会员'
  325. : this.userInfo.lessonPrice <= 0
  326. ? '免费领取'
  327. : `立即购买`}
  328. </Button>
  329. </div>
  330. </ColSticky>
  331. )}
  332. <Popup
  333. v-model:show={this.shareStatus}
  334. style={{ background: 'transparent' }}
  335. >
  336. <ColShare
  337. teacherId={this.userInfo.id}
  338. shareUrl={this.shareUrl}
  339. shareType="video"
  340. >
  341. <LiveItem
  342. class={styles.shareCourse}
  343. coverClass={styles.coverClass}
  344. liveInfo={{
  345. backgroundPic: this.userInfo.lessonCoverUrl,
  346. courseGroupId: this.userInfo.lessonId,
  347. courseGroupName: this.userInfo.lessonName,
  348. courseNum: this.userInfo.lessonNum,
  349. coursePrice: this.userInfo.lessonPrice,
  350. teacherName: this.userInfo.username,
  351. payType: this.userInfo.payType,
  352. teacherId: this.userInfo.id,
  353. avatar: this.userInfo.headUrl,
  354. studentCount: this.userInfo.buyNum,
  355. existBuy: 0,
  356. subjectName: this.userInfo.lessonSubjectName
  357. }}
  358. />
  359. </ColShare>
  360. </Popup>
  361. </div>
  362. )
  363. }
  364. })