Browse Source

修改样式

lex-xin 4 months ago
parent
commit
6b08aae271
23 changed files with 1186 additions and 422 deletions
  1. 17 0
      src/components/globalTools/globalTools.ts
  2. BIN
      src/components/globalTools/images/g-arrow-right.png
  3. BIN
      src/components/globalTools/images/icon-note.png
  4. BIN
      src/components/globalTools/images/icon-tool.png
  5. BIN
      src/components/globalTools/images/icon-whiteboard.png
  6. 102 0
      src/components/globalTools/index.module.less
  7. 231 0
      src/components/globalTools/index.tsx
  8. 1 1
      src/teacher/music/upload/message-tip/index.tsx
  9. 65 0
      src/tenant/music/coursewarePlay/component/courseware-tips/index.module.less
  10. 28 0
      src/tenant/music/coursewarePlay/component/courseware-tips/index.tsx
  11. 173 0
      src/tenant/music/coursewarePlay/component/courseware-type/index.module.less
  12. 28 0
      src/tenant/music/coursewarePlay/component/courseware-type/index.tsx
  13. 8 6
      src/tenant/music/coursewarePlay/component/point.module.less
  14. BIN
      src/tenant/music/coursewarePlay/component/tips/icon-close.png
  15. 73 0
      src/tenant/music/coursewarePlay/component/tips/index.module.less
  16. 37 0
      src/tenant/music/coursewarePlay/component/tips/index.tsx
  17. BIN
      src/tenant/music/coursewarePlay/component/tips/top-bg.png
  18. 72 49
      src/tenant/music/coursewarePlay/component/tools/pen.tsx
  19. 41 22
      src/tenant/music/coursewarePlay/component/video-play.tsx
  20. 47 155
      src/tenant/music/coursewarePlay/component/video.module.less
  21. 0 0
      src/tenant/music/coursewarePlay/image/icons.json
  22. 86 15
      src/tenant/music/coursewarePlay/index.module.less
  23. 177 174
      src/tenant/music/coursewarePlay/index.tsx

+ 17 - 0
src/components/globalTools/globalTools.ts

@@ -0,0 +1,17 @@
+import { ref } from "vue"
+
+/** 工具栏状态 */
+export const toolOpen = ref(false)
+// 批注
+export const penShow = ref(false)
+// 白板
+export const whitePenShow = ref(false)
+// 是否正在播放
+export const isPlay = ref(false)
+// 是否隐藏
+export const isHidden = ref(true)
+
+/** 是否隐藏工具栏 */
+export const handleHidden = (status = true) => {
+   isHidden.value = status
+}

BIN
src/components/globalTools/images/g-arrow-right.png


BIN
src/components/globalTools/images/icon-note.png


BIN
src/components/globalTools/images/icon-tool.png


BIN
src/components/globalTools/images/icon-whiteboard.png


+ 102 - 0
src/components/globalTools/index.module.less

@@ -0,0 +1,102 @@
+.globalTools {
+  &.isPlay {
+     .iconTools,
+     .expendTools {
+        opacity: 0.4;
+     }
+  }
+  &.isHidden {
+     .iconTools,
+     .expendTools {
+        opacity: 0;
+        display: none;
+     }
+  }
+
+  .mask {
+     position: fixed;
+     left: 0;
+     right: 0;
+     top: 0;
+     bottom: 0;
+     background-color: transparent;
+     z-index: 2998;
+  }
+  .iconTools,
+  .expendTools {
+     position: fixed;
+     right: -2px;
+     top: 0;
+     transform: translateY(var(--toolTranslateY));
+     // margin-top: -29px;
+     z-index: 2999;
+     // padding: 0 5px;
+     background: rgba(0, 0, 0, 0.4);
+     border-radius: 200px 0px 0px 200px;
+     border: 1px solid rgba(255, 255, 255, 0.3);
+     border-right-width: 0;
+     cursor: pointer;
+     font-size: 0;
+     // transition: transform 0.2s ease;
+     img {
+        padding: 5px 8px;
+        width: 24px;
+        height: 24px;
+        box-sizing: content-box;
+        -moz-user-select: none;
+        /* 火狐浏览器 */
+        -webkit-user-drag: none;
+        /* 谷歌、Safari和Opera浏览器 */
+        -webkit-user-select: none;
+        /* 谷歌、Safari和Opera浏览器 */
+        -ms-user-select: none;
+        /* IE10+浏览器 */
+        user-select: none;
+        /* 通用 */
+        -webkit-touch-callout: none;
+        /* iOS Safari */
+
+        &:hover {
+           opacity: 0.8;
+        }
+     }
+  }
+
+  .iconTools {
+     // transition-delay: 0.2s;
+  }
+
+  .expendTools {
+     // transform: translateX(100%);
+     display: none;
+     img {
+        cursor: pointer;
+        padding-left: 12px;
+        padding-right: 12px;
+     }
+     .iconWhiteboard {
+        // margin: 0 30px;
+        padding-left: 8px;
+        padding-right: 8px;
+     }
+     .iconArrow {
+        padding: 7px 12px;
+        width: 18px;
+        height: 18px;
+     }
+  }
+
+  .hideTools {
+     // transition: transform 0.2s ease;
+     transform: translateY(var(--toolTranslateY));
+     display: none;
+  }
+
+  .showTools {
+     // transition: transform 0.2s ease;
+     // transition-delay: 0.2s;
+     transform: translateY(var(--toolTranslateY));
+     display: flex;
+     align-items: center;
+  }
+}

+ 231 - 0
src/components/globalTools/index.tsx

