|
@@ -0,0 +1,1429 @@
|
|
|
+import {
|
|
|
+ computed,
|
|
|
+ defineComponent,
|
|
|
+ nextTick,
|
|
|
+ onMounted,
|
|
|
+ onUnmounted,
|
|
|
+ reactive,
|
|
|
+ ref,
|
|
|
+ watch
|
|
|
+} from 'vue'
|
|
|
+import umiRequest from 'umi-request'
|
|
|
+import { useRoute, useRouter } from 'vue-router'
|
|
|
+import request from '@/helpers/request'
|
|
|
+import ColHeader from '@/components/col-header'
|
|
|
+import { postMessage, promisefiyPostMessage } from '@/helpers/native-message'
|
|
|
+import {
|
|
|
+ Button,
|
|
|
+ Cell,
|
|
|
+ CellGroup,
|
|
|
+ Checkbox,
|
|
|
+ Dialog,
|
|
|
+ Icon,
|
|
|
+ Image,
|
|
|
+ Popup,
|
|
|
+ RadioGroup,
|
|
|
+ Sticky,
|
|
|
+ Tag,
|
|
|
+ Radio,
|
|
|
+ Toast,
|
|
|
+ Picker
|
|
|
+} from 'vant'
|
|
|
+import styles from './index.module.less'
|
|
|
+// import Item from '../list/item'
|
|
|
+import { useRect } from '@vant/use'
|
|
|
+import { Vue3Lottie } from 'vue3-lottie'
|
|
|
+import { getRandomKey, musicBuy } from '../music'
|
|
|
+import { getOssUploadUrl, state } from '@/state'
|
|
|
+// import { useEventTracking } from '@/helpers/hooks'
|
|
|
+import ColSticky from '@/components/col-sticky'
|
|
|
+import { browser, moneyFormat } from '@/helpers/utils'
|
|
|
+import { orderStatus } from '@/views/order-detail/orderStatus'
|
|
|
+import iconShare from '@/views/music/album/icon_share.svg'
|
|
|
+import iconAlbum from './images/icon_album.png'
|
|
|
+import iconAlbum2 from './images/icon_album2.png'
|
|
|
+import iconDownload from './images/icon_download.png'
|
|
|
+import iconChange from './images/icon-change.png'
|
|
|
+import iconAddCourse from './images/icon-add-course.png'
|
|
|
+import iconRemoveCourse from './images/icon-remove-course.png'
|
|
|
+
|
|
|
+import AstronautJSON from './animate/bigLoad.json'
|
|
|
+import ColShare from '@/components/col-share'
|
|
|
+import iconCollect from './images/icon_collect.png'
|
|
|
+import iconCollectActive from './images/icon_collect_active.png'
|
|
|
+import iconListen from './images/icon_listen.png'
|
|
|
+import iconTeacher from '@common/images/icon_teacher.png'
|
|
|
+import emtpy from './images/emtpy.png'
|
|
|
+
|
|
|
+import activeButtonIcon from '@common/images/icon_checkbox.png'
|
|
|
+import inactiveButtonIcon from '@common/images/icon_checkbox_default.png'
|
|
|
+import staffDetafult from './images/staff-default.png'
|
|
|
+// import staffActive from './images/staff-active.png'
|
|
|
+import firstDefault from './images/first-default.png'
|
|
|
+// import firstActive from './images/first-active.png'
|
|
|
+import fixedDefault from './images/fixed-default.png'
|
|
|
+// import fixedActive from './images/fixed-active.png'
|
|
|
+
|
|
|
+import Plyr from 'plyr'
|
|
|
+import 'plyr/dist/plyr.css'
|
|
|
+import Download from './download'
|
|
|
+import { getInstrumentName } from '@/constant/instruments'
|
|
|
+import { getUploadSign, onOnlyFileUpload } from '@/helpers/oss-file-upload'
|
|
|
+import { svgtopng } from '@/tenant/music/music-detail/formatSvgToImg'
|
|
|
+import { useThrottleFn } from '@vueuse/core'
|
|
|
+import {
|
|
|
+ formatXML,
|
|
|
+ getCustomInfo,
|
|
|
+ onlyVisible
|
|
|
+} from '@/tenant/music/music-detail/instrument'
|
|
|
+
|
|
|
+export const getAssetsHomeFile = (fileName: string) => {
|
|
|
+ const path = `../component/images/${fileName}`
|
|
|
+ const modules = import.meta.globEager('../component/images/*')
|
|
|
+ return modules[path].default
|
|
|
+}
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: 'MusicDetail',
|
|
|
+ setup() {
|
|
|
+ localStorage.setItem('behaviorId', getRandomKey())
|
|
|
+ const router = useRouter()
|
|
|
+ const route = useRoute()
|
|
|
+ const loading = ref(false)
|
|
|
+ const aId = Number(route.query.activityId) || 0
|
|
|
+ const studentActivityId = ref(aId)
|
|
|
+ const isError = ref(false)
|
|
|
+ const headers = ref(null)
|
|
|
+ const footers = ref(null)
|
|
|
+ const heightInfo = ref<any>('0')
|
|
|
+ const musicDetail = ref<any>(null)
|
|
|
+ const audioFileUrl = ref('')
|
|
|
+ const showImg = ref([] as any)
|
|
|
+ const firstList = ref<Array<any>>([])
|
|
|
+ const fixedList = ref<Array<any>>([])
|
|
|
+ const staffList = ref<Array<any>>([])
|
|
|
+ const musicPdfUrl = ref('')
|
|
|
+
|
|
|
+ const defaultImgs = ref({
|
|
|
+ first: false,
|
|
|
+ fixed: false,
|
|
|
+ staff: false
|
|
|
+ })
|
|
|
+ const accompanyUrl = ref<string>('')
|
|
|
+ const downloadStatus = ref<boolean>(false)
|
|
|
+ const staff = reactive({
|
|
|
+ status: false,
|
|
|
+ radio: 'staff' // staff first fixed
|
|
|
+ })
|
|
|
+
|
|
|
+ const colors: any = {
|
|
|
+ FREE: {
|
|
|
+ color: '#01B84F',
|
|
|
+ text: '免费'
|
|
|
+ },
|
|
|
+ VIP: {
|
|
|
+ color: '#CD863E',
|
|
|
+ text: '会员'
|
|
|
+ },
|
|
|
+ CHARGE: {
|
|
|
+ color: '#3591CE',
|
|
|
+ text: '点播'
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更改预览状态
|
|
|
+ const onChangeStaff = (type: string) => {
|
|
|
+ staff.radio = type
|
|
|
+ staff.status = false
|
|
|
+ if (type == 'first') {
|
|
|
+ loading.value = false
|
|
|
+ const tempPdf = musicDetail.value?.firstPdfUrl
|
|
|
+ initIframe(tempPdf, 'first', staffData.musicXml)
|
|
|
+ } else if (type == 'fixed') {
|
|
|
+ loading.value = false
|
|
|
+ const tempPdf = musicDetail.value?.jianPdfUrl
|
|
|
+ console.log(tempPdf, 'tempPdf')
|
|
|
+ initIframe(tempPdf, 'fixed', staffData.musicXml)
|
|
|
+ } else {
|
|
|
+ loading.value = false
|
|
|
+ const tempPdf = musicDetail.value?.musicPdfUrl
|
|
|
+ initIframe(tempPdf, 'staff', staffData.musicXml)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const initIframe = (tempPdf: string, staff: string, xml: string) => {
|
|
|
+ if (tempPdf) {
|
|
|
+ musicPdfUrl.value = tempPdf
|
|
|
+ renderStaff()
|
|
|
+ } else {
|
|
|
+ musicPdfUrl.value = ''
|
|
|
+ // 为了处理,之前是使用pdf渲染,现在又用osmd,iframe没有重新加载
|
|
|
+ if (
|
|
|
+ !staffData.iframeSrc ||
|
|
|
+ staffData.iframeSrc.indexOf('pdf/web') !== -1
|
|
|
+ ) {
|
|
|
+ renderStaff()
|
|
|
+ } else {
|
|
|
+ resetRenderPage(staff, xml)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ watch(
|
|
|
+ () => staff.radio,
|
|
|
+ (val: string) => {
|
|
|
+ if (val == 'first') {
|
|
|
+ showImg.value = firstList.value
|
|
|
+ } else if (val == 'fixed') {
|
|
|
+ showImg.value = fixedList.value
|
|
|
+ } else {
|
|
|
+ showImg.value = staffList.value
|
|
|
+ }
|
|
|
+ }
|
|
|
+ )
|
|
|
+ const FetchList = async (id?: any) => {
|
|
|
+ if (loading.value) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ loading.value = true
|
|
|
+ isError.value = false
|
|
|
+ try {
|
|
|
+ const res = await request.get(`/music/sheet/detail/${route.query.id}`, {
|
|
|
+ prefix:
|
|
|
+ state.platformType === 'TEACHER' ? '/api-teacher' : '/api-student'
|
|
|
+ })
|
|
|
+ musicDetail.value = res.data
|
|
|
+ // console.log(musicDetail.value.notation, 'musicDetail')
|
|
|
+ // 取原音,如果有多个则默认第一个
|
|
|
+ const background = res.data.background
|
|
|
+ audioFileUrl.value =
|
|
|
+ background && background.length > 0 ? background[0].audioFileUrl : ''
|
|
|
+ // const arrImgs = res.data.musicImg ? res.data.musicImg.split(',') : []
|
|
|
+ showImg.value = res.data.musicImg ? res.data.musicImg.split(',') : []
|
|
|
+ firstList.value = res.data.firstTone
|
|
|
+ ? res.data.firstTone.split(',')
|
|
|
+ : []
|
|
|
+ fixedList.value = res.data.fixedTone
|
|
|
+ ? res.data.fixedTone.split(',')
|
|
|
+ : []
|
|
|
+ staffList.value = res.data.musicImg ? res.data.musicImg.split(',') : []
|
|
|
+
|
|
|
+ // 初始化默认数据是否有值
|
|
|
+ if (firstList.value.length > 0) {
|
|
|
+ defaultImgs.value.first = true
|
|
|
+ }
|
|
|
+ if (fixedList.value.length > 0) {
|
|
|
+ defaultImgs.value.fixed = true
|
|
|
+ }
|
|
|
+ if (staffList.value.length > 0) {
|
|
|
+ defaultImgs.value.staff = true
|
|
|
+ }
|
|
|
+
|
|
|
+ nextTick(async () => {
|
|
|
+ await toDetail()
|
|
|
+ renderStaff()
|
|
|
+ })
|
|
|
+
|
|
|
+ if (res.data.auditStatus === 'DOING') {
|
|
|
+ Dialog.confirm({
|
|
|
+ message: '曲目审核中',
|
|
|
+ showConfirmButton: true,
|
|
|
+ showCancelButton: false,
|
|
|
+ confirmButtonColor: 'var(--van-primary)'
|
|
|
+ }).then(() => {
|
|
|
+ if (browser().isApp) {
|
|
|
+ postMessage({ api: 'goBack' })
|
|
|
+ } else {
|
|
|
+ router.back()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ isError.value = true
|
|
|
+ }
|
|
|
+ if (musicDetail.value?.musicSheetType !== 'CONCERT') {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const player = ref<any>(null)
|
|
|
+ const audio = ref<any>(null)
|
|
|
+ const freeRate = ref<any>(0)
|
|
|
+ const initAudio = async () => {
|
|
|
+ const controls = [
|
|
|
+ 'play-large',
|
|
|
+ 'play',
|
|
|
+ 'progress',
|
|
|
+ 'captions',
|
|
|
+ // 'fullscreen',
|
|
|
+ 'duration'
|
|
|
+ ]
|
|
|
+ player.value = new Plyr(audio.value, {
|
|
|
+ controls: controls
|
|
|
+ })
|
|
|
+
|
|
|
+ const config = await request.get(
|
|
|
+ '/api-student/sysConfig/queryByParamNameList',
|
|
|
+ {
|
|
|
+ params: {
|
|
|
+ paramNames: 'music_sheet_free_rate'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ )
|
|
|
+ freeRate.value = config.data[0]?.paramValue || 0
|
|
|
+
|
|
|
+ player.value.on('timeupdate', () => {
|
|
|
+ // 允许播放时间
|
|
|
+ const players = player.value
|
|
|
+ const playTime = (players.duration * freeRate.value) / 100 || 0
|
|
|
+ // 时间,不能播放
|
|
|
+ if (players.currentTime >= playTime && !buyState.value.play) {
|
|
|
+ players.stop()
|
|
|
+ // players.pause()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ const showLoading = async (e: any) => {
|
|
|
+ if (e.data?.api === 'musicStaffRender') {
|
|
|
+ const osmdImg = e.data.osmdImg
|
|
|
+ showImg.value = []
|
|
|
+ const imgs: any = []
|
|
|
+ for (let i = 0; i < osmdImg.length; i++) {
|
|
|
+ const img = await svgtopng(
|
|
|
+ osmdImg[i].img,
|
|
|
+ osmdImg[i].width,
|
|
|
+ osmdImg[i].height
|
|
|
+ )
|
|
|
+ imgs.push(img)
|
|
|
+ }
|
|
|
+ showImg.value = imgs
|
|
|
+
|
|
|
+ loading.value = e.data.loading
|
|
|
+ }
|
|
|
+ }
|
|
|
+ onMounted(async () => {
|
|
|
+ postMessage({
|
|
|
+ api: 'setStatusBarTextColor',
|
|
|
+ content: { statusBarTextColor: true }
|
|
|
+ })
|
|
|
+ await FetchList()
|
|
|
+ const { height } = useRect(headers as any)
|
|
|
+ const footer = useRect(footers as any)
|
|
|
+ heightInfo.value = height + footer.height
|
|
|
+
|
|
|
+ // 初始化音频
|
|
|
+ if (audioFileUrl.value) {
|
|
|
+ initAudio()
|
|
|
+ }
|
|
|
+
|
|
|
+ window.addEventListener('message', showLoading)
|
|
|
+ })
|
|
|
+ onUnmounted(() => {
|
|
|
+ postMessage({
|
|
|
+ api: 'setStatusBarTextColor',
|
|
|
+ content: { statusBarTextColor: false }
|
|
|
+ })
|
|
|
+ window.removeEventListener('message', showLoading)
|
|
|
+ })
|
|
|
+
|
|
|
+ const toggleFavorite = async () => {
|
|
|
+ /**
|
|
|
+ * 酷乐秀老师端 收藏曲目 music/sheet/favorite/id?providerType=?? 添加参数
|
|
|
+ * @ApiModelProperty("曲目评测来源 TENANT 机构 PLATFORM 平台")
|
|
|
+ * private String providerType;
|
|
|
+ * 表示收藏的是机构曲目,还是平台曲目,
|
|
|
+ */
|
|
|
+ let apiUrl = '', providerType = ''
|
|
|
+ if (browser().isTeacher) {
|
|
|
+ providerType = state.projectType === 'tenant' ? 'TENANT' : 'PLATFORM'
|
|
|
+ }
|
|
|
+ apiUrl = `/music/sheet/favorite/${musicDetail.value?.id}`
|
|
|
+ try {
|
|
|
+ await request.post(apiUrl, {
|
|
|
+ requestType: 'form',
|
|
|
+ data: {
|
|
|
+ providerType
|
|
|
+ },
|
|
|
+ prefix:
|
|
|
+ state.platformType === 'TEACHER' ? '/api-teacher' : '/api-student'
|
|
|
+ })
|
|
|
+ musicDetail.value.favorite = musicDetail.value?.favorite ? 0 : 1
|
|
|
+ musicDetail.value.favoriteCount = musicDetail.value?.favorite
|
|
|
+ ? musicDetail.value.favoriteCount + 1
|
|
|
+ : musicDetail.value.favoriteCount - 1 < 0
|
|
|
+ ? 0
|
|
|
+ : musicDetail.value.favoriteCount - 1
|
|
|
+ setTimeout(() => {
|
|
|
+ Toast(musicDetail.value?.favorite ? '收藏成功' : '取消收藏成功')
|
|
|
+ }, 100)
|
|
|
+ } catch (error) {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const onAddCourse = async () => {
|
|
|
+ try {
|
|
|
+ const res = await request.post('/api-teacher/courseCourseware/submit', {
|
|
|
+ data: {
|
|
|
+ musicSheetId: musicDetail.value.id,
|
|
|
+ clientType: 'TEACHER',
|
|
|
+ userId: state.user.data?.userId
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // console.log(res)
|
|
|
+ setTimeout(() => {
|
|
|
+ musicDetail.value.coursewareId = res.data.id || ''
|
|
|
+ Toast('已将曲目添加到课件')
|
|
|
+ musicDetail.value.coursewareStatus = 1
|
|
|
+ }, 100)
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const removeCourse = async () => {
|
|
|
+ Dialog.confirm({
|
|
|
+ title: '提示',
|
|
|
+ message: '您是否确定移出课件',
|
|
|
+ confirmButtonColor: '#269a93',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ confirmButtonText: '确定'
|
|
|
+ }).then(async () => {
|
|
|
+ try {
|
|
|
+ await request.post(
|
|
|
+ '/api-teacher/courseCourseware/remove/' +
|
|
|
+ musicDetail.value.coursewareId,
|
|
|
+ {
|
|
|
+ data: {}
|
|
|
+ }
|
|
|
+ )
|
|
|
+ setTimeout(() => {
|
|
|
+ Toast('移出成功')
|
|
|
+ musicDetail.value.coursewareStatus = 0
|
|
|
+ }, 100)
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ const onBuy = async () => {
|
|
|
+ const music = musicDetail.value
|
|
|
+ orderStatus.orderObject.orderType = 'MUSIC'
|
|
|
+ orderStatus.orderObject.orderName = music.musicSheetName
|
|
|
+ orderStatus.orderObject.orderDesc = music.musicSheetName
|
|
|
+ orderStatus.orderObject.actualPrice = music.musicPrice
|
|
|
+ orderStatus.orderObject.recomUserId = route.query.recomUserId || 0
|
|
|
+ orderStatus.orderObject.activityId = route.query.activityId || 0
|
|
|
+ orderStatus.orderObject.orderNo = ''
|
|
|
+ orderStatus.orderObject.orderList = [
|
|
|
+ {
|
|
|
+ orderType: 'MUSIC',
|
|
|
+ goodsName: music.musicSheetName,
|
|
|
+ actualPrice: music.musicPrice,
|
|
|
+ ...music
|
|
|
+ }
|
|
|
+ ]
|
|
|
+
|
|
|
+ const res = await request.post('/api-student/userOrder/getPendingOrder', {
|
|
|
+ data: {
|
|
|
+ goodType: 'MUSIC',
|
|
|
+ bizId: music.id
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ const result = res.data
|
|
|
+ if (result) {
|
|
|
+ Dialog.confirm({
|
|
|
+ title: '提示',
|
|
|
+ message: '您有一个未支付的订单,是否继续支付?',
|
|
|
+ confirmButtonColor: '#269a93',
|
|
|
+ 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
|
|
|
+ }
|
|
|
+ routerTo()
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ Dialog.close()
|
|
|
+ // 只用取消订单,不用做其它处理
|
|
|
+ cancelPayment(result.orderNo)
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ routerTo()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const routerTo = () => {
|
|
|
+ const music = musicDetail.value
|
|
|
+ router.push({
|
|
|
+ path: '/orderDetail',
|
|
|
+ query: {
|
|
|
+ orderType: 'MUSIC',
|
|
|
+ musicId: music.id
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ const cancelPayment = async (orderNo: string) => {
|
|
|
+ try {
|
|
|
+ await request.post('/api-student/userOrder/orderCancel', {
|
|
|
+ data: {
|
|
|
+ orderNo
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } catch {}
|
|
|
+ }
|
|
|
+
|
|
|
+ const paymentType = computed(() => {
|
|
|
+ let paymentType = musicDetail.value?.paymentType
|
|
|
+ if (typeof paymentType === 'string') {
|
|
|
+ paymentType = paymentType.split(',')
|
|
|
+ return paymentType
|
|
|
+ }
|
|
|
+ return []
|
|
|
+ })
|
|
|
+
|
|
|
+ const buyState = computed(() => {
|
|
|
+ const music = musicDetail.value
|
|
|
+ return {
|
|
|
+ hasTenantAlbum: route.query?.tenantAlbumId ? true : false, // 是否从专辑来的
|
|
|
+ play: music.play ? true : false, // 是否可以播放
|
|
|
+ free: music?.paymentType.includes('FREE'),
|
|
|
+ charge: music?.paymentType.includes('CHARGE'),
|
|
|
+ vip: music?.paymentType.includes('VIP'),
|
|
|
+ buy: music?.orderStatus === 'PAID' // 是否已买
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ const shareStatus = ref(false)
|
|
|
+ const shareUrl = ref('')
|
|
|
+ const shareDiscount = ref(0)
|
|
|
+ // console.log(data)
|
|
|
+ const onShare = async () => {
|
|
|
+ try {
|
|
|
+ const res = await request.post('/api-teacher/open/musicShareProfit', {
|
|
|
+ data: {
|
|
|
+ bizId: musicDetail.value?.id,
|
|
|
+ userId: state.user.data?.userId
|
|
|
+ }
|
|
|
+ })
|
|
|
+ let url =
|
|
|
+ location.origin +
|
|
|
+ `/teacher/#/shareMusic?id=${musicDetail.value?.id}&recomUserId=${state.user.data?.userId}&userType=${state.platformType}`
|
|
|
+ // 判断是否有活动
|
|
|
+ if (res.data.discount === 1) {
|
|
|
+ url += `&activityId=${res.data.activityId}`
|
|
|
+ }
|
|
|
+ shareDiscount.value = res.data.discount || 0
|
|
|
+ console.log(url)
|
|
|
+ shareUrl.value = url
|
|
|
+ shareStatus.value = true
|
|
|
+ return
|
|
|
+ } catch {}
|
|
|
+ }
|
|
|
+
|
|
|
+ const staffData = reactive({
|
|
|
+ open: false,
|
|
|
+ iframeSrc: '',
|
|
|
+ musicXml: '',
|
|
|
+ instrumentName: '',
|
|
|
+ iframeRef: null as any,
|
|
|
+ partIndex: 0,
|
|
|
+ partXmlIndex: 0,
|
|
|
+ tempPartList: [] as any[],
|
|
|
+ partList: [] as any[],
|
|
|
+ xmlPartList: [] as any[]
|
|
|
+ })
|
|
|
+ /** 渲染五线谱 */
|
|
|
+ const sortList = {
|
|
|
+ 长笛: 1,
|
|
|
+ 单簧管: 2,
|
|
|
+ 中音单簧管: 3,
|
|
|
+ 低音单簧管: 4,
|
|
|
+ 高音萨克斯风: 5,
|
|
|
+ 中音萨克斯风: 6,
|
|
|
+ 次中音萨克斯风: 7,
|
|
|
+ 低音萨克斯风: 8,
|
|
|
+ 小号: 9,
|
|
|
+ 长号: 10,
|
|
|
+ 圆号: 11,
|
|
|
+ 大号: 12,
|
|
|
+ 上低音号: 13
|
|
|
+ }
|
|
|
+ const instrumentSort = (list: Array<any>) => {
|
|
|
+ list.sort((a, b) => {
|
|
|
+ return (
|
|
|
+ (sortList[getInstrumentName(a.track)] || 20) -
|
|
|
+ (sortList[getInstrumentName(b.track)] || 20)
|
|
|
+ )
|
|
|
+ })
|
|
|
+ return list
|
|
|
+ }
|
|
|
+
|
|
|
+ const toDetail = async () => {
|
|
|
+ try {
|
|
|
+ if (musicDetail.value?.xmlFileUrl) {
|
|
|
+ // 获取文件
|
|
|
+ const res = await umiRequest.get(musicDetail.value?.xmlFileUrl, {
|
|
|
+ mode: 'cors'
|
|
|
+ })
|
|
|
+ let partNames: string[] = []
|
|
|
+ const xml: any = new DOMParser().parseFromString(res, 'text/xml')
|
|
|
+ for (const item of xml.getElementsByTagName('part-name')) {
|
|
|
+ if (item.textContent) {
|
|
|
+ partNames.push(item.textContent?.trim())
|
|
|
+ }
|
|
|
+ }
|
|
|
+ partNames = partNames.filter(
|
|
|
+ (item: any) => !item?.toLocaleUpperCase()?.includes('COMMON')
|
|
|
+ )
|
|
|
+ const partList: any = []
|
|
|
+ for (let j = 0; j < partNames.length; j++) {
|
|
|
+ partList.push({
|
|
|
+ name: partNames[j],
|
|
|
+ value: j
|
|
|
+ })
|
|
|
+ }
|
|
|
+ staffData.xmlPartList = partList
|
|
|
+ }
|
|
|
+
|
|
|
+ // staffData.iframeSrc = `${location.origin}/osmd/index.html`
|
|
|
+ // staffData.iframeSrc = `${location.origin}${location.pathname}osmd/index.html`
|
|
|
+ staffData.musicXml = musicDetail.value?.xmlFileUrl || ''
|
|
|
+ const tempList = musicDetail.value?.background || []
|
|
|
+ const tempPartList = [] as any
|
|
|
+ staffData.xmlPartList.forEach((part: any) => {
|
|
|
+ const item = tempList.find((item: any) => item.track === part.name)
|
|
|
+ if (item) {
|
|
|
+ tempPartList.push({
|
|
|
+ ...item,
|
|
|
+ index: part.value
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ staffData.partList = tempPartList
|
|
|
+ staffData.tempPartList = JSON.parse(JSON.stringify(staffData.partList))
|
|
|
+ staffData.partList = instrumentSort(staffData.partList)
|
|
|
+ staffData.partXmlIndex = staffData.partList[0]?.index || 0
|
|
|
+
|
|
|
+ staffData.instrumentName =
|
|
|
+ musicDetail.value?.musicSheetType === 'CONCERT'
|
|
|
+ ? getInstrumentName(staffData.partList[staffData.partIndex]?.track)
|
|
|
+ : ''
|
|
|
+
|
|
|
+ if (musicDetail.value?.musicSheetType === 'SINGLE') {
|
|
|
+ musicPdfUrl.value = musicDetail.value?.musicPdfUrl
|
|
|
+ } else {
|
|
|
+ musicPdfUrl.value = staffData.partList[0]?.musicPdfUrl
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ //
|
|
|
+ console.log(error, 'error')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const renderStaff = async () => {
|
|
|
+ try {
|
|
|
+ nextTick(() => {
|
|
|
+ if (musicPdfUrl.value) {
|
|
|
+ // const url = `${location.origin}/pdf/web/viewer-pdf.html?file=${encodeURIComponent(
|
|
|
+ // musicPdfUrl.value
|
|
|
+ // )}&t=${Date.now()}`
|
|
|
+ const url = `${location.origin}${
|
|
|
+ location.pathname
|
|
|
+ }pdf/web/viewer-pdf.html?file=${encodeURIComponent(
|
|
|
+ musicPdfUrl.value
|
|
|
+ )}&t=${Date.now()}`
|
|
|
+
|
|
|
+ const iframeRef = document.querySelector('#staffIframeRef') as any
|
|
|
+ iframeRef.contentWindow.location.replace(url)
|
|
|
+ staffData.iframeSrc = url
|
|
|
+ } else {
|
|
|
+ const url = `${location.origin}${
|
|
|
+ location.pathname
|
|
|
+ }osmd/index.html?t=${new Date().getTime()}`
|
|
|
+ // const url = `${location.origin}/osmd/index.html`
|
|
|
+
|
|
|
+ const iframeRef = document.querySelector('#staffIframeRef') as any
|
|
|
+ iframeRef.contentWindow.location.replace(
|
|
|
+ `${location.origin}${location.pathname}osmd/index.html`
|
|
|
+ )
|
|
|
+ staffData.iframeSrc = url
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } catch (error) {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const musicIframeLoad = async () => {
|
|
|
+ const iframeRef: any = document.getElementById('staffIframeRef')
|
|
|
+ if (iframeRef && iframeRef.contentWindow.renderXml) {
|
|
|
+ const res = await umiRequest.get(staffData.musicXml, {
|
|
|
+ mode: 'cors'
|
|
|
+ })
|
|
|
+ const parseXmlInfo = getCustomInfo(res)
|
|
|
+ const xml = formatXML(parseXmlInfo.parsedXML)
|
|
|
+
|
|
|
+ const currentXml = onlyVisible(xml, staffData.partXmlIndex)
|
|
|
+ iframeRef.contentWindow.renderXml(currentXml, 0, staff.radio)
|
|
|
+
|
|
|
+ // iframeRef.contentWindow.renderXml(
|
|
|
+ // staffData.musicXml,
|
|
|
+ // staffData.partXmlIndex
|
|
|
+ // )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const resetRender = async () => {
|
|
|
+ const iframeRef: any = document.getElementById('staffIframeRef')
|
|
|
+ if (iframeRef && iframeRef.contentWindow.renderXml) {
|
|
|
+ loading.value = true
|
|
|
+ // iframeRef.contentWindow.resetRender(staffData.partXmlIndex)
|
|
|
+ const res = await umiRequest.get(staffData.musicXml, {
|
|
|
+ mode: 'cors'
|
|
|
+ })
|
|
|
+ const parseXmlInfo = getCustomInfo(res)
|
|
|
+ const xml = formatXML(parseXmlInfo.parsedXML)
|
|
|
+
|
|
|
+ const currentXml = onlyVisible(xml, staffData.partXmlIndex)
|
|
|
+ iframeRef.contentWindow.renderXml(currentXml, 0)
|
|
|
+
|
|
|
+ staffData.instrumentName = getInstrumentName(
|
|
|
+ staffData.partList[staffData.partIndex]?.track
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const resetRenderPage = async (type: string, xmlUrl: string) => {
|
|
|
+ const iframeRef: any = document.getElementById('staffIframeRef')
|
|
|
+ if (iframeRef && iframeRef.contentWindow.renderXml) {
|
|
|
+ loading.value = true
|
|
|
+ const res = await umiRequest.get(staffData.musicXml, {
|
|
|
+ mode: 'cors'
|
|
|
+ })
|
|
|
+ const parseXmlInfo = getCustomInfo(res)
|
|
|
+ const xml = formatXML(parseXmlInfo.parsedXML)
|
|
|
+
|
|
|
+ const currentXml = onlyVisible(xml, staffData.partXmlIndex)
|
|
|
+ iframeRef.contentWindow.resetRenderPage(type, currentXml)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const partColumns = computed(() => {
|
|
|
+ return staffData.partList.map((item: any, index: number) => {
|
|
|
+ const instrumentName =
|
|
|
+ musicDetail.value?.musicSheetType === 'CONCERT'
|
|
|
+ ? getInstrumentName(item.track)
|
|
|
+ : ''
|
|
|
+ return {
|
|
|
+ text: item.track + (instrumentName ? `(${instrumentName})` : ''),
|
|
|
+ value: index,
|
|
|
+ instrumentName,
|
|
|
+ musicPdfUrl: item.musicPdfUrl,
|
|
|
+ firstPdfUrl: item.firstPdfUrl,
|
|
|
+ jianPdfUrl: item.jianPdfUrl,
|
|
|
+ xmlValue: item.index,
|
|
|
+ track: item.track
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ return () => {
|
|
|
+ return (
|
|
|
+ <div class={styles.detail}>
|
|
|
+ <ColSticky position="top">
|
|
|
+ <div ref={headers}>
|
|
|
+ <ColHeader
|
|
|
+ background="transparent"
|
|
|
+ hideHeader={false}
|
|
|
+ border={false}
|
|
|
+ isFixed={false}
|
|
|
+ color="#fff"
|
|
|
+ title={musicDetail.value?.musicSheetName}
|
|
|
+ backIconColor="white"
|
|
|
+ v-slots={{
|
|
|
+ right: () => (
|
|
|
+ <div
|
|
|
+ class={styles.shareBtn}
|
|
|
+ style={{
|
|
|
+ color: '#fff'
|
|
|
+ }}
|
|
|
+ onClick={onShare}
|
|
|
+ >
|
|
|
+ <Image src={iconShare} />
|
|
|
+ 分享
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </ColSticky>
|
|
|
+
|
|
|
+ <img class={styles.bgImg} src={musicDetail.value?.titleImg} />
|
|
|
+ <div class={styles.bgContent}></div>
|
|
|
+ <div
|
|
|
+ class={styles.musicContainer}
|
|
|
+ style={{
|
|
|
+ marginTop: '16px',
|
|
|
+ height: `calc(100vh - var(--header-height) - var(--bottom-height) - 16px)`
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <div>
|
|
|
+ <Cell
|
|
|
+ border={false}
|
|
|
+ center
|
|
|
+ class={styles.musicInfo}
|
|
|
+ v-slots={{
|
|
|
+ icon: () => (
|
|
|
+ <Image
|
|
|
+ class={styles.pImg}
|
|
|
+ src={musicDetail.value?.titleImg}
|
|
|
+ />
|
|
|
+ ),
|
|
|
+ title: () => (
|
|
|
+ <div class={styles.info}>
|
|
|
+ <h4
|
|
|
+ class="van-ellipsis"
|
|
|
+ // onClick={() => handleGotoMusicScore(musicDetail.value)}
|
|
|
+ >
|
|
|
+ {musicDetail.value?.musicSheetName}
|
|
|
+ </h4>
|
|
|
+ <p
|
|
|
+ style={{
|
|
|
+ display: 'flex',
|
|
|
+ alignItems: 'center'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {paymentType.value.map(
|
|
|
+ tag =>
|
|
|
+ tag && (
|
|
|
+ <Tag
|
|
|
+ style={{ color: colors[tag]?.color }}
|
|
|
+ class={styles.tag}
|
|
|
+ type="success"
|
|
|
+ plain
|
|
|
+ >
|
|
|
+ {colors[tag].text}
|
|
|
+ </Tag>
|
|
|
+ )
|
|
|
+ )}
|
|
|
+ {musicDetail.value?.exquisiteFlag === 1 && (
|
|
|
+ <Image
|
|
|
+ class={styles.exquisiteFlag}
|
|
|
+ src={getAssetsHomeFile('icon_exquisite.png')}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+
|
|
|
+ {musicDetail.value?.albumNums > 0 && (
|
|
|
+ <Image
|
|
|
+ class={styles.songAlbum}
|
|
|
+ src={getAssetsHomeFile('icon_album_active.png')}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ <span
|
|
|
+ class={[
|
|
|
+ styles.coomposer,
|
|
|
+ browser().isApp &&
|
|
|
+ musicDetail.value?.sourceType === 'TEACHER' &&
|
|
|
+ state.platformType === 'STUDENT' &&
|
|
|
+ styles.links
|
|
|
+ ]}
|
|
|
+ onClick={() => {
|
|
|
+ if (
|
|
|
+ browser().isApp &&
|
|
|
+ musicDetail.value?.sourceType === 'TEACHER' &&
|
|
|
+ state.platformType === 'STUDENT'
|
|
|
+ ) {
|
|
|
+ router.push({
|
|
|
+ path: '/teacherHome',
|
|
|
+ query: {
|
|
|
+ teacherId: musicDetail.value?.userId,
|
|
|
+ tabs: 'music'
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <img class={styles.iconAlbum2} src={iconAlbum2} />
|
|
|
+ <span>
|
|
|
+ {musicDetail.value?.userName ||
|
|
|
+ '游客' + (musicDetail.value?.userId || '')}
|
|
|
+ </span>
|
|
|
+ </span>
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ ),
|
|
|
+ value: () => (
|
|
|
+ <>
|
|
|
+ <span
|
|
|
+ style={{
|
|
|
+ visibility:
|
|
|
+ state.platformType === 'TEACHER'
|
|
|
+ ? 'visible'
|
|
|
+ : 'hidden'
|
|
|
+ }}
|
|
|
+ class={styles.download}
|
|
|
+ onClick={() => {
|
|
|
+ if (musicDetail.value?.coursewareStatus) {
|
|
|
+ removeCourse()
|
|
|
+ } else {
|
|
|
+ onAddCourse()
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ src={
|
|
|
+ musicDetail.value?.coursewareStatus
|
|
|
+ ? iconRemoveCourse
|
|
|
+ : iconAddCourse
|
|
|
+ }
|
|
|
+ />
|
|
|
+ <span>
|
|
|
+ {musicDetail.value?.coursewareStatus
|
|
|
+ ? '移出课件'
|
|
|
+ : '添加课件'}
|
|
|
+ </span>
|
|
|
+ </span>
|
|
|
+ <span
|
|
|
+ class={styles.download}
|
|
|
+ onClick={() => toggleFavorite()}
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ src={
|
|
|
+ musicDetail.value?.favorite
|
|
|
+ ? iconCollectActive
|
|
|
+ : iconCollect
|
|
|
+ }
|
|
|
+ />
|
|
|
+ <span>收藏</span>
|
|
|
+ </span>
|
|
|
+ </>
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <div class={styles.functionSection}>
|
|
|
+ <div
|
|
|
+ class={styles.functionItem}
|
|
|
+ onClick={() => {
|
|
|
+ router.push({
|
|
|
+ path: '/look-album-list',
|
|
|
+ query: {
|
|
|
+ id: musicDetail.value?.id,
|
|
|
+ musicSubject: musicDetail.value?.musicSubject
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <img src={iconAlbum} />
|
|
|
+ <span>专辑</span>
|
|
|
+ </div>
|
|
|
+ {/* {musicDetail.value?.notation ? (
|
|
|
+ <span
|
|
|
+ class={styles.download}
|
|
|
+ onClick={() => {
|
|
|
+ staff.status = true
|
|
|
+ }}
|
|
|
+ style={{
|
|
|
+ display:
|
|
|
+ musicDetail.value?.musicSheetType !== 'CONCERT'
|
|
|
+ ? ''
|
|
|
+ : 'none'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <img src={iconChangeStaff} />
|
|
|
+ <span>转谱</span>
|
|
|
+ </span>
|
|
|
+ ) : null} */}
|
|
|
+ <div
|
|
|
+ class={styles.functionItem}
|
|
|
+ style={{
|
|
|
+ display:
|
|
|
+ musicDetail.value?.musicSheetType === 'CONCERT'
|
|
|
+ ? ''
|
|
|
+ : 'none'
|
|
|
+ }}
|
|
|
+ onClick={() => {
|
|
|
+ if (musicDetail.value?.musicSheetType === 'CONCERT') {
|
|
|
+ staffData.open = true
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <img src={iconChange} />
|
|
|
+ <span>切换乐器</span>
|
|
|
+ </div>
|
|
|
+ {musicDetail.value?.notation ? (
|
|
|
+ <div
|
|
|
+ class={styles.functionItem}
|
|
|
+ style={{
|
|
|
+ display:
|
|
|
+ musicDetail.value?.musicSheetType === 'SINGLE'
|
|
|
+ ? ''
|
|
|
+ : 'none'
|
|
|
+ }}
|
|
|
+ onClick={() => {
|
|
|
+ staff.status = true
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <img src={iconChange} />
|
|
|
+ <span>转谱</span>
|
|
|
+ </div>
|
|
|
+ ) : null}
|
|
|
+
|
|
|
+ <div
|
|
|
+ class={styles.functionItem}
|
|
|
+ onClick={() => {
|
|
|
+ if (musicPdfUrl.value) {
|
|
|
+ const songName =
|
|
|
+ musicDetail.value?.musicSheetName +
|
|
|
+ (staffData.instrumentName
|
|
|
+ ? `(${staffData.instrumentName})`
|
|
|
+ : '')
|
|
|
+ promisefiyPostMessage({
|
|
|
+ api: 'downloadFile',
|
|
|
+ content: {
|
|
|
+ downloadUrl: musicPdfUrl.value,
|
|
|
+ fileName: songName
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (showImg.value.length > 0) {
|
|
|
+ downloadStatus.value = true
|
|
|
+ } else {
|
|
|
+ Toast('暂无图片')
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <img src={iconDownload} />
|
|
|
+ <span>下载</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class={styles.musicContent}>
|
|
|
+ {musicDetail.value?.musicSheetType === 'CONCERT' ||
|
|
|
+ musicPdfUrl.value ||
|
|
|
+ !defaultImgs.value[staff.radio] ? (
|
|
|
+ <>
|
|
|
+ {musicPdfUrl.value ? (
|
|
|
+ <iframe
|
|
|
+ id="staffIframeRef"
|
|
|
+ style={{
|
|
|
+ opacity: loading.value ? 0 : 1
|
|
|
+ }}
|
|
|
+ src={staffData.iframeSrc}
|
|
|
+ onLoad={() => {
|
|
|
+ // 判断是用哪个渲染的
|
|
|
+ loading.value = false
|
|
|
+ }}
|
|
|
+ ></iframe>
|
|
|
+ ) : (
|
|
|
+ <>
|
|
|
+ <p class={styles.musicTitle}>
|
|
|
+ {(musicDetail.value?.musicSheetName
|
|
|
+ ? musicDetail.value?.musicSheetName
|
|
|
+ : '') +
|
|
|
+ (staffData.instrumentName
|
|
|
+ ? `(${staffData.instrumentName})`
|
|
|
+ : '')}
|
|
|
+ </p>
|
|
|
+ {loading.value && (
|
|
|
+ <div>
|
|
|
+ <Vue3Lottie
|
|
|
+ animationData={AstronautJSON}
|
|
|
+ class={styles.finch}
|
|
|
+ ></Vue3Lottie>
|
|
|
+ {/* <p class={styles.finchLoad}>加载中...</p> */}
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ <iframe
|
|
|
+ id="staffIframeRef"
|
|
|
+ style={{
|
|
|
+ opacity: loading.value ? 0 : 1
|
|
|
+ }}
|
|
|
+ // src={staffData.iframeSrc}
|
|
|
+ onLoad={() => {
|
|
|
+ musicIframeLoad()
|
|
|
+ }}
|
|
|
+ ></iframe>
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ </>
|
|
|
+ ) : (
|
|
|
+ // <>
|
|
|
+ // {loading.value && (
|
|
|
+ // <>
|
|
|
+ // <Vue3Lottie
|
|
|
+ // animationData={AstronautJSON}
|
|
|
+ // class={styles.finch}
|
|
|
+ // ></Vue3Lottie>
|
|
|
+ // <p class={styles.finchLoad}>加载中...</p>
|
|
|
+ // </>
|
|
|
+ // )}
|
|
|
+ // <iframe
|
|
|
+ // id="staffIframeRef"
|
|
|
+ // style={{
|
|
|
+ // opacity: loading.value ? 0 : 1
|
|
|
+ // }}
|
|
|
+ // src={staffData.iframeSrc}
|
|
|
+ // onLoad={() => {
|
|
|
+ // if (!defaultImgs.value[staff.radio]) {
|
|
|
+ // onChangeStaff(staff.radio)
|
|
|
+ // } else {
|
|
|
+ // musicIframeLoad()
|
|
|
+ // }
|
|
|
+ // }}
|
|
|
+ // ></iframe>
|
|
|
+ // </>
|
|
|
+ <>
|
|
|
+ <p class={styles.musicTitle}>
|
|
|
+ {(musicDetail.value?.musicSheetName
|
|
|
+ ? musicDetail.value?.musicSheetName
|
|
|
+ : '') +
|
|
|
+ (staffData.instrumentName
|
|
|
+ ? `(${staffData.instrumentName})`
|
|
|
+ : '')}
|
|
|
+ </p>
|
|
|
+ {showImg.value.length > 0 ? (
|
|
|
+ <div class={styles.musicImg}>
|
|
|
+ <img src={showImg.value[0]} alt="" />
|
|
|
+ </div>
|
|
|
+ ) : loading.value ? (
|
|
|
+ <>
|
|
|
+ <Vue3Lottie
|
|
|
+ animationData={AstronautJSON}
|
|
|
+ class={styles.finch}
|
|
|
+ ></Vue3Lottie>
|
|
|
+ <p class={styles.finchLoad}>加载中...</p>
|
|
|
+ </>
|
|
|
+ ) : (
|
|
|
+ <div class={styles.empty}>
|
|
|
+ <Image src={emtpy} class={styles.emptyImg} />
|
|
|
+ <p class={styles.emptyTip}>暂无乐谱预览图</p>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {musicDetail.value?.id && (
|
|
|
+ <ColSticky
|
|
|
+ position="bottom"
|
|
|
+ background="white"
|
|
|
+ varName="--bottom-height"
|
|
|
+ >
|
|
|
+ <div ref={footers}>
|
|
|
+ <div class={styles.videoOperation}>
|
|
|
+ {audioFileUrl.value && (
|
|
|
+ <>
|
|
|
+ {!buyState.value.play &&
|
|
|
+ freeRate.value != 100 &&
|
|
|
+ freeRate.value != 0 && (
|
|
|
+ <div class={[styles.audition]}>
|
|
|
+ <img src={iconListen} />
|
|
|
+ <span>每首曲目可试听{freeRate.value}%</span>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+
|
|
|
+ <div class={[styles.audio, styles.collectCell]}>
|
|
|
+ <audio id="player" controls ref={audio}>
|
|
|
+ <source src={audioFileUrl.value} type="audio/mp3" />
|
|
|
+ </audio>
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ {/* 判断是否是免费的,或者已经购买过,是否从专辑过来的 */}
|
|
|
+ {buyState.value.play ||
|
|
|
+ (state.platformType === 'TEACHER' &&
|
|
|
+ buyState.value.hasTenantAlbum) ? (
|
|
|
+ <Button
|
|
|
+ round
|
|
|
+ block
|
|
|
+ type="primary"
|
|
|
+ color="linear-gradient(180deg, #59E5D5 0%, #2DC7AA 100%)"
|
|
|
+ onClick={() => {
|
|
|
+ const throttleFn = useThrottleFn(() => {
|
|
|
+ player.value && player.value.stop()
|
|
|
+ const item: any = partColumns.value.find(
|
|
|
+ (c: any) => c.value === staffData.partIndex
|
|
|
+ )
|
|
|
+ // const index = staffData.tempPartList.findIndex(
|
|
|
+ // (i: any) => i.track === item?.track
|
|
|
+ // )
|
|
|
+ // 新版云教练的谱面类型使用musicRenderType字段
|
|
|
+ const musicRenderType = staff.radio === 'staff' ? 'staff' : staff.radio === 'first' ? 'firstTone' : staff.radio === 'fixed' ? 'fixedTone' : '';
|
|
|
+ let extraParam: any = {
|
|
|
+ 'part-index': item?.xmlValue || 0,
|
|
|
+ musicRenderType,
|
|
|
+ }
|
|
|
+ if (route.query.tenantAlbumId) {
|
|
|
+ extraParam.albumId = route.query.tenantAlbumId
|
|
|
+ }
|
|
|
+ musicBuy(musicDetail.value, () => {}, extraParam)
|
|
|
+ }, 500)
|
|
|
+
|
|
|
+ throttleFn()
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ 立即练习
|
|
|
+ </Button>
|
|
|
+ ) : (
|
|
|
+ <div class={styles.colSticky}>
|
|
|
+ {/* 只有,有点播类型的才显示价格 */}
|
|
|
+ {buyState.value.charge && (
|
|
|
+ <div class={styles.priceSection}>
|
|
|
+ <span>点播价:</span>
|
|
|
+ <span class={styles.price}>
|
|
|
+ <i>¥</i>
|
|
|
+ {moneyFormat(musicDetail.value?.musicPrice)}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ <div class={[styles.buyBtn]}>
|
|
|
+ {/* 判断是否是需要收费的 */}
|
|
|
+ {buyState.value.charge && (
|
|
|
+ <Button
|
|
|
+ round
|
|
|
+ type="primary"
|
|
|
+ color="linear-gradient(180deg, #59E5D5 0%, #2DC7AA 100%)"
|
|
|
+ class={styles.primary}
|
|
|
+ onClick={onBuy}
|
|
|
+ >
|
|
|
+ 立即点播
|
|
|
+ </Button>
|
|
|
+ )}
|
|
|
+
|
|
|
+ {/* 判断是否有会员的 */}
|
|
|
+ {buyState.value.vip && (
|
|
|
+ <Button
|
|
|
+ round
|
|
|
+ block={!buyState.value.charge ? true : false}
|
|
|
+ type="primary"
|
|
|
+ color="linear-gradient(180deg, #F7BD8D 0%, #CD8806 100%)"
|
|
|
+ class={styles.memeber}
|
|
|
+ onClick={() => {
|
|
|
+ router.push({
|
|
|
+ path: '/memberCenter',
|
|
|
+ query: {
|
|
|
+ ...route.query
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {studentActivityId.value > 0 && (
|
|
|
+ <div class={[styles.buttonDiscount]}>专属优惠</div>
|
|
|
+ )}
|
|
|
+ 开通会员
|
|
|
+ </Button>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </ColSticky>
|
|
|
+ )}
|
|
|
+
|
|
|
+ <Popup
|
|
|
+ v-model:show={shareStatus.value}
|
|
|
+ style={{ background: 'transparent' }}
|
|
|
+ teleport="body"
|
|
|
+ >
|
|
|
+ <ColShare
|
|
|
+ teacherId={state.user.data?.userId}
|
|
|
+ shareUrl={shareUrl.value}
|
|
|
+ shareType="music"
|
|
|
+ >
|
|
|
+ <div class={styles.shareMate}>
|
|
|
+ {shareDiscount.value === 1 && (
|
|
|
+ <div class={styles.tagDiscount}>专属优惠</div>
|
|
|
+ )}
|
|
|
+
|
|
|
+ <img
|
|
|
+ class={styles.icon}
|
|
|
+ crossorigin="anonymous"
|
|
|
+ src={musicDetail.value?.titleImg + `?t=${+new Date()}`}
|
|
|
+ />
|
|
|
+ <div class={styles.info}>
|
|
|
+ <h4 class="van-multi-ellipsis--l2">
|
|
|
+ {musicDetail.value?.musicSheetName}
|
|
|
+ </h4>
|
|
|
+ <p>作曲人:{musicDetail.value?.composer}</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </ColShare>
|
|
|
+ </Popup>
|
|
|
+
|
|
|
+ <Popup v-model:show={downloadStatus.value} position="bottom" round>
|
|
|
+ {downloadStatus.value && (
|
|
|
+ <Download
|
|
|
+ imgList={JSON.parse(JSON.stringify(showImg.value))}
|
|
|
+ musicSheetName={
|
|
|
+ musicDetail.value?.musicSheetName +
|
|
|
+ (staffData.instrumentName
|
|
|
+ ? `(${staffData.instrumentName})`
|
|
|
+ : '')
|
|
|
+ }
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </Popup>
|
|
|
+
|
|
|
+ <Popup
|
|
|
+ v-model:show={staff.status}
|
|
|
+ teleport="body"
|
|
|
+ closeable
|
|
|
+ style={{ width: '80%' }}
|
|
|
+ round
|
|
|
+ >
|
|
|
+ <div class={styles.staffContainer}>
|
|
|
+ <div class={styles.staffTitle}>选择转换曲谱</div>
|
|
|
+ <RadioGroup v-model={staff.radio}>
|
|
|
+ <CellGroup border={false}>
|
|
|
+ <Cell
|
|
|
+ center
|
|
|
+ border={false}
|
|
|
+ class={staff.radio === 'staff' ? styles.active : ''}
|
|
|
+ onClick={() => onChangeStaff('staff')}
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ icon: () => (
|
|
|
+ <Image src={staffDetafult} class={styles.staffImg} />
|
|
|
+ ),
|
|
|
+ title: () => <span class={styles.name}>五线谱</span>,
|
|
|
+ value: () => (
|
|
|
+ <Radio name="staff">
|
|
|
+ {{
|
|
|
+ icon: (props: any) => (
|
|
|
+ <Icon
|
|
|
+ class={styles.boxStyle}
|
|
|
+ size={16}
|
|
|
+ name={
|
|
|
+ props.checked
|
|
|
+ ? activeButtonIcon
|
|
|
+ : inactiveButtonIcon
|
|
|
+ }
|
|
|
+ />
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </Radio>
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </Cell>
|
|
|
+ <Cell
|
|
|
+ center
|
|
|
+ border={false}
|
|
|
+ class={staff.radio === 'first' ? styles.active : ''}
|
|
|
+ onClick={() => onChangeStaff('first')}
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ icon: () => (
|
|
|
+ <Image src={firstDefault} class={styles.staffImg} />
|
|
|
+ ),
|
|
|
+ title: () => <span class={styles.name}>简谱-首调</span>,
|
|
|
+ value: () => (
|
|
|
+ <Radio name="first">
|
|
|
+ {{
|
|
|
+ icon: (props: any) => (
|
|
|
+ <Icon
|
|
|
+ class={styles.boxStyle}
|
|
|
+ size={16}
|
|
|
+ name={
|
|
|
+ props.checked
|
|
|
+ ? activeButtonIcon
|
|
|
+ : inactiveButtonIcon
|
|
|
+ }
|
|
|
+ />
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </Radio>
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </Cell>
|
|
|
+ <Cell
|
|
|
+ center
|
|
|
+ border={false}
|
|
|
+ class={staff.radio === 'fixed' ? styles.active : ''}
|
|
|
+ onClick={() => onChangeStaff('fixed')}
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ icon: () => (
|
|
|
+ <Image src={fixedDefault} class={styles.staffImg} />
|
|
|
+ ),
|
|
|
+ title: () => <span class={styles.name}>简谱-固定调</span>,
|
|
|
+ value: () => (
|
|
|
+ <Radio name="fixed">
|
|
|
+ {{
|
|
|
+ icon: (props: any) => (
|
|
|
+ <Icon
|
|
|
+ class={styles.boxStyle}
|
|
|
+ size={16}
|
|
|
+ name={
|
|
|
+ props.checked
|
|
|
+ ? activeButtonIcon
|
|
|
+ : inactiveButtonIcon
|
|
|
+ }
|
|
|
+ />
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </Radio>
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </Cell>
|
|
|
+ </CellGroup>
|
|
|
+ </RadioGroup>
|
|
|
+ </div>
|
|
|
+ </Popup>
|
|
|
+
|
|
|
+ <Popup
|
|
|
+ teleport="body"
|
|
|
+ position="bottom"
|
|
|
+ round
|
|
|
+ v-model:show={staffData.open}
|
|
|
+ >
|
|
|
+ <Picker
|
|
|
+ columns={partColumns.value}
|
|
|
+ onConfirm={value => {
|
|
|
+ staffData.open = false
|
|
|
+ staffData.partIndex = value.value
|
|
|
+ staffData.partXmlIndex = value.xmlValue
|
|
|
+ staffData.instrumentName = value.instrumentName
|
|
|
+ showImg.value = []
|
|
|
+ nextTick(() => {
|
|
|
+ let tempPdf = value?.musicPdfUrl
|
|
|
+ if (musicDetail.value?.musicSheetType !== 'CONCERT') {
|
|
|
+ // tempPdf = ''
|
|
|
+ if (staff.radio === 'first') {
|
|
|
+ tempPdf = value?.firstPdfUrl
|
|
|
+ } else if (staff.radio === 'fixed') {
|
|
|
+ tempPdf = value?.jianPdfUrl
|
|
|
+ } else if (staff.radio === 'staff') {
|
|
|
+ tempPdf = value?.musicPdfUrl
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tempPdf) {
|
|
|
+ musicPdfUrl.value = tempPdf
|
|
|
+ renderStaff()
|
|
|
+ } else {
|
|
|
+ musicPdfUrl.value = ''
|
|
|
+ loading.value = true
|
|
|
+ // 为了处理,之前是使用pdf渲染,现在又用osmd,iframe没有重新加载
|
|
|
+ if (staffData.iframeSrc.indexOf('pdf/web') !== -1) {
|
|
|
+ renderStaff()
|
|
|
+ } else {
|
|
|
+ resetRender()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }}
|
|
|
+ onCancel={() => (staffData.open = false)}
|
|
|
+ />
|
|
|
+ </Popup>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+})
|