瀏覽代碼

作品分享页

黄琪勇 11 月之前
父節點
當前提交
f83511c63d

二進制
src/views/creation/images/logo.png


二進制
src/views/creation/images/logo1.png


二進制
src/views/creation/images/play.png


+ 365 - 285
src/views/creation/index-share.tsx

@@ -9,13 +9,20 @@ import {
 // import WaveSurfer from 'wavesurfer.js';
 // import Regions from 'wavesurfer.js/dist/plugins/regions.js';
 import styles from './index.module.less';
-import { Cell, Image, List, Popup, Slider, showDialog } from 'vant';
+import { Cell, Image, List, Popup, Sticky, TextEllipsis } from 'vant';
 import iconMember from './images/icon-member.png';
 import iconZan from './images/icon-zan.png';
 import iconZanActive from './images/icon-zan-active.png';
-import iconZ from './images/icon-z.png';
+import logoImg from './images/logo.png';
+import logo1Img from './images/logo1.png';
+import iconUpward from './images/upward.png';
 import iconPlay from './images/icon-play.png';
 import iconPause from './images/icon-pause.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 { browser, getGradeCh, getSecondRPM } from '@/helpers/utils';
 import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';
 import {
@@ -33,32 +40,32 @@ import { setLogout } from '@/state';
 import { storage } from '@/helpers/storage';
 import { ACCESS_TOKEN } from '@/store/mutation-types';
 import MWxTip from '@/components/m-wx-tip';
-import { usePageVisibility } from '@vant/use';
+import { usePageVisibility, useEventListener } from '@vant/use';
 import videoBg from './images/video-bg.png';
 import LoginChangeModel from './login-change-model';
+import MSticky from '@/components/m-sticky';
+import "plyr/dist/plyr.css";
+import Plyr from "plyr";
+import { Vue3Lottie } from "vue3-lottie";
+import audioBga from "./images/audioBga.json";
+import videobg from "./images/videobg.png";
 
 export default defineComponent({
   name: 'creation-detail',
   setup() {
     const route = useRoute();
     const router = useRouter();
-    const audioId = 'a' + +Date.now() + Math.floor(Math.random() * 100);
-
+    const isScreenScroll = ref(false)
+    const lottieDom = ref()
     const state = reactive({
       id: route.query.id,
+      isEmpty:false,
       loginTag: false, // 是否登录标识
       loginStatus: false,
       loginChangeState: false, // 切换账号
       credential: {} as any,
       playType: '' as 'Audio' | 'Video' | '', // 播放类型
       musicDetail: {} as any,
-      timer: null as any,
-      paused: true,
-      audioWidth: 0,
-      currentTime: 0,
-      duration: 0.1,
-      loop: false,
-      dragStatus: false, // 是否开始拖动
       isClick: false,
       list: [] as any,
       listState: {
@@ -71,37 +78,17 @@ export default defineComponent({
         rows: 20
       },
       messageStatus: false,
-      message: ''
+      message: '',
+      _plrl: null as any,
+      heightV:0,
+      heightB:0
     });
-    const wavesurfer = ref();
-    // 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
+    })
     // 点赞
     const onStarChange = async () => {
       await checkLogin();
@@ -164,66 +151,156 @@ export default defineComponent({
         }
       });
     };
-
-    const initAudio = () => {
-      try {
-        audioDom.src = state.musicDetail.videoUrl;
-        audioDom.load();
-        audioDom.oncanplaythrough = () => {
-          state.paused = audioDom.paused;
-          state.duration = audioDom.duration;
-        };
-        // 播放时监听
-        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;
-        });
-        // wavesurfer.value = WaveSurfer.create({
-        //   container: document.querySelector(`#${audioId}`) as HTMLElement,
-        //   waveColor: '#fff',
-        //   progressColor: '#2FA1FD',
-        //   url: state.musicDetail.videoUrl,
-        //   cursorWidth: 0,
-        //   height: 35,
-        //   width: 'auto',
-        //   normalize: true,
-        //   // Set a bar width
-        //   barWidth: 2,
-        //   // Optionally, specify the spacing between bars
-        //   barGap: 2,
-        //   // And the bar radius
-        //   barRadius: 4,
-        //   barHeight: 1.2,
-        //   /** If autoScroll is enabled, keep the cursor in the center of the waveform during playback */
-        //   // autoCenter: true,
-        //   hideScrollbar: false,
-        //   media: audioDom
-        // });
-        // // console.log(wavesurfer.value);
-
-        // // const wsRegions = wavesurfer.value.registerPlugin(Regions.create());
-        // wavesurfer.value.once('interaction', () => {
-        //   // wavesurfer.value.play();
-        // });
-        // wavesurfer.value.once('ready', () => {
-        //   state.paused = audioDom.paused;
-        //   state.duration = audioDom.duration;
-        // });
-
-        // wavesurfer.value.on('finish', () => {
-        //   state.paused = true;
-        // });
-      } catch (e) {
-        //
-        console.log(e);
+    // 初始化 媒体播放
+    function initMediaPlay(){
+      const id = state.playType === "Audio" ? "#audioMediaSrc" : "#videoMediaSrc";
+      state._plrl = new Plyr(id, {
+        controls: ["progress"],
+        fullscreen: { enabled: false },
+      });
+      const player = state._plrl
+        // 创建音波数据
+      if(state.playType === "Audio"){
+        setTimeout(() => {
+          const audioDom = document.querySelector("#audioMediaSrc") as HTMLAudioElement
+          const canvasDom = document.querySelector("#audioVisualizer") as HTMLCanvasElement
+          const { pauseVisualDraw, playVisualDraw } = audioVisualDraw(audioDom, canvasDom)
+          player.on('play', () => {
+            lottieDom.value.play()
+            playVisualDraw()
+          });
+          player.on('pause', () => {
+            lottieDom.value.pause()
+            pauseVisualDraw()
+          });
+        }, 300); // 弹窗动画是0.25秒 这里用定时器 确保canvas 能获取到宽高
       }
-    };
-
+      player.on("timeupdate", ()=>{
+        plyrState.currentTime = player.currentTime
+      })
+      player.on('play', () => {
+        plyrState.playIngShow = false
+      });
+      player.on('pause', () => {
+        plyrState.playIngShow = true
+      });
+      // 处理按压事件
+      const handleStart = () => {
+        plyrState.duration = player.duration
+        plyrState.mediaTimeShow = true
+      };
+      // 处理松开事件
+      const handleEnd = () => {
+        plyrState.mediaTimeShow = false
+      };
+      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(){
+      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")!
+      const { width, height } = canvasDom.getBoundingClientRect()
+      canvasDom.width = width
+      canvasDom.height = height
+      // audio
+      const audioCtx = new AudioContext()
+      const analyser = audioCtx.createAnalyser()
+      const source = audioCtx.createMediaElementSource(audioDom)
+      analyser.fftSize = fftSize
+      source.connect(analyser)
+      analyser.connect(audioCtx.destination)
+      const dataArray = new Uint8Array(analyser.frequencyBinCount)
+      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
+        const step = (w / 2 - lineGap * dataLen) / dataLen
+        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(dataArray, canvasCtx, {
+            lineGap: 2,
+            canvWidth: width,
+            canvHeight: height,
+            canvFillColor: "transparent",
+            lineColor: "rgba(255, 255, 255, 0.7)"
+          })
+          if (!isPause) {
+            requestAnimationFrameFun()
+          }
+        })
+      }
+      let isPause = true
+      const playVisualDraw = () => {
+        isPause = false
+        audioCtx.resume()
+        requestAnimationFrameFun()
+      }
+      const pauseVisualDraw = () => {
+        isPause = true
+        audioCtx.suspend()
+      }
+      return {
+        playVisualDraw,
+        pauseVisualDraw
+      }
+    }
     const checkLogin = async () => {
       try {
         // 判断是否登录
@@ -251,7 +328,6 @@ export default defineComponent({
       await checkLogin();
       try {
         const res = await api_openUserMusicDetail(state.id);
-
         if (res.code === 999) {
           state.message = res.message;
           state.messageStatus = true;
@@ -260,225 +336,231 @@ export default defineComponent({
           state.musicDetail = res.data;
           getList();
           // 判断是视频还是音频
-
           if (res.data.videoUrl.lastIndexOf('mp4') !== -1) {
             state.playType = 'Video';
           } else {
             state.playType = 'Audio';
-            // 初始化
-            nextTick(() => {
-              initAudio();
-            });
           }
-        }
+          // 初始化
+          nextTick(() => {
+            initMediaPlay();
+          });
+}
       } catch (err) {
-        //
+        // 没有的时候显示缺省页
+        state.isEmpty = true
         state.listState.dataShow = false;
       }
     };
-
-    const pageVisibility = usePageVisibility();
-    watch(pageVisibility, value => {
-      console.log(value);
-      if (value === 'hidden') {
-        if (audioDom) {
-          audioDom.pause();
-          state.paused = audioDom.paused;
+    // 滚动事件
+    const cleanScrollEvent = useEventListener('scroll', () => {
+      const height =
+        window.scrollY ||
+        document.documentElement.scrollTop
+        // 防止多次调用
+        if(height > 0 && isScreenScroll.value === false){
+          isScreenScroll.value = true
         }
-      }
-    });
+        if(height <= 0){
+          isScreenScroll.value = false
+        }
+    })
+    function handlerDownLoad(){
+      router.push({
+        path:"/transfer"
+      })
+    }
     onMounted(async () => {
       __init();
     });
 
     onUnmounted(() => {
-      if (audioDom) {
-        audioDom.pause();
-        state.paused = audioDom.paused;
-      }
+      cleanScrollEvent()
     });
 
     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.list = [];
+      if(state._plrl){
+        state._plrl.destroy()
+      }
       __init();
     });
     return () => (
       <div
+        style={
+          {
+            '--barheight':state.heightV + "px"
+          }
+        }
         class={[
           styles.creation,
-          browser().isTablet ? styles.creationTablet : ''
+          browser().isTablet ? styles.creationTablet : '',
+          isScreenScroll.value && styles.isShareScreenScroll
         ]}>
-        {/* <video
-          src={state.musicDetail.videoUrl}
-          style="width: 100%;height: 200px"
-          controls></video> */}
-        <div class={styles.playSection}>
-          {state.playType === 'Video' && (
-            <MVideo
-              class={styles.videoSection}
-              src={state.musicDetail.videoUrl}
-              poster={state.musicDetail?.videoImg || videoBg}
-            />
-          )}
-          {state.playType === 'Audio' && (
-            <div class={styles.audioSection}>
-              <div class={styles.audioContainer}>
-                {/* <div
-                  id={audioId}
-                  onClick={(e: MouseEvent) => {
-                    e.stopPropagation();
-                  }}></div> */}
-                <div
-                  class={styles.waveActive}
-                  style={{
-                    width: state.audioWidth + '%'
-                  }}></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();
-                }}
-                onTouchmove={(e: TouchEvent) => {
-                  // emit('close');
-                }}>
-                <div class={styles.actions}>
-                  <div class={styles.actionBtn} onClick={onToggleAudio}>
-                    <img src={state.paused ? iconPlay : iconPause} />
-                  </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);
-                    }}
-                    onDragStart={() => {
-                      state.dragStatus = true;
-                      console.log('onDragStart');
-                    }}
-                    onDragEnd={() => {
-                      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 class={styles.creationBg}></div>
+        <MSticky position="top"
+          onBarHeight={(height: any) => {
+            console.log(height, 'height', height)
+            state.heightV = height
+          }}
+        >
+            <div class={styles.logoDownload}>
+              <img src={isScreenScroll.value ? logo1Img : logoImg} class={styles.logoImg}></img>
+              <div class={styles.logTit} onClick={handlerDownLoad}>下载App</div>
             </div>
-          )}
-        </div>
-
-        <Cell class={styles.userSection} center border={false}>
-          {{
-            icon: () => (
-              <Image class={styles.userLogo} src={state.musicDetail.avatar} />
-            ),
-            title: () => (
-              <div class={styles.userInfo}>
-                <p class={styles.name}>
-                  <span>{state.musicDetail.username}</span>
-                  {state.musicDetail.vipFlag && (
-                    <img src={iconMember} class={styles.iconMember} />
-                  )}
-                </p>
-                <p class={styles.sub}>
-                  {state.musicDetail.subjectName}{' '}
-                  {getGradeCh(state.musicDetail.currentGradeNum - 1)}
-                </p>
+        </MSticky>
+        {
+          state.isEmpty ?
+          <div class={styles.isEmpty}>
+            <MEmpty description="作品已删除~" />
+          </div> :
+          <>
+            <div class={styles.singerBox}>
+              <div class={styles.musicSheetName}>
+                {state.musicDetail?.musicSheetName}
               </div>
-            ),
-            value: () => (
-              <div
-                class={[
-                  styles.zan,
-                  state.musicDetail.starFlag && styles.zanActive
-                ]}
-                onClick={onStarChange}>
-                <img
-                  src={state.musicDetail.starFlag ? iconZanActive : iconZan}
-                  class={styles.iconZan}
-                />
-                {state.musicDetail.likeNum}
+              <div class={styles.singerName}>
+                演奏:{state.musicDetail?.username}
               </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>
+            <Sticky offsetTop={state.heightV - 1 + "px"}>
+              <div class={[styles.playSection, plyrState.mediaTimeShow && styles.mediaTimeShow]} id="playMediaSection" onClick={handlerClickPlay}>
+                {
+                  state.playType &&
+                  <>
+                    {
+                      state.playType === 'Audio' &&
+                      <div class={styles.audioBox}>
+                        <canvas class={styles.audioVisualizer} id="audioVisualizer"></canvas>
+                        <Vue3Lottie ref={lottieDom} class={styles.audioBga} animationData={audioBga} autoPlay={false} loop={true}></Vue3Lottie>
+                        <audio
+                          crossorigin="anonymous"
+                          id="audioMediaSrc"
+                          src={state.musicDetail?.videoUrl}
+                          controls="false"
+                          preload="metadata"
+                          playsinline
+                        />
+                      </div>
+                    }
+                    {
+                      state.playType === 'Video' &&
+                      <video
+                        id="videoMediaSrc"
+                        class={styles.videoBox}
+                        src={state.musicDetail?.videoUrl}
+                        data-poster={videobg}
+                        preload="metadata"
+                        playsinline
                       />
-
-                      <div class={styles.iconZan}>{item.likeNum}</div>
+                    }
+                    <div class={[styles.playLarge, plyrState.playIngShow && styles.playIngShow]}></div>
+                    <div class={styles.mediaTime}>
+                      <div>
+                        {getSecondRPM(plyrState.currentTime)}
+                      </div>
+                      <div class={styles.note}>/</div>
+                      <div class={styles.duration}>
+                        {getSecondRPM(plyrState.duration)}
+                      </div>
                     </div>
-                    <div class={[styles.cellTitle, 'van-ellipsis']}>
-                      {item.musicSheetName}
+                  </>
+                }
+              </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 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 class={styles.linkes}  onClick={onStarChange}>
+                  <img src={state.musicDetail.starFlag ? iconZanActive : iconZan} class={styles.iconZan} />
+                  <span>{state.musicDetail.likeNum}</span>
+                </div>
               </div>
-            </List>
-          ) : (
-            <MEmpty description="暂无数据" />
-          )}
-        </div>
-
+              <TextEllipsis class={styles.textEllipsis} rows={2} content={state.musicDetail?.desc} expand-text="展开" collapse-text="收起" />
+            </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}>
+                  {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}>{item.username}</div>
+                            </div>
+                          </div>
+                        ),
+                        value: () => (
+                          <img src={playImg} class={styles.playImg} />
+                        )
+                      }}
+                    </Cell>
+                  ))}
+                </List>
+              ) : (
+                <MEmpty description="暂无数据" />
+              )}
+            </div>
+            {
+              !isScreenScroll.value &&
+              <MSticky position="bottom" offsetBottom={state.heightB - 1 + "px"} >
+                <div class={styles.upward}>
+                  <img src={iconUpward} />
+                </div>
+              </MSticky>
+            }
+          </>
+        }
         <Popup
           v-model:show={state.loginStatus}
           style={{ background: 'transparent', overflow: 'inherit' }}>
