فهرست منبع

feat: 作品分享页面修改

TIANYONG 8 ماه پیش
والد
کامیت
5b5b41c6ee

+ 10 - 4
src/components/col-header/index.tsx

@@ -53,6 +53,10 @@ export default defineComponent({
     hideHeader: {
     hideHeader: {
       type: Boolean,
       type: Boolean,
       default: false
       default: false
+    },
+    leftClickDefault: {
+      type: Boolean,
+      default: true
     }
     }
   },
   },
   emits: ['leftClick'],
   emits: ['leftClick'],
@@ -124,10 +128,12 @@ export default defineComponent({
     },
     },
     onClickLeft() {
     onClickLeft() {
       this.$emit('leftClick', null)
       this.$emit('leftClick', null)
-      if (browser().isApp) {
-        postMessage({ api: 'goBack' })
-      } else {
-        this.$router.back()
+      if(this.leftClickDefault) {
+        if (browser().isApp) {
+          postMessage({ api: 'goBack' })
+        } else {
+          this.$router.back()
+        }
       }
       }
     },
     },
     clickRight() {
     clickRight() {

+ 1 - 1
src/helpers/request.ts

@@ -37,7 +37,7 @@ request.interceptors.request.use(
   (url, options: any) => {
   (url, options: any) => {
     hideErrorMessage = options.hideErrorMessage
     hideErrorMessage = options.hideErrorMessage
     // 作品页面不需要默认的加载loading,使用作品页面自己的加载loading
     // 作品页面不需要默认的加载loading,使用作品页面自己的加载loading
-    const isCreationPage = window.location.href.includes('creation')
+    const isCreationPage = window.location.href.includes('creation') || window.location.href.includes('shareCreation')
     if (!isCreationPage) {
     if (!isCreationPage) {
       if (!options.hideLoading) {
       if (!options.hideLoading) {
         clearTimeout(toast)
         clearTimeout(toast)

BIN
src/views/creation/images/btn.png


BIN
src/views/creation/images/logo.png


BIN
src/views/creation/images/logo1.png


BIN
src/views/creation/images/play.png


+ 631 - 252
src/views/creation/index-share.tsx

@@ -2,23 +2,33 @@ import {
   defineComponent,
   defineComponent,
   onMounted,
   onMounted,
   onUnmounted,
   onUnmounted,
+  onBeforeMount,
   reactive,
   reactive,
   ref,
   ref,
-  watch
+  watch,
+  nextTick
 } from 'vue'
 } from 'vue'
 // import WaveSurfer from 'wavesurfer.js';
 // import WaveSurfer from 'wavesurfer.js';
 // import Regions from 'wavesurfer.js/dist/plugins/regions.js';
 // import Regions from 'wavesurfer.js/dist/plugins/regions.js';
 import styles from './index.module.less'
 import styles from './index.module.less'
-import { Cell, Image, List, Popup, Slider } from 'vant'
-// import iconMember from './images/icon-member.png'
-import iconVip from './images/icon-vip.png'
-import iconSVip from './images/icon-svip.png'
+import { Cell, Image, List, Popup, Slider, Sticky, NoticeBar, Toast } from 'vant'
+import TextEllipsis from './text-ellipsis/index';
+import MSticky from '@/components/col-sticky'
+import MHeader from '@/components/col-header'
+import iconMember from './images/icon-member.png'
 import iconZan from './images/icon-zan.png'
 import iconZan from './images/icon-zan.png'
 import iconZanActive from './images/icon-zan-active.png'
 import iconZanActive from './images/icon-zan-active.png'
-import iconZ from './images/icon-z.png'
-import iconPlay from './images/icon-play.png'
-import iconPause from './images/icon-pause.png'
-import videoBg from './images/video-bg.png'
+import logoImg from './images/logo.png';
+import logo1Img from './images/logo1.png';
+import backImg from "./images/back.png";
+import videobg from "./images/videobg.png";
+import audioPan from './images/audio-pan.png';
+import audioLabel from './share-model/images/audioLabel.png';
+import videoLabel from './share-model/images/videoLabel.png';
+import musicBg from './share-model/images/music-bg.png';
+import playImg from './images/play.png';
+import btnImg from './images/btn.png';
+import iconUpward from './images/upward.png';
 import {
 import {
   browser,
   browser,
   getAuth,
   getAuth,
@@ -26,6 +36,7 @@ import {
   getSecondRPM,
   getSecondRPM,
   removeAuth
   removeAuth
 } from '@/helpers/utils'
 } from '@/helpers/utils'
+import { postMessage, promisefiyPostMessage } from '@/helpers/native-message'
 import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router'
 import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router'
 import {
 import {
   api_openUserMusicDetail,
   api_openUserMusicDetail,
@@ -34,21 +45,26 @@ import {
   api_verification
   api_verification
 } from './api'
 } from './api'
 import MEmpty from '@/components/col-result'
 import MEmpty from '@/components/col-result'
-import { nextTick } from 'process'
-import MVideo from '@/components/col-video-tcplayer'
 import LoginModel from './login-model'
 import LoginModel from './login-model'
 import { setLogout } from '@/state'
 import { setLogout } from '@/state'
 import MWxTip from '@/components/the-wx-tip'
 import MWxTip from '@/components/the-wx-tip'
 import { usePageVisibility } from '@vant/use'
 import { usePageVisibility } from '@vant/use'
+import "plyr/dist/plyr.css";
+import Plyr from "plyr";
+import audioVisualDraw from "./audioVisualDraw"
+import Loading from './loading';
 
 
 export default defineComponent({
 export default defineComponent({
   name: 'creation-detail',
   name: 'creation-detail',
   setup() {
   setup() {
+    const {isApp, isTablet, weixin} = browser()
     const route = useRoute()
     const route = useRoute()
     const router = useRouter()
     const router = useRouter()
-
+    const isScreenScroll = ref(false)
+    const creationHeight = ref(0)
     const state = reactive({
     const state = reactive({
       id: route.query.id,
       id: route.query.id,
+      isEmpty: false,
       loginTag: false, // 是否登录标识
       loginTag: false, // 是否登录标识
       loginStatus: false,
       loginStatus: false,
       playType: '' as 'Audio' | 'Video' | '', // 播放类型
       playType: '' as 'Audio' | 'Video' | '', // 播放类型
@@ -72,38 +88,35 @@ export default defineComponent({
         rows: 20
         rows: 20
       },
       },
       messageStatus: false,
       messageStatus: false,
-      message: ''
+      message: '' as any,
+      _plrl: null as any,
+      heightV: 0,
+      heightB: 0,
     })
     })
-    // window.AudioContext = window.AudioContext || window.webkitAudioContext;
-    const audioDom = new Audio()
-    audioDom.controls = true
-    audioDom.style.width = '100%'
-    audioDom.className = styles.audio
-
-    /** 改变播放时间 */
-    const handleChangeTime = (val: number) => {
-      state.currentTime = val
-      clearTimeout(state.timer)
-      state.timer = setTimeout(() => {
-        audioDom.currentTime = val
-        state.timer = null
-      }, 60)
-    }
-
-    // 切换音频播放
-    const onToggleAudio = (e: any) => {
-      e.stopPropagation()
-      if (audioDom.paused) {
-        audioDom.play()
-      } else {
-        audioDom.pause()
-      }
-
-      state.paused = audioDom.paused
-    }
+    const plyrState = reactive({
+      duration: 0,
+      currentTime: 0,
+      mediaTimeShow: false,
+      playIngShow: true,
+      loaded:false
+    })
+    // 谱面
+    const staffState = reactive({
+      staffSrc: "",
+      isShow: false,
+      height:"initial",
+      speedRate:1,
+      musicRenderType:"staff",
+      partIndex:0
+    })    
+    const isLandscapeScreen = ref(false)
+    const wxStatus = ref(false)
+    const staffDom= ref<HTMLIFrameElement>()
+    const {playStaff, pauseStaff, updateProgressStaff} = staffMoveInstance()
 
 
     // 点赞
     // 点赞
     const onStarChange = async () => {
     const onStarChange = async () => {
+      await checkLogin();
       // 是否登录
       // 是否登录
       if (!state.loginTag) {
       if (!state.loginTag) {
         state.loginStatus = true
         state.loginStatus = true
@@ -140,9 +153,9 @@ export default defineComponent({
         state.listState.loading = false
         state.listState.loading = false
         const result = res.data || {}
         const result = res.data || {}
         // 处理重复请求数据
         // 处理重复请求数据
-        if (state.list.length > 0 && result.current === 1) {
-          return
-        }
+        // if (state.list.length > 0 && result.current === 1) {
+        //   return
+        // }
         state.list = state.list.concat(result.rows || [])
         state.list = state.list.concat(result.rows || [])
         state.listState.finished = result.current >= result.pages
         state.listState.finished = result.current >= result.pages
         state.params.page = result.current + 1
         state.params.page = result.current + 1
@@ -155,6 +168,16 @@ export default defineComponent({
       }
       }
     }
     }
 
 
+    function handleChangeList() {
+      if(state.listState.finished){
+        state.listState.finished = false
+        state.params.page = 1;
+        getList()
+      }else{
+        getList()
+      }
+    }
+
     const onDetail = (item: any) => {
     const onDetail = (item: any) => {
       router.push({
       router.push({
         path: '/shareCreation',
         path: '/shareCreation',
@@ -163,32 +186,148 @@ export default defineComponent({
         }
         }
       })
       })
     }
     }
-
-    const initAudio = () => {
-      try {
-        audioDom.src = state.musicDetail.videoUrl
-        audioDom.load()
-        audioDom.oncanplaythrough = () => {
-          state.paused = audioDom.paused
-          state.duration = audioDom.duration
+    // 初始化 媒体播放
+    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
         }
         }
-        // 播放时监听
-        audioDom.addEventListener('timeupdate', () => {
-          state.duration = audioDom.duration
-          state.currentTime = audioDom.currentTime
-          const rate = (state.currentTime / state.duration) * 100
-          state.audioWidth = rate > 100 ? 100 : rate
-        })
-        audioDom.addEventListener('ended', () => {
-          state.paused = audioDom.paused
-        })
-      } catch (e) {
-        //
-        console.log(e)
+      });
+      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', () => {
+        plyrState.loaded = true
+        //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);
     }
     }
-
-    const __init = async () => {
+    //点击改变播放状态
+    function handlerClickPlay(event?:MouseEvent){
+      // 原生 播放暂停按钮 点击的时候 不触发
+      // @ts-ignore
+      if(event?.target?.matches('button.plyr__control')){
+        return
+      }
+      const player = state._plrl;
+      if (player.playing) {
+        player.pause();
+      } else {
+        player.play();
+      }
+    }
+    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(isApp){
+        landscapeScreen()
+        return
+      }
+      if(weixin){
+        wxStatus.value = true
+      }else{
+        const t = Date.now()
+        const str  = location.href
+        shareCall(str)
+        setTimeout(() => {
+          if(Date.now() - t < 3500){
+            window.location.href = location.origin + '/classroom-app/#/transfer'
+          }
+        }, 3000)
+      }
+    }
+    const shareCall = (str: string, params?: any) => {
+      const query = {
+        url: str,
+        action: params?.action || 'h5', // app, h5
+        pageTag: params?.pageTag || 1 // 页面标识
+      }
+      const iosStr = encodeURIComponent(JSON.stringify(query))
+      const userAgent = navigator.userAgent || navigator.vendor;
+      const platform = navigator.platform || 'unknown';
+      if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent) || (platform === 'MacIntel')) {
+        window.location.href = `BandInstrumentTeam://linkUrl=${iosStr}`
+      } else if (/(Android)/i.test(userAgent)) {
+        window.location.href = `colexiukt://html:8888/SplashActivity?url=${iosStr}`
+      } else {
+        Toast('请用手机或移动设备打开')
+      }
+    }
+    const checkLogin = async () => {
       try {
       try {
         // 判断是否登录
         // 判断是否登录
         const Authorization = getAuth() // storage.get(ACCESS_TOKEN) || ''
         const Authorization = getAuth() // storage.get(ACCESS_TOKEN) || ''
@@ -208,238 +347,466 @@ export default defineComponent({
         removeAuth()
         removeAuth()
         setLogout()
         setLogout()
       }
       }
+    };
+    
+    const __init = async () => {
+      await checkLogin();
       try {
       try {
         const res = await api_openUserMusicDetail(state.id)
         const res = await api_openUserMusicDetail(state.id)
 
 
         if (res.code === 999) {
         if (res.code === 999) {
-          state.message = res.msg
-          state.messageStatus = true
+          // 没有的时候显示缺省页
+          state.isEmpty = true
+          staffState.isShow = true
           return
           return
         } else {
         } else {
           state.musicDetail = res.data
           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()
           getList()
           getList()
           // 判断是视频还是音频
           // 判断是视频还是音频
-
           if (res.data.videoUrl.lastIndexOf('mp4') !== -1) {
           if (res.data.videoUrl.lastIndexOf('mp4') !== -1) {
             state.playType = 'Video'
             state.playType = 'Video'
           } else {
           } else {
             state.playType = 'Audio'
             state.playType = 'Audio'
-            // 初始化
-            nextTick(() => {
-              initAudio()
-            })
           }
           }
+          // 初始化
+          nextTick(() => {
+            initMediaPlay();
+          });
         }
         }
       } catch (err) {
       } catch (err) {
-        //
         state.listState.dataShow = false
         state.listState.dataShow = false
+        // 没有的时候显示缺省页
+        state.message = err;
+        state.messageStatus = true;
+      }
+    }
+    // 滚动事件
+    const handleScroll = () => {
+      // 作品已删除不让滚动变色
+      if(state.isEmpty) return
+      const height =
+        window.scrollY ||
+        document.documentElement.scrollTop
+        // 防止多次调用
+        if(height > 0 && isScreenScroll.value === false){
+          isScreenScroll.value = true
+          if(isApp){
+            setStatusBarTextColor(false)
+          }
+        }
+        if(height <= 0){
+          isScreenScroll.value = false
+          if(isApp){
+            setStatusBarTextColor(true)
+          }
+        }
+    }
+    // 跳转下载页
+    function handlerDownLoad(){
+      if(weixin){
+        wxStatus.value = true
+      }else{
+        router.push({
+          path:"/transfer"
+        })
       }
       }
     }
     }
 
 
     const pageVisibility = usePageVisibility()
     const pageVisibility = usePageVisibility()
     watch(pageVisibility, value => {
     watch(pageVisibility, value => {
       if (value === 'hidden') {
       if (value === 'hidden') {
-        if (audioDom) {
-          audioDom.pause()
-          state.paused = audioDom.paused
+        state._plrl?.pause();
+      }
+    });
+    // 初始化五线谱
+    function initStaff(){
+      // const src = `/klx-music-score/#/simple-detail?id=${state.musicDetail.musicSheetId}&musicRenderType=${staffState.musicRenderType}&part-index=${staffState.partIndex}&userMusicId=${state.id}`;
+      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"
+          // 如果是播放中自动开始播放  不是播放 自动跳转到当前位置
+          // if(playProgressData.playState){
+          //   handlerClickPlay()
+          // }else{
+          //   updateProgressStaff(state._plrl.currentTime)
+          // }
         }
         }
+      });
+    }
+    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
+      }
+    }
+    // 设置导航栏颜色
+    function setStatusBarTextColor(isWhite:boolean){
+      postMessage({
+        api: 'setStatusBarTextColor',
+        content: { statusBarTextColor: isWhite }
+      })
+    }
+    function setFullHeight(){
+      creationHeight.value = window.innerHeight
+    }    
+    onBeforeMount(() => {
+      if(isApp) {
+        postMessage({
+          api: "setRequestedOrientation",
+          content: {
+            orientation: 1,
+          },
+        });
+        setStatusBarTextColor(true)
+      }
+    })    
     onMounted(async () => {
     onMounted(async () => {
+      window.addEventListener("scroll", handleScroll)
       __init()
       __init()
+      setFullHeight()
+      window.addEventListener('resize', setFullHeight)
     })
     })
 
 
     onUnmounted(() => {
     onUnmounted(() => {
-      if (audioDom) {
-        audioDom.pause()
-        state.paused = audioDom.paused
-      }
+      window.removeEventListener("scroll", handleScroll)
+      window.removeEventListener('resize', setFullHeight)
+      state._plrl?.destroy()
     })
     })
 
 
     onBeforeRouteUpdate((to: any) => {
     onBeforeRouteUpdate((to: any) => {
-      state.id = to.query.id
-      state.playType = ''
-      state.params.page = 1
-      if (audioDom) {
-        audioDom.currentTime = 0
-        audioDom.pause()
-        state.paused = audioDom.paused
+      state.id = to.query.id;
+      state.playType = '';
+      state.params.page = 1;
+      state.list = [];
+      if(state._plrl){
+        state._plrl.destroy()
       }
       }
-      state.list = []
-      __init()
+      plyrState.playIngShow = true
+      staffState.staffSrc = ""
+      staffState.isShow = false
+      staffState.height = "initial"
+      __init();
     })
     })
     return () => (
     return () => (
-      <div class={styles.creation}>
-        <div class={styles.playSection}>
-          {state.playType === 'Video' && (
-            <MVideo
-              src={state.musicDetail.videoUrl}
-              poster={state.musicDetail.videoImg || videoBg}
-            />
-          )}
-          {state.playType === 'Audio' && (
-            <div class={styles.audioSection}>
-              <div class={styles.audioContainer}>
-                <div
-                  class={styles.waveActive}
-                  style={{
-                    width: state.audioWidth + '%'
+      <div
+        style={
+          {
+            '--barheight':state.heightV + "px",
+            "--creationHeight":creationHeight.value ? creationHeight.value+"px" : "100vh"
+          }
+        }
+        class={[
+          styles.creation,
+          isTablet ? styles.creationTablet : '',
+          isScreenScroll.value && styles.isShareScreenScroll
+        ]}>
+        <div class={styles.creationBg}></div>
+        <MSticky position="top"
+          onGetHeight={(height: any) => {
+            console.log(height, 'height', height)
+            state.heightV = height
+          }}
+        >
+            {
+              isApp ? <MHeader
+                  leftClickDefault={false}
+                  color={isScreenScroll.value ? "#333333" : "#ffffff"}
+                  background={isScreenScroll.value ? `rgb(255,255,255` : "transparent"}
+                  border={false}
+                  isBack={route.query.platformType != 'ANALYSIS'}
+                  title={"作品详情"}
+                  onLeftClick={()=>{
+                    setStatusBarTextColor(false)
+                    postMessage({
+                      api: 'back'
+                    });
                   }}
                   }}
-                ></div>
-                <div class={styles.waveDefault}></div>
-              </div>
-
-              <div class={styles.audioBox}>
-                <div
-                  class={[styles.audioPan, state.paused && styles.imgRotate]}
-                >
-                  <Image class={styles.audioImg} src={state.musicDetail?.img} />
-                </div>
-                <i class={styles.audioPoint}></i>
-                <i
-                  class={[styles.audioZhen, state.paused && styles.active]}
-                ></i>
-              </div>
-              <div
-                class={[styles.controls]}
-                onClick={(e: Event) => {
-                  e.stopPropagation()
-                }}
-              >
-                <div class={styles.actions}>
-                  <div class={styles.actionBtn} onClick={onToggleAudio}>
-                    <img src={state.paused ? iconPlay : iconPause} />
+                />
+                : <div class={styles.logoDownload}>
+                    <img src={isScreenScroll.value ? logo1Img : logoImg} class={styles.logoImg}></img>
+                    <div class={styles.logTit} onClick={handlerDownLoad}>下载App</div>
                   </div>
                   </div>
-                </div>
-                <div class={[styles.slider]}>
-                  <Slider
-                    step={0.01}
-                    class={styles.timeProgress}
-                    v-model={state.currentTime}
-                    max={state.duration}
-                    onUpdate:modelValue={val => {
-                      handleChangeTime(val)
-                    }}
-                    onDrag-start={() => {
-                      state.dragStatus = true
-                      console.log('onDragStart')
-                    }}
-                    onDrag-end={() => {
-                      state.dragStatus = false
-                      console.log('onDragEnd')
-                    }}
-                  />
-                </div>
-                <div class={styles.time}>
-                  <div>{getSecondRPM(state.currentTime)}</div>
-                  <span>/</span>
-                  <div>{getSecondRPM(state.duration)}</div>
-                </div>
-              </div>
-            </div>
-          )}
-        </div>
-
-        <Cell class={styles.userSection} center border={false}>
-          {{
-            icon: () => (
-              <div
-                class={[
-                  styles.userLogoSection,
-                  (state.musicDetail.vipType === 'SVIP' ||
-                    state.musicDetail.vipType === 'PERMANENT_SVIP') &&
-                    styles.userSVip,
-                  state.musicDetail.vipType === 'VIP' && styles.userVip
-                ]}
-              >
-                <Image class={styles.userLogo} src={state.musicDetail.avatar} />
-                <i class={styles.showMemeber}></i>
-              </div>
-            ),
-            title: () => (
-              <div class={styles.userInfo}>
-                <p class={styles.name}>
-                  <span>{state.musicDetail.username}</span>
-                  {/* {state.musicDetail.vipType === 'VIP' && (
-                    <img src={iconVip} class={styles.iconMember} />
-                  )} */}
-                  {/* {(state.musicDetail.vipType === 'SVIP' ||
-                    state.musicDetail.vipType === 'PERMANENT_SVIP') && (
-                    <img src={iconSVip} class={styles.iconMember} />
-                  )} */}
-                </p>
-                <p class={styles.sub}>
-                  {state.musicDetail.subjectName}{' '}
-                  {getGradeCh(state.musicDetail.currentGradeNum - 1)}
-                </p>
-              </div>
-            ),
-            value: () => (
-              <div
-                class={[
-                  styles.zan,
-                  state.musicDetail.starFlag && styles.zanActive
-                ]}
-                onClick={onStarChange}
-              >
-                <img
-                  src={state.musicDetail.starFlag ? iconZanActive : iconZan}
-                  class={styles.iconZan}
+            }
+        </MSticky>
+        {
+          state.isEmpty ?
+          <div class={styles.isEmpty}>
+            <MEmpty tips="作品已删除~" btnStatus={false} />
+          </div> :
+          <>
+            <div class={styles.singerBox}>
+              <div class={styles.musicSheetName}>
+                <NoticeBar
+                    text={state.musicDetail?.musicSheetName}
+                    background="none"
                 />
                 />
-                {state.musicDetail.likeNum}
               </div>
               </div>
-            )
-          }}
-        </Cell>
-
-        <div class={styles.musicSection}>
-          <div class={styles.musicName}>
-            <span class={styles.musicTag}>曲目名称</span>
-            {state.musicDetail?.musicSheetName}
-          </div>
-          {state.musicDetail?.desc && (
-            <div class={styles.musicDesc}>{state.musicDetail?.desc}</div>
-          )}
-        </div>
-
-        <div class={styles.likeSection}>
-          <div class={styles.likeTitle}>推荐作品</div>
-
-          {state.listState.dataShow ? (
-            <List
-              finished={state.listState.finished}
-              finishedText=" "
-              class={[styles.container, styles.containerInformation]}
-              onLoad={getList}
-              immediateCheck={false}
-            >
-              <div class={styles.cellGroup}>
-                {state.list.map((item: any) => (
-                  <div class={styles.cell} onClick={() => onDetail(item)}>
-                    <div class={styles.cellImg}>
-                      <Image
-                        class={styles.cellImage}
-                        src={item.img}
-                        fit="cover"
+              <div class={styles.singerName}>
+                演奏:{state.musicDetail?.username}
+              </div>
+            </div>
+            <Sticky zIndex={1000} offsetTop={state.heightV - 1 + "px"}>
+              <div class={[styles.playSection, plyrState.mediaTimeShow && styles.mediaTimeShow,!plyrState.loaded && styles.notLoaded,isLandscapeScreen.value&&styles.isLandscapeScreen]} id="playMediaSection" onClick={handlerClickPlay}>
+                {
+                  isLandscapeScreen.value &&
+                    <div class={styles.backBox}>
+                      <img class={styles.backImg} src={backImg} onClick={handlerBack}/>
+                      <div class={styles.musicDetail}>
+                        <div class={styles.musicSheetName}>
+                            <NoticeBar
+                                text={state.musicDetail?.musicSheetName}
+                                background="none"
+                            />
+                        </div>
+                        <div class={styles.username}>演奏:{state.musicDetail?.username}</div>
+                      </div>
+                    </div>
+                }
+                {
+                  state.playType &&
+                  <>
+                    {
+                      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="./img/ty.png" class={styles.tyBg} />
+                        <div class="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.iconZan}>{item.likeNum}</div>
+                    }
+                    <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>
-                    <div class={[styles.cellTitle, 'van-ellipsis']}>
-                      {item.musicSheetName}
+                    <div class={styles.landscapeScreen} onClick={handlerLandscapeScreen}></div>
+                    {/* 谱面 */}
+                    {
+                      staffState.staffSrc &&
+                      <div class={[styles.staffBoxCon, staffState.isShow && styles.staffBoxShow]}>
+                        <div
+                          class={styles.staffBox}
+                          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, styles.musicShareSection]}>
+              <div class={styles.avatarInfoBox}>
+                <div class={styles.avatar}>
+                  <Image class={styles.userLogo} src={state.musicDetail.avatar} />
+                  <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>
-                    <div class={styles.users}>
-                      <Image src={item.avatar} class={styles.userImg} />
-                      <span class={styles.name}>{item.username}</span>
+                    <div class={styles.sub}>
+                      {state.musicDetail.subjectName}{' '}
+                      {getGradeCh(state.musicDetail.currentGradeNum - 1)}
                     </div>
                     </div>
                   </div>
                   </div>
-                ))}
+                </div>
+                <div class={styles.linkes}  onClick={onStarChange}>
+                  <img src={state.musicDetail.starFlag ? iconZanActive : iconZan} class={styles.iconZan} />
+                  <span>{state.musicDetail.likeNum}</span>
+                </div>
               </div>
               </div>
-            </List>
-          ) : (
-            <MEmpty tips="暂无数据" btnStatus={false} />
-          )}
-        </div>
+              <TextEllipsis class={styles.textEllipsis} text={state.musicDetail?.desc || ''} />
+            </div>
+            <div class={styles.likeSection}>
+              <div class={styles.likeTitle}>推荐作品</div>
+              {state.listState.dataShow ? (
+                <>
+                  <List
+                    finished={true}
+                    finishedText=" "
+                    class={[styles.container, styles.containerInformation]}
+                    //onLoad={getList}
+                    immediateCheck={false}>
+                    {state.list.map((item: any, index:number) => (
+                      <Cell
+                        class={[styles.likeShareItem, index===state.list.length-1&&styles.likeShareItemLast]}
+                        border={false}
+                        onClick={() => onDetail(item)}
+                      >
+                        {{
+                          icon: () => (
+                            <div class={styles.audioImgBox}>
+                              <img
+                                src={audioPan}
+                                class={styles.audioPan}
+                                crossorigin="anonymous"
+                              />
+                              <img
+                                src={
+                                  item.img || musicBg
+                                }
+                                class={styles.muploader}
+                                crossorigin="anonymous"
+                              />
+                              <img class={styles.imgLabel} src={item.videoUrl?.lastIndexOf('mp4') !== -1 ? videoLabel : audioLabel} />
+                            </div>
+                          ),
+                          title: () => (
+                            <div class={styles.userInfo}>
+                              <div class={[styles.musicSheetName,'van-ellipsis']}>{item.musicSheetName}</div>
+                              <div class={styles.usernameCon}>
+                                <div class={styles.likeNum}>
+                                  <img src={iconZanActive} />
+                                  <span>{item.likeNum}</span>
+                                </div>
+                                <div class={[styles.username, 'van-ellipsis']}>{item.username}</div>
+                              </div>
+                            </div>
+                          ),
+                          value: () => (
+                            <img src={playImg} class={styles.playImg} />
+                          )
+                        }}
+                      </Cell>
+                    ))}
+                  </List>
+                  {
+                    (!state.listState.finished || state.params.page>2) &&
+                      <div class={styles.btnImg}>
+                        <img onClick={handleChangeList} onTouchstart={()=>{}} src={btnImg} />
+                      </div>
+                  }
+                </>
+              ) : (
+                <MEmpty tips="暂无作品~" btnStatus={false} />
+              )}
+            </div>
+            {
+              !isScreenScroll.value &&
+              <MSticky position="bottom" offsetBottom={state.heightB - 1 + "px"} >
+                <div class={styles.upward}>
+                  <img src={iconUpward} />
+                </div>
+              </MSticky>
+            }
+          </>
+        }
+
 
 
         <Popup
         <Popup
           v-model:show={state.loginStatus}
           v-model:show={state.loginStatus}
@@ -461,6 +828,18 @@ export default defineComponent({
           message={state.message}
           message={state.message}
           showButton={false}
           showButton={false}
         />
         />
+        {
+          !staffState.isShow && <Loading></Loading>
+        }
+        {wxStatus.value && (
+          <div
+            class={styles.wxpopup}
+            onClick={() => {
+              wxStatus.value = false;
+            }}>
+            <img src={wxBg} alt="" />
+          </div>
+        )}        
       </div>
       </div>
     )
     )
   }
   }

+ 4 - 4
src/views/creation/index.module.less

@@ -516,17 +516,17 @@
     background-color: rgba(255, 255, 255, 0.3) ;
     background-color: rgba(255, 255, 255, 0.3) ;
   }
   }
   .logoImg{
   .logoImg{
-    width: 159px;
-    height: 29px;
+    width: 107px;
+    height: 30px;
   }
   }
   .logTit{
   .logTit{
     font-weight: 400;
     font-weight: 400;
     font-size: 14px;
     font-size: 14px;
     color: #FFFFFF;
     color: #FFFFFF;
-    line-height: 20px;
+    line-height: 22px;
     padding: 2px 10px;
     padding: 2px 10px;
     border-radius: 20px;
     border-radius: 20px;
-    border: 1px solid rgba(255, 255, 255, 0.5);
+    background: #2DC7AA;
   }
   }
 }
 }
 .isShareScreenScroll{
 .isShareScreenScroll{

BIN
src/views/creation/share-model/images/audioLabel.png


BIN
src/views/creation/share-model/images/videoLabel.png


+ 2 - 2
src/views/creation/text-ellipsis/index.tsx

@@ -91,8 +91,8 @@ export default defineComponent({
         return (
         return (
             <div ref="ellipsisDom" class={[styles.ellipsis, !this.ellipsisData.computedReady && styles.vis]} key={this.ellipsisData.key}>
             <div ref="ellipsisDom" class={[styles.ellipsis, !this.ellipsisData.computedReady && styles.vis]} key={this.ellipsisData.key}>
                 <span ref="textDom">{ this.text }</span>
                 <span ref="textDom">{ this.text }</span>
-                <span v-show="ellipsisData.oversize && !ellipsisData.expanded">...</span>
-                <span v-show="ellipsisData.oversize" class="ellipsisAct" onClick={this.handleExpand}>{ this.ellipsisData.expanded ? "收起" : "展开" }</span>
+                {this.ellipsisData.oversize && !this.ellipsisData.expanded && <span>...</span>}
+                {this.ellipsisData.oversize && <span class="ellipsisAct" onClick={this.handleExpand}>{ this.ellipsisData.expanded ? "收起" : "展开" }</span>}
             </div>
             </div>
         )
         )
     }
     }