@@ -0,0 +1,231 @@
+import {
+  toolOpen,
+  whitePenShow,
+  penShow,
+  isPlay,
+  isHidden
+} from './globalTools';
+import { defineComponent, onMounted, onUnmounted, ref, watch } from 'vue';
+import { useRoute } from 'vue-router';
+import styles from './index.module.less';
+import iconTool from './images/icon-tool.png';
+import iconNote from './images/icon-note.png';
+import iconWhiteboard from './images/icon-whiteboard.png';
+import gArrowRight from './images/g-arrow-right.png';
+import { nextTick } from 'process';
+import Pen from '@/tenant/music/coursewarePlay/component/tools/pen';
+import { useNetwork } from '@vueuse/core';
+import { Toast } from 'vant';
+
+export default defineComponent({
+  name: 'globalTools',
+  setup() {
+    const { isOnline } = useNetwork()
+    const isMask = ref(false); // 是否显示遮罩层,为了处理云教练里面拖动不了的问题
+    const route = useRoute();
+    // watch(
+    //   () => route.path,
+    //   () => {
+    //     handleStatus();
+    //   }
+    // );
+    const iconToolsDom = ref<HTMLDivElement>();
+    const expendToolsDom = ref<HTMLDivElement>();
+
+    function openTool() {
+      if (isLock) return;
+      isPlay.value = false
+      toolOpen.value = !toolOpen.value;
+    }
+
+    function openType(type: 'note' | 'whiteboard') {
+      if (isLock) return;
+      console.log(isOnline.value, 'isOnline.value')
+      if(!isOnline.value) {
+        Toast('网络异常')
+        return
+      }
+      if (type === 'note') {
+        penShow.value = true;
+
+        isHidden.value = true;
+      } else if (type === 'whiteboard') {
+        whitePenShow.value = true;
+        isHidden.value = true;
+      }
+    }
+
+    function handleStatus() {
+      isHidden.value = route.path === '/login' ? true : false;
+    }
+
+    function computePos(type: 'width' | 'height', value: number) {
+      const clientNum =
+        type == 'width'
+          ? document.documentElement.clientWidth
+          : document.documentElement.clientHeight;
+      console.log(value, clientNum)
+      return {
+        pos: ((clientNum - value) / 2).toFixed(5)
+      };
+    }
+
+    /* 拖拽还没有兼容rem */
+    let isLock = false;
+    let toolMoveY = 0; // 移动的距离
+    function drag(el: HTMLElement) {
+      function mousedown(e: MouseEvent | TouchEvent) {
+        const isTouchEv = isTouchEvent(e);
+        const event = isTouchEv ? e.touches[0] : e;
+        isLock = false;
+        isMask.value = true;
+        const parentElement = el;
+        const parentElementRect = parentElement.getBoundingClientRect();
+        const downX = event.clientX;
+        const downY = event.clientY;
+        // const clientWidth = document.documentElement.clientWidth
+        const clientHeight = document.documentElement.clientHeight;
+        // const minLeft = 0
+        const minTop = 0;
+        // const maxLeft = clientWidth - parentElementRect.width
+        const maxTop = clientHeight - parentElementRect.height;
+        function onMousemove(e: MouseEvent | TouchEvent) {
+          const event = isTouchEvent(e) ? e.touches[0] : e;
+          // let moveX = parentElementRect.left + (e.clientX - downX)
+          let moveY = parentElementRect.top + (event.clientY - downY);
+          // let moveY = e.clientY - downY
+          // moveX = moveX < minLeft ? minLeft : moveX > maxLeft ? maxLeft : moveX
+          moveY = moveY < minTop ? minTop : moveY > maxTop ? maxTop : moveY;
+          toolMoveY = moveY;
+          document.documentElement.style.setProperty(
+            '--toolTranslateY',
+            `${moveY}px`
+          );
+
+          // 计算移动的距离
+          const cX = event.clientX - downX;
+          const cY = event.clientY - downY;
+
+          // 如果移动距离超过一定阈值,则认为是拖动
+          if (Math.abs(cX) > 3 || Math.abs(cY) > 3) {
+            isLock = true; // 设置为拖动状态
+          }
+        }
+        function onMouseup() {
+          document.removeEventListener(
+            isTouchEv ? 'touchmove' : 'mousemove',
+            onMousemove
+          );
+          document.removeEventListener(
+            isTouchEv ? 'touchend' : 'mouseup',
+            onMouseup
+          );
+          isMask.value = false;
+        }
+        document.addEventListener(
+          isTouchEv ? 'touchmove' : 'mousemove',
+          onMousemove
+        );
+        document.addEventListener(
+          isTouchEv ? 'touchend' : 'mouseup',
+          onMouseup
+        );
+      }
+      el.addEventListener('mousedown', mousedown);
+      el.addEventListener('touchstart', mousedown);
+    }
+    function isTouchEvent(e: MouseEvent | TouchEvent): e is TouchEvent {
+      return window.TouchEvent && e instanceof window.TouchEvent;
+    }
+    //重新计算位置 居中
+    function refreshPos() {
+      // computePos("height", iconToolsDom.value?.clientHeight ||
+      console.log(iconToolsDom.value?.clientHeight);
+      const posHeight = computePos(
+        'height',
+        iconToolsDom.value?.clientHeight || 0
+      );
+      if (iconToolsDom.value) {
+        document.documentElement.style.setProperty(
+          '--toolTranslateY',
+          `${posHeight.pos}px`
+        );
+      }
+    }
+    let rect: any;
+    function onResize() {
+      rect = rect ? rect : iconToolsDom.value?.getBoundingClientRect();
+      const clientHeight = document.documentElement.clientHeight;
+      const maxTop = clientHeight - rect.height;
+      if (toolMoveY >= maxTop) {
+        document.documentElement.style.setProperty(
+          '--toolTranslateY',
+          `${maxTop}px`
+        );
+      }
+    }
+    onMounted(() => {
+      handleStatus();
+      drag(iconToolsDom.value!);
+      drag(expendToolsDom.value!);
+      nextTick(() => {
+        refreshPos();
+      })
+      window.addEventListener('resize', onResize);
+    });
+
+    onUnmounted(() => {
+      window.removeEventListener('resize', onResize);
+    });
+    return () => (
+      <div>
+        <div
+          class={[
+            styles.globalTools,
+            isPlay.value ? styles.isPlay : '',
+            isHidden.value ? styles.isHidden : ''
+          ]}>
+          {isMask.value && <div class={styles.mask}></div>}
+
+          <div
+            class={[[styles.iconTools, toolOpen.value ? styles.hideTools : '']]}
+            ref={iconToolsDom}>
+            <img onClick={openTool} src={iconTool} />
+          </div>
+          <div
+            class={[styles.expendTools, toolOpen.value ? styles.showTools : '']}
+            ref={expendToolsDom}>
+            <img onClick={() => openType('note')} src={iconNote} />
+            <img
+              onClick={() => openType('whiteboard')}
+              class={styles.iconWhiteboard}
+              src={iconWhiteboard}
+            />
+            <img
+              onClick={openTool}
+              class={styles.iconArrow}
+              src={gArrowRight}
+            />
+          </div>
+        </div>
+        <Pen
+          show={penShow.value}
+          tip="请确认是否退出批注?"
+          close={() => {
+            penShow.value = false;
+            isHidden.value = false;
+          }}
+        />
+        <Pen
+          show={whitePenShow.value}
+          isWhite
+          tip="请确认是否退出白板?"
+          close={() => {
+            whitePenShow.value = false;
+            isHidden.value = false;
+          }}
+        />
+      </div>
+    );
+  }
+});

+ 1 - 1
src/teacher/music/upload/message-tip/index.tsx

