Browse Source

Merge branch 'hqyDev' of http://git.dayaedu.com/lex/classroom-instruments into online

黄琪勇 3 months ago
parent
commit
bc0ae23199

+ 1 - 1
dev-dist/sw.js

@@ -82,7 +82,7 @@ define(['./workbox-88bf3160'], (function (workbox) { 'use strict';
     "revision": "3ca0b8505b4bec776b69afdba2768812"
   }, {
     "url": "index.html",
-    "revision": "0.07uic5uubv8"
+    "revision": "0.4v8s4holqi"
   }], {});
   workbox.cleanupOutdatedCaches();
   workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {

+ 1 - 1
index.html

@@ -16,7 +16,7 @@
   <meta name="viewport" content="width=device-width,initial-scale=1.0">
   <meta name="apple-mobile-web-app-capable" content="yes" />
   <!-- 自动将HTTP请求升级成安全的HTTPS请求 -->
-  <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />
+  <!-- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" /> -->
   <!-- 设置苹果工具栏颜色 -->
   <meta name="apple-mobile-web-app-status-bar-style" content="black" />
   <!-- 忽略页面中的数字识别为电话,忽略email识别 -->

+ 5 - 1
public/version.json

@@ -1 +1,5 @@
-{"version":1734688888992}
+<<<<<<< HEAD
+{"version":1734688888992}
+=======
+{"version":1734921568773}
+>>>>>>> dafbc000b30a4310271ed07e72508665b517fda8

+ 1 - 1
src/utils/contants.ts

@@ -27,7 +27,7 @@ export const resourceType = {
   IMG: '图片',
   SONG: '音频',
   VIDEO: '视频',
-  PPT: 'PPT'
+  // PPT: 'PPT'
 };
 
 /**

+ 16 - 0
src/utils/urlUtils.ts

@@ -33,3 +33,19 @@ export function vaildMusicScoreUrl() {
   }
   return returnUrl;
 }
+
+export function vaildPPTUrl() {
+  const url: string = window.location.hostname;
+  let returnUrl = '';
+
+  if (/test/.test(url)) {
+    returnUrl = 'https://test.kt.colexiu.com/classroom-ppt';
+  } else if (/dev/.test(url)) {
+    returnUrl = 'https://dev.kt.colexiu.com/classroom-ppt';
+  } else if (/localhost/.test(url)) {
+    returnUrl = 'http://192.168.3.122:9527';
+  } else {
+    returnUrl = 'https://mec.colexiu.com/classroom-ppt';
+  }
+  return returnUrl;
+}

+ 13 - 0
src/views/attend-class/component/pptList.module.less

@@ -0,0 +1,13 @@
+.pptList {
+  position: relative;
+  width: 100%;
+  height: 100%;
+  .container {
+    position: relative;
+    display: block;
+    border: none;
+    width: 100%;
+    height: 100%;
+    z-index: 10;
+  }
+}

+ 62 - 0
src/views/attend-class/component/pptList.tsx

@@ -0,0 +1,62 @@
+import { defineComponent, ref, onMounted, onUnmounted } from 'vue';
+import styles from './pptList.module.less';
+import { vaildPPTUrl } from '/src/utils/urlUtils';
+import { useUserStore } from '/src/store/modules/users';
+
+export default defineComponent({
+  name: 'pptList',
+  props: {
+    pptData: {
+      type: Object,
+      default: () => ({})
+    },
+    fromType: {
+      type: String, // 'PLATFORM' | 'TEACHER' | 'CLASS'
+      default: 'TEACHER'
+    }
+  },
+  emits: ['initPPT', 'changeSlideIndex'],
+  setup(props, { emit, expose }) {
+    const userStore = useUserStore();
+    const iframeRef = ref<HTMLIFrameElement>();
+    const src = `${vaildPPTUrl()}/#/pptScreen?id=${
+      props.pptData.id
+    }&Authorization=${userStore.getToken}&hideFullScreen=true&fromType=${
+      props.fromType
+    }`;
+    // 上一页下一页
+    function handleChangeSlide(type: 'prev' | 'next') {
+      iframeRef.value?.contentWindow?.postMessage(
+        { type: 'changePageSlide', content: type },
+        '*'
+      );
+    }
+    function handleMessage(event: any) {
+      const { type, content } = event.data || {};
+      console.log(content, 'message');
+      if (type === 'initPPT') {
+        emit('initPPT', content);
+      } else if (type === 'changeSlideIndex') {
+        emit('changeSlideIndex', content);
+      }
+    }
+    onMounted(() => {
+      window.addEventListener('message', handleMessage);
+    });
+    onUnmounted(() => {
+      window.removeEventListener('message', handleMessage);
+    });
+    expose({
+      handleChangeSlide
+    });
+    return () => (
+      <div class={styles.pptList}>
+        <iframe
+          ref={iframeRef}
+          class={[styles.container]}
+          frameborder="0"
+          src={src}></iframe>
+      </div>
+    );
+  }
+});

+ 3 - 0
src/views/attend-class/index.module.less

@@ -643,6 +643,9 @@
     opacity: 0.7;
     cursor: not-allowed;
   }
+  .hideBtn {
+    display: none;
+  }
 }
 
 :global {

+ 75 - 17
src/views/attend-class/index.tsx

@@ -13,6 +13,7 @@ import {
 import styles from './index.module.less';
 import 'plyr/dist/plyr.css';
 import MusicScore from './component/musicScore';
+import PptList from './component/pptList';
 // import iconChange from './image/icon-change.png';
 // import iconMenu from './image/icon-menu.png';
 // import iconUp from './image/icon-up.png';
@@ -214,8 +215,15 @@ export default defineComponent({
       selectResourceStatus: false,
       videoState: 'init' as 'init' | 'play',
       videoItemRef: null as any,
-      animationState: 'start' as 'start' | 'end'
+      animationState: 'start' as 'start' | 'end',
+      coursewareType: 'CLASSIC' as 'CLASSIC' | 'PPT' // 课件类型
     });
+    const pptData = reactive({
+      pptEl: null as any,
+      slidesLen: 1,
+      activeLen: 0
+    });
+
     const activeData = reactive({
       isAutoPlay: false, // 是否自动播放
       nowTime: 0,
@@ -236,7 +244,7 @@ export default defineComponent({
         const res = await api_teacherChapterLessonCoursewareDetail(
           data.courseId
         );
-
+        data.coursewareType = res.data.coursewareType || 'CLASSIC';
         data.teacherChapterName = res.data.name || '';
         // 布置的作业编号
         data.lessonPreTrainingId = res.data.lessonPreTrainingId;
@@ -876,6 +884,19 @@ export default defineComponent({
 
     // 上一个知识点, 下一个知识点
     const handlePreAndNext = async (type: string) => {
+      // 这里新加了ppt 逻辑所以需要
+      if (data.coursewareType === 'PPT') {
+        if (type === 'up' && pptData.activeLen > 0) {
+          pptData.pptEl?.handleChangeSlide('prev');
+          return;
+        } else if (
+          type === 'down' &&
+          pptData.activeLen < pptData.slidesLen - 1
+        ) {
+          pptData.pptEl?.handleChangeSlide('next');
+          return;
+        }
+      }
       if (type === 'up') {
         // 判断上面是否还有章节
         if (popupData.activeIndex > 0) {
@@ -1140,6 +1161,11 @@ export default defineComponent({
 
     // 是否允许上一页
     const isUpArrow = computed(() => {
+      if (data.coursewareType === 'PPT') {
+        if (pptData.activeLen > 0) {
+          return true;
+        }
+      }
       /**
        * 1,判断当前课程中是否处在第一个资源;
        * 2,判断当前课程是否在当前章节的第一个;
@@ -1209,6 +1235,11 @@ export default defineComponent({
 
     // 是否允许下一页
     const isDownArrow = computed(() => {
+      if (data.coursewareType === 'PPT') {
+        if (pptData.activeLen < pptData.slidesLen - 1) {
+          return true;
+        }
+      }
       if (popupData.activeIndex < data.itemList.length - 1) {
         return true;
       }
@@ -1360,23 +1391,26 @@ export default defineComponent({
       //   id: 6
       // }
     ];
-    const mirrorAddressCatch = (type: 'get' | 'set'  = 'get', value?: string): any => {
+    const mirrorAddressCatch = (
+      type: 'get' | 'set' = 'get',
+      value?: string
+    ): any => {
       const localStorageName = 'mirrorAddressCatch';
-      
-      if(type === "get") {
-        const catchName = localStorage.getItem(localStorageName)
-        return catchName || null
-      } else if(type === "set") {
-        localStorage.setItem(localStorageName, value || '')
+
+      if (type === 'get') {
+        const catchName = localStorage.getItem(localStorageName);
+        return catchName || null;
+      } else if (type === 'set') {
+        localStorage.setItem(localStorageName, value || '');
       }
-    }
+    };
     // 默认收起菜单
     const columnShow = ref(true);
     // 菜单位置
     const columnPos = ref<'left' | 'right'>('left');
 
-    if(mirrorAddressCatch()) {
-      columnPos.value = mirrorAddressCatch()
+    if (mirrorAddressCatch()) {
+      columnPos.value = mirrorAddressCatch();
     }
 
     watch(columnPos, () => {
@@ -1920,7 +1954,7 @@ export default defineComponent({
                           activeStatus={popupData.activeIndex === mIndex}
                           ref={(el: any) => (m.iframeRef = el)}
                         />
-                      ) : (
+                      ) : m.type === 'MUSIC' ? (
                         <MusicScore
                           activeModel={activeData.model}
                           instrumentId={data.instrumentId}
@@ -1932,6 +1966,18 @@ export default defineComponent({
                             m.iframeRef = el;
                           }}
                         />
+                      ) : (
+                        <PptList
+                          ref={el => {
+                            pptData.pptEl = el;
+                          }}
+                          onInitPPT={({ slidesLen }) => {
+                            pptData.slidesLen = slidesLen;
+                          }}
+                          onChangeSlideIndex={({ slideIndex }) => {
+                            pptData.activeLen = slideIndex;
+                          }}
+                          pptData={m}></PptList>
                       )}
                     </div>
                   ) : null;
@@ -1952,7 +1998,13 @@ export default defineComponent({
               : styles.rightColumnHide
           ]}>
           {rightList.map((item: any) => (
-            <div class={styles.columnItemBox}>
+            <div
+              class={[
+                styles.columnItemBox,
+                item.id === 14 && data.coursewareType === 'PPT'
+                  ? styles.hideBtn
+                  : ''
+              ]}>
               <div
                 class={[
                   styles.columnItem,
@@ -2011,7 +2063,7 @@ export default defineComponent({
                 onClick={() => {
                   columnPos.value = 'right';
                   columnShow.value = true;
-                  mirrorAddressCatch('set', 'right')
+                  mirrorAddressCatch('set', 'right');
                 }}
               />
             ),
@@ -2027,7 +2079,13 @@ export default defineComponent({
               : styles.leftColumnHide
           ]}>
           {rightList.map((item: any) => (
-            <div class={styles.columnItemBox}>
+            <div
+              class={[
+                styles.columnItemBox,
+                item.id === 14 && data.coursewareType === 'PPT'
+                  ? styles.hideBtn
+                  : ''
+              ]}>
               <div
                 class={[
                   styles.columnItem,
@@ -2079,7 +2137,7 @@ export default defineComponent({
                 onClick={() => {
                   columnPos.value = 'left';
                   columnShow.value = true;
-                  mirrorAddressCatch('set', 'left')
+                  mirrorAddressCatch('set', 'left');
                 }}
               />
             ),

+ 2 - 1
src/views/attend-class/model/select-class/index.tsx

@@ -58,7 +58,8 @@ export default defineComponent({
             fromChapterLessonCoursewareId: item.fromChapterLessonCoursewareId,
             name: item.name,
             coverImg: firstItem?.bizInfo.coverImg,
-            type: firstItem?.bizInfo.type
+            type: firstItem?.bizInfo.type,
+            coursewareType: item.coursewareType
           });
         });
         forms.tableList = tempList;

+ 6 - 4
src/views/natural-resources/components/my-resources/save-modal/index.tsx

@@ -108,8 +108,8 @@ export default defineComponent({
         'jpeg',
         'png',
         'mp4',
-        'ppt',
-        'pptx',
+        // 'ppt',
+        // 'pptx',
         'mp3'
       ];
       if (!isAllowedFileType(file.file.name, allowedExtensions)) {
@@ -430,7 +430,8 @@ export default defineComponent({
           // }}
           customRequest={onCustomRequest}
           v-model:fileList={fileListRef.value}
-          accept=".jpg,jpeg,.png,audio/mp3,video/mp4,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation"
+          // accept=".jpg,jpeg,.png,audio/mp3,video/mp4,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation"
+          accept=".jpg,jpeg,.png,audio/mp3,video/mp4"
           multiple={true}
           max={10}
           // disabled={props.disabled}
@@ -446,7 +447,8 @@ export default defineComponent({
               <div class={styles.iconUploadAdd} />
               <h3>点击或者拖动文件到该区域来上传</h3>
               <p>
-                仅支持JPG、PNG、MP3、MP4、PPT格式文件,单次最多支持
+                {/* 仅支持JPG、PNG、MP3、MP4、PPT格式文件,单次最多支持 */}
+                仅支持JPG、PNG、MP3、MP4,单次最多支持
                 <br />
                 上传10个文件
               </p>

