lex-xin 7 月之前
父節點
當前提交
4a0f12d099

+ 5 - 0
src/helpers/utils.ts

@@ -81,6 +81,11 @@ export const browser = () => {
   }
 }
 
+export const getHttpOrigin = () => {
+	return window.location.origin
+}
+
+
 /**
  * @description 格式化日期控件显示内容
  * @param type

+ 32 - 51
src/tenant/music/music-detail/formatSvgToImg.ts

@@ -1,49 +1,44 @@
-import { Canvg, presets } from 'canvg'
+import { Canvg, presets } from "canvg";
 
 // https://gist.githubusercontent.com/n1ru4l/9c7eff52fe084d67ff15ae6b0af5f171/raw/da9fe36d72171d4e36b92aced587b48dc5182792/offscreen-canvas-polyfill.js
 if (!window.OffscreenCanvas) {
   // eslint-disable-next-line @typescript-eslint/ban-ts-comment
   // @ts-ignore
   window.OffscreenCanvas = class OffscreenCanvas {
-    canvas: HTMLCanvasElement
+    canvas: HTMLCanvasElement;
     constructor(width: number, height: number) {
-      this.canvas = document.createElement('canvas')
-      this.canvas.width = width
-      this.canvas.height = height
+      this.canvas = document.createElement("canvas");
+      this.canvas.width = width;
+      this.canvas.height = height;
 
       // eslint-disable-next-line @typescript-eslint/ban-ts-comment
       // @ts-ignore
       this.canvas.convertToBlob = () => {
-        return new Promise(resolve => {
-          this.canvas.toBlob(resolve)
-        })
-      }
+        return new Promise((resolve) => {
+          this.canvas.toBlob(resolve);
+        });
+      };
 
       // eslint-disable-next-line @typescript-eslint/ban-ts-comment
       // @ts-ignore
-      return this.canvas
+      return this.canvas;
     }
-  }
+  };
 }
 
-const preset = presets.offscreen()
+const preset = presets.offscreen();
 const blobToBase64 = (blob: any) => {
   return new Promise((resolve, _) => {
-    const reader = new FileReader()
-    reader.onloadend = () => resolve(reader.result)
-    reader.readAsDataURL(blob)
-  })
-}
-let canvas = null as any
-export const svgtopng = async (svg: any, width: any, height: any) => {
-  // console.log(canvas, +new Date() + '-----')
+    const reader = new FileReader();
+    reader.onloadend = () => resolve(reader.result);
+    reader.readAsDataURL(blob);
+  });
+};
 
-  if (!canvas) {
-    canvas = new OffscreenCanvas(width, height)
-  }
-
-  const ctx = canvas.getContext('2d')!
-  let v: any = await Canvg.fromString(ctx!, svg, preset)
+export const svgtopng = async (svg: any, width: any, height: any) => {
+  let canvas: any = new OffscreenCanvas(width, height);
+  const ctx = canvas.getContext("2d")!;
+  let v: any = await Canvg.fromString(ctx!, svg, preset);
 
   /**
    * Resize SVG to fit in given size.
@@ -51,30 +46,16 @@ export const svgtopng = async (svg: any, width: any, height: any) => {
    * @param height
    * @param preserveAspectRatio
    */
-  v.resize(width * 2, height * 2, 'xMidYMid meet')
+  v.resize(width / 1.2, height / 1.2, "xMidYMid meet");
 
   // Render only first frame, ignoring animations and mouse.
-  await v.start()
-  const blob = await canvas.convertToBlob()
-  const base64 = await blobToBase64(blob)
-  // canvas.drawImage(base64
-  // await v.stop()
-  // releaseCanvas(canvas)
-  ctx.clearRect(0, 0, canvas.width, canvas.height)
-  // canvas = null
-  // console.log(canvas, 'draw')
-  await v.stop()
-  v = null
-  return base64
-}
-
-// function releaseCanvas(canvasElement) {
-//   // 清空 Canvas 上的内容
-//   const ctx = canvasElement.getContext('2d')
-//   ctx.clearRect(0, 0, canvasElement.width, canvasElement.height)
-
-//   // 停止任何正在进行的动画或定时器
-//   cancelAnimationFrame(canvasElement.animationId)
-//   // 删除对 Canvas 元素的引用
-//   canvasElement = null
-// }
+  await v.start();
+  let blob: any = await canvas.convertToBlob();
+  const base64 = await blobToBase64(blob);
+  ctx.clearRect(0, 0, canvas.width, canvas.height);
+  canvas = null;
+  v.stop();
+  v = null;
+  blob = null;
+  return base64;
+};

