video-detail.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  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. console.log(lessonGroup.payType, userInfo.isVip)
  96. console.log(this.userInfo, 'this.userInfo')
  97. } catch {
  98. //
  99. }
  100. },
  101. onPlay(detail: any) {
  102. this.$router.push({
  103. path: '/videoClassDetail',
  104. query: {
  105. groupId: this.params.groupId,
  106. classId: detail.id
  107. }
  108. })
  109. },
  110. async onBuy() {
  111. try {
  112. if (this.userInfo.payType === 'VIP') {
  113. if (browser().isApp) {
  114. postMessage({
  115. api: 'openWebView',
  116. content: {
  117. url: `${location.origin}${location.pathname}#/memberCenter`,
  118. orientation: 1,
  119. isHideTitle: false
  120. }
  121. })
  122. } else {
  123. this.$router.push({
  124. path: '/memberCenter'
  125. })
  126. }
  127. return
  128. }
  129. const userInfo = this.userInfo
  130. orderStatus.orderObject.orderType = 'VIDEO'
  131. orderStatus.orderObject.orderName = '视频课购买'
  132. orderStatus.orderObject.orderDesc = '视频课购买'
  133. orderStatus.orderObject.actualPrice = userInfo.lessonPrice
  134. orderStatus.orderObject.recomUserId = this.recomUserId
  135. orderStatus.orderObject.orderNo = ''
  136. orderStatus.orderObject.orderList = [
  137. {
  138. orderType: 'VIDEO',
  139. goodsName: '视频课购买',
  140. courseGroupId: userInfo.id,
  141. courseGroupName: userInfo.lessonName,
  142. coursePrice: userInfo.lessonPrice,
  143. teacherName: userInfo.username || `游客${userInfo.teacherId || ''}`,
  144. teacherId: userInfo.teacherId,
  145. avatar: userInfo.headUrl,
  146. relationType: this.userInfo.relationType,
  147. courseInfo: this.detailList,
  148. recomUserId: this.recomUserId
  149. }
  150. ]
  151. // 判断是否是0无订单
  152. if (userInfo.lessonPrice <= 0) {
  153. await onSubmitZero(() => {
  154. Dialog.alert({
  155. message: '领取成功',
  156. confirmButtonText: '确定',
  157. confirmButtonColor: '#2dc7aa'
  158. }).then(() => {
  159. this._init()
  160. })
  161. })
  162. return
  163. }
  164. const res = await request.post(
  165. '/api-student/userOrder/getPendingOrder',
  166. {
  167. data: {
  168. goodType: 'VIDEO',
  169. bizId: this.params.groupId
  170. }
  171. }
  172. )
  173. const result = res.data
  174. if (result) {
  175. Dialog.confirm({
  176. title: '提示',
  177. message: '您有一个未支付的订单,是否继续支付?',
  178. confirmButtonColor: '#269a93',
  179. cancelButtonText: '取消订单',
  180. confirmButtonText: '继续支付'
  181. })
  182. .then(async () => {
  183. tradeOrder(result, this.routerTo)
  184. })
  185. .catch(() => {
  186. Dialog.close()
  187. // 只用取消订单,不用做其它处理
  188. this.cancelPayment(result.orderNo)
  189. })
  190. } else {
  191. this.routerTo()
  192. }
  193. } catch {}
  194. },
  195. routerTo() {
  196. this.$router.push({
  197. path: '/orderDetail',
  198. query: {
  199. orderType: 'VIDEO',
  200. courseGroupId: this.params.groupId
  201. }
  202. })
  203. },
  204. async cancelPayment(orderNo: string) {
  205. try {
  206. await request.post('/api-student/userOrder/orderCancel', {
  207. data: {
  208. orderNo
  209. }
  210. })
  211. } catch {}
  212. }
  213. },
  214. watch: {
  215. pageVisibility() {
  216. // 如果不是会员则不用刷新
  217. if (this.userInfo.payType !== 'VIP') {
  218. return
  219. }
  220. request
  221. .get('/api-student/student/queryUserInfo', {
  222. initRequest: true // 初始化接口
  223. })
  224. .then((res: any) => {
  225. setLogin(res.data)
  226. this.userInfo.alreadyBuy = res.data?.isVip ? true : false
  227. })
  228. }
  229. },
  230. render() {
  231. return (
  232. <div class={[styles['video-detail']]}>
  233. <ColHeader
  234. v-slots={{
  235. right: () => (
  236. <img src={iconShare} onClick={() => (this.shareStatus = true)} />
  237. )
  238. }}
  239. />
  240. <UserDetail
  241. userInfo={this.userInfo}
  242. onUserDetail={(item: any) => {
  243. if (browser().isApp && state.platformType === 'STUDENT') {
  244. this.$router.push({
  245. path: '/teacherHome',
  246. query: {
  247. teacherId: item.teacherId,
  248. tabs: 'video'
  249. }
  250. })
  251. }
  252. }}
  253. />
  254. <SectionDetail border={false}>
  255. <p class={styles.introduction}>{this.userInfo.lessonDesc}</p>
  256. </SectionDetail>
  257. <SectionDetail
  258. title="课程列表"
  259. icon="courseList"
  260. class="mb12"
  261. border={false}
  262. >
  263. {this.detailList.map((item: any) => {
  264. const musicAlbumInfos = item.musicAlbumInfos || []
  265. const temp = musicAlbumInfos.map((info: any) => {
  266. return {
  267. relationMusicAlbum: info.relationType,
  268. musicAlbumName: info.name,
  269. musicAlbumId: info.musicAlbumId,
  270. status: info.status, // 是否上架
  271. useRelationType: this.userInfo.relationType
  272. }
  273. })
  274. return (
  275. <CourseVideoItem
  276. musicAlbumInfos={temp}
  277. class={[styles.videoItem]}
  278. detail={{
  279. id: item.id,
  280. title: item.videoTitle,
  281. content: item.videoContent,
  282. imgUrl: item.coverUrl
  283. }}
  284. onPlay={this.onPlay}
  285. onMusicAlbumDetail={(item: any) => {
  286. if (!this.userInfo.alreadyBuy && !item.status) {
  287. Toast('数据正在更新,请稍后再试')
  288. return
  289. }
  290. if (item.relationMusicAlbum === 'MUSIC') {
  291. this.$router.push({
  292. path: '/music-detail',
  293. query: {
  294. id: item.musicAlbumId
  295. }
  296. })
  297. } else if (item.relationMusicAlbum === 'ALBUM') {
  298. this.$router.push({
  299. path: '/music-album-detail/' + item.musicAlbumId
  300. })
  301. }
  302. }}
  303. />
  304. )
  305. })}
  306. </SectionDetail>
  307. {this.userInfo.id && !this.userInfo.alreadyBuy && (
  308. // <Sticky offsetBottom={0} position="bottom">
  309. // <div class={['btnGroup', styles.btnMore]}>
  310. // <Button block round type="primary" onClick={this.onBuy}>
  311. // {this.userInfo.lessonPrice <= 0 ? '免费领取' : `立即购买`}
  312. // </Button>
  313. // </div>
  314. // </Sticky>
  315. <ColSticky position="bottom" background="white">
  316. <div class={['btnGroup', styles.btnMore]}>
  317. <Button
  318. block
  319. round
  320. type="primary"
  321. onClick={this.onBuy}
  322. disabled={this.platformStatus}
  323. >
  324. {this.userInfo.payType === 'VIP'
  325. ? '开通会员'
  326. : this.userInfo.lessonPrice <= 0
  327. ? '免费领取'
  328. : `立即购买`}
  329. </Button>
  330. </div>
  331. </ColSticky>
  332. )}
  333. <Popup
  334. v-model:show={this.shareStatus}
  335. style={{ background: 'transparent' }}
  336. >
  337. <ColShare
  338. teacherId={this.userInfo.id}
  339. shareUrl={this.shareUrl}
  340. shareType="video"
  341. >
  342. <LiveItem
  343. class={styles.shareCourse}
  344. coverClass={styles.coverClass}
  345. liveInfo={{
  346. backgroundPic: this.userInfo.lessonCoverUrl,
  347. courseGroupId: this.userInfo.lessonId,
  348. courseGroupName: this.userInfo.lessonName,
  349. courseNum: this.userInfo.lessonNum,
  350. coursePrice: this.userInfo.lessonPrice,
  351. teacherName: this.userInfo.username,
  352. payType: this.userInfo.payType,
  353. teacherId: this.userInfo.id,
  354. avatar: this.userInfo.headUrl,
  355. studentCount: this.userInfo.buyNum,
  356. existBuy: 0,
  357. subjectName: this.userInfo.lessonSubjectName
  358. }}
  359. />
  360. </ColShare>
  361. </Popup>
  362. </div>
  363. )
  364. }
  365. })