+ 15 - 6
src/views/prepare-lessons/api.ts

@@ -289,6 +289,18 @@ export const api_teacherChapterLessonCoursewareDetail = (id: string) => {
 };
 
 /**
+ * 平台课件转老师课件
+ */
+export const api_coursewareToTeacherCourseware = (id: string) => {
+  return request.post(
+    '/edu-app/teacherChapterLessonCourseware/coursewareToTeacherCourseware',
+    {
+      data: { id }
+    }
+  );
+};
+
+/**
  *  @description: 素材详情
  * @param params
  */
@@ -296,7 +308,6 @@ export const api_materialDetail = (id: string) => {
   return request.get('/edu-app/material/detail/' + id);
 };
 
-
 /**
  *  @description: 老师查询教材分类
  * @param params
@@ -305,17 +316,15 @@ export const api_lessonCoursewareTeacherCategory = () => {
   return request.get('/edu-app/lessonCourseware/teacherCategory');
 };
 
-
-
 /**
  *  @description: 备课页面检测声部
  * @param params
  */
 export const api_courseScheduleCheck = (params: {
-  classGroupId: string
-  chapterLessonCoursewareId: string
+  classGroupId: string;
+  chapterLessonCoursewareId: string;
 }) => {
   return request.post('/edu-app/courseSchedule/check', {
     data: params
   });
-};
+};