@@ -105,7 +105,7 @@ export default defineComponent({
                   </div>
                   <p class={styles.cTitle}>曲谱审核标准:</p>
                   <div class={[styles.cContent, styles.cContentBottom]}>
-                    1、文件大小不要超过5MB,不符合版面规范的乐谱,审核未通过的不予上架,详情参考
+                    1、文件大小不要超过10MB,不符合版面规范的乐谱,审核未通过的不予上架,详情参考
                     <span onClick={() => onDetail('music')}>
                       《曲谱排版规范》
                     </span>

+ 65 - 0
src/tenant/music/coursewarePlay/component/courseware-tips/index.module.less

@@ -0,0 +1,65 @@
+.container {
+  position: relative;
+  width: 453px;
+  height: 80vh;
+  max-height: 302px;
+  // background: url('../../image/tips-bg.png') top center no-repeat #fff;
+  // background-size: contain;
+  border-radius: 20px;
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+  background-color: #fff;
+
+  &::before {
+    content: '';
+    width: 100%;
+    height: 46px;
+    display: block;
+    position: absolute;
+    top: 0;
+    left: 0;
+    border-top-left-radius: 20px;
+    border-top-right-radius: 20px;
+    background: linear-gradient(to bottom, #FFEAEE, #ffffff);
+  }
+
+  .iconClose {
+    position: relative;
+    z-index: 1;
+    width: 18px;
+    height: 19px;
+    position: absolute;
+    top: 14px;
+    right: 20px;
+    z-index: 9;
+    background: url('../tips/icon-close.png') no-repeat center;
+    background-size: contain;
+  }
+
+  .title {
+    position: relative;
+    z-index: 1;
+    font-weight: 600;
+    font-size: 16px;
+    color: #131415;
+    line-height: 22px;
+    text-align: center;
+    padding: 12px 0;
+    flex-shrink: 0;
+  }
+
+  .content {
+    flex: 1;
+    overflow-x: hidden;
+    overflow-y: auto;
+    padding: 0 20px;
+    margin-bottom: 16px;
+    font-size: 14px;
+    line-height: 1.6;
+
+    &::-webkit-scrollbar {
+      display: none;
+    }
+  }
+}

+ 28 - 0
src/tenant/music/coursewarePlay/component/courseware-tips/index.tsx

@@ -0,0 +1,28 @@
+import { defineComponent, PropType } from "vue";
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'coruseware-tips',
+  props: {
+    titleName: {
+      type: String,
+      default: '阶段目标'
+    },
+    content: {
+      type: String,
+      default: ''
+    }
+  },
+  emits: ['close'],
+  setup(props, { emit }) {
+    return () => <div class={styles.container}>
+      <i
+          class={styles.iconClose}
+          onClick={() => (emit("close"))}></i>
+      <div class={styles.title}>
+        {props.titleName}
+      </div>
+      <div class={styles.content} v-html={props.content}></div>
+    </div>
+  }
+})

+ 173 - 0
src/tenant/music/coursewarePlay/component/courseware-type/index.module.less

@@ -0,0 +1,173 @@
+.container {
+  display: flex;
+  flex-direction: column;
+  min-width: 300px;
+  max-width: 300px;
+  height: 100vh;
+  color: #fff;
+  font-size: 12px;
+  box-sizing: border-box;
+}
+
+.pointHead {
+  display: flex;
+  align-items: center;
+  padding: 13px 10px 15px 15px;
+  flex-shrink: 0;
+  font-size: 16px;
+  font-weight: 500;
+
+  img {
+    width: 20px;
+    height: 20px;
+    margin-right: 6px;
+  }
+}
+
+.content {
+  flex: 1;
+  overflow-y: auto;
+  padding: 0 8px;
+}
+
+
+.item {
+  display: inline-block;
+  margin: 0 0 18px;
+  padding: 0 8px;
+  width: calc(33.333% - 16px);
+  box-sizing: content-box;
+
+  .cover {
+    position: relative;
+    border-radius: 2px;
+    overflow: hidden;
+    margin-bottom: 8px;
+    box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.2);
+  }
+
+  .currentText {
+    width: 28px;
+    height: 13px;
+    position: absolute;
+    top: 2px;
+    left: 2px;
+    background: url('../../image/icon-current.png') no-repeat center center;
+    background-size: contain;
+  }
+
+  .model {
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.4);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: #fff;
+    font-size: 12px;
+    line-height: 18px;
+
+    img {
+      width: 12px;
+      height: 12px;
+      margin-right: 4px;
+    }
+  }
+
+  .coverNum {
+    position: absolute;
+    bottom: 12px;
+    left: 50%;
+    transform: translateX(-50%);
+    border-radius: 20px;
+    color: rgba(116, 44, 0, 1);
+    background-color: #fff;
+    padding: 4px 6px;
+    line-height: 1;
+    font-size: 12px;
+    z-index: 1;
+    white-space: nowrap;
+    word-break: break-all;
+    min-width: 50px;
+    text-align: center;
+  }
+
+  .coverImg {
+    width: 100%;
+    background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAMAAAAPdrEwAAABOFBMVEUAAAC0tLTT09PU1NTt7e3////T09P////T09P////T09P////X19f////U1NTU1NTT09PT09PU1NTU1NTV1dXT09PU1NTU1NTV1dXZ2dn+/v7R0dH////////KysrIyMjT09O0tLTU1NS0tLTU1NS0tLTT09PT09PT09PU1NTU1NTU1NTT09O2trbU1NTV1dXV1dXW1tbV1dXW1tbV1dXJycm4uLj///+0tLT///+0tLT////p6em0tLT4+Pj///+2trb///+1tbX///+0tLT////T09P5+fn+/v63t7e8vLz8/Pzl5eXW1tbBwcH39/fw8PDs7Ozb29v7+/vg4ODOzs65ubny8vLJycnp6enGxsbFxcW+vr62trb09PTY2NjLy8vCwsLn5+fi4uLS0tLu7u7Q0NDd3d02Mu/gAAAARHRSTlMAnPwvBfv07ODdw5AbGezmyrirl5B4aT0kDZyclTwsIPj48+Ta1tPS0LGhiIaEcGJgV05FNhMS7++8vKyslZRzc1ZWJRSpe/cAAALfSURBVFjD7djXcuIwGAVg1pTQAiT0Ekiy6b1v7whsA6b3EGAJu+//BstaiWNiCYGlXGTG55KBDzH6j2xjMmJET5ZdDivQFavDtTxLXlsCFFlam7HmiUxl49ftApRxYWkHLe3A0lZa2oqlAXUMGk/fHG9vpCnSk/pZNJ18m6aOWELRN1CmtbMI+jjNJH0Evc2GlhD0Bhu6h6DTjPIq6Pqonb8XXoCWmjKSHTCnpccp5ges6bHCZAW2dBc8JcOWLqjoPFu6oqLLr2bVQxX9h/GElBWmKDCmxSKAyXWYt1GE677rLtLGejsLcuOCQMI7lVFlsMjxJJUeW3bP+OSTskBJqcuSFppAFT4vsqMrYDrVAitazMHV8kBJs8WGzsPmNoRCFSj5fcuA7vJKvcQ8UJKrCNT0WH0mdEpASbFOSdfhyClvzagGsSzR0D14LHTSSho1/mkQaw39dB9u2vThCU8KQj1JtFiVt+z5ONSLmnoSaeszuia/+lfzAaGS09STQDum6SH/cOXX5rY9Xz0Rj6Sqy0YmjUzrbp56ah6kIT2AH8Pe4M5TT83jP6ThsnALmq+eiD8tlIt/G8POWU8FVNMNuXc8rnH4epJpOHg1jIivJ5mWcvLg4ZqMryeZhnOLm1hyPfF0C95R9PAcvp4jcSYNL7UDHEWuJ56GO46FyPXE0+/+/7Lhgs+ffU093yPoDwCAEcki1/Mjgv4BQFUkSeR6/jQh8gn0SQy5np9NqFi+CgSDWE9rwmJCJ/X9yxt9iSdisVji2y+TESNGXjiW6LU7FYkkzQ9JRiIp93XUoodyX12cBg/9qyvOHbvXxmUw4Wxe+45zZdV/GDy9uHJbZqPhk7jTjrTI4ezO+EkY8wUBW4Y6tgCSPvNxtDLnOzOhEw2HAvt7Hj2oZ28/EApHyRtpvjwPBY/8B5Ot9O1u2b2eTds6x8nr4tZtmx6vfWvXN9nCA/9RMHR+aZ5sohEji+YfnN0/51L6d+cAAAAASUVORK5CYII=');
+    background-repeat: no-repeat;
+    background-position: center;
+    background-size: 50%;
+    border-radius: 2px;
+    overflow: hidden;
+
+    &>img {
+      display: block;
+      width: 100%;
+      height: 95px;
+      opacity: 0;
+      transition: opacity .3s;
+    }
+
+    :global {
+      .van-image__loading {
+        position: relative;
+        height: 95px;
+        animation: van-skeleton-blink var(--van-skeleton-duration) ease-in-out infinite;
+      }
+    }
+
+    &::before {
+      content: '';
+      position: absolute;
+      left: 5px;
+      width: 5px;
+      height: 100%;
+      background: linear-gradient(270deg, rgba(0, 0, 0, 0.25) 0%, rgba(0, 0, 0, 0.03) 100%);
+      box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.2);
+      z-index: 1;
+    }
+  }
+
+  .name {
+    width: 100%;
+    font-size: 12px;
+    font-weight: 600;
+    color: rgba(255,255,255,0.5);
+    line-height: 20px !important;
+
+    :global {
+      .van-notice-bar {
+        padding: 0 !important;
+        line-height: 20px !important;
+        height: 20px !important;
+      }
+    }
+
+    &.active {
+      :global {
+        .van-notice-bar__content {
+          color: #FFFFFF;
+          transition-property: transform;
+        }
+      }
+    }
+
+    &.disabled {
+      :global {
+        .van-notice-bar__content {
+          color: rgba(255,255,255,0.5);
+          transition-duration: 0s !important;
+          transform: none !important;
+          width: 100%;
+          overflow: hidden;
+          white-space: nowrap;
+          text-overflow: ellipsis;
+        }
+      }
+    }
+  }
+}