@@ -499,7 +581,6 @@ export default defineComponent({
             }}
           />
         </Popup>
-
         <Popup
           v-model:show={state.loginChangeState}
           style={{ background: 'transparent', overflow: 'inherit' }}>
@@ -517,7 +598,6 @@ export default defineComponent({
             }}
           />
         </Popup>
-
         <MWxTip
           v-model:show={state.messageStatus}
           message={state.message}

+ 144 - 85
src/views/creation/index.module.less

@@ -67,6 +67,10 @@
           }
       }
   }
+  .videoBox{
+    width: 100%;
+    height: 100%;
+  }
   .audioBox{
       width: 100%;
       height: 100%;
@@ -381,108 +385,163 @@
   }
 }
 
-.cellGroup {
+// 分享样式
+.logoDownload{
   display: flex;
-  flex-wrap: wrap;
+  justify-content: space-between;
+  align-items: center;
+  padding: 10px 13px;
+  position: relative;
+  &::after{
+    content: "";
+    position: absolute;
+    bottom: 0;
+    left: 13px;
+    width: calc(100% - 26px);
+    height: 1px;
+    background-color: rgba(255, 255, 255, 0.5) ;
+  }
+  .logoImg{
+    width: 159px;
+    height: 29px;
+  }
+  .logTit{
+    font-weight: 400;
+    font-size: 14px;
+    color: #FFFFFF;
+    line-height: 20px;
+    padding: 2px 10px;
+    border-radius: 20px;
+    border: 1px solid rgba(255, 255, 255, 0.5);
+  }
 }
-
-.cell {
-  // display: flex;
-  // flex-direction: column;
-  width: 96px;
-  margin-right: 18px;
-  margin-bottom: 18px;
-
-  &:nth-child(3n + 3) {
-    margin-right: 0;
+.isShareScreenScroll{
+  .logoDownload{
+    background-color: #ffffff;
+    .logTit{
+      background: linear-gradient( 90deg, #44C9FF 0%, #259CFE 100%);
+      border: none;
+      padding: 3px 11px;
+    }
   }
-
-  .cellImg {
+}
+.singerBox{
+  height: 20vh;
+  display: flex;
+  flex-direction: column;
+  justify-content: end;
+  .musicSheetName{
+    text-align: center;
+    font-weight: 600;
+    font-size: 20px;
+    color: #FFFFFF;
+    line-height: 28px;
+    margin-bottom: 10px;
+  }
+  .singerName{
+    text-align: center;
+    font-weight: 400;
+    font-size: 14px;
+    color: rgba(255,255,255,0.7);
+    line-height: 20px;
+    margin-bottom: 10px;
+  }
+}
+.musicShareSection{
+  min-height: calc(100vh - var(--barheight) - 20vh - 210px - 40px);
+}
+.likeShareItem{
+  background-color: initial;
+  padding: 0;
+  margin-top: 25px;
+  &:first-child{
+    margin-top: 20px;
+  }
+  &.likeShareItemLast{
+    padding-bottom: 20px;
+  }
+  .audioImgBox{
     position: relative;
-
-    &::before {
-      content: '';
+    width: 51px;
+    height: 51px;
+    margin-right: 14px;
+    .audioPan{
       position: absolute;
-      right: -8px;
-      top: 3px;
-      z-index: 8;
-      width: 84px;
-      height: 84px;
-      background: url('./images/audio-pan.png') no-repeat center;
-      background-size: contain;
-      display: flex;
-      align-items: center;
-      justify-content: center;
+      width: 100%;
+      height: 100%;
+      right: -6px;
+      top: 0;
     }
-
-    .iconZan {
+    .muploader{
+      position: relative;
+      z-index: 1;
+      width: 100%;
+      height: 100%;
+      border-radius: 6px;
+    }
+    .imgLabel{
       position: absolute;
-      bottom: 4px;
-      left: 4px;
+      right: 0;
+      top: 0;
+      width: 28px;
+      height: 14px;
       z-index: 10;
-      padding: 3px;
-      background: rgba(67, 67, 67, 0.3);
-      border-radius: 8px;
-      backdrop-filter: blur(4px);
-
-      font-size: 9px;
-      font-weight: 500;
+    }
+  }
+  .userInfo{
+    .musicSheetName{
+      font-weight: 600;
+      font-size: 16px;
       color: #FFFFFF;
-      line-height: 13px;
+      line-height: 22px;
+      width: 200px;
+    }
+    .usernameCon{
       display: flex;
       align-items: center;
-
-      &::before {
-        content: '';
-        display: inline-block;
-        width: 12px;
-        height: 12px;
-        background: url('./images/icon-z.png') no-repeat center;
-        background-size: contain;
+      margin-top: 6px;
+      .likeNum{
+        display: flex;
+        border-radius: 3px;
+        background-color: rgba(255,255,255,.22);
+        padding: 1px 2px 1px 1px;
+        img{
+          width: 14px;
+          height: 15px;
+        }
+        span{
+          font-weight: 400;
+          font-size: 10px;
+          color: #FFFFFF;
+          line-height: 14px;
+          margin-left: 2px;
+        }
       }
-    }
-  }
-
-  .cellImage {
-    position: relative;
-    width: 88px;
-    height: 88px;
-    border-radius: 12px;
-    z-index: 9;
-
-    :global {
-      img {
-        border-radius: 12px;
+      .username{
+        margin-left: 4px;
+        font-weight: 400;
+        font-size: 13px;
+        color: #DEDEDE;
+        line-height: 13px;
       }
     }
   }
-
-  .cellTitle {
-    font-size: 13px;
-    color: #131415;
-    line-height: 18px;
-    margin: 8px 0 6px;
-  }
-
-  .users {
-    display: flex;
-    align-items: center;
-
-    .userImg {
-      width: 20px;
-      height: 20px;
-      border-radius: 50%;
-      overflow: hidden;
-      margin-right: 4px;
-      flex-shrink: 0;
-    }
-
-    .name {
-      font-size: 12px;
-      color: #402424;
-      line-height: 14px;
+  :global{
+    .van-cell__value{
+      display: flex;
+      align-items: center;
+      justify-content: end;
     }
   }
+  .playImg{
+    width: 20px;
+    height: 20px;
+  }
+}
+.isEmpty{
+  height: calc(100vh - var(--barheight));
+  display: flex;
+  align-items: center;
 }
 
 // 平板样式

+ 0 - 4
src/views/creation/index.tsx

@@ -319,10 +319,6 @@ export default defineComponent({
 				pauseVisualDraw
 			}
 		}
-    const pageVisibility = usePageVisibility();
-    watch(pageVisibility, value => {
-      if (value === 'hidden') {}
-    });
     onMounted(async () => {
       setStatusBarTextColor(true)
       try {