+ 5 - 5
src/views/prepare-lessons/components/lesson-main/courseware-head/index.tsx

@@ -17,7 +17,7 @@ export default defineComponent({
   name: 'courseware-head',
   setup(props, { emit, expose }) {
     const prepareStore = usePrepareStore();
-    // 第一个课件标题,第二个课件声部
+    // 第一个课件名称,第二个课件声部
     const checkForms = ref<any[]>(['', '']);
     const subjectList = ref([] as any);
     const forms = reactive({
@@ -72,7 +72,7 @@ export default defineComponent({
     };
 
     const updateSubjectList = (ids?: any[]) => {
-      // 获取课件乐器编号 ,修改的乐器编号,集合
+      // 获取适用乐器编号 ,修改的乐器编号,集合
       ids = ids || [];
       const courseIds: any = [];
       prepareStore.getInstrumentList.forEach((item: any) => {
@@ -142,10 +142,10 @@ export default defineComponent({
         <div class={styles.formContainer}>
           <div class={[styles.btnItem, styles.block]}>
             <span class={[styles.btnTitle]}>
-              <span>*</span>课件标题
+              <span>*</span>课件名称
             </span>
             <NInput
-              placeholder="请输入课件标题"
+              placeholder="请输入课件名称"
               v-model:value={forms.name}
               maxlength={20}
               clearable
@@ -158,7 +158,7 @@ export default defineComponent({
           </div>
           <div class={[styles.btnItem, styles.block]}>
             <span class={[styles.btnTitle]}>
-              <span>*</span>课件乐器
+              <span>*</span>适用乐器
             </span>
             <NCascader
               status={checkForms.value[1]}

+ 85 - 1
src/views/prepare-lessons/components/lesson-main/courseware-presets/index.module.less

@@ -56,6 +56,28 @@
   .presetsLeft {
     flex: 1;
     transition: all .1s ease;
+    .popoverItem {
+      font-weight: 600;
+      font-size: max(16px, 12Px);
+      width: 120px;
+      height: 36px;
+      color: #484F59;
+      border-radius: 8px;
+      text-align: center;
+      line-height: 36px;
+      cursor: pointer;
+      &:hover {
+        background: #F5F6FA;
+      }
+    }
+
+    :global {
+      .n-popover {
+        box-shadow: 0px 2px 12px 0px rgba(0,0,0,0.1);
+        border-radius: 10px;
+        padding: 8px 6px !important;
+      }
+    }
   }
 
   .presetsRight {
@@ -441,4 +463,66 @@
       background: url('@/views/prepare-lessons/images/icon-arrow-2.png') no-repeat center center / contain;
     }
   }
-}
+}
+
+.pptCoursewareModal{
+  width: 486px;
+  :global{
+    .n-card-header{
+      background: #F5F6FA;
+    }
+    .n-card__content{
+      padding: 30px;
+      .n-form-item .n-form-item-label{
+        color: #666666;
+        .n-form-item-label__text{
+          font-size: max(18px, 13Px);
+        }
+      }
+    }
+  }
+  .updateBtnGroup {
+    padding: 0;
+    justify-content: center !important;
+    :global {
+      .n-button {
+        height: 48px !important;
+        min-width: 156px;
+      }
+    }
+  }
+  .btnItem {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin-bottom: 38px;
+
+    &.block {
+      flex-direction: column;
+      align-items: flex-start;
+
+      .btnTitle {
+        padding-bottom: 8px;
+      }
+    }
+
+    .btnTitle {
+      flex-shrink: 0;
+      font-size: max(18px, 13Px);
+      font-weight: 400;
+      display: flex;
+      align-items: center;
+      color: #666666;
+    }
+
+    .iconQuestion {
+      display: inline-block;
+      margin-left: 6px;
+      width: 13Px;
+      height: 14Px;
+      background: url('../../../images/icon-question.png') no-repeat center;
+      background-size: contain;
+      cursor: pointer;
+    }
+  }
+}

+ 372 - 56
src/views/prepare-lessons/components/lesson-main/courseware-presets/index.tsx

@@ -18,7 +18,14 @@ import {
   NTabPane,
   NTabs,
   useMessage,
-  NPopselect
+  NPopselect,
+  NPopover,
+  NForm,
+  NFormItem,
+  NInput,
+  NSpace,
+  NCascader,
+  NSwitch
 } from 'naive-ui';
 import { usePrepareStore } from '/src/store/modules/prepareLessons';
 import add from '@/views/studentList/images/add.png';
@@ -43,6 +50,15 @@ import PreviewWindow from '/src/views/preview-window';
 import Related from './related';
 import Train from '../train';
 import ResourceMain from '../../resource-main';
+import { useCatchStore } from '/src/store/modules/catchData';
+import deepClone from '/src/helpers/deep-clone';
+import {
+  api_teacherChapterLessonCoursewareAdd,
+  api_coursewareToTeacherCourseware,
+  api_updateCoursewareInfo
+} from '../../../api';
+import { vaildPPTUrl } from '/src/utils/urlUtils';
+import { useUserStore } from '/src/store/modules/users';
 
 export default defineComponent({
   name: 'courseware-presets',
@@ -103,7 +119,7 @@ export default defineComponent({
       workVisiable: false,
       wikiCategoryIdChild: null,
       instrumentErrorVisiable: false,
-      instrumentErrorContent: ""
+      instrumentErrorContent: ''
     });
 
     const getCoursewareList = async () => {
@@ -137,7 +153,11 @@ export default defineComponent({
             name: item.name,
             coverImg: firstItem && firstItem[0]?.bizInfo.coverImg,
             type: firstItem && firstItem[0]?.bizInfo.type,
-            isNotWork: item.lessonPreTrainingNum <= 0 ? true : false // 是否布置作业
+            isNotWork: item.lessonPreTrainingNum <= 0 ? true : false, // 是否布置作业
+            coursewareType: item.coursewareType,
+            instrumentIds: item.instrumentIds,
+            pptId: firstItem && firstItem[0]?.id,
+            teacherSaveFlag: item.teacherSaveFlag
           });
         });
         forms.tableList = tempList;
@@ -422,43 +442,37 @@ export default defineComponent({
     };
 
     /** 上课前检测声部 */
-    const onClassCheckInstrument = async (item: any,
+    const onClassCheckInstrument = async (
+      item: any,
       classGroupId: any,
-      instrumentId?: any) => {
-        
+      instrumentId?: any
+    ) => {
       try {
-        if(classGroupId) {
-          const {data} = await api_courseScheduleCheck({
+        if (classGroupId) {
+          const { data } = await api_courseScheduleCheck({
             classGroupId,
             chapterLessonCoursewareId: item.id
-          })
+          });
           forms.attendClassItem = item;
           forms.attendClassId = classGroupId;
-          if(!data.chapterLessonCoursewareFlag) {
+          if (!data.chapterLessonCoursewareFlag) {
             forms.instrumentErrorVisiable = true;
-            forms.instrumentErrorContent = '课件支持的乐器与班级不符,是否继续使用该课件上课?'
-          } else if(!data.materialFlag) {
+            forms.instrumentErrorContent =
+              '课件支持的乐器与班级不符,是否继续使用该课件上课?';
+          } else if (!data.materialFlag) {
             forms.instrumentErrorVisiable = true;
-            forms.instrumentErrorContent = '课件中含有不符合班级乐器的资源,是否继续使用该课件上课?'
+            forms.instrumentErrorContent =
+              '课件中含有不符合班级乐器的资源,是否继续使用该课件上课?';
           } else {
-            onStartClass(
-              item,
-              classGroupId,
-              instrumentId
-            );
+            onStartClass(item, classGroupId, instrumentId);
           }
         } else {
-          onStartClass(
-            item,
-            classGroupId,
-            instrumentId
-          );
+          onStartClass(item, classGroupId, instrumentId);
         }
-        
       } catch {
-        // 
+        //
       }
-    }
+    };
 
     const selectChildObj = (item: any) => {
       const obj: any = {};
@@ -487,6 +501,151 @@ export default defineComponent({
       });
       return instrumentId;
     });
+    /* ppt课件 */
+    const userStore = useUserStore();
+    const pptCourseware = reactive({
+      pptCoursewareShow: false,
+      id: '',
+      name: '',
+      subjects: [],
+      openFlagEnable: true,
+      openFlag: false
+    });
+    const pptFormsRef = ref();
+    const subjectList = ref<any[]>([]);
+    const updateSubjectList = (ids?: any[]) => {
+      // 获取适用乐器编号 ,修改的乐器编号,集合
+      ids = ids || [];
+      const courseIds: any = [];
+      prepareStore.getInstrumentList.forEach((item: any) => {
+        if (Array.isArray(item.instruments)) {
+          item.instruments.forEach((child: any) => {
+            courseIds.push(child.id);
+          });
+        }
+      });
+      const allIds = [...new Set([...courseIds, ...ids])];
+
+      const tempList: any = [];
+      useCatchStore().getSubjectList.forEach((item: any) => {
+        const temp = deepClone(item);
+        temp.enableFlag = false;
+        if (Array.isArray(temp.instruments)) {
+          temp.instruments.forEach((child: any) => {
+            child.enableFlag = false;
+            if (allIds.includes(child.id)) {
+              child.enableFlag = true;
+              temp.enableFlag = true;
+            }
+          });
+        }
+        tempList.push(temp);
+      });
+      const tempSubjects: any[] = [];
+      tempList.forEach((subject: any) => {
+        if (subject.enableFlag) {
+          const { instruments, ...r } = subject;
+
+          if (instruments && instruments.length > 0) {
+            const tempChild: any[] = [];
+            instruments?.forEach((instrument: any) => {
+              if (instrument.enableFlag) {
+                tempChild.push(instrument);
+              }
+            });
+
+            if (tempChild.length > 0)
+              tempSubjects.push({ ...r, instruments: tempChild });
+          }
+        }
+      });
+      subjectList.value = tempSubjects;
+    };
+    const chioseAll = (list: any) => {
+      // 全选
+      const ids = [] as any;
+      list.map((item: any) => {
+        if (Array.isArray(item.instruments)) {
+          item.instruments.forEach((c: any) => {
+            ids.push(c.value);
+          });
+        }
+      }) as any;
+      pptCourseware.subjects = ids;
+    };
+    function handlePptConfirm() {
+      pptFormsRef.value?.validate(async (err: any) => {
+        if (err) {
+          return;
+        }
+        const { id, name, subjects, openFlag, openFlagEnable } = pptCourseware;
+        if (id) {
+          const params = {
+            id,
+            name,
+            instrumentIds: subjects.join(','),
+            openFlag,
+            autoPlay: false,
+            openFlagEnable
+          };
+          api_updateCoursewareInfo(params).then(res => {
+            if (res.code === 200) {
+              pptCourseware.pptCoursewareShow = false;
+              getCoursewareList();
+              eventGlobal.emit('openCoursewareChanged');
+            }
+          });
+        } else {
+          const params = {
+            name,
+            instrumentIds: subjects.join(','),
+            openFlag,
+            autoPlay: false,
+            coursewareDetailKnowledgeId: prepareStore.getSelectKey,
+            coursewareType: 'PPT'
+          };
+          api_teacherChapterLessonCoursewareAdd(params).then(res => {
+            if (res.code === 200) {
+              pptCourseware.pptCoursewareShow = false;
+              getCoursewareList();
+              eventGlobal.emit('openCoursewareChanged');
+              const { teacherSaveFlag, id, chapterKnowledgeList } = res.data;
+              handleRouterPPT({
+                teacherSaveFlag,
+                id,
+                pptId:
+                  chapterKnowledgeList[0]?.chapterKnowledgeMaterialList[0]?.id
+              });
+            }
+          });
+        }
+      });
+    }
+    function handlePptEdit(item: Record<string, any>) {
+      updateSubjectList();
+      pptCourseware.id = item.id;
+      pptCourseware.name = item.name;
+      pptCourseware.subjects = item.instrumentIds
+        ? item.instrumentIds.split(',')
+        : [];
+      pptCourseware.openFlag = item.openFlag;
+      pptCourseware.openFlagEnable = item.openFlagEnable;
+      pptCourseware.pptCoursewareShow = true;
+    }
+    async function handleRouterPPT(item: Record<string, any>) {
+      // 当teacherSaveFlag为false时候,需要把平台数据转为老师自己的课件
+      if (!item.teacherSaveFlag) {
+        await api_coursewareToTeacherCourseware(item.id);
+        item.teacherSaveFlag = true;
+      }
+      const href = `${vaildPPTUrl()}/#/pptEditor?id=${
+        item.pptId
+      }&Authorization=${userStore.getToken}`;
+      window.open(href);
+    }
+    onMounted(async () => {
+      await useCatchStore().getSubjects();
+    });
     return () => (
       <div
         class={[
@@ -527,23 +686,57 @@ export default defineComponent({
             }}
             v-slots={{
               suffix: () => (
-                <NButton
-                  class={styles.addBtn}
-                  type="primary"
-                  bordered={false}
-                  onClick={() => {
-                    eventGlobal.emit('teacher-slideshow', true);
-                    emit('change', {
-                      status: true,
-                      type: 'create'
-                    });
-                  }}>
-                  <NImage
-                    class={styles.addBtnIcon}
-                    previewDisabled
-                    src={add}></NImage>
-                  创建课件
-                </NButton>
+                <NPopover
+                  placement="bottom"
+                  trigger="hover"
+                  showArrow={false}
+                  to={false}
+                  duration={50}>
+                  {{
+                    trigger: () => (
+                      <NButton
+                        class={styles.addBtn}
+                        type="primary"
+                        bordered={false}>
+                        <NImage
+                          class={styles.addBtnIcon}
+                          previewDisabled
+                          src={add}></NImage>
+                        创建课件
+                      </NButton>
+                    ),
+                    default: () => (
+                      <div>
+                        <div
+                          class={styles.popoverItem}
+                          onClick={() => {
+                            eventGlobal.emit('teacher-slideshow', true);
+                            emit('change', {
+                              status: true,
+                              type: 'create'
+                            });
+                          }}>
+                          <span>数字化课件</span>
+                        </div>
+                        <div
+                          class={styles.popoverItem}
+                          onClick={() => {
+                            updateSubjectList();
+                            Object.assign(pptCourseware, {
+                              pptCoursewareShow: true,
+                              id: '',
+                              name: '',
+                              subjects: [],
+                              openFlagEnable: true,
+                              openFlag: false
+                            });
+                          }}>
+                          <span>PPT</span>
+                        </div>
+                      </div>
+                    )
+                  }}
+                </NPopover>
               )
             }}>
             {[
@@ -617,14 +810,23 @@ export default defineComponent({
                           //   forms.editTitle = item.name;
                           //   forms.editTitleVisiable = true;
                           // }}
-                          onEdit={() => {
+                          onEdit={type => {
                             //
-                            eventGlobal.emit('teacher-slideshow', true);
-                            emit('change', {
-                              status: true,
-                              type: 'update',
-                              groupItem: { id: item.id }
-                            });
+                            if (item.coursewareType === 'PPT') {
+                              if (type === 'PPT') {
+                                // 进入 ppt 编辑页面
+                                handleRouterPPT(item);
+                              } else {
+                                handlePptEdit(item);
+                              }
+                            } else {
+                              eventGlobal.emit('teacher-slideshow', true);
+                              emit('change', {
+                                status: true,
+                                type: 'update',
+                                groupItem: { id: item.id }
+                              });
+                            }
                           }}
                           onStartClass={() =>
                             onClassCheckInstrument(item, forms.classGroupId)
@@ -798,14 +1000,10 @@ export default defineComponent({
             contentDirection="left"
             onClose={() => {
               forms.instrumentErrorVisiable = false;
-              
             }}
             onConfirm={() => {
-              // 
-              onStartClass(
-                forms.attendClassItem,
-                forms.attendClassId
-              );
+              //
+              onStartClass(forms.attendClassItem, forms.attendClassId);
             }}
           />
         </NModal>
@@ -885,6 +1083,124 @@ export default defineComponent({
             </div>
           </div>
         </NModal>
+        {/* 新建ppt课件 */}
+        <NModal
+          maskClosable={modalClickMask}
+          v-model:show={pptCourseware.pptCoursewareShow}
+          preset="card"
+          class={['modalTitle', styles.pptCoursewareModal]}
+          title={'课件设置'}>
+          <NForm
+            ref={pptFormsRef}
+            model={pptCourseware}
+            labelAlign="right"
+            labelPlacement="left">
+            <NFormItem
+              label="课件名称"
+              path="name"
+              rule={[
+                {
+                  required: true,
+                  message: '请输入课件名称',
+                  trigger: ['blur', 'change']
+                }
+              ]}>
+              <NInput
+                placeholder="请输入课件名称"
+                v-model:value={pptCourseware.name}
+                maxlength={20}
+                clearable
+              />
+            </NFormItem>
+            <NFormItem
+              label="适用乐器"
+              path="subjects"
+              rule={[
+                {
+                  required: true,
+                  message: '请选择适用乐器',
+                  trigger: ['blur', 'change'],
+                  type: 'array'
+                }
+              ]}>
+              <NCascader
+                placeholder="请选择乐器(可多选)"
+                class={styles.btnSubjectList}
+                options={subjectList.value}
+                checkStrategy="child"
+                showPath={false}
+                childrenField="instruments"
+                expandTrigger="hover"
+                labelField="name"
+                valueField="id"
+                clearable
+                filterable
+                multiple
+                maxTagCount={1}
+                v-model:value={pptCourseware.subjects}
+                v-slots={{
+                  action: () => (
+                    <>
+                      <NButton
+                        text
+                        style=" --n-width: 100% "
+                        size="small"
+                        onClick={() => chioseAll(subjectList.value)}>
+                        全选
+                      </NButton>
+                    </>
+                  )
+                }}
+              />
+            </NFormItem>
+            <div class={styles.btnItem}>
+              <span class={styles.btnTitle}>
+                公开课件
+                <NTooltip style={{ maxWidth: '200px' }} showArrow={false}>
+                  {{
+                    trigger: () => <i class={styles.iconQuestion}></i>,
+                    default: () => '公开课件后,其它老师可以使用该课件上课'
+                  }}
+                </NTooltip>
+              </span>
+              {!pptCourseware.openFlagEnable ? (
+                <NTooltip style={{ maxWidth: '200px' }} showArrow={false}>
+                  {{
+                    trigger: () => (
+                      <NSwitch
+                        size="large"
+                        v-model:value={pptCourseware.openFlag}
+                        disabled={!pptCourseware.openFlagEnable}
+                      />
+                    ),
+                    default: () =>
+                      '为尊重课件原作者,在“相关课件”中添加的课件不支持公开'
+                  }}
+                </NTooltip>
+              ) : (
+                <NSwitch
+                  size="large"
+                  v-model:value={pptCourseware.openFlag}
+                  disabled={!pptCourseware.openFlagEnable}
+                />
+              )}
+            </div>
+            <NSpace class={styles.updateBtnGroup}>
+              <NButton
+                strong
+                type="default"
+                round
+                onClick={() => {
+                  pptCourseware.pptCoursewareShow = false;
+                }}>
+                取消
+              </NButton>
+              <NButton strong type="primary" round onClick={handlePptConfirm}>
+                确认
+              </NButton>
+            </NSpace>
+          </NForm>
+        </NModal>
       </div>
     );
   }

+ 1 - 1
src/views/prepare-lessons/components/lesson-main/courseware-presets/select-related/resource-search-group/index.tsx

@@ -25,7 +25,7 @@ export default defineComponent({
         <div class={styles.searchGroup}>
           <NInput
             type="text"
-            placeholder="请输入课件标题关键词"
+            placeholder="请输入课件名称关键词"
             clearable
             v-model:value={forms.keyword}
             class={styles.inputSearch}

+ 16 - 16
src/views/prepare-lessons/components/lesson-main/courseware/addCourseware.tsx

@@ -195,7 +195,7 @@ export default defineComponent({
     /** 检测当前素材是否包含所选声部 */
     const checkCurrentIsInstrument = (instruments: string, type: string, hasNotCheck = false) => {
       // 当前素材是否在选中的乐器里面
-      let isError = false 
+      let isError = false
       if(forms.subjects.length <= 0) {
         return true
       }
@@ -215,7 +215,7 @@ export default defineComponent({
     /** 检测之后的提示 */
     const checkCurrentInstrumentTip = (isError = false) => {
       if(isError) {
-        message.error('您添加的资源与课件乐器不符')
+        message.error('您添加的资源与适用乐器不符')
       } else {
         message.success('添加成功');
       }
@@ -286,12 +286,12 @@ export default defineComponent({
       } else if (type === 'save' || type === 'pageLive' || type === "checkInstrument") {
         if (forms.messageOperation.loading) return;
         if (!forms.name) {
-          message.error('请输入课件标题');
+          message.error('请输入课件名称');
           forms.messageOperation.visiable = false;
           return;
         }
         if (forms.subjects.length <= 0) {
-          message.error('请选择课件乐器');
+          message.error('请选择适用乐器');
           forms.messageOperation.visiable = false;
           return;
         }
@@ -415,7 +415,7 @@ export default defineComponent({
             forms.coursewareList[item.index || 0].list.push(m);
           });
           // if(item.isError) {
-          //   message.error('您添加的资源与课件乐器不符')
+          //   message.error('您添加的资源与适用乐器不符')
           // } else {
           //   message.success('添加成功');
           // }
@@ -465,7 +465,7 @@ export default defineComponent({
         forms.coursewareList[item.index || 0].list = array;
 
         if(item.isError) {
-          message.error('您添加的资源与课件乐器不符')
+          message.error('您添加的资源与适用乐器不符')
         }
 
         timer = setTimeout(() => {
@@ -509,7 +509,7 @@ export default defineComponent({
           loading: false,
           contentDirection: 'center',
           title: '温馨提示',
-          content: '课件中含有不符合课件乐器的资源,是否继续保存?',
+          content: '课件中含有不符合适用乐器的资源,是否继续保存?',
           cancelButtonText: '取消',
           confirmButtonText: '继续保存',
           index: 0
@@ -525,11 +525,11 @@ export default defineComponent({
         coursewareListRef.value.validate();
         eventGlobal.emit('checkCoursewareForm');
         if (!forms.name) {
-          message.error('请输入课件标题');
+          message.error('请输入课件名称');
           return;
         }
         if (forms.subjects.length <= 0) {
-          message.error('请选择课件乐器');
+          message.error('请选择适用乐器');
           return;
         }
         if (forms.coursewareList.length <= 0) {
@@ -627,7 +627,7 @@ export default defineComponent({
 
     const addItem = (item: any, point?: any) => {
       if(forms.subjects.length <= 0) {
-        message.error('请先选择课件乐器')
+        message.error('请先选择适用乐器')
         eventGlobal.emit('checkCoursewareForm', 'subject')
         return
       }
@@ -756,7 +756,7 @@ export default defineComponent({
       })
 
       if(isTips) {
-        message.error('您添加的资源与课件乐器不符')
+        message.error('您添加的资源与适用乐器不符')
       }
     }
 
@@ -780,7 +780,7 @@ export default defineComponent({
       // 保存
       eventGlobal.on('coursewareSave', onSubmitCourseware);
       eventGlobal.on('coursewareHeadSyncData', syncLeftFormData);
-      
+
     });
 
     onUnmounted(() => {
@@ -896,7 +896,7 @@ export default defineComponent({
                       if (dropItem.sourceForm === 'resource-item') {
                         if(forms.subjects.length <= 0) {
                           list.splice(evt.newDraggableIndex, 1)
-                          message.error('请先选择课件乐器')
+                          message.error('请先选择适用乐器')
                           eventGlobal.emit('checkCoursewareForm', 'subject')
                           return
                         }
@@ -1000,7 +1000,7 @@ export default defineComponent({
                               ]}
                               onClick={() => {
                                 if(forms.subjects.length <= 0) {
-                                  message.error('请先选择课件乐器')
+                                  message.error('请先选择适用乐器')
                                   eventGlobal.emit('checkCoursewareForm', 'subject')
                                   return
                                 }
@@ -1068,7 +1068,7 @@ export default defineComponent({
             onClose={() => (forms.addCoursewareVisiable = false)}
             onConfirm={(selects: number[]) => {
               if (Array.isArray(selects) && selects.length > 0) {
-                
+
                 selects.forEach(select => {
                   addCoursewareItem({
                     ...forms.addCoursewareItem,
@@ -1077,7 +1077,7 @@ export default defineComponent({
                 });
                 console.log(forms.addCoursewareItem, '----', forms.subjects)
                 forms.addCoursewareVisiable = false;
-               
+
                 checkCurrentInstrumentTip(forms.addCoursewareItem.isError)
               } else {
                 message.error('请选择需要添加的知识点');

BIN
src/views/prepare-lessons/images/setup.png


+ 24 - 12
src/views/prepare-lessons/model/courseware-type/index.module.less

@@ -139,18 +139,24 @@
       background: url('../../images/icon-no-work.png') no-repeat center;
       background-size: contain;
     }
-
-    .status {
+    .statusCon{
       position: absolute;
-      top: 7px;
-      left: 7px;
-      background: linear-gradient(226deg, #13BFFF 0%, #1183FF 100%);
-      border-radius: 4px;
-      font-weight: 600;
-      font-size: max(12px, 11Px);
-      color: #FFFFFF;
-      padding: 3px 10px;
+      top: 6px;
+      left: 6px;
       z-index: 9;
+      display: flex;
+      align-items: center;
+      .status {
+        background: rgba(0, 0, 0, 0.5);
+        border-radius: 4px;
+        font-weight: 600;
+        font-size: max(12px, 11Px);
+        color: #FFFFFF;
+        padding: 2px 10px;
+        & + .status {
+          margin-left: 8px;
+        }
+      }
     }
 
     :global {
@@ -420,7 +426,8 @@
   //   // }
   // }
   .iconEdit,
-  .iconDelete {
+  .iconDelete,
+  .iconSetup {
     display: inline-block;
     width: 24px;
     height: 24px;
@@ -431,6 +438,11 @@
     background-size: contain;
   }
 
+  .iconSetup {
+    background: url('../../images/setup.png') no-repeat center;
+    background-size: contain;
+  }
+
   .iconDelete {
     background: url('../../images/icon-courseware-delete.png') no-repeat center;
     background-size: contain;
@@ -514,4 +526,4 @@
     }
   }
 
-}
+}

+ 32 - 9
src/views/prepare-lessons/model/courseware-type/index.tsx

@@ -74,9 +74,15 @@ export default defineComponent({
             props.isShowAdd && styles.isShowAdd
           ]}
           onClick={() => emit('click')}>
-          {props.item.openFlag && props.isShowOpenFlag && (
-            <span class={styles.status}>公开</span>
-          )}
+          <div class={styles.statusCon}>
+            <div class={styles.status}>
+              {props.item.coursewareType === 'PPT' ? 'PPT' : '数字化课件'}
+            </div>
+            {props.isShowOpenFlag && props.item.openFlag && (
+              <div class={styles.status}>公开</div>
+            )}
+          </div>
+
           <NImage
             objectFit="cover"
             previewDisabled
@@ -158,12 +164,29 @@ export default defineComponent({
                     trigger: () => <div class={[styles.menu]}></div>,
                     default: () => (
                       <div class={styles.popoverList}>
-                        <div
-                          class={styles.popoverItem}
-                          onClick={() => emit('edit')}>
-                          <i class={styles.iconEdit}></i>
-                          <span>编辑课件</span>
-                        </div>
+                        {props.item.coursewareType === 'PPT' ? (
+                          <>
+                            <div
+                              class={styles.popoverItem}
+                              onClick={() => emit('edit', 'PPT')}>
+                              <i class={styles.iconEdit}></i>
+                              <span>编辑PPT</span>
+                            </div>
+                            <div
+                              class={styles.popoverItem}
+                              onClick={() => emit('edit')}>
+                              <i class={styles.iconSetup}></i>
+                              <span>课件设置</span>
+                            </div>
+                          </>
+                        ) : (
+                          <div
+                            class={styles.popoverItem}
+                            onClick={() => emit('edit')}>
+                            <i class={styles.iconEdit}></i>
+                            <span>编辑课件</span>
+                          </div>
+                        )}
                         <div
                           class={styles.popoverItem}
                           onClick={() => emit('delete')}>

+ 3 - 2
src/views/prepare-lessons/model/related-class/index.tsx

@@ -71,7 +71,8 @@ export default defineComponent({
             coverImg: firstItem?.bizInfo.coverImg,
             type: firstItem?.bizInfo.type,
             isAdd: item.addFlag,
-            isNotWork: item.lessonPreTrainingNum <= 0 ? true : false // 是否布置作业
+            isNotWork: item.lessonPreTrainingNum <= 0 ? true : false, // 是否布置作业
+            coursewareType: item.coursewareType
           });
         });
 
@@ -134,7 +135,7 @@ export default defineComponent({
             style={{ width: '200px' }}
           />
           <NInput
-            placeholder="请输入课件标题关键词"
+            placeholder="请输入课件名称关键词"
             clearable
             v-model:value={forms.searchGroup.keyword}
             onKeyup={(e: KeyboardEvent) => {