File diff suppressed because it is too large
+ 28 - 0
src/tenant/music/coursewarePlay/component/courseware-type/index.tsx


+ 8 - 6
src/tenant/music/coursewarePlay/component/point.module.less

@@ -1,8 +1,8 @@
 .container {
   display: flex;
   flex-direction: column;
-  min-width: 288px;
-  max-width: 288px;
+  min-width: 300px;
+  max-width: 300px;
   height: 100vh;
   color: #fff;
   font-size: 12px;
@@ -14,15 +14,17 @@
   align-items: center;
   padding: 13px 10px 15px 15px;
   flex-shrink: 0;
-  font-size: 14px;
+  font-size: 16px;
+  font-weight: 500;
 
   img {
-    width: 16px;
-    height: 16px;
-    margin-right: 7px;
+    width: 20px;
+    height: 20px;
+    margin-right: 6px;
   }
 }
 
+
 .content {
   flex: 1;
   overflow-y: auto;

BIN
src/tenant/music/coursewarePlay/component/tips/icon-close.png


+ 73 - 0
src/tenant/music/coursewarePlay/component/tips/index.module.less

@@ -0,0 +1,73 @@
+
+.courseDialog {
+  padding: 20px !important;
+  max-width: 310px !important;
+  min-width: 295px !important;
+  // background: url('./top-bg.png') no-repeat top center #fff !important;
+  // background-size: contain !important;
+  overflow: hidden;
+  border-radius: 20px !important;
+  overflow: hidden;
+  background-color: #fff;
+
+  &::before {
+    content: '';
+    width: 100%;
+    height: 49px;
+    display: block;
+    position: absolute;
+    top: 0;
+    left: 0;
+    border-top-left-radius: 20px;
+    border-top-right-radius: 20px;
+    background: linear-gradient(to bottom, #FFEAEE, #ffffff);
+  }
+
+  .iconClose {
+    position: relative;
+    width: 18px;
+    height: 19px;
+    position: absolute;
+    top: 23px;
+    right: 20px;
+    z-index: 9;
+    background: url('./icon-close.png') no-repeat center;
+    background-size: contain;
+  }
+
+  .title {
+    position: relative;
+    font-size: 18px;
+    font-weight: 600;
+    color: #1A1A1A;
+    line-height: 25px;
+    text-align: center;
+  }
+
+  .content {
+    padding: 20px 0 25px;
+    font-size: 16px;
+    color: #666666;
+    line-height: 24px;
+    text-align: center;
+  }
+
+  .popupBtnGroup {
+    display: flex;
+    align-items: center;
+
+    &>button {
+      flex: 1;
+      font-weight: 500;
+      font-size: 16px !important;
+
+      &:last-child {
+        margin-left: 15px;
+      }
+    }
+
+    :global {
+      --van-button-default-height: 40px;
+    }
+  }
+}

+ 37 - 0
src/tenant/music/coursewarePlay/component/tips/index.tsx

@@ -0,0 +1,37 @@
+import { Button, Popup } from 'vant';
+import { defineComponent, reactive } from 'vue';
+import styles from './index.module.less';
+
+export const tipState = reactive({
+  show: false,
+  title: '温馨提示',
+  content: '退出后将清空批注内容',
+  cancelText: '取消',
+  confirmText: '确认退出'
+})
+
+export default defineComponent({
+  name: 'tips-popup',
+  emits: ['confirm'],
+  setup(props, { emit }) {
+    return () => (
+      <Popup v-model:show={tipState.show} round class={styles.courseDialog}>
+        <i
+          class={styles.iconClose}
+          onClick={() => (tipState.show = false)}></i>
+        <div class={styles.title}>{tipState.title}</div>
+
+        <div class={styles.content}>
+          {tipState.content}
+        </div>
+
+        <div class={styles.popupBtnGroup}>
+          <Button round onClick={() => tipState.show = false}>{tipState.cancelText}</Button>
+          <Button round type="primary" onClick={() => emit("confirm")}>
+            {tipState.confirmText}
+          </Button>
+        </div>
+      </Popup>
+    );
+  }
+});

BIN
src/tenant/music/coursewarePlay/component/tips/top-bg.png


+ 72 - 49
src/tenant/music/coursewarePlay/component/tools/pen.tsx

@@ -1,6 +1,5 @@
-import { promisefiyPostMessage } from '@/helpers/native-message'
-import html2canvas from 'html2canvas'
-import { Toast } from 'vant'
+import { promisefiyPostMessage } from '@/helpers/native-message';
+import html2canvas from 'html2canvas';
 import {
   defineComponent,
   toRefs,
@@ -9,12 +8,22 @@ import {
   onMounted,
   onUnmounted,
   nextTick
-} from 'vue'
-import styles from './pen.module.less'
+} from 'vue';
+import styles from './pen.module.less';
+import Tips, { tipState } from '../tips';
+import { Toast } from 'vant';
 
 export default defineComponent({
   name: 'tools-pen',
   props: {
+    isWhite: {
+      type: Boolean,
+      default: false
+    },
+    tip: {
+      type: String,
+      default: '请确认是否退出?'
+    },
     show: {
       type: Boolean,
       default: false
@@ -25,64 +34,68 @@ export default defineComponent({
     }
   },
   setup(props) {
-    const { show } = toRefs(props)
-    const firstRender = ref(true)
+    const { show } = toRefs(props);
+    const firstRender = ref(true);
     const src = /(localhost|192)/.test(location.host)
       ? 'https://test.lexiaoya.cn/whiteboard-noCollab'
-      : `https://kt.colexiu.com/classroom-whiteboard`
+      : `https://online.lexiaoya.cn/whiteboard-noCollab`;
 
     const exportImg = (event: MessageEvent) => {
-      const data = event.data
+      const data = event.data;
       // console.log('🚀 ~ event:', data)
       if (data.api === 'excalidraw_exportImg') {
-        imgs.base64 = data.base64
-        imgs.exported = true
+        imgs.base64 = data.base64;
+        imgs.exported = true;
         nextTick(() => {
-          onSaveImg()
-        })
+          onSaveImg();
+        });
       }
-    }
+    };
     onMounted(() => {
-      window.addEventListener('message', exportImg)
-    })
+      window.addEventListener('message', exportImg);
+    });
     onUnmounted(() => {
-      window.removeEventListener('message', exportImg)
-    })
+      window.removeEventListener('message', exportImg);
+    });
 
     const imgs = reactive({
       exported: false,
       saveLoading: false,
       base64: '',
       image: ''
-    })
+    });
 
     const saveImg = async () => {
-      Toast.loading({ message: '图片生成中...', forbidClick: true })
+      Toast.loading({
+        message: '图片生成中...',
+        forbidClick: true
+      })
       setTimeout(() => {
-        imgs.saveLoading = false
-      }, 100)
+        imgs.saveLoading = false;
+      }, 100);
       const res = await promisefiyPostMessage({
         api: 'savePicture',
         content: {
           base64: imgs.image
         }
-      })
+      });
       if (res?.content?.status === 'success') {
-        Toast.success('保存成功')
+        // showSuccessToast('保存成功');
+        Toast.success("保存成功")
       } else {
         Toast.fail('保存失败')
       }
