123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560 |
- import request from '@/helpers/request'
- import { state } from '@/state'
- import { Button, Cell, CellGroup, Popup, Dialog, Toast, Circle } from 'vant'
- import { Vue3Lottie } from 'vue3-lottie'
- import AstronautJSON from '../music-detail/animate/refresh_anim.json'
- import {
- defineComponent,
- onMounted,
- reactive,
- onUnmounted,
- TransitionGroup,
- ref
- } from 'vue'
- import styles from './index.module.less'
- import { useRoute, useRouter } from 'vue-router'
- import { state as baseState } from '@/state'
- import { orderStatus } from '@/views/order-detail/orderStatus'
- import {
- listenerMessage,
- postMessage,
- removeListenerMessage
- } from '@/helpers/native-message'
- import iconCourse from './image/icon-course.png'
- import iconCachePoint from './image/icon-cache-point.png'
- import play from './image/paly.png'
- import { browser } from '@/helpers/utils'
- import ColResult from '@/components/col-result'
- import { useEventListener } from '@vant/use'
- import TheSticky from '@/components/the-sticky'
- import ColHeader from '@/components/col-header'
- import iconList from './image/icon-list.png'
- // import OSticky from '@/components/o-sticky';
- export default defineComponent({
- name: 'courseList',
- setup() {
- const route = useRoute()
- const router = useRouter()
- const browserInfo = browser()
- const data = reactive({
- titleOpacity: 0,
- catchStatus: false,
- catchItem: {} as any,
- loading: true,
- detail: {} as Record<string, any>,
- list: [] as any,
- isDownloading: false // 是否在下载资源
- })
- const apiSuffix = ref(
- baseState.platformType === 'STUDENT' ? '/api-student' : '/api-teacher'
- )
- /** 获取课件详情 */
- const getDetail = async () => {
- try {
- const res: any = await request.post(
- apiSuffix.value + `/tenantAlbumMusic/getLessonCoursewareDetail`,
- {
- data: {
- lessonCoursewareId: route.query.id,
- albumId: route.query.albumId
- }
- }
- )
- data.detail = res?.data || {}
- } catch {
- //
- }
- }
- const getList = async () => {
- data.loading = true
- try {
- const res: any = await request.get(
- apiSuffix.value +
- '/tenantAlbumMusic/getLessonCoursewareCourseList/' +
- route.query.id
- )
- if (Array.isArray(res?.data)) {
- data.list = res.data
- res.data.forEach((item: any) => {
- const { knowledgePointList, ...res } = item
- const tempK = knowledgePointList || []
- tempK.forEach((child: any) => {
- child.materialList = [
- ...(child.materialList || []),
- ...getKnowledgeMaterials(child.children || [])
- ]
- child.children = null
- })
- })
- // 由于ios没有对应api
- const _list = await checkCoursewareCache(res.data)
- data.list = browserInfo.isApp
- ? res.data.map((item: any) => {
- const _item = _list.find(
- (n: any) =>
- n.lessonCoursewareDetailId == item.lessonCoursewareDetailId
- )
- const n = {
- ...item
- }
- if (_item) {
- n.hasCache = _item.hasCache
- }
- return n
- })
- : res.data
- }
- } catch (error) {
- //
- }
- data.loading = false
- }
- // 获取子节点数据
- const getKnowledgeMaterials = (list: any = []) => {
- const tempList: any = []
- list.forEach((item: any) => {
- if (item.materialList && item.materialList.length > 0) {
- tempList.push(...(item.materialList || []))
- }
- if (item.children && item.children.length > 0) {
- tempList.push(...getKnowledgeMaterials(item.children || []))
- }
- })
- return tempList
- }
- onMounted(() => {
- getDetail()
- getList()
- listenerMessage('downloadCoursewareToCache', getProgress)
- })
- onUnmounted(() => {
- removeListenerMessage('downloadCoursewareToCache', getProgress)
- })
- const handleClick = async (item: any) => {
- if (!data.detail?.play) {
- if (!browser().isApp) {
- onDownloadApp()
- return
- }
- onSubmit()
- return
- }
- if (!item.knowledgePointList) {
- Dialog.confirm({
- message: '该课件暂无知识点'
- })
- return
- }
- if (!item.hasCache) {
- // const hasFree = String(item.accessScope) === '0';
- // if (!hasFree) {
- // 下载中不提示
- if (item.downloadStatus == 1) {
- // 取消下载
- postMessage({ api: 'cancelDownloadCourseware' })
- setTimeout(() => {
- postMessage({ api: 'cancelDownloadCourseware' })
- item.downloadStatus = 0
- data.isDownloading = false
- }, 1000)
- Toast.loading({
- message: '取消中...',
- forbidClick: false,
- loadingType: 'spinner',
- duration: 1000
- })
- return
- }
- // 重新下载
- if (item.downloadStatus == 3) {
- downCatch(item)
- return
- }
- data.catchStatus = true
- data.catchItem = item
- return
- }
- gotoPlay(item)
- }
- // 去课件播放
- const gotoPlay = (item: any) => {
- data.catchStatus = false
- if (browser().isApp) {
- postMessage({
- api: 'openWebView',
- content: {
- url: `${location.origin}${location.pathname}#/coursewarePlay?id=${item.coursewareDetailId}&source=my-course`,
- orientation: 0,
- isHideTitle: true,
- statusBarTextColor: false,
- isOpenLight: true,
- showLoadingAnim: true
- }
- })
- } else {
- router.push({
- path: '/coursewarePlay',
- query: {
- id: item.coursewareDetailId,
- source: 'my-course'
- }
- })
- }
- }
- // 检查数据的缓存状态
- const checkCoursewareCache = (list: []): Promise<any[]> => {
- if (!browser().isApp) {
- return Promise.resolve(list)
- }
- return new Promise(resolve => {
- postMessage(
- {
- api: 'checkCoursewareCache',
- content: {
- data: list
- }
- },
- res => {
- if (res?.content?.data) {
- resolve(res.content.data)
- return
- }
- return []
- }
- )
- })
- }
- // 下载缓存
- const downCatch = async (item: any) => {
- console.log(item)
- if (browserInfo.isApp) {
- data.catchStatus = false
- data.isDownloading = true
- const res = await postMessage({
- api: 'downloadCoursewareToCache',
- content: {
- data: item
- }
- })
- return res
- }
- return true
- }
- // 下载缓存进度
- const getProgress = (res: any) => {
- //console.log('🚀 ~ res', res)
- // if (!data.isDownloading) {
- // return
- // }
- if (res?.content?.lessonCoursewareDetailId) {
- const { lessonCoursewareDetailId, downloadStatus, progress } =
- res.content
- const course = data.list.find(
- (n: any) => n.lessonCoursewareDetailId == lessonCoursewareDetailId
- )
- if (course) {
- course.downloadStatus = downloadStatus
- course.progress = progress
- if (downloadStatus == 2) {
- course.hasCache = 1
- course.progress = 100
- // 下载完成
- data.isDownloading = false
- }
- }
- }
- }
- useEventListener('scroll', () => {
- const height =
- window.scrollY ||
- window.pageYOffset ||
- document.documentElement.scrollTop
- data.titleOpacity = height > 100 ? 1 : height / 100
- })
- // 购买
- const onSubmit = async () => {
- const url =
- apiSuffix.value +
- '/tenantGroupAlbum/buyAlbumInfo?tenantGroupAlbumId=' +
- (route.query.taId || '')
- // if (state.albumId) {
- // url = url + '?albumId=' + state.albumId
- // }
- const { data } = await request.get(url)
- const details = data[0]
- orderStatus.orderObject.orderType = 'TENANT_ALBUM'
- orderStatus.orderObject.orderName = details.name
- orderStatus.orderObject.orderDesc = details.name
- orderStatus.orderObject.actualPrice = details.actualPrice
- // orderStatus.orderObject.recomUserId = route.query.recomUserId || 0
- // orderStatus.orderObject.activityId = route.query.activityId || 0
- orderStatus.orderObject.orderNo = ''
- orderStatus.orderObject.orderList = [
- {
- orderType: 'TENANT_ALBUM',
- goodsName: details.name,
- actualPrice: details.actualPrice,
- price: details.actualPrice,
- ...details
- }
- ]
- const res = await request.post('/api-student/userOrder/getPendingOrder', {
- data: {
- goodType: 'TENANT_ALBUM',
- bizId: details.id
- }
- })
- const result = res.data
- if (result) {
- Dialog.confirm({
- title: '提示',
- message: '您有一个未支付的订单,是否继续支付?',
- theme: 'round-button',
- className: 'confirm-button-group',
- cancelButtonText: '取消订单',
- confirmButtonText: '继续支付'
- })
- .then(async () => {
- orderStatus.orderObject.orderNo = result.orderNo
- orderStatus.orderObject.actualPrice = result.actualPrice
- orderStatus.orderObject.discountPrice = result.discountPrice
- orderStatus.orderObject.paymentConfig = {
- ...result.paymentConfig,
- paymentVendor: result.paymentVendor,
- paymentVersion: result.paymentVersion
- }
- routerToALBUM(details.id)
- })
- .catch(() => {
- Dialog.close()
- // 只用取消订单,不用做其它处理
- cancelPaymentALBUM(result.orderNo)
- })
- } else {
- routerToALBUM(details.id)
- }
- }
- const cancelPaymentALBUM = async (orderNo: string) => {
- try {
- await request.post('/api-student/userOrder/orderCancel/v2', {
- data: {
- orderNo
- }
- })
- } catch {
- //
- }
- }
- const routerToALBUM = (id: string) => {
- router.push({
- path: '/orderDetail',
- query: {
- orderType: 'ALBUM',
- album: id
- }
- })
- }
- const onDownloadApp = () => {
- Dialog.alert({
- title: '提示',
- message: '请在酷乐秀APP中使用',
- confirmButtonColor: '#2dc7aa'
- }).then(() => {
- window.location.href = location.origin + '/student/#/download'
- })
- }
- return () => (
- <div class={styles.courseList}>
- <TheSticky position="top">
- <ColHeader
- hideHeader={false}
- background={`rgba(255,255,255, ${data.titleOpacity})`}
- isFixed={false}
- border={false}
- title={'教程详情'}
- color="#131415"
- />
- </TheSticky>
- <div class={styles.periodContent}>
- <div class={styles.cover}>
- <img
- src={data.detail.coverImg}
- onLoad={(e: Event) => {
- if (e.target) {
- ;(e.target as any).style.opacity = 1
- }
- }}
- />
- </div>
- <div>
- <div class={styles.contentTitle}>{data.detail.name}</div>
- <div class={styles.contentLabel}>
- 教学目标:{data.detail.lessonTargetDesc}
- </div>
- </div>
- </div>
- <TransitionGroup name="van-fade">
- {!data.loading && (
- <>
- <div key="periodTitle" class={styles.periodTitle}>
- <img class={styles.pIcon} src={iconList} />
- <div class={styles.pTitle}>课程列表</div>
- <div class={styles.pNum}>共{data.list.length}课</div>
- </div>
- <div key="list" class={styles.periodList}>
- <CellGroup inset>
- {data.list.map((item: any) => {
- // const isLock =
- // item.lockFlag ||
- // ((route.query.code == 'select' ||
- // state.platformType == 'STUDENT') &&
- // !item.unlock);
- // const isSelect = route.query.code === 'select';
- return (
- <Cell
- border
- center
- title={item.coursewareDetailName}
- // label={
- // !browserInfo.isStudent
- // ? `已使用${item.useNum || 0}次`
- // : ''
- // }
- onClick={() => handleClick(item)}
- >
- {{
- icon: () => (
- <div class={styles.periodItem}>
- <div class={styles.periodItemModel}>
- <img src={iconCourse} />
- {item.hasCache ? (
- <img
- class={styles.iconCachePoint}
- src={iconCachePoint}
- />
- ) : (
- ''
- )}
- {item.downloadStatus == 1 && (
- <div class={styles.downloading}>{`${
- item.progress || 0
- }%`}</div>
- )}
- </div>
- </div>
- ),
- value: () => (
- <>
- {item.knowledgePointList ? (
- <>
- {item.hasCache ||
- item.downloadStatus !== 1 ? (
- <img class={styles.basePlay} src={play} />
- ) : (
- <div class={styles.circleProgress}>
- <div class={styles.tips}></div>
- <Circle
- v-model:current-rate={item.progress}
- rate={item.progress}
- speed={10}
- stroke-width={80}
- layer-color={'#B3B3B3'}
- color={'#FE2451'}
- />
- </div>
- )}
- </>
- ) : (
- ''
- )}
- </>
- )
- }}
- </Cell>
- )
- })}
- </CellGroup>
- </div>
- </>
- )}
- </TransitionGroup>
- {data.loading && (
- <div>
- <Vue3Lottie
- animationData={AstronautJSON}
- class={styles.finch}
- ></Vue3Lottie>
- {/* <p class={styles.finchLoad}>加载中...</p> */}
- </div>
- )}
- {!data.loading && !data.list.length && (
- <ColResult tips="暂无内容" classImgSize="SMALL" btnStatus={false} />
- )}
- <TheSticky position="bottom">
- {data.detail.id && !data.detail.play && (
- <div class={styles.footers}>
- <Button
- round
- block
- type="primary"
- color="linear-gradient(270deg, #FF204B 0%, #FE5B71 100%)"
- onClick={() => {
- if (!browser().isApp) {
- onDownloadApp()
- return
- }
- onSubmit()
- }}
- >
- 开通训练教程
- </Button>
- </div>
- )}
- </TheSticky>
- <Popup
- v-model:show={data.catchStatus}
- round
- class={styles.courseDialog}
- >
- <i
- class={styles.iconClose}
- onClick={() => (data.catchStatus = false)}
- ></i>
- <div class={styles.title}>下载提醒</div>
- <div class={styles.content}>
- 您尚未下载课件,为了更加流畅的学习体验,推荐您下载后观看课件。
- </div>
- <div class={styles.popupBtnGroup}>
- <Button
- class={styles.btnLeft}
- round
- onClick={() => gotoPlay(data.catchItem)}
- >
- 直接观看
- </Button>
- <Button
- class={styles.btnRight}
- round
- type="primary"
- onClick={() => downCatch(data.catchItem)}
- >
- 下载课件
- </Button>
- </div>
- </Popup>
- </div>
- )
- }
- })
|