+ 70 - 68
src/views/music/music-detail/imageFunction.ts

@@ -1,97 +1,99 @@
 import imgList from './images/logoWatermark.png'
+
+export const clearCanvas = (canvas: any) => {
+  let ctx = canvas?.getContext('2d');
+
+  // 在绘制新内容之前清除画布
+  ctx && ctx.clearRect(0, 0, canvas.width, canvas.height);
+}
+
 export const imgToCanvas = async (url: string) => {
-  console.log('imgToCanvas', url)
-  const img = document.createElement('img')
-  img.setAttribute('crossOrigin', 'anonymous')
+  // console.log("imgToCanvas", url);
+  const img = document.createElement("img");
+  img.setAttribute("crossOrigin", "anonymous");
   // 为了处理base64 和 连接加载不同的
-  if (url && typeof url == 'string' && url.includes('data:image')) {
-    img.src = url
+  if (url && typeof url == "string" && url.includes("data:image")) {
+    img.src = url;
   } else {
-    img.src = url + `?t=${+new Date()}`
+    img.src = url + `?t=${+new Date()}`;
   }
-
+  
   // 防止跨域引起的 Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
-  await new Promise(resolve => (img.onload = resolve))
+  await new Promise((resolve) => (img.onload = resolve));
   // 创建canvas DOM元素,并设置其宽高和图片一样
-
-  const canvas = document.createElement('canvas')
-  canvas.width = img.width
-  canvas.height = img.height
+  const canvas = document.createElement("canvas");
+  canvas.width = img.width;
+  canvas.height = img.height;
   // 坐标(0,0) 表示从此处开始绘制,相当于偏移。
-  const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
+  const ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
 
-  ctx.fillStyle = 'rgb(255, 255, 255)'
-  ctx.fillStyle = '#fff'
-  ctx.fillRect(0, 0, img.width, img.height)
-  ctx.drawImage(img, 0, 0)
-  return canvas
-}
+  ctx.fillStyle = "rgb(255, 255, 255)";
+  ctx.fillStyle = "#fff";
+  // console.log('图片宽高123',img.width,img.height)
+  ctx.fillRect(0, 0, img.width, img.height);
+  ctx.drawImage(img, 0, 0);
+  return canvas;
+};
 
 /* canvas添加水印
-
 * @param {canvas对象} canvas
-
 * @param {水印文字} text
-
 */
