| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820 | import { defineComponent, onMounted, onUnmounted, reactive, watch, ref, onBeforeMount } from 'vue'// import WaveSurfer from 'wavesurfer.js';import styles from './index.module.less'import MSticky from '@/components/col-sticky'import MHeader from '@/components/col-header'import { Button, Cell, Dialog, Image, List, Popup, Slider, Toast, Sticky, NoticeBar } from 'vant'import iconDownload from './images/icon-download.png'import iconShare from './images/icon-share.png'import iconDelete from './images/icon-delete.png'import iconVip from './images/icon-vip.png'import iconSVip from './images/icon-svip.png'import iconZan from './images/icon-zan.png'import { postMessage, promisefiyPostMessage } from '@/helpers/native-message'import { browser, getGradeCh, getSecondRPM } from '@/helpers/utils'import { useRoute, useRouter } from 'vue-router'import {  api_userMusicDetail,  api_userMusicRemove,  api_userMusicStarPage} from './api'import MEmpty from '@/components/col-result'import dayjs from 'dayjs'import { nextTick } from 'process'import ShareModel from './share-model'import { usePageVisibility } from '@vant/use'import "plyr/dist/plyr.css";import Plyr from "plyr";import { generateMixedData } from "./audioVisualDraw"import backImg from "./images/back.png";import back1Img from "./images/back1.png";import musicBg from "./images/music_bg.png";import videobg from "./images/videobg.png";import iconUpward from './images/upward.png';import iconEdit from './images/edit.png';import iconMember from './images/icon-member.png';import vipIcon from './images/vip_icon.png';import svipIcon from './images/svip_icon.png';import tyBg from './images/ty.png';import TextEllipsis from './text-ellipsis/index';import Loading from './loading';import { state as originState } from '@/state'export default defineComponent({  name: 'creation-detail',  setup() {    const {isApp, isTablet, isTeacher} = browser()    const route = useRoute()    const router = useRouter()    const isScreenScroll = ref(false)    const mStickyBottom = ref()    const mStickyUpward = ref()    const state = reactive({      id: route.query.id,      deleteStatus: false,      shareStatus: false,      playType: '' as 'Audio' | 'Video' | '', // 播放类型      musicDetail: {} as any,      isClick: false,      list: [] as any,      listState: {        dataShow: true, // 判断是否有数据        loading: false,        finished: false      },      params: {        page: 1,        rows: 20      },      _plrl: null as any,      heightV:0,      heightB:0    });    const plyrState = reactive({      duration: 0,      currentTime: 0,      mediaTimeShow: false,      playIngShow: true    })    // 谱面    const staffState = reactive({      staffSrc: "",      isShow: false,      height:"initial",      speedRate:1,      musicRenderType:"staff",      partIndex: 0    })    const isLandscapeScreen = ref(false)    const staffDom= ref<HTMLIFrameElement>()    const {playStaff, pauseStaff, updateProgressStaff} = staffMoveInstance()    // 获取列表    const getStarList = async () => {      try {        if (state.isClick) return        state.isClick = true        const res = await api_userMusicStarPage({          userMusicId: state.id,          ...state.params        })        state.listState.loading = false        const result = res.data || {}        // 处理重复请求数据        if (state.list.length > 0 && result.current === 1) {          return        }        state.list = state.list.concat(result.rows || [])        state.listState.finished = result.current >= result.pages        state.params.page = result.current + 1        state.listState.dataShow = state.list.length > 0        state.isClick = false      } catch {        state.listState.dataShow = false        state.listState.finished = true        state.isClick = false      }    }    // 删除作品    const onDelete = async () => {      try {        await api_userMusicRemove({ id: state.id });        setTimeout(() => {          state.deleteStatus = false;          Toast('删除成功');        }, 100);        setTimeout(() => {          if (isApp) {            postMessage({              api: 'goBack'            });          } else {            router.back();          }        }, 1200);      } catch {        //      }    };    // 下载    const onDownload = async () => {      await promisefiyPostMessage({        api: 'saveFile',        content: {          url: state.musicDetail.videoUrl        }      });    };    // 滚动事件    const handleScroll = () => {      console.log('滚动',123)      const height =        window.scrollY ||        document.documentElement.scrollTop        // 防止多次调用        if(height > 0 && isScreenScroll.value === false){          isScreenScroll.value = true          setStatusBarTextColor(false)        }        if(height <= 0){          isScreenScroll.value = false          setStatusBarTextColor(true)        }    }    // 设置导航栏颜色    function setStatusBarTextColor(isWhite:boolean){      postMessage({        api: 'setStatusBarTextColor',        content: { statusBarTextColor: isWhite }      })    }    const pageVisibility = usePageVisibility();    watch(pageVisibility, value => {      if (value === 'hidden') {        state._plrl?.pause();      }    });    // 初始化 媒体播放    function initMediaPlay(){      const id = state.playType === "Audio" ? "#audioMediaSrc" : "#videoMediaSrc";      state._plrl = new Plyr(id, {        controls: ["play", "progress", "current-time", "duration"],        fullscreen: {          enabled: false,          fallback: false        }      });      const player = state._plrl        // 创建音波数据      if(state.playType === "Audio"){        const audioDom = document.querySelector("#audioMediaSrc") as HTMLAudioElement        const canvasDom = document.querySelector("#audioVisualizer") as HTMLCanvasElement        const { pauseVisualDraw, playVisualDraw } = audioVisualDraw(audioDom, canvasDom)        player.on('play', () => {          playVisualDraw()        });        player.on('pause', () => {          pauseVisualDraw()        });      }      // player.on('loadedmetadata', () => {      //   player.currentTime = playProgressData.playProgress      // });      player.on("timeupdate", ()=>{        plyrState.currentTime = player.currentTime      })      player.on('play', () => {        plyrState.playIngShow = false        playStaff()      });      player.on('pause', () => {        plyrState.playIngShow = true        pauseStaff()      });      player.on('ended', () => {        player.currentTime = 0        if(!player.playing){          setTimeout(() => {            updateProgressStaff(player.currentTime)          }, 100);        }      });      // 处理按压事件      const handleStart = () => {        if(isLandscapeScreen.value){          return        }        plyrState.duration = player.duration        plyrState.mediaTimeShow = true      };      // 处理松开事件      const handleEnd = () => {        plyrState.mediaTimeShow = false        // 暂停的时候调用        if(!player.playing){          updateProgressStaff(player.currentTime)        }      };      const progressDom = document.querySelector("#playMediaSection .plyr__controls .plyr__progress__container") as HTMLElement      progressDom.addEventListener('mousedown', handleStart);      progressDom.addEventListener('touchstart', handleStart);      progressDom.addEventListener('mouseup', handleEnd);      progressDom.addEventListener('touchend', handleEnd);    }    //点击改变播放状态    function handlerClickPlay(event?:MouseEvent){      // 原生 播放暂停按钮 点击的时候 不触发      // @ts-ignore      if(event?.target?.matches('button.plyr__control')){        return      }      if (state._plrl.playing) {        state._plrl.pause();      } else {        state._plrl.play();      }    }    /**		 * 音频可视化		 * @param audioDom		 * @param canvasDom		 * @param fftSize  2的幂数,最小为32		 */    function audioVisualDraw(audioDom: HTMLAudioElement, canvasDom: HTMLCanvasElement, fftSize = 128) {      type propsType = { canvWidth: number; canvHeight: number; canvFillColor: string; lineColor: string; lineGap: number }      // canvas      const canvasCtx = canvasDom.getContext("2d")!      let { width, height } = canvasDom.getBoundingClientRect()      width = Math.ceil(width)      height = Math.ceil(height)      canvasDom.width = width      canvasDom.height = height      // audio      // let audioCtx : AudioContext | null = null      // let analyser : AnalyserNode | null = null      // let source : MediaElementAudioSourceNode | null = null      // const dataArray = new Uint8Array(fftSize / 2)      const draw = (data: Uint8Array, ctx: CanvasRenderingContext2D, { lineGap, canvWidth, canvHeight, canvFillColor, lineColor }: propsType) => {        if (!ctx) return        const w = canvWidth        const h = canvHeight        fillCanvasBackground(ctx, w, h, canvFillColor)          // 可视化        const dataLen = data.length        let step = (w / 2 - lineGap * dataLen) / dataLen        step < 1 && (step = 1)        const midX = w / 2        const midY = h / 2        let xLeft = midX        for (let i = 0; i < dataLen; i++) {          const value = data[i]          const percent = value / 255 // 最大值为255          const barHeight = percent * midY          canvasCtx.fillStyle = lineColor          // 中间加间隙          if (i === 0) {            xLeft -= lineGap / 2          }          canvasCtx.fillRect(xLeft - step, midY - barHeight, step, barHeight)          canvasCtx.fillRect(xLeft - step, midY, step, barHeight)          xLeft -= step + lineGap        }        let xRight = midX        for (let i = 0; i < dataLen; i++) {          const value = data[i]          const percent = value / 255 // 最大值为255          const barHeight = percent * midY          canvasCtx.fillStyle = lineColor          if (i === 0) {            xRight += lineGap / 2          }          canvasCtx.fillRect(xRight, midY - barHeight, step, barHeight)          canvasCtx.fillRect(xRight, midY, step, barHeight)          xRight += step + lineGap        }      }      const fillCanvasBackground = (ctx: CanvasRenderingContext2D, w: number, h: number, colors: string) => {        ctx.clearRect(0, 0, w, h)        ctx.fillStyle = colors        ctx.fillRect(0, 0, w, h)      }      const requestAnimationFrameFun = () => {        // requestAnimationFrame(() => {        //   //analyser?.getByteFrequencyData(dataArray)        //   draw(generateMixedData(48), canvasCtx, {        //     lineGap: 2,        //     canvWidth: width,        //     canvHeight: height,        //     canvFillColor: "transparent",        //     lineColor: "rgba(255, 255, 255, 0.7)"        //   })        //   if (!isPause) {        //     requestAnimationFrameFun()        //   }        // })        const _time = setInterval(() => {          if (isPause) {            clearInterval(_time)            return          }          //analyser?.getByteFrequencyData(dataArray)          draw(generateMixedData(48), canvasCtx, {            lineGap: 2,            canvWidth: width,            canvHeight: height,            canvFillColor: "transparent",            lineColor: "rgba(255, 255, 255, 0.7)"          })        }, 300);      }      let isPause = true      const playVisualDraw = () => {        // if (!audioCtx) {        //   audioCtx = new AudioContext()        //   source = audioCtx.createMediaElementSource(audioDom)        //   analyser = audioCtx.createAnalyser()        //   analyser.fftSize = fftSize        //   source?.connect(analyser)        //   analyser.connect(audioCtx.destination)        // }        //audioCtx.resume()  // 重新更新状态   加了暂停和恢复音频音质发生了变化  所以这里取消了        isPause = false        requestAnimationFrameFun()      }      const pauseVisualDraw = () => {        isPause = true        requestAnimationFrame(()=>{          canvasCtx.clearRect(0, 0, width, height);        })        //audioCtx?.suspend()  // 暂停   加了暂停和恢复音频音质发生了变化  所以这里取消了        // source?.disconnect()        // analyser?.disconnect()      }      return {        playVisualDraw,        pauseVisualDraw      }    }    function handlerBack(event:any){      event.stopPropagation()      verticalScreen()    }    function landscapeScreen(){      postMessage({        api: "setRequestedOrientation",        content: {          orientation: 0,        },      });      isLandscapeScreen.value = true    }    function verticalScreen(){      postMessage({        api: "setRequestedOrientation",        content: {          orientation: 1,        },      });      isLandscapeScreen.value = false    }    function handlerLandscapeScreen(event:any){      event.stopPropagation()      if(!isLandscapeScreen.value){        landscapeScreen()      }      // playProgressData.playState = !!state._plrl?.playing      // playProgressData.playProgress = state._plrl?.currentTime || 0      // router.push({      //   path:"/playCreation",      //   query:{      //     resourceUrl:encodeURIComponent(state.musicDetail?.videoUrl),      //     videoBgUrl:encodeURIComponent(state.musicDetail?.videoImg || ""),      //     musicSheetName:encodeURIComponent(state.musicDetail?.musicSheetName),      //     username:encodeURIComponent(state.musicDetail?.username),      //     musicSheetId:encodeURIComponent(state.musicDetail?.musicSheetId),      //     speedRate:encodeURIComponent(staffState.speedRate),      //     musicRenderType:encodeURIComponent(staffState.musicRenderType),      //     partIndex:encodeURIComponent(staffState.partIndex),      //   }      // })    }    // 初始化五线谱    function initStaff(){      const systemType = originState.platformType === 'TEACHER' || isTeacher ? 'teacher' : 'student'      const src = `/klx-music-score/#/simple-detail?id=${state.musicDetail.musicSheetId}&musicRenderType=${staffState.musicRenderType}&part-index=${staffState.partIndex}&userMusicId=${state.id}&systemType=${systemType}`;      // const src = `http://192.168.3.68:3000/instrument.html#/simple-detail?id=${state.musicDetail.musicSheetId}&musicRenderType=${staffState.musicRenderType}&part-index=${staffState.partIndex}&userMusicId=${state.id}`;      staffState.staffSrc = src      window.addEventListener('message', (event) => {        const { api, height } = event.data;        if (api === 'api_musicPage') {          staffState.isShow = true          staffState.height = height + "px"        }      });    }    function staffMoveInstance(){      let isPause = true      const requestAnimationFrameFun = () => {				requestAnimationFrame(() => {          staffDom.value?.contentWindow?.postMessage(            {              api: 'api_playProgress',              content: {                currentTime: state._plrl.currentTime * staffState.speedRate              }            },            "*"          )					if (!isPause) {						requestAnimationFrameFun()					}				})			}      const playStaff = () => {        // 没渲染不执行        if(!staffState.isShow) return				isPause = false        staffDom.value?.contentWindow?.postMessage(          {            api: 'api_play'          },          "*"        )				requestAnimationFrameFun()			}			const pauseStaff = () => {        // 没渲染不执行        if(!staffState.isShow) return				isPause = true        staffDom.value?.contentWindow?.postMessage(          {            api: 'api_paused'          },          "*"        )			}      const updateProgressStaff = (currentTime: number) => {        // 没渲染不执行        if(!staffState.isShow) return        staffDom.value?.contentWindow?.postMessage(          {            api: 'api_updateProgress',            content: {              currentTime: currentTime * staffState.speedRate            }          },          "*"        )      }			return {				playStaff,				pauseStaff,        updateProgressStaff			}    }     onMounted(async () => {      document.addEventListener("scroll", handleScroll)      setStatusBarTextColor(true)      try {        const res = await api_userMusicDetail(state.id)        // console.log(res);        if (res.code === 999) {          Dialog.alert({            message: res.msg,            theme: 'round-button',            confirmButtonColor: '#2DC7AA'          }).then(() => {            if (isApp) {              postMessage({                api: 'goBack'              })            } else {              router.back()            }          })          return        }        state.musicDetail = res.data || {}        try{          const jsonConfig = JSON.parse(res.data.jsonConfig)          jsonConfig.speedRate && (staffState.speedRate = jsonConfig.speedRate)          jsonConfig.musicRenderType && (staffState.musicRenderType = jsonConfig.musicRenderType)          jsonConfig["part-index"] && (staffState.partIndex = jsonConfig["part-index"])        }catch{        }             // 五线谱        initStaff()           getStarList()        // 判断是视频还是音频        if (res.data.videoUrl.lastIndexOf('mp4') !== -1) {          state.playType = 'Video'        } else {          state.playType = 'Audio'        }        // 初始化        nextTick(() => {          initMediaPlay()        })      } catch {        //      }    })    onUnmounted(() => {      document.removeEventListener("scroll", handleScroll)      state._plrl?.destroy()    })    return () => (      <div        style={          {            '--barheight':state.heightV + "px"          }        }        class={[          styles.creation,          isTablet && styles.creationTablet,          isScreenScroll.value && styles.isScreenScroll        ]}>        <div class={styles.creationBg}></div>        <MSticky position="top"          onGetHeight={(height: any) => {            console.log(height, 'height', height)            state.heightV = height          }}        >          <MHeader            color={isScreenScroll.value ? "#333333" : "#ffffff"}            background={isScreenScroll.value ? `rgb(255,255,255` : "transparent"}            title={state.musicDetail?.musicSheetName}            border={false}            isBack={route.query.platformType != 'ANALYSIS'}            onLeftClick={()=>{ setStatusBarTextColor(false) }}          />        </MSticky>        <div class={styles.singer}>          演奏:{state.musicDetail?.username}        </div>                <Sticky zIndex={1000} offsetTop={state.heightV - 1 + "px"}>          <div class={[styles.playSection, plyrState.mediaTimeShow && styles.mediaTimeShow, isLandscapeScreen.value&&styles.isLandscapeScreen, state.playType === 'Audio' && styles.isLandscapeScreen2]} id="playMediaSection" onClick={handlerClickPlay}>            {              isLandscapeScreen.value &&                <div class={styles.backBox}>                  <img class={[styles.backImg, state.playType === 'Video' && styles.back1Img]} src={state.playType === 'Video' ? back1Img : backImg} onClick={handlerBack}/>                  <div class={[styles.musicDetail, state.playType === 'Audio' && styles.adMusicDetail]}>                    <div class={styles.musicSheetName}>                        <NoticeBar                            text={state.musicDetail?.musicSheetName}                            background="none"                        />                    </div>                    <div class={styles.username}>演奏:{state.musicDetail?.username}</div>                  </div>                </div>            }            {              state.playType === 'Audio' &&              <div class={styles.audioBox}>                <canvas class={styles.audioVisualizer} id="audioVisualizer"></canvas>                <audio                  crossorigin="anonymous"                  id="audioMediaSrc"                  src={state.musicDetail?.videoUrl}                  controls="false"                  preload="metadata"                  playsinline                  webkit-playsinline                />                <img src={tyBg} class={styles.tyBg} />                <div class={styles.audioBoxBg}>                    <div class={[styles.audioPan,  plyrState.playIngShow && styles.imgRotate]}>                      <img class={styles.audioImg} src={state.musicDetail.img || musicBg} />                    </div>                    <i class={styles.audioPoint}></i>                    <i class={[styles.audioZhen, plyrState.playIngShow && styles.active]}></i>                </div>                              </div>            }            {              state.playType === 'Video' &&              <video                id="videoMediaSrc"                class={styles.videoBox}                src={state.musicDetail?.videoUrl}                data-poster={ state.musicDetail?.videoImg || videobg}                poster={ state.musicDetail?.videoImg || videobg}                preload="metadata"                playsinline                webkit-playsinline                x5-playsinline              />            }            <div class={[styles.playLarge, !plyrState.mediaTimeShow && plyrState.playIngShow && styles.playIngShow]}></div>            <div class={styles.mediaTimeCon}>              <div class={styles.mediaTime}>                <div>                  {getSecondRPM(plyrState.currentTime)}                </div>                <div class={styles.note}>/</div>                <div class={styles.duration}>                  {getSecondRPM(plyrState.duration)}                </div>              </div>            </div>            <div class={styles.landscapeScreen} onClick={handlerLandscapeScreen}></div>            {/* 谱面 */}            {              staffState.staffSrc &&              <div class={[styles.staffBoxCon, staffState.isShow && styles.staffBoxShow]}>                <div                  class={[styles.staffBox, state.playType === 'Video' && styles.staffBoxBg]}                  style={                    {                      '--staffBoxHeight':staffState.height                    }                  }                >                  <div class={styles.mask}></div>                  <iframe                    ref={staffDom}                    class={styles.staff}                    frameborder="0"                    src={staffState.staffSrc}>                  </iframe>                </div>              </div>            }          </div>        </Sticky>        <div class={styles.musicSection}>          <div class={styles.avatarInfoBox}>            <div class={styles.avatar}>              <div class={styles.avatarImg}>                <img class={[styles.userLogo, state.musicDetail.vipType === 'VIP' ? styles.vipLogo : state.musicDetail.vipType === 'PERMANENT_SVIP' || state.musicDetail.vipType === 'SVIP' ? styles.svipLogo : '']} src={state.musicDetail.avatar} />                {                  (state.musicDetail.vipType === 'VIP' || state.musicDetail.vipType === 'PERMANENT_SVIP' || state.musicDetail.vipType === 'SVIP') &&                  <img class={styles.vipIcon} src={state.musicDetail.vipType === 'VIP' ? vipIcon : svipIcon} />                }                              </div>              <div class={styles.infoCon}>                <div class={styles.info}>                  <span class={styles.userName}>{state.musicDetail?.username}</span>                  {state.musicDetail.vipFlag && (                    <img src={iconMember} class={styles.iconMember} />                  )}                </div>                <div class={styles.sub}>                  {state.musicDetail.subjectName}{' '}                  {getGradeCh(state.musicDetail.currentGradeNum - 1)}                </div>              </div>            </div>            <div class={styles.linkes}>              <img src={iconZan} class={styles.iconZan} />              <span>{state.musicDetail.likeNum}</span>            </div>          </div>          <TextEllipsis class={styles.textEllipsis} text={state.musicDetail.desc || ''} />        </div>        <div class={styles.likeSection}>          <div class={styles.likeTitle}>点赞记录</div>          {state.listState.dataShow ? (            <List              finished={state.listState.finished}              finishedText=" "              onLoad={getStarList}              immediateCheck={false}>              {state.list.map((item: any, index: number) => (                <Cell                  class={[styles.likeItem, index===state.list.length-1&&styles.likeItemLast]}                  border={false}                >                  {{                    icon: () => (                      <Image src={item.userAvatar} class={styles.userLogo} />                    ),                    title: () => (                      <div class={styles.userInfo}>                        <p class={styles.name}>{item.userName}</p>                        <p class={styles.sub}>                          {item.subjectName}{' '}                          {getGradeCh(item.currentGradeNum - 1)}                        </p>                      </div>                    ),                    value: () => (                      <div class={styles.time}>                        {dayjs(item.createTime).format('YYYY-MM-DD HH:mm')}                      </div>                    )                  }}                </Cell>              ))}            </List>          ) : (            <MEmpty class={styles.mEmpty} tips="暂无内容" btnStatus={false} />          )}        </div>        {          !isScreenScroll.value &&          <MSticky ref={mStickyUpward} position="bottom" offsetBottom={state.heightB - 1 + "px"} >            <div class={styles.upward}>              <img src={iconUpward} />            </div>          </MSticky>        }        <MSticky ref={mStickyBottom} position="bottom" onGetHeight={(height: any) => {            console.log(height, 'height', height)            state.heightB = height        }}>          <div class={styles.bottomSection}>            <div class={styles.bottomShare}>              <p onClick={onDownload}>                <img src={iconDownload} />                <span>下载</span>              </p>              <p onClick={() => (state.shareStatus = true)}>                <img src={iconShare} />                <span>分享</span>              </p>              <p onClick={() => (state.deleteStatus = true)}>                <img src={iconDelete} />                <span>删除</span>              </p>            </div>            <img src={iconEdit}              class={styles.btnEdit}              onClick={() => {                router.push({                  path: '/creation-edit',                  query: {                    id: state.id                  }                });              }}            />          </div>        </MSticky>        <Popup          v-model:show={state.deleteStatus}          round          class={styles.popupContainer}        >          <p class={styles.popupTit}>温馨提示</p>          <p class={styles.popupContent}>确认删除作品吗?</p>          <div class={styles.popupBtnGroup}>            <Button round onClick={() => (state.deleteStatus = false)}>              取消            </Button>            <Button round type="primary" onClick={onDelete}>              确认            </Button>          </div>        </Popup>        <Popup          position="bottom"          v-model:show={state.shareStatus}          style={{ background: 'transparent' }}        >          <ShareModel            playType={state.playType}            musicDetail={state.musicDetail}            onClose={() => (state.shareStatus = false)}          />        </Popup>        {          !staffState.isShow && <Loading></Loading>        }              </div>    )  }})
 |