-      imgs.exported = false
-    }
+      imgs.exported = false;
+    };
 
     const onSaveImg = async () => {
       // 判断是否在保存中...
       if (imgs.saveLoading) {
-        return
+        return;
       }
-      console.log('开始')
-      imgs.saveLoading = true
-      const container: any = document.getElementById(`app`)
+      console.log('开始');
+      imgs.saveLoading = true;
+      const container: any = document.getElementById(`app`);
       html2canvas(container, {
         allowTaint: true,
         useCORS: true,
@@ -93,20 +106,20 @@ export default defineComponent({
           // document.body.appendChild(canvas)
           // const url = await canvas.toDataURL()
           try {
-            imgs.image = canvas.toDataURL()
+            imgs.image = canvas.toDataURL();
           } catch (error) {
-            console.log(error)
+            console.log(error);
           }
-          console.log('🚀 ~ imgs.image:', imgs.image)
-          saveImg()
+          console.log('🚀 ~ imgs.image:', imgs.image);
+          saveImg();
         })
         .catch(error => {
-          console.log('🚀 ~ error:', error)
+          console.log('🚀 ~ error:', error);
           Toast.clear()
-          imgs.saveLoading = false
-          imgs.exported = false
-        })
-    }
+          imgs.saveLoading = false;
+          imgs.exported = false;
+        });
+    };
 
     return () => (
       <div
@@ -114,32 +127,42 @@ export default defineComponent({
           styles.pen,
           firstRender.value ? styles.dely : '',
           show.value ? styles.open : styles.hide
-        ]}
-      >
+        ]}>
         <iframe
           class={styles.iframe}
+          style={{
+            background: props.isWhite ? '#fff' : 'transparent'
+          }}
           frameborder="0"
           width="100vw"
           height="100vh"
           src={src}
           onLoad={() => {
-            firstRender.value = false
-          }}
-        ></iframe>
+            firstRender.value = false;
+          }}></iframe>
         {imgs.exported ? (
           <img crossorigin="anonymous" class={styles.img} src={imgs.base64} />
         ) : (
-          <div class={styles.rightItem} onClick={() => props.close()}>
+          <div class={styles.rightItem} onClick={() => {
+            tipState.content = props.tip
+            tipState.show = true
+            console.log('1111')
+          }}>
             <svg width="22px" height="20px" viewBox="0 0 22 20">
               <path
                 transform="translate(-1.000000, -2.000000)"
                 fill="#FFFFFF"
-                d="M13,2 C13.5522847,2 14,2.44771525 14,3 C14,3.51283584 13.6139598,3.93550716 13.1166211,3.99327227 L13,4 L3,4 L3,20 L13,20 C13.5128358,20 13.9355072,20.3860402 13.9932723,20.8833789 L14,21 C14,21.5128358 13.6139598,21.9355072 13.1166211,21.9932723 L13,22 L2,22 C1.48716416,22 1.06449284,21.6139598 1.00672773,21.1166211 L1,21 L1,3 C1,2.48716416 1.38604019,2.06449284 1.88337887,2.00672773 L2,2 L13,2 Z M17.7071068,7.05025253 L21.9497475,11.2928932 L21.9497475,11.2928932 C22.3402718,11.6834175 22.3402718,12.3165825 21.9497475,12.7071068 L17.7071068,16.9497475 C17.3165825,17.3402718 16.6834175,17.3402718 16.2928932,16.9497475 C15.9023689,16.5592232 15.9023689,15.9260582 16.2928932,15.5355339 L18.828,12.999 L9.29368112,13 C8.74139637,13 8.29368112,12.5522847 8.29368112,12 C8.29368112,11.4871642 8.67972131,11.0644928 9.17706,11.0067277 L9.29368112,11 L18.827,10.999 L16.2928932,8.46446609 C15.9023689,8.0739418 15.9023689,7.44077682 16.2928932,7.05025253 C16.6834175,6.65972824 17.3165825,6.65972824 17.7071068,7.05025253 Z"
-              ></path>
+                d="M13,2 C13.5522847,2 14,2.44771525 14,3 C14,3.51283584 13.6139598,3.93550716 13.1166211,3.99327227 L13,4 L3,4 L3,20 L13,20 C13.5128358,20 13.9355072,20.3860402 13.9932723,20.8833789 L14,21 C14,21.5128358 13.6139598,21.9355072 13.1166211,21.9932723 L13,22 L2,22 C1.48716416,22 1.06449284,21.6139598 1.00672773,21.1166211 L1,21 L1,3 C1,2.48716416 1.38604019,2.06449284 1.88337887,2.00672773 L2,2 L13,2 Z M17.7071068,7.05025253 L21.9497475,11.2928932 L21.9497475,11.2928932 C22.3402718,11.6834175 22.3402718,12.3165825 21.9497475,12.7071068 L17.7071068,16.9497475 C17.3165825,17.3402718 16.6834175,17.3402718 16.2928932,16.9497475 C15.9023689,16.5592232 15.9023689,15.9260582 16.2928932,15.5355339 L18.828,12.999 L9.29368112,13 C8.74139637,13 8.29368112,12.5522847 8.29368112,12 C8.29368112,11.4871642 8.67972131,11.0644928 9.17706,11.0067277 L9.29368112,11 L18.827,10.999 L16.2928932,8.46446609 C15.9023689,8.0739418 15.9023689,7.44077682 16.2928932,7.05025253 C16.6834175,6.65972824 17.3165825,6.65972824 17.7071068,7.05025253 Z"></path>
             </svg>
           </div>
         )}
+
+        <Tips onConfirm={() => {
+          props.close()
+          tipState.show = false
+        }} />
       </div>
-    )
+    );
   }
-})
+});
+

+ 41 - 22
src/tenant/music/coursewarePlay/component/video-play.tsx

@@ -287,8 +287,23 @@ export default defineComponent({
       })
       videoErrorCount++
     }