-
-export const addWatermark = async (canvas, text) => {
-  console.log('addWatermark')
+export const addWatermark = async (canvas: any, text: any) => {
+  console.log("addWatermark");
   try {
-    const ctx = canvas.getContext('2d')
+    const ctx = canvas.getContext("2d");
     // ctx.fillStyle = '#fff'
-    const img = document.createElement('img')
-    img.setAttribute('crossOrigin', 'anonymous')
+    const img = document.createElement("img");
+    img.setAttribute("crossOrigin", "anonymous");
     // 为了处理base64 和 连接加载不同的
-    if (
-      imgList &&
-      typeof imgList == 'string' &&
-      imgList.includes('data:image')
-    ) {
-      img.src = imgList
+    if (imgList && typeof imgList == "string" && imgList.includes("data:image")) {
+      img.src = imgList;
     } else {
-      img.src = imgList + `?${new Date().getTime()}`
+      img.src = imgList + `?${new Date().getTime()}`;
     }
     // 防止跨域引起的 Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
-    await new Promise(resolve => (img.onload = resolve))
+    await new Promise((resolve) => (img.onload = resolve));
     // 创建canvas DOM元素,并设置其宽高和图片一样
-    const water = document.createElement('canvas')
-    water.width = 600
-    water.height = 500
+    const water = document.createElement("canvas");
+    water.width = 600;
+    water.height = 500;
 
     // 第一层
-    const waterCtx = water.getContext('2d') as CanvasRenderingContext2D
-    waterCtx.clearRect(0, 0, water.width, water.height)
+    const waterCtx = water.getContext("2d") as CanvasRenderingContext2D;
+    waterCtx.clearRect(0, 0, water.width, water.height);
     // 小水印中文字偏转角度
-    waterCtx.rotate((-30 * Math.PI) / 180)
-    waterCtx.drawImage(img, 0, 300)
-    const pat = ctx.createPattern(water, 'repeat')
-    ctx.fillStyle = pat
-    ctx.fillRect(0, 0, canvas.width, canvas.height)
-
-    return canvas
+    waterCtx.rotate((-30 * Math.PI) / 180);
+    waterCtx.drawImage(img, 0, 300);
+    const pat = ctx.createPattern(water, "repeat");
+    ctx.fillStyle = pat;
+    ctx.fillRect(0, 0, canvas.width, canvas.height);
+    // console.log('图片宽高1234',img.width,img.height,canvas.width, canvas.height)
+    return canvas;
   } catch (e) {
-    console.log(e)
+    console.log(e);
   }
-}
+};
+
+export const addMusicTitle = (canvas: any, info: any) => {
+  canvas.getContext("2d");
+  const water = document.createElement("canvas");
 
-export const addMusicTitle = (canvas, info) => {
-  canvas.getContext('2d')
-  const water = document.createElement('canvas')
   // 小水印画布大小
-  water.width = canvas.width
-  water.height = canvas.height + 80
-  const waterCtx = water.getContext('2d') as CanvasRenderingContext2D
-  waterCtx.fillStyle = '#fff'
-  waterCtx.fillRect(0, 0, water.width, water.height)
-  waterCtx.font = `26pt Calibri`
-  waterCtx.fillStyle = '#000'
-  waterCtx.textAlign = 'center'
-  waterCtx.drawImage(canvas, 0, 40)
-  waterCtx.fillText(info.title, canvas.width / 2, 40)
-  return water
-}
+  water.width = canvas.width;
+  water.height = canvas.height + 28;
+  const waterCtx = water.getContext("2d") as CanvasRenderingContext2D;
+  waterCtx.fillStyle = "#fff";
+  waterCtx.fillRect(0, 0, canvas.width, canvas.height + 70);
+  // console.log('图片宽高12345',canvas.width, canvas.height)
+  waterCtx.font = (info.size || 30) + `pt Calibri`;
+  waterCtx.fillStyle = "#000";
+  waterCtx.textAlign = "center";
+  waterCtx.drawImage(canvas, 0, 70);
+  waterCtx.fillText(info.title, canvas.width / 2, 70);
+  return water;
+};
 
-export const convasToImg = canvas => {
-  return canvas.toDataURL('image/png')
-}
+export const convasToImg = (canvas: any) => {
+  return canvas.toDataURL("image/png");
+};

+ 1429 - 0
src/views/music/music-detail/index---copy.tsx

@@ -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>
+      )
+    }
+  }
+})

+ 410 - 209
src/views/music/music-detail/index.tsx

@@ -29,6 +29,7 @@ import {
   Toast,
   Picker
 } from 'vant'
+import qs from 'query-string'
 import styles from './index.module.less'
 // import Item from '../list/item'
 import { useRect } from '@vant/use'
