|
@@ -31,6 +31,8 @@ import request from '@/helpers/request'
|
|
|
import Search from '@/components/col-search'
|
|
|
import iconAlbumCover from '../../images/icon-album-cover.png'
|
|
|
import iconTimer from './images/icon-timer.png'
|
|
|
+import iconBell from './images/icon-bell.png'
|
|
|
+import iconLock from './images/icon-lock.png'
|
|
|
import iconArrow from './images/icon-arrow.png'
|
|
|
import { state as baseState, setLogout } from '@/state'
|
|
|
import Song from '../component/song'
|
|
@@ -48,7 +50,7 @@ import { Swiper, SwiperSlide } from 'swiper/vue'
|
|
|
import 'swiper/css'
|
|
|
import 'swiper/css/pagination'
|
|
|
import CourseItem from '../lessonCourseware/component/CourseItem'
|
|
|
-
|
|
|
+import dayjs from 'dayjs'
|
|
|
|
|
|
export default defineComponent({
|
|
|
name: 'train-tool',
|
|
@@ -96,7 +98,7 @@ export default defineComponent({
|
|
|
teacherSubjectName: null as any,
|
|
|
teacherSubjectIndex: 0,
|
|
|
subjectList: [] as any, // 声部列表
|
|
|
- instrumentId: '',
|
|
|
+ instrumentId: ''
|
|
|
})
|
|
|
// const params = reactive({
|
|
|
// keyword: (route.query.search as string) || '',
|
|
@@ -117,13 +119,13 @@ export default defineComponent({
|
|
|
})
|
|
|
const searchRef = ref()
|
|
|
const params = reactive({
|
|
|
- keyword: toolSubject?.keyword || null as any,
|
|
|
+ keyword: toolSubject?.keyword || (null as any),
|
|
|
// subjectType: '',
|
|
|
- subjectId: toolSubject?.subjectId ||null,
|
|
|
+ subjectId: toolSubject?.subjectId || null,
|
|
|
// albumId: route.query.albumId,
|
|
|
// albumName: '',
|
|
|
- level: toolSubject?.level ||'',
|
|
|
- type: toolSubject?.type ||'',
|
|
|
+ level: toolSubject?.level || '',
|
|
|
+ type: toolSubject?.type || '',
|
|
|
courseTypeCode: '',
|
|
|
// title: '',
|
|
|
page: 1,
|
|
@@ -188,6 +190,20 @@ export default defineComponent({
|
|
|
// }
|
|
|
const { data } = await request.get(url)
|
|
|
state.albumList = data || []
|
|
|
+
|
|
|
+ state.albumList.forEach((item: any) => {
|
|
|
+ let albumStatus = ''
|
|
|
+ if (!item.endTime) {
|
|
|
+ albumStatus = 'NO_BUY'
|
|
|
+ } else if (dayjs().isBefore(dayjs(item.endTime))) {
|
|
|
+ albumStatus = 'EXPIRED'
|
|
|
+ } else {
|
|
|
+ albumStatus = 'NORMAL'
|
|
|
+ }
|
|
|
+ item.albumStatus = albumStatus
|
|
|
+ item.endTime = dayjs(item.endTime).format('YYYY-MM-DD')
|
|
|
+ })
|
|
|
+
|
|
|
if (state.albumList.length > 0) {
|
|
|
let index = 0
|
|
|
// 以缓存为优先 其次 请求头 state.albumId
|
|
@@ -341,7 +357,10 @@ export default defineComponent({
|
|
|
(item: any) => item.id == state.teacherSubjectId
|
|
|
)
|
|
|
state.teacherSubjectIndex = index === -1 ? 0 : index
|
|
|
- state.instrumentId = index === -1 ? state.subjectList[0]?.instrumentId : state.subjectList[index]?.instrumentId
|
|
|
+ state.instrumentId =
|
|
|
+ index === -1
|
|
|
+ ? state.subjectList[0]?.instrumentId
|
|
|
+ : state.subjectList[index]?.instrumentId
|
|
|
} catch (e) {
|
|
|
console.log(e)
|
|
|
}
|
|
@@ -442,7 +461,7 @@ export default defineComponent({
|
|
|
: 'ENSEMBLE'
|
|
|
setTimeout(() => {
|
|
|
state.showLoading = false
|
|
|
- }, 0);
|
|
|
+ }, 0)
|
|
|
}
|
|
|
const onSubmit = async () => {
|
|
|
const album = state.details
|
|
@@ -645,7 +664,7 @@ export default defineComponent({
|
|
|
modules={[Pagination]}
|
|
|
pagination={{ clickable: true }}
|
|
|
onSlideChange={(swiper: any) => {
|
|
|
- if(state.initLoadPage) return
|
|
|
+ if (state.initLoadPage) return
|
|
|
params.subjectId = null
|
|
|
params.keyword = null
|
|
|
params.level = ''
|
|
@@ -659,7 +678,7 @@ export default defineComponent({
|
|
|
}
|
|
|
state.details = state.albumList[swiper.activeIndex]
|
|
|
// 等tab渲染完了之后再切换 不然tab会自动重新赋值
|
|
|
- nextTick(async() => {
|
|
|
+ nextTick(async () => {
|
|
|
// 当有初始值的时候不刷新
|
|
|
// if (state.initialSlide) {
|
|
|
// state.initialSlide = 0
|
|
@@ -684,6 +703,19 @@ export default defineComponent({
|
|
|
限购{album.buyedTimes}/{album.buyTimes}次
|
|
|
</span>
|
|
|
)}
|
|
|
+ {/* 是否解锁 并且 未购买 */}
|
|
|
+ {state.details?.albumStatus !== 'NORMAL' &&
|
|
|
+ state.buy != '1' && (
|
|
|
+ <div class={styles.iconLock}>
|
|
|
+ <img src={iconLock} />
|
|
|
+ <p>
|
|
|
+ {state.details?.albumStatus === 'NO_BUY'
|
|
|
+ ? '未开通'
|
|
|
+ : '已过期'}
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+
|
|
|
<Image
|
|
|
class={styles.image}
|
|
|
width="100%"
|
|
@@ -718,10 +750,29 @@ export default defineComponent({
|
|
|
{state.buy != '1' && baseState.platformType === 'STUDENT' && (
|
|
|
<div class={styles.albumPriceGroup}>
|
|
|
<div class={styles.albumTimer}>
|
|
|
- <img src={iconTimer} class={styles.iconTimer} />
|
|
|
- <span>有效期:{state.details?.purchaseNum || 0}天</span>
|
|
|
+ <img
|
|
|
+ src={
|
|
|
+ state.details?.albumStatus === 'NORMAL'
|
|
|
+ ? iconTimer
|
|
|
+ : iconBell
|
|
|
+ }
|
|
|
+ class={styles.iconTimer}
|
|
|
+ />
|
|
|
+ {state.details?.albumStatus === 'NO_BUY' && (
|
|
|
+ <span>开通教程,解锁高效训练方式!</span>
|
|
|
+ )}
|
|
|
+ {state.details?.albumStatus === 'EXPIRED' && (
|
|
|
+ <span>教程续费,解锁优质训练资源!</span>
|
|
|
+ )}
|
|
|
+ {state.details?.albumStatus === 'NORMAL' && (
|
|
|
+ <span>
|
|
|
+ <span>{state.details?.endTime}</span>
|
|
|
+ 到期,续费后有效期将延长
|
|
|
+ </span>
|
|
|
+ )}
|
|
|
</div>
|
|
|
- <div class={styles.albumPriceList}>
|
|
|
+
|
|
|
+ {/* <div class={styles.albumPriceList}>
|
|
|
{(state.details?.originalPrice || 0) >
|
|
|
(state.details?.actualPrice || 0) && (
|
|
|
<del class={styles.originPrice}>
|
|
@@ -735,7 +786,7 @@ export default defineComponent({
|
|
|
¥{moneyFormat(state.details?.actualPrice || 0)}
|
|
|
</span>
|
|
|
</span>
|
|
|
- </div>
|
|
|
+ </div> */}
|
|
|
</div>
|
|
|
)}
|
|
|
</div>
|
|
@@ -764,19 +815,22 @@ export default defineComponent({
|
|
|
FetchList()
|
|
|
}}
|
|
|
>
|
|
|
- {!state.showLoading && <>
|
|
|
- {state.coursewareCounts && (
|
|
|
- <Tab title="云课堂" name="COURSEWARE"></Tab>
|
|
|
- )}
|
|
|
- {state.subjectCounts && (
|
|
|
- <Tab title="基础云练" name="SUBJECT"></Tab>
|
|
|
- )}
|
|
|
- {state.musicCounts && (
|
|
|
- <Tab title="独奏云练" name="MUSIC"></Tab>
|
|
|
- )}
|
|
|
- {state.ensembleCounts && (
|
|
|
- <Tab title="合奏云练" name="ENSEMBLE"></Tab>
|
|
|
- )}</>}
|
|
|
+ {!state.showLoading && (
|
|
|
+ <>
|
|
|
+ {state.coursewareCounts && (
|
|
|
+ <Tab title="云课堂" name="COURSEWARE"></Tab>
|
|
|
+ )}
|
|
|
+ {state.subjectCounts && (
|
|
|
+ <Tab title="基础云练" name="SUBJECT"></Tab>
|
|
|
+ )}
|
|
|
+ {state.musicCounts && (
|
|
|
+ <Tab title="独奏云练" name="MUSIC"></Tab>
|
|
|
+ )}
|
|
|
+ {state.ensembleCounts && (
|
|
|
+ <Tab title="合奏云练" name="ENSEMBLE"></Tab>
|
|
|
+ )}
|
|
|
+ </>
|
|
|
+ )}
|
|
|
</Tabs>
|
|
|
<Search
|
|
|
modelValue={params.keyword}
|
|
@@ -793,188 +847,180 @@ export default defineComponent({
|
|
|
type="tenant"
|
|
|
v-slots={{
|
|
|
left: () =>
|
|
|
- isSearchStatus.value && state.activeTab !== 'COURSEWARE' && (
|
|
|
+ isSearchStatus.value &&
|
|
|
+ state.activeTab !== 'COURSEWARE' && (
|
|
|
<DropdownMenu zIndex={2999}>
|
|
|
- <DropdownItem
|
|
|
- onOpen={() => {
|
|
|
- const targetElement: any =
|
|
|
- document.querySelector('.musicList')
|
|
|
- const targetPosition =
|
|
|
- targetElement.getBoundingClientRect().top +
|
|
|
- window.scrollY
|
|
|
+ <DropdownItem
|
|
|
+ onOpen={() => {
|
|
|
+ const targetElement: any =
|
|
|
+ document.querySelector('.musicList')
|
|
|
+ const targetPosition =
|
|
|
+ targetElement.getBoundingClientRect().top +
|
|
|
+ window.scrollY
|
|
|
|
|
|
- window.scrollTo({
|
|
|
- top: targetPosition - state.heightV + 1
|
|
|
- })
|
|
|
+ window.scrollTo({
|
|
|
+ top: targetPosition - state.heightV + 1
|
|
|
+ })
|
|
|
+ }}
|
|
|
+ teleport="body"
|
|
|
+ titleClass={
|
|
|
+ params.subjectId || params.type || params.level
|
|
|
+ ? styles.titleActive
|
|
|
+ : ''
|
|
|
+ }
|
|
|
+ title="筛选"
|
|
|
+ ref={searchRef}
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class={styles.searchResult}
|
|
|
+ style={{
|
|
|
+ maxHeight: '45vh',
|
|
|
+ overflowY: 'auto'
|
|
|
}}
|
|
|
- teleport="body"
|
|
|
- titleClass={
|
|
|
- params.subjectId ||
|
|
|
- params.type ||
|
|
|
- params.level
|
|
|
- ? styles.titleActive
|
|
|
- : ''
|
|
|
- }
|
|
|
- title="筛选"
|
|
|
- ref={searchRef}
|
|
|
>
|
|
|
- <div
|
|
|
- class={styles.searchResult}
|
|
|
- style={{
|
|
|
- maxHeight: '45vh',
|
|
|
- overflowY: 'auto'
|
|
|
+ {searchObj.value[state.activeTab].subjects &&
|
|
|
+ searchObj.value[state.activeTab].subjects
|
|
|
+ .length > 0 && (
|
|
|
+ <>
|
|
|
+ <div class={styles.searchTitle}>声部</div>
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles['radio-group'],
|
|
|
+ styles.radio,
|
|
|
+ styles['organ-radio']
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ {searchObj.value[
|
|
|
+ state.activeTab
|
|
|
+ ].subjects.map((subject: any) => {
|
|
|
+ const isActive =
|
|
|
+ subject.id === params.subjectId
|
|
|
+ const type = isActive
|
|
|
+ ? 'primary'
|
|
|
+ : 'default'
|
|
|
+ return (
|
|
|
+ <Tag
|
|
|
+ size="large"
|
|
|
+ plain={isActive}
|
|
|
+ type={type}
|
|
|
+ round
|
|
|
+ onClick={() => {
|
|
|
+ params.subjectId = subject.id
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {subject.name}
|
|
|
+ </Tag>
|
|
|
+ )
|
|
|
+ })}
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ {searchObj.value[state.activeTab].levelList &&
|
|
|
+ searchObj.value[state.activeTab].levelList
|
|
|
+ .length > 0 && (
|
|
|
+ <>
|
|
|
+ <div class={styles.searchTitle}>级别</div>
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles['radio-group'],
|
|
|
+ styles.radio,
|
|
|
+ styles['organ-radio']
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ {searchObj.value[
|
|
|
+ state.activeTab
|
|
|
+ ].levelList.map((subject: any) => {
|
|
|
+ const isActive =
|
|
|
+ subject.id === params.level
|
|
|
+ const type = isActive
|
|
|
+ ? 'primary'
|
|
|
+ : 'default'
|
|
|
+ return (
|
|
|
+ <Tag
|
|
|
+ size="large"
|
|
|
+ plain={isActive}
|
|
|
+ type={type}
|
|
|
+ round
|
|
|
+ onClick={() => {
|
|
|
+ params.level = subject.id
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {subject.value}
|
|
|
+ </Tag>
|
|
|
+ )
|
|
|
+ })}
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ {searchObj.value[state.activeTab].typeList &&
|
|
|
+ searchObj.value[state.activeTab].typeList
|
|
|
+ .length > 0 && (
|
|
|
+ <>
|
|
|
+ <div class={styles.searchTitle}>类型</div>
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles['radio-group'],
|
|
|
+ styles.radio,
|
|
|
+ styles['organ-radio']
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ {searchObj.value[
|
|
|
+ state.activeTab
|
|
|
+ ].typeList.map((subject: any) => {
|
|
|
+ const isActive =
|
|
|
+ subject.id === params.type
|
|
|
+ const type = isActive
|
|
|
+ ? 'primary'
|
|
|
+ : 'default'
|
|
|
+ return (
|
|
|
+ <Tag
|
|
|
+ size="large"
|
|
|
+ plain={isActive}
|
|
|
+ type={type}
|
|
|
+ round
|
|
|
+ onClick={() => {
|
|
|
+ params.type = subject.id
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {subject.value}
|
|
|
+ </Tag>
|
|
|
+ )
|
|
|
+ })}
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class={[styles.btnGroup2, 'btnMore']}>
|
|
|
+ <Button
|
|
|
+ class={styles.resetting}
|
|
|
+ type="primary"
|
|
|
+ plain
|
|
|
+ round
|
|
|
+ onClick={() => {
|
|
|
+ params.subjectId = null
|
|
|
+ params.level = ''
|
|
|
+ params.type = ''
|
|
|
}}
|
|
|
>
|
|
|
- {searchObj.value[state.activeTab].subjects &&
|
|
|
- searchObj.value[state.activeTab].subjects
|
|
|
- .length > 0 && (
|
|
|
- <>
|
|
|
- <div class={styles.searchTitle}>
|
|
|
- 声部
|
|
|
- </div>
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles['radio-group'],
|
|
|
- styles.radio,
|
|
|
- styles['organ-radio']
|
|
|
- ]}
|
|
|
- >
|
|
|
- {searchObj.value[
|
|
|
- state.activeTab
|
|
|
- ].subjects.map((subject: any) => {
|
|
|
- const isActive =
|
|
|
- subject.id === params.subjectId
|
|
|
- const type = isActive
|
|
|
- ? 'primary'
|
|
|
- : 'default'
|
|
|
- return (
|
|
|
- <Tag
|
|
|
- size="large"
|
|
|
- plain={isActive}
|
|
|
- type={type}
|
|
|
- round
|
|
|
- onClick={() => {
|
|
|
- params.subjectId = subject.id
|
|
|
- }}
|
|
|
- >
|
|
|
- {subject.name}
|
|
|
- </Tag>
|
|
|
- )
|
|
|
- })}
|
|
|
- </div>
|
|
|
- </>
|
|
|
- )}
|
|
|
- {searchObj.value[state.activeTab].levelList &&
|
|
|
- searchObj.value[state.activeTab].levelList
|
|
|
- .length > 0 && (
|
|
|
- <>
|
|
|
- <div class={styles.searchTitle}>
|
|
|
- 级别
|
|
|
- </div>
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles['radio-group'],
|
|
|
- styles.radio,
|
|
|
- styles['organ-radio']
|
|
|
- ]}
|
|
|
- >
|
|
|
- {searchObj.value[
|
|
|
- state.activeTab
|
|
|
- ].levelList.map((subject: any) => {
|
|
|
- const isActive =
|
|
|
- subject.id === params.level
|
|
|
- const type = isActive
|
|
|
- ? 'primary'
|
|
|
- : 'default'
|
|
|
- return (
|
|
|
- <Tag
|
|
|
- size="large"
|
|
|
- plain={isActive}
|
|
|
- type={type}
|
|
|
- round
|
|
|
- onClick={() => {
|
|
|
- params.level = subject.id
|
|
|
- }}
|
|
|
- >
|
|
|
- {subject.value}
|
|
|
- </Tag>
|
|
|
- )
|
|
|
- })}
|
|
|
- </div>
|
|
|
- </>
|
|
|
- )}
|
|
|
- {searchObj.value[state.activeTab].typeList &&
|
|
|
- searchObj.value[state.activeTab].typeList
|
|
|
- .length > 0 && (
|
|
|
- <>
|
|
|
- <div class={styles.searchTitle}>
|
|
|
- 类型
|
|
|
- </div>
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles['radio-group'],
|
|
|
- styles.radio,
|
|
|
- styles['organ-radio']
|
|
|
- ]}
|
|
|
- >
|
|
|
- {searchObj.value[
|
|
|
- state.activeTab
|
|
|
- ].typeList.map((subject: any) => {
|
|
|
- const isActive =
|
|
|
- subject.id === params.type
|
|
|
- const type = isActive
|
|
|
- ? 'primary'
|
|
|
- : 'default'
|
|
|
- return (
|
|
|
- <Tag
|
|
|
- size="large"
|
|
|
- plain={isActive}
|
|
|
- type={type}
|
|
|
- round
|
|
|
- onClick={() => {
|
|
|
- params.type = subject.id
|
|
|
- }}
|
|
|
- >
|
|
|
- {subject.value}
|
|
|
- </Tag>
|
|
|
- )
|
|
|
- })}
|
|
|
- </div>
|
|
|
- </>
|
|
|
- )}
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class={[styles.btnGroup2, 'btnMore']}>
|
|
|
- <Button
|
|
|
- class={styles.resetting}
|
|
|
- type="primary"
|
|
|
- plain
|
|
|
- round
|
|
|
- onClick={() => {
|
|
|
- params.subjectId = null
|
|
|
- params.level = ''
|
|
|
- params.type = ''
|
|
|
- }}
|
|
|
- >
|
|
|
- 重置
|
|
|
- </Button>
|
|
|
-
|
|
|
- <Button
|
|
|
- class={styles.confirm}
|
|
|
- type="primary"
|
|
|
- color="linear-gradient( 270deg, #FF204B 0%, #FE5B71 100%)"
|
|
|
- round
|
|
|
- block
|
|
|
- onClick={() => {
|
|
|
- onSearch(params.keyword)
|
|
|
- searchRef.value?.toggle()
|
|
|
- }}
|
|
|
- >
|
|
|
- 确定
|
|
|
- </Button>
|
|
|
- </div>
|
|
|
- </DropdownItem>
|
|
|
+ 重置
|
|
|
+ </Button>
|
|
|
|
|
|
+ <Button
|
|
|
+ class={styles.confirm}
|
|
|
+ type="primary"
|
|
|
+ color="linear-gradient( 270deg, #FF204B 0%, #FE5B71 100%)"
|
|
|
+ round
|
|
|
+ block
|
|
|
+ onClick={() => {
|
|
|
+ onSearch(params.keyword)
|
|
|
+ searchRef.value?.toggle()
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ 确定
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </DropdownItem>
|
|
|
</DropdownMenu>
|
|
|
)
|
|
|
}}
|
|
@@ -1094,7 +1140,16 @@ export default defineComponent({
|
|
|
color="linear-gradient(270deg, #FF204B 0%, #FE5B71 100%)"
|
|
|
onClick={onSubmit}
|
|
|
>
|
|
|
- 开通训练教程
|
|
|
+ {/* 开通训练教程 */}
|
|
|
+ <span>
|
|
|
+ ¥{state.details?.actualPrice || 0}/
|
|
|
+ {state.details?.purchaseNum || 0}天
|
|
|
+ </span>
|
|
|
+ <span>
|
|
|
+ {state.details?.albumStatus === 'NO_BUY'
|
|
|
+ ? '立即开通'
|
|
|
+ : '立即续费'}
|
|
|
+ </span>
|
|
|
</Button>
|
|
|
</div>
|
|
|
</TheSticky>
|