+    const parentContainer = reactive({
+      width: '100vw'
+    })
+    const setContainer = () => {
+      const min = Math.min(screen.width, screen.height)
+      const max = Math.max(screen.width, screen.height)
+      const width = min * (16 / 9)
+      if (width > max) {
+        parentContainer.width = '100vw'
+        return
+      } else {
+        parentContainer.width = width + 'px'
+      }
+    }
 
     onMounted(() => {
+      setContainer()
       videoItem.value = TCPlayer(videoID, {
         appID: '',
         controls: false,
@@ -360,16 +375,19 @@ export default defineComponent({
           data.speedControl = false
         }}
       >
-        <video
-          style={{ width: '100%', height: '100%' }}
-          src={item.value.content}
-          ref={videoRef}
-          id={videoID}
-          preload="auto"
-          playsinline
-          webkit-playsinline
-        ></video>
-        <div class={styles.videoSection}></div>
+        <div style={{ width: parentContainer.width, height: '100%', margin: '0 auto' }}>
+          <video
+            style={{ width: '100%', height: '100%' }}
+            src={item.value.content}
+            ref={videoRef}
+            id={videoID}
+            preload="auto"
+            playsinline
+            webkit-playsinline
+          ></video>
+          <div class={styles.videoSection}></div>
+        </div>
+        
 
         <div
           class={[styles.controls, data.showBar ? '' : styles.hide]}
@@ -380,11 +398,11 @@ export default defineComponent({
           //   emit('close')
           // }}
         >
-          <div class={styles.time}>
-            <div>{getSecondRPM(data.currentTime)}</div>/
-            <div>{getSecondRPM(data.duration)}</div>
-          </div>
           <div class={styles.slider}>
+            <div class={styles.time}>
+              <div>{getSecondRPM(data.currentTime)}</div>/
+              <div>{getSecondRPM(data.duration)}</div>
+            </div>
             <Slider
               step={0.01}
               class={styles.timeProgress}
@@ -407,7 +425,7 @@ export default defineComponent({
                 <img src={data.playState === 'pause' ? iconPlay : iconPause} />
               </div>
               <div
-                class={styles.actionBtn}
+                class={[styles.actionBtn, styles.btnLoop]}
                 onClick={() => {
                   toggleLoop()
                   Toast(data.loop ? '已打开循环播放' : '已关闭循环播放')
@@ -419,16 +437,17 @@ export default defineComponent({
                 <img src={iconSpeed} />
               </div>
             </div>
-            <div class={styles.name}>{item.value.name}</div>
+            {/* <div class={styles.name}>{item.value.name}</div> */}
+            {item.value.materialMusicId && (
+              <div
+                class={[styles.goPractice, data.showBar ? '' : styles.hide]}
+                onClick={gotoAccomany}
+              ></div>
+            )}
           </div>
         </div>
 
-        {item.value.materialMusicId && (
-          <div
-            class={[styles.goPractice, data.showBar ? '' : styles.hide]}
-            onClick={gotoAccomany}
-          ></div>
-        )}
+        
 
         <div
           style={{

File diff suppressed because it is too large
+ 47 - 155
src/tenant/music/coursewarePlay/component/video.module.less


File diff suppressed because it is too large
+ 0 - 0
src/tenant/music/coursewarePlay/image/icons.json


+ 86 - 15
src/tenant/music/coursewarePlay/index.module.less

@@ -5,6 +5,21 @@
   overflow: hidden;
   --plyr-color-main: var(--van-primary);
   --plyr-range-track-height: 3px;
+
+  img {
+    -moz-user-select: none;
+    /* 火狐浏览器 */
+    -webkit-user-drag: none;
+    /* 谷歌、Safari和Opera浏览器 */
+    -webkit-user-select: none;
+    /* 谷歌、Safari和Opera浏览器 */
+    -ms-user-select: none;
+    /* IE10+浏览器 */
+    user-select: none;
+    /* 通用 */
+    -webkit-touch-callout: none;
+    /* iOS Safari */
+  }
 }
 
 .coursewarePlay {
@@ -31,9 +46,9 @@
   right: 0;
   z-index: 10;
   display: flex;
-  align-items: center;
+  align-items: flex-start;
   justify-content: space-between;
-  height: 40px;
+  // height: 40px;
   background: linear-gradient(180deg, rgba(0, 0, 0, 0.6), transparent);
   transition: transform 0.5s;
   box-sizing: border-box;
@@ -45,20 +60,50 @@
 }
 
 .backBtn {
-  font-weight: 500;
-  font-size: 16px;
-  color: #ffffff;
+  color: #fff;
   height: 100%;
   display: flex;
   justify-content: space-between;
-  align-items: center;
+  align-items: flex-start;
   z-index: 10;
-  padding: 0 15px;
-  pointer-events: auto;
+  font-size: 18px;
+  padding: 12px 15px 20px 40px;
 
   :global {
     .van-icon {
       margin-right: 8px;
+      pointer-events: auto;
+    }
+  }
+
+  .titleSection {
+    .title {
+      font-weight: 600;
+      font-size: 16px;
+      color: #ffffff;
+      line-height: 22px;
+    }
+  }
+  .titleContent {
+    display: flex;
+    align-items: center;
+    padding-top: 6px;
+    p {
+      font-size: 14px;
+      color: #ffffff;
+      line-height: 20px;
+    }
+    span {
+      margin-left: 6px;
+      font-size: 11px;
+      color: #ffffff;
+      line-height: 1.3;
+      background: rgba(0, 0, 0, 0.1);
+      border-radius: 10px;
+      border: 1px solid rgba(255, 255, 255, 0.7);
+      padding: 2px 8px;
+      box-sizing: content-box;
+      pointer-events: auto;
     }
   }
 }
@@ -169,8 +214,9 @@
 }
 
 .fullBtn {
-  width: 38px;
-  height: 50px;
+  width: 24px;
+  height: 24px;
+  padding: 10px 9px;
   display: flex;
   flex-direction: column;
   align-items: center;
@@ -178,10 +224,21 @@
   justify-content: space-evenly;
   overflow: hidden;
   white-space: nowrap;
+  box-sizing: content-box;
+  border-radius: 7px;
 
   &:active {
     background: rgba(255, 255, 255, 0.2);
   }
+
+  &.disabled {
+    opacity: 0.4;
+  }
+
+  img {
+    width: inherit;
+    height: inherit;
+  }
 }
 
 .rightFixedBtns {
@@ -200,12 +257,10 @@
   position: absolute;
   top: 50%;
   transform: translateY(-50%);
-  left: 12px;
+  left: 40px;
   z-index: 10;
-
-  .prePoint {
-    margin-bottom: 8px;
-  }
+  background: rgba(0, 0, 0, 0.4);
+  border-radius: 7px;
 }
 
 .btnsWrap {
@@ -265,6 +320,22 @@
 .popup {
   background: rgba(0, 0, 0, 0.5);
 }
+.popupCoursewarePlay {
+  background: rgba(0, 0, 0, 0.8) !important;
+  box-shadow: -6px 0px 20px 0px rgba(0,0,0,0.3) !important;
+  border-radius: 16px 0px 0px 16px !important;
+  backdrop-filter: blur(12px);
+}
+.popupPoint {
+  :global {
+    .van-popup__close-icon {
+      font-size: 18px;
+      top: 14px;
+      right: 20px;
+      color: #333333;
+    }
+  }
+}
 
 .overlayClass {
   --van-overlay-background: transparent;

+ 177 - 174
src/tenant/music/coursewarePlay/index.tsx

@@ -23,14 +23,15 @@ import {
   listenerMessage
 } from '@/helpers/native-message'
 import MusicScore from './component/musicScore'
-import iconDian from './image/icon-dian.svg'
-import iconPoint from './image/icon-point.svg'
+// import iconDian from './image/icon-dian.svg'
+// import iconPoint from './image/icon-point.svg'
 import { state as baseState } from '@/state'
 import {
   iconUp,
   iconDown,
   // iconPen,
   iconTouping,
+  iconCourseType,
   iconMenu
 } from './image/icons.json'
 import Points from './component/points'
@@ -46,6 +47,11 @@ import Pen from './component/tools/pen'
 // import VideoItem from './component/video-item';
 import VideoPlay from './component/video-play'
 import { musicBuy } from '../music'
+import { penShow, whitePenShow } from '@/components/globalTools/globalTools'
+import CoursewareTips from './component/courseware-tips'
+import GlobalTools from '@/components/globalTools'
+import CoursewareType from './component/courseware-type'
+import { useNetwork } from '@vueuse/core'
 
 export default defineComponent({
   name: 'CoursewarePlay',
@@ -54,6 +60,7 @@ export default defineComponent({
       baseState.platformType === 'STUDENT' ? '/api-student' : '/api-teacher'
     )
     const pageVisibility = usePageVisibility()
+    const { isOnline } = useNetwork()
     /** 页面显示和隐藏 */
     watch(
       () => pageVisibility.value,
@@ -63,24 +70,33 @@ export default defineComponent({
         }
       }
     )
+    // 白板的批注打开时暂停播放
+    watch(
+      () => [whitePenShow.value, penShow.value],
+      () => {
+        if (whitePenShow.value || penShow.value) {
+          handleStop()
+        }
+      }
+    )
     /** 设置播放容器 16:9 */
     const parentContainer = reactive({
       width: '100vw'
     })
-    const setContainer = () => {
-      const min = Math.min(screen.width, screen.height)
-      const max = Math.max(screen.width, screen.height)
-      const width = min * (16 / 9)
-      if (width > max) {
-        parentContainer.width = '100vw'
-        return
-      } else {
-        parentContainer.width = width + 'px'
-      }
-    }
+    // const setContainer = () => {
+    //   const min = Math.min(screen.width, screen.height)
+    //   const max = Math.max(screen.width, screen.height)
+    //   const width = min * (16 / 9)
+    //   if (width > max) {
+    //     parentContainer.width = '100vw'
+    //     return
+    //   } else {
+    //     parentContainer.width = width + 'px'
+    //   }
+    // }
     const handleInit = (type = 0) => {
       //设置容器16:9
-      setContainer()
+      // setContainer()
       // 横屏
       postMessage(
         {
@@ -124,6 +140,7 @@ export default defineComponent({
     const route = useRoute()
     const headeRef = ref()
     const data = reactive({
+      currentId: route.query.id as any,
       detail: null as any,
       knowledgePointList: [] as any,
       itemList: [] as any,
@@ -131,7 +148,7 @@ export default defineComponent({
       isCourse: false,
       isRecordPlay: false,
       videoRefs: {},
-
+      refLevelList: [] as any,
       videoState: 'init' as 'init' | 'play',
       videoItemRef: null as any,
       animationState: 'start' as 'start' | 'end',
@@ -287,11 +304,11 @@ export default defineComponent({
         }, 500)
       })
     }
-    const getDetail = async () => {
+    const getDetail = async (id?: any) => {
       try {
         const res: any = await request.get(
           apiSuffix.value +
-            `/tenantAlbumMusic/getLessonCourseDetail/${route.query.id}`,
+            `/tenantAlbumMusic/getLessonCourseDetail/${id || route.query.id}`,
           {
             hideLoading: true
           }
@@ -366,11 +383,24 @@ export default defineComponent({
           console.log(data.knowledgePointList, 'data.knowledgePointList')
           getItemList()
         }
+        return true
       } catch (error) {
         console.log(error)
       }
     }
 
+    const onTitleTip = (type: "phaseGoals" | "checkItem", text: string) => {
+      handleStop()
+      popupData.pointOpen = true
+      popupData.pointContent = text
+      if(type === "checkItem") {
+        popupData.pointTitle = '检查事项'
+      } else if(type === "phaseGoals") {
+        popupData.pointTitle = '阶段目标'
+      }
+    }
+
+
     // ifram事件处理
     const iframeHandle = (ev: MessageEvent) => {
       console.log('headerTogge', ev)
@@ -459,27 +489,24 @@ export default defineComponent({
       }
     }
 
+    const getRefLevel = async (id?: any) => {
+      try {
+        const res = await request.post(apiSuffix.value + '/tenantAlbumMusic/refLevel', {
+          data: {
+            lessonCoursewareDetailId: id || route.query.id
+          }
+        })
+        data.refLevelList = res.data || []
+        return true
+      } catch {
+        // 
+      }
+    }
+
     onMounted(async () => {
       await sysParamConfig()
+      await getRefLevel()
       await getDetail()
-      // const hasFree = String(data.detail?.accessScope) === '0'
-      // if (!hasFree) {
-      //   if (state.platformType === 'STUDENT') {
-      //     const hasVip = handleCheckVip()
-      //     if (!hasVip) {
-      //       nextTick(() => {
-      //         postMessage({
-      //           api: 'courseLoading',
-      //           content: {
-      //             show: false,
-      //             type: 'fullscreen'
-      //           }
-      //         })
-      //       })
-      //       return
-      //     }
-      //   }
-      // }
       // getCourseSchedule();
       window.addEventListener('message', iframeHandle)
 
@@ -522,6 +549,10 @@ export default defineComponent({
     }
 
     const popupData = reactive({
+      pointOpen: false,
+      pointContent: "", 
+      pointTitle: "",
+      coursewareOpen: false,
       open: false,
       activeIndex: 0,
       playIndex: 0,
@@ -840,25 +871,6 @@ export default defineComponent({
               }
               class={styles.itemDiv}
             >
-              {/* <VideoItem
-                ref={(el: any) => (data.videoItemRef = el)}
-                item={activeVideoItem.value}
-                activeModel={activeData.model}
-                onClose={setModelOpen}
-                onPlay={() => {
-                  data.videoState = 'play';
-                }}
-                onPause={() => {
-                  clearTimeout(activeData.timer);
-                  activeData.model = true;
-                }}
-                onEnded={() => {
-                  const _index = popupData.activeIndex + 1;
-                  if (_index < data.itemList.length) {
-                    handleSwipeChange(_index);
-                  }
-                }}
-              /> */}
               <VideoPlay
                 ref={(el: any) => (data.videoItemRef = el)}
                 item={activeVideoItem.value}
@@ -866,6 +878,9 @@ export default defineComponent({
                 onPlay={() => {
                   data.videoState = 'play'
                   data.animationState = 'end'
+                  if(whitePenShow.value || penShow.value || popupData.coursewareOpen || popupData.open || popupData.guideOpen || popupData.pointOpen) {
+                    handleStop()
+                  } 
                 }}
                 onLoadedmetadata={(videoItem: any) => {
                   data.videoState = 'play'
@@ -914,52 +929,6 @@ export default defineComponent({
                       : {}
                   }
                 >
-                  {/* {m.type === 'VIDEO' && (
-                      <>
-                        <VideoPlay
-                          ref={(v: any) => (data.videoRefs[mIndex] = v)}
-                          item={m}
-                          isActive={activeEle}
-                          isEmtry={isEmtry}
-                          onPrepare={(val) => {
-                            m.isprepare = val
-                          }}
-                          onLoadedmetadata={(videoItem: any) => {
-                            m.videoEle = videoItem
-                          }}
-                          onTogglePlay={(paused: boolean) => {
-                            // console.log('播放切换', paused)
-                            if (!m.isprepare) {
-                              m.isprepare = true
-                            }
-                            m.autoPlay = false
-                            if (paused || popupData.open || popupData.guideOpen) {
-                              clearTimeout(activeData.timer)
-                            } else {
-                              setModelOpen()
-                            }
-                          }}
-                          onEnded={() => {
-                            const _index = popupData.activeIndex + 1
-                            if (_index < data.itemList.length) {
-                              handleSwipeChange(_index)
-                            }
-                          }}
-                          onReset={() => {
-                            if (!m.videoEle?.paused) {
-                              setModelOpen()
-                            }
-                          }}
-                        />
-                        <Transition name="van-fade">
-                          {!m.isprepare && (
-                            <div class={styles.loadWrap}>
-                              <Vue3Lottie animationData={playLoadData}></Vue3Lottie>
-                            </div>
-                          )}
-                        </Transition>
-                      </>
-                    )} */}
                   <Transition name="van-fade">
                     {m.typeCode === 'VIDEO' &&
                       data.animationState !== 'end' &&
@@ -1007,7 +976,7 @@ export default defineComponent({
               )
             })}
           </div>
-          <Transition name="right">
+          {/* <Transition name="right">
             {activeData.model && (
               <div
                 class={styles.rightFixedBtns}
@@ -1027,13 +996,6 @@ export default defineComponent({
                 </div>
 
                 <div class={[styles.btnsWrap, styles.btnsBottom]}>
-                  {/* <div
-                    class={styles.fullBtn}
-                    onClick={() => (popupData.guideOpen = true)}
-                  >
-                    <img src={iconTouping} />
-                    <span>投屏</span>
-                  </div> */}
                   {data.isCourse && (
                     <>
                       <div
@@ -1055,7 +1017,7 @@ export default defineComponent({
                 </div>
               </div>
             )}
-          </Transition>
+          </Transition> */}
 
           <Transition name="left">
             {activeData.model && (
@@ -1063,48 +1025,84 @@ export default defineComponent({
                 class={styles.leftFixedBtns}
                 onClick={(e: Event) => e.stopPropagation()}
               >
-                {popupData.activeIndex != 0 && (
-                  <div class={[styles.btnsWrap, styles.prePoint]}>
+
+                <div class={[styles.btnsWrap, styles.prePoint]}>
+                  <div class={styles.fullBtn} onClick={() => {
+                    handleStop()
+                    popupData.coursewareOpen = true
+                  }}>
+                    <img src={iconCourseType} />
+                  </div>
+                  <div class={styles.fullBtn} onClick={() => {
+                    handleStop()
+                    popupData.open = true
+                  }}>
+                    <img src={iconMenu} />
+                    {/* <span>知识点</span> */}
+                  </div>
+                  
                     <div
-                      class={styles.fullBtn}
+                      class={[styles.fullBtn, !(popupData.activeIndex != 0) && styles.disabled]}
                       onClick={() => {
-                        // useThrottleFn(() => {
-                        //   handlePreAndNext('up')
-                        // }, 300)
-                        // onChangeSwiper('up')
-                        handlePreAndNext('up')
+                        if(popupData.activeIndex != 0) handlePreAndNext('up')
                       }}
                     >
                       <img src={iconUp} />
-                      <span style={{ textAlign: 'center' }}>上一个</span>
+                      {/* <span style={{ textAlign: 'center' }}>上一个</span> */}
                     </div>
-                  </div>
-                )}
-                {popupData.activeIndex != data.itemList.length - 1 && (
-                  <div class={styles.btnsWrap}>
                     <div
-                      class={styles.fullBtn}
+                      class={[styles.fullBtn, !(popupData.activeIndex != data.itemList.length - 1) && styles.disabled]}
                       onClick={() => {
-                        // console.log('click down')
-                        // useThrottleFn(() => {
-                        //   console.log('click down pass')
-                        //   handlePreAndNext('down')
-                        // }, 300)
-                        // onChangeSwiper('down')
-                        handlePreAndNext('down')
+                        if(popupData.activeIndex != data.itemList.length - 1) handlePreAndNext('down')
                       }}
                     >
-                      <span style={{ textAlign: 'center' }}>下一个</span>
+                      {/* <span style={{ textAlign: 'center' }}>下一个</span> */}
                       <img src={iconDown} />
                     </div>
-                  </div>
-                )}
+                 </div>
               </div>
             )}
           </Transition>
         </div>
 
+
         <div
+            style={{ transform: activeData.model ? '' : 'translateY(-100%)' }}
+            id="coursePlayHeader"
+            class={styles.headerContainer}
+            ref={headeRef}
+          >
+            <div class={styles.backBtn}>
+              <Icon name={iconBack} onClick={() => {
+                goback()
+              }} />
+              <div class={styles.titleSection}>
+                <div class={styles.title}>{popupData.tabName}</div>
+                <div class={styles.titleContent}>
+                  <p>{data.itemList[popupData.activeIndex]?.name}</p>
+                  {data.detail?.lessonTargetDesc ? <span onClick={() => onTitleTip('phaseGoals', data.detail?.lessonTargetDesc)}>阶段目标</span>: ""}
+                  {data.itemList[popupData.activeIndex]?.checkItem ? <span onClick={() => onTitleTip('checkItem', data.itemList[popupData.activeIndex]?.checkItem)}>检查事项</span> : ""}
+                </div>
+              </div>
+            </div>
+            {state.platformType === 'TEACHER' && (
+              <div
+                class={styles.headRight}
+                onClick={(e: Event) => {
+                  e.stopPropagation()
+                  clearTimeout(activeData.timer)
+                }}
+              >
+                <div class={styles.rightBtn} onClick={() => {
+                  handleStop()
+                  popupData.guideOpen = true
+                }}>
+                  <img src={iconTouping} />
+                </div>
+              </div>
+            )}
+          </div>
+        {/* <div
           style={{ transform: activeData.model ? '' : 'translateY(-100%)' }}
           id="coursePlayHeader"
           class={styles.headerContainer}
@@ -1112,11 +1110,7 @@ export default defineComponent({
         >
           <div class={styles.backBtn} onClick={() => goback()}>
             <Icon name={iconBack} />
-            返回
           </div>
-          {data.isCourse && (
-            <PlayRecordTime ref={playRef} list={data.knowledgePointList} />
-          )}
           <div
             class={styles.menu}
             onClick={() => {
@@ -1129,37 +1123,8 @@ export default defineComponent({
             {popupData.tabName}
           </div>
 
-          {state.platformType === 'TEACHER' && (
-            <div
-              class={styles.headRight}
-              onClick={(e: Event) => {
-                e.stopPropagation()
-                clearTimeout(activeData.timer)
-              }}
-            >
-              {/* <div
-                class={styles.rightBtn}
-                onClick={() => (popupData.guideOpen = true)}
-              >
-                <img src={iconTouping} />
-              </div> */}
-              {/* <div
-                class={styles.rightBtn}
-                onClick={() => {
-                  openStudyTool({
-                    type: 'pen',
-                    icon: iconPen,
-                    name: '批注'
-                  });
-                }}>
-                <img src={iconPen} />
-              </div> */}
-              {/* <div class={styles.rightBtn} onClick={() => (popupData.toolOpen = true)}>
-                <img src={iconMore} />
-              </div> */}
-            </div>
-          )}
-        </div>
+          
+        </div> */}
 
         {/* 更多弹窗 */}
         <Popup
@@ -1174,8 +1139,7 @@ export default defineComponent({
         </Popup>
 
         <Popup
-          class={styles.popup}
-          style={{ background: 'rgba(0,0,0, 0.7)' }}
+          class={[styles.popup, styles.popupCoursewarePlay]}
           overlayClass={styles.overlayClass}
           position="right"
           round
@@ -1195,7 +1159,37 @@ export default defineComponent({
         </Popup>
 
         <Popup
-          class={styles.popup}
+          class={[styles.popup, styles.popupCoursewarePlay]}
+          overlayClass={styles.overlayClass}
+          position="right"
+          round
+          v-model:show={popupData.coursewareOpen}
+          onClose={handleClosePopup}>
+            {/* 课件类型 */}
+            <CoursewareType list={data.refLevelList} onConfirm={async (item: any) => {
+              // 判断是否为当前课程类型
+              if(data.currentId === item.id) {
+                return
+              }
+              data.currentId = item.id;
+              const n = await getDetail(item.id);
+              const s = await getRefLevel(item.id);
+              if(n && s) {
+                popupData.coursewareOpen = false;
+                popupData.activeIndex = 0;
+                nextTick(() => {
+                  popupData.open = true
+                })
+              } else {
+                if(!isOnline.value) {
+                  Toast('网络异常')
+                }
+              }
+            }} />
+        </Popup>
+
+        <Popup
+          class={[styles.popup, styles.popupCoursewarePlay]}
           overlayClass={styles.overlayClass}
           position="right"
           round
@@ -1205,9 +1199,18 @@ export default defineComponent({
           <OGuide />
         </Popup>
 
-        {studyData.penShow && (
-          <Pen show={studyData.type === 'pen'} close={() => closeStudyTool()} />
-        )}
+        <Popup
+          class={[styles.popup, styles.popupPoint]}
+          round
+          style={{ background: 'transparent !important' }}
+          v-model:show={popupData.pointOpen}
+          onClose={handleClosePopup}>
+          <CoursewareTips onClose={() => {
+            popupData.pointOpen = false
+          }} content={popupData.pointContent} titleName={popupData.pointTitle} />
+        </Popup>
+
+        <GlobalTools />
       </div>
     )
   }

Some files were not shown because too many files changed in this diff