@@ -37,7 +38,7 @@ 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 { browser, getHttpOrigin, 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'
@@ -52,23 +53,17 @@ 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 {
@@ -86,7 +81,8 @@ export const getAssetsHomeFile = (fileName: string) => {
 export default defineComponent({
   name: 'MusicDetail',
   setup() {
-    localStorage.setItem('behaviorId', getRandomKey())
+    const behaviorId = ref(getRandomKey())
+    localStorage.setItem('behaviorId', behaviorId.value)
     const router = useRouter()
     const route = useRoute()
     const loading = ref(false)
@@ -104,12 +100,45 @@ export default defineComponent({
     const staffList = ref<Array<any>>([])
     const musicPdfUrl = ref('')
 
+    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[]
+
+      musicId: route.query.id as any,
+      isConcert: false, // 是否合奏
+      details: {} as any,
+      list: [], // 列表数据
+      open: false,
+      closed: true,
+      audioReady: false,
+      iframeSrc: "",
+      musicXml: "",
+      instrumentName: "",
+      iframeRef: null as any,
+      imgs: [] as any,
+      musicPdfUrl: "", // 当前声轨PDF
+      partList: [] as any[],
+      partNames: [] as string[],
+      selectedPartName: "" as any,
+      selectedPartIndex: 0,
+      isComberRender: false, // 是否合并谱显示
+      metronomeUrl: "", // 合奏使用链接
+      metronomeMp3Url: "", // 独奏使用链接
+    })
+
     const defaultImgs = ref({
       first: false,
       fixed: false,
       staff: false
     })
-    const accompanyUrl = ref<string>('')
     const downloadStatus = ref<boolean>(false)
     const staff = reactive({
       status: false,
@@ -187,62 +216,74 @@ export default defineComponent({
       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
-        }
+        const { data } = await request.get(state.platformType === 'TEACHER' ? '/api-teacher' : '/api-student' + '/musicSheet/cbsDetail/' + route.query.id)
+        musicDetail.value = data
+        staffData.details = data
+
+
+
+        // const res = await request.get(`/music/sheet/detail/${route.query.id}`, {
+        //   prefix:
+        //     state.platformType === 'TEACHER' ? '/api-teacher' : '/api-student'
+        // })
+        // musicDetail.value = res.data
+        // 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
+        // }
+        await toDetail(data)
+
 
         nextTick(async () => {
-          await toDetail()
-          renderStaff()
-        })
+          if (
+            (staffData.isConcert && staffData.metronomeUrl) ||
+            (!staffData.isConcert && staffData.metronomeMp3Url)
+          ) {
+            initAudio();
+          } else {
+            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()
-            }
-          })
-        }
+
+
+        // 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
-      }
+      loading.value = false
     }
     const player = ref<any>(null)
     const audio = ref<any>(null)
@@ -309,10 +350,10 @@ export default defineComponent({
       const footer = useRect(footers as any)
       heightInfo.value = height + footer.height
 
-      // 初始化音频
-      if (audioFileUrl.value) {
-        initAudio()
-      }
+      // // 初始化音频
+      // if (audioFileUrl.value) {
+      //   initAudio()
+      // }
 
       window.addEventListener('message', showLoading)
     })
@@ -335,7 +376,7 @@ export default defineComponent({
       if (browser().isTeacher) {
         providerType = state.projectType === 'tenant' ? 'TENANT' : 'PLATFORM'
       }
-      apiUrl = `/music/sheet/favorite/${musicDetail.value?.id}`
+      apiUrl = `/music/sheet/favorite/${musicDetail.value?.bizId}`
       try {
         await request.post(apiUrl, {
           requestType: 'form',
@@ -363,7 +404,7 @@ export default defineComponent({
       try {
         const res = await request.post('/api-teacher/courseCourseware/submit', {
           data: {
-            musicSheetId: musicDetail.value.id,
+            musicSheetId: musicDetail.value.bizId,
             clientType: 'TEACHER',
             userId: state.user.data?.userId
           }
@@ -407,8 +448,8 @@ export default defineComponent({
     const onBuy = async () => {
       const music = musicDetail.value
       orderStatus.orderObject.orderType = 'MUSIC'
-      orderStatus.orderObject.orderName = music.musicSheetName
-      orderStatus.orderObject.orderDesc = music.musicSheetName
+      orderStatus.orderObject.orderName = music.name
+      orderStatus.orderObject.orderDesc = music.name
       orderStatus.orderObject.actualPrice = music.musicPrice
       orderStatus.orderObject.recomUserId = route.query.recomUserId || 0
       orderStatus.orderObject.activityId = route.query.activityId || 0
@@ -416,7 +457,7 @@ export default defineComponent({
       orderStatus.orderObject.orderList = [
         {
           orderType: 'MUSIC',
-          goodsName: music.musicSheetName,
+          goodsName: music.name,
           actualPrice: music.musicPrice,
           ...music
         }
@@ -502,18 +543,20 @@ export default defineComponent({
     const shareStatus = ref(false)
     const shareUrl = ref('')
     const shareDiscount = ref(0)
+
+    const partColumns = ref<any>([]);
     // console.log(data)
     const onShare = async () => {
       try {
         const res = await request.post('/api-teacher/open/musicShareProfit', {
           data: {
-            bizId: musicDetail.value?.id,
+            bizId: musicDetail.value?.bizId,
             userId: state.user.data?.userId
           }
         })
         let url =
           location.origin +
-          `/teacher/#/shareMusic?id=${musicDetail.value?.id}&recomUserId=${state.user.data?.userId}&userType=${state.platformType}`
+          `/teacher/#/shareMusic?id=${musicDetail.value?.bizId}&recomUserId=${state.user.data?.userId}&userType=${state.platformType}`
         // 判断是否有活动
         if (res.data.discount === 1) {
           url += `&activityId=${res.data.activityId}`
@@ -526,18 +569,7 @@ export default defineComponent({
       } 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,
@@ -564,76 +596,202 @@ export default defineComponent({
       return list
     }
 
-    const toDetail = async () => {
+    const getPartNames = async (xmlUrl: string) => {
+      const partNames: string[] = [];
       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())
-            }
+        const res = await umiRequest.get(xmlUrl, { mode: "cors" });
+        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
         }
+      } catch (error) {}
+      return partNames;
+    };
 
-        // 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
-            })
-          }
-        })
+    // 根据当前选中的声部和曲目筛选出对应的声轨
+    function filterSoundCodes(musicalInstruments: any) {
+      // 老师端,加上乐器id
+      const instrumentIds = 1005 // appState.instrumentId || appState.user?.instrumentId || route.query.instrumentId
+      if (instrumentIds) {
+        const { code } =  musicalInstruments.find((item: any) => {
+               return instrumentIds == item.id
+            }) || {}
+        return code
+      }
+      return null
+   }
 
-        staffData.partList = tempPartList
-        staffData.tempPartList = JSON.parse(JSON.stringify(staffData.partList))
-        staffData.partList = instrumentSort(staffData.partList)
-        staffData.partXmlIndex = staffData.partList[0]?.index || 0
+   // 根据当前选中的声部和曲目筛选出对应的声轨
+   function filterSoundInfo(musicalInstruments: any) {
+    if(musicalInstruments.length <= 0) return null
+    // 老师端,加上乐器id
+    const instrumentIds = 1005 //appState.instrumentId || appState.user?.instrumentId || route.query.instrumentId
+    if (instrumentIds) {
+      const item =  musicalInstruments.find((item: any) => {
+             return instrumentIds == item.musicalInstrumentId && item.audioPlayType == 'PLAY'
+          }) || null
+      return item
+    }
+    return null
+  }
 
-        staffData.instrumentName =
-          musicDetail.value?.musicSheetType === 'CONCERT'
-            ? getInstrumentName(staffData.partList[staffData.partIndex]?.track)
-            : ''
+  const toDetail = async (row) => {
+    const partNames = await getPartNames(row.xmlFileUrl);
+    staffData.partNames = partNames;
+    let partList = staffData.list || [];
+    partList = partList.filter(
+      (item: any) => !item.track?.toLocaleUpperCase()?.includes("COMMON")
+    );
+    partColumns.value = partList.map((item: any, index: number) => {
+      const xmlIndex = staffData.partNames.filter((text: string) => text.toLocaleUpperCase() !== "COMMON").findIndex(
+        (name: any) => name.trim() === item.track
+      );
+      const defaultIndex = row.musicSheetType !== "SINGLE" && row.isScoreRender ? index + 1 : index
+      return {
+        text: getInstrumentName(item.track as string),
+        name: getInstrumentName(item.track as string), // true
+        track: item.track,
+        musicPdfUrl: item.soundMusicPdfUrl,
+        xmlIndex,
+        value: defaultIndex,
+      };
+    });
+
+    staffData.details = row || {};
+    staffData.musicXml = staffData.details?.xmlFileUrl;
+    staffData.isComberRender = staffData.details?.isScoreRender;
+    
+
+    let defaultShowStaff
+    if(staffData.details?.musicalInstruments) {
+      const soundCodes = filterSoundCodes(staffData.details?.musicalInstruments)
+      if (soundCodes) {
+        const soundCodesArr = soundCodes.split(",").map((code: string) => {
+          return code
+              .toLowerCase()
+              .replace(/^\d+|\d+$/g, "")
+              .trim()
+        })
+        defaultShowStaff = partColumns.value.find((item: any) =>
+          soundCodesArr.includes(
+              item.track &&
+                item.track
+                    .toLowerCase()
+                    .replace(/^\d+|\d+$/g, "")
+                    .trim()
+          )
+        )
+        if(defaultShowStaff) {
+          staffData.selectedPartIndex = defaultShowStaff.value
+        }
+      }
+    }
+    
 
-        if (musicDetail.value?.musicSheetType === 'SINGLE') {
-          musicPdfUrl.value = musicDetail.value?.musicPdfUrl
+    if (row.musicSheetType === "SINGLE") {
+      staffData.musicPdfUrl = row.musicPdfUrl;
+      // 生成的图片
+      // staffData.imgs = row.musicImg ? row.musicImg.split(',') : []; 
+    } else {
+      // 初始化数据
+      // 是否显示总谱
+      if (staffData.isComberRender) {
+        partColumns.value.unshift({
+          text: "总谱",
+          value: 0,
+          xmlIndex: 999,
+          track: "",
+          name: "总谱",
+        });
+        // 如果是总谱则默认选中,否则选择
+        console.log(defaultShowStaff, 'defaultShowStaff')
+        staffData.selectedPartIndex = row.defaultScoreRender? 0 : defaultShowStaff  ? defaultShowStaff.value : 1
+        if(row.defaultScoreRender) {
+          staffData.musicPdfUrl = row.musicPdfUrl;
         } else {
-          musicPdfUrl.value = staffData.partList[0]?.musicPdfUrl
+          staffData.musicPdfUrl = defaultShowStaff.musicPdfUrl;
+        }
+      } else {
+        const item = partColumns.value.find((item: any) => item.value === staffData.selectedPartIndex)
+        console.log(item, partColumns.value, staffData.selectedPartIndex, 'selectedPartIndex')
+        if (item) {
+          staffData.musicPdfUrl = item.musicPdfUrl;
+        } else {
+          staffData.musicPdfUrl = "";
+        }
+      }
+    }
+
+    // 通过isScoreRender判断是否合并渲染
+    // 多声轨,  不是单声部多声轨, 不是老师布置作业选择曲谱
+    if (row.musicSheetType === "SINGLE") {
+      staffData.isConcert = false;
+      const musicSheetSoundList = staffData.details?.musicSheetSoundList  || []
+      const songs = filterSoundInfo(musicSheetSoundList)
+      if(songs) {
+        staffData.metronomeMp3Url = songs.audioFileUrl
+      } else {
+        // 为了处理节奏练习
+        if(musicSheetSoundList.length > 0) {
+          console.log(musicSheetSoundList, 'musicSheetSoundList')
+          staffData.metronomeMp3Url = musicSheetSoundList[0].audioFileUrl
         }
-      } catch (error) {
-        //
-        console.log(error, 'error')
       }
+    } else {  
+      staffData.isConcert = true;
+      const { audioFileUrl } = row.musicSheetAccompanimentList.find((item: any) => item.audioPlayType == 'PLAY')
+      staffData.metronomeUrl = audioFileUrl
     }
+  }
 
+
+  const getPreViewCloud = (musicId: string, partIndex: number) => {
+    const Authorization = sessionStorage.getItem("Authorization") || "";
+    const musicScorePath = "/klx-music-score/";
+    const musicScoreUrl = getHttpOrigin() + musicScorePath;
+    // const musicScoreUrl = "https://test.gym.lexiaoya.cn" + musicScorePath;
+    // const musicScoreUrl = 'http://192.168.3.68:3000/instrument.html';
+    let href = `${musicScoreUrl}?t=${Date.now()}#/?id=${musicId}&Authorization=${Authorization}&part-index=${partIndex}&isPreView=true&zoom=0.5&downPng=A4`; 
+    // // 老师端加上systemType=teacher
+    const browserInfo = browser()
+    href += ('&systemType=' +( browserInfo.isStudent ? `student` : 'teacher'));
+    // if (location.pathname.includes("accompany-teacher")) {
+    //   href += `&systemType=teacher`;
+    // }    
+    return href
+    
+  };
     const renderStaff = async () => {
+      // try {
+      //   if (staffData.musicPdfUrl) {
+      //     // staffData.iframeSrc =
+      //     //   "/pdf/web/viewer.html?file=" +
+      //     //   encodeURIComponent(staffData.musicPdfUrl);
+      //     // https://cdn.oss.dayaedu.com/daya202409/UOFW4q5.pdf
+      //     // https://cdn.oss.dayaedu.com/daya202409/UOFVK2A.pdf
+      //     // https://cdn.oss.dayaedu.com/daya202409/UODQffO.pdf
+
+      //     staffData.iframeSrc = `${getHttpOrigin()}${
+      //       location.pathname
+      //     }pdf/web/viewer.html?file=${encodeURIComponent(
+      //       staffData.musicPdfUrl
+      //     )}`;
+      //   } else {
+      //     staffData.iframeSrc = getPreViewCloud(
+      //       staffData.musicId,
+      //       currentColumn.value.xmlIndex
+      //     );
+      //     // staffData.iframeSrc = `/osmd/index.html`;
+      //     // staffData.iframeSrc = `${getHttpOrigin()}${location.pathname}osmd/index.html`;
+      //   }
+      // } catch (error) {
+      //   //
+      // }
       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(
@@ -644,16 +802,23 @@ export default defineComponent({
             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 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
+            // const iframeRef = document.querySelector('#staffIframeRef') as any
+            // iframeRef.contentWindow.location.replace(
+            //   `${location.origin}${location.pathname}osmd/index.html`
+            // )
+            // staffData.iframeSrc = url
+
+            staffData.iframeSrc = getPreViewCloud(
+              //       staffData.musicId,
+              //       currentColumn.value.xmlIndex
+              //     );
+              //     // staffData.iframeSrc = `/osmd/index.html`;
+              //     // staffData.iframeSrc = `${getHttpOrigin()}${location.pathname}osmd/index.html`;
           }
         })
       } catch (error) {
@@ -712,24 +877,24 @@ export default defineComponent({
         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
-        }
-      })
-    })
+    // 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}>
@@ -741,7 +906,7 @@ export default defineComponent({
                 border={false}
                 isFixed={false}
                 color="#fff"
-                title={musicDetail.value?.musicSheetName}
+                title={musicDetail.value?.name}
                 backIconColor="white"
                 v-slots={{
                   right: () => (
@@ -761,7 +926,7 @@ export default defineComponent({
             </div>
           </ColSticky>
 
-          <img class={styles.bgImg} src={musicDetail.value?.titleImg} />
+          <img class={styles.bgImg} src={musicDetail.value?.musicCover} />
           <div class={styles.bgContent}></div>
           <div
             class={styles.musicContainer}
@@ -779,7 +944,7 @@ export default defineComponent({
                   icon: () => (
                     <Image
                       class={styles.pImg}
-                      src={musicDetail.value?.titleImg}
+                      src={musicDetail.value?.musicCover}
                     />
                   ),
                   title: () => (
@@ -788,7 +953,7 @@ export default defineComponent({
                         class="van-ellipsis"
                         // onClick={() => handleGotoMusicScore(musicDetail.value)}
                       >
-                        {musicDetail.value?.musicSheetName}
+                        {musicDetail.value?.name}
                       </h4>
                       <p
                         style={{
@@ -910,7 +1075,7 @@ export default defineComponent({
                     router.push({
                       path: '/look-album-list',
                       query: {
-                        id: musicDetail.value?.id,
+                        id: musicDetail.value?.bizId,
                         musicSubject: musicDetail.value?.musicSubject
                       }
                     })
@@ -976,7 +1141,7 @@ export default defineComponent({
                   onClick={() => {
                     if (musicPdfUrl.value) {
                       const songName =
-                        musicDetail.value?.musicSheetName +
+                        musicDetail.value?.name +
                         (staffData.instrumentName
                           ? `(${staffData.instrumentName})`
                           : '')
@@ -1003,7 +1168,72 @@ export default defineComponent({
             </div>
 
             <div class={styles.musicContent}>
-              {musicDetail.value?.musicSheetType === 'CONCERT' ||
+              {staffData.details.id ? (
+                <>
+                  {staffData.musicPdfUrl ? (
+                    <>
+                      {loading.value && (
+                        <>
+                          <Vue3Lottie
+                            animationData={AstronautJSON}
+                            class={styles.finch}
+                          ></Vue3Lottie>
+                          <p class={styles.finchLoad}>加载中...</p>
+                        </>
+                      )}
+                      <iframe
+                        style={{
+                          opacity: loading.value ? 0 : 1,
+                        }}
+                        id="staffIframeRef"
+                        src={staffData.iframeSrc}
+                        onLoad={() => {
+                          // 判断是用哪个渲染的
+                          loading.value = false;
+                        }}
+                      ></iframe>
+                    </>
+                  ) : (
+                    <>
+                      <p class={styles.musicTitle}>
+                        {staffData.details?.name && (
+                          <>
+                            {staffData.details?.name}
+                            {/* {staffData.isConcert &&
+                            currentColumn.value?.name
+                              ? `(${
+                                  currentColumn.value
+                                    ?.name || ""
+                                })`
+                              : ""} */}
+                          </>
+                        )}
+                      </p>
+                      {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={() => {
+                          loading.value = false;
+                          // musicIframeLoad();
+                        }}
+                      ></iframe>
+                    </>
+                  )}
+                </>
+              ) : null}
+              {/* {musicDetail.value?.musicSheetType === 'CONCERT' ||
               musicPdfUrl.value ||
               !defaultImgs.value[staff.radio] ? (
                 <>
@@ -1022,8 +1252,8 @@ export default defineComponent({
                   ) : (
                     <>
                       <p class={styles.musicTitle}>
-                        {(musicDetail.value?.musicSheetName
-                          ? musicDetail.value?.musicSheetName
+                        {(musicDetail.value?.name
+                          ? musicDetail.value?.name
                           : '') +
                           (staffData.instrumentName
                             ? `(${staffData.instrumentName})`
@@ -1035,7 +1265,6 @@ export default defineComponent({
                             animationData={AstronautJSON}
                             class={styles.finch}
                           ></Vue3Lottie>
-                          {/* <p class={styles.finchLoad}>加载中...</p> */}
                         </div>
                       )}
                       <iframe
@@ -1052,35 +1281,10 @@ export default defineComponent({
                   )}
                 </>
               ) : (
-                // <>
-                //   {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
+                    {(musicDetail.value?.name
+                      ? musicDetail.value?.name
                       : '') +
                       (staffData.instrumentName
                         ? `(${staffData.instrumentName})`
@@ -1105,11 +1309,11 @@ export default defineComponent({
                     </div>
                   )}
                 </>
-              )}
+              )} */}
             </div>
           </div>
 
-          {musicDetail.value?.id && (
+          {musicDetail.value?.bizId && (
             <ColSticky
               position="bottom"
               background="white"
@@ -1151,9 +1355,6 @@ export default defineComponent({
                         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 = {
@@ -1245,11 +1446,11 @@ export default defineComponent({
                 <img
                   class={styles.icon}
                   crossorigin="anonymous"
-                  src={musicDetail.value?.titleImg + `?t=${+new Date()}`}
+                  src={musicDetail.value?.musicCover}
                 />
                 <div class={styles.info}>
                   <h4 class="van-multi-ellipsis--l2">
-                    {musicDetail.value?.musicSheetName}
+                    {musicDetail.value?.name}
                   </h4>
                   <p>作曲人:{musicDetail.value?.composer}</p>
                 </div>
@@ -1261,8 +1462,8 @@ export default defineComponent({
             {downloadStatus.value && (
               <Download
                 imgList={JSON.parse(JSON.stringify(showImg.value))}
-                musicSheetName={
-                  musicDetail.value?.musicSheetName +
+                name={
+                  musicDetail.value?.name +
                   (staffData.instrumentName
                     ? `(${staffData.instrumentName})`
                     : '')