lex hai 1 ano
pai
achega
56014c52cd

+ 218 - 213
src/store/modules/catchData.ts

@@ -1,213 +1,218 @@
-import { defineStore } from 'pinia';
-import { store } from '@/store';
-import {
-  getSubjectList,
-  getSubjectList2,
-  getCategories,
-  api_musicalInstrumentList
-} from '@/api/user';
-
-export const useCatchStore = defineStore('catch-store', {
-  state: () => ({
-    bookVersionList: [] as any[], // 其它类型
-    musicTypeList: [] as any[], // 乐谱分类
-    subjectList: [] as any[], // 声部列表,
-    musicInstrumentList: [] as any[], // 乐器列表,
-    subjectInstruemnts: [] as any[] // 乐器列表,
-  }),
-  getters: {
-    getBookVersion(): any[] {
-      return this.bookVersionList;
-    },
-    getMusicCategories(): any[] {
-      return this.musicTypeList;
-    },
-    getMusicInstruments(): any[] {
-      return this.musicInstrumentList;
-    },
-    getAllMusicCategories(): any[] {
-      return [
-        {
-          name: '全部',
-          id: null
-        },
-        ...this.musicTypeList
-      ];
-    },
-    getSubjectList(): any[] {
-      return this.subjectList;
-    },
-    getSubjectAllList(): any[] {
-      return [
-        {
-          name: '全部',
-          id: null
-        },
-        ...this.subjectList
-      ];
-    },
-    /**
-     * 获取所有启用的声部
-     */
-    getEnableSubjects(): any[] {
-      const temp: any[] = [];
-      this.subjectList.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);
-              }
-            });
-
-            temp.push({ ...r, instruments: tempChild });
-          }
-        }
-      });
-      return temp;
-    },
-    getSubjectInstruments(): any[] {
-      return [
-        {
-          name: '全部',
-          id: null,
-          label: '全部',
-          value: null
-        },
-        ...this.subjectInstruemnts
-      ];
-    }
-  },
-  actions: {
-    setBookVersion(books: any[]) {
-      this.bookVersionList = books;
-    },
-    setMusicCategories(musics: any[]) {
-      this.musicTypeList = musics;
-    },
-    setSubjects(subjects: any[]) {
-      this.subjectList = subjects;
-    },
-    setSubjectInstruemnts(subjects: any[]) {
-      this.subjectInstruemnts = subjects;
-    },
-    setMusicInstruments(instruments: any[]) {
-      this.musicInstrumentList = instruments;
-    },
-    /**
-     * 判断是否有声部数据,如不存在则获取声部列表
-     * @returns Promise
-     */
-    async getSubjects() {
-      try {
-        // 判断是否存在声部数据
-        if (this.getSubjectList && this.getSubjectList.length > 0) {
-          return Promise.resolve();
-        }
-        const { data } = await getSubjectList2({
-          // enableFlag: true,
-          delFlag: 0,
-          page: 1,
-          rows: 999
-        });
-
-        const tempSubjectList = data || [];
-
-        const tempSubjectInstruments: any = [];
-        tempSubjectList.forEach((item: any) => {
-          item.value = item.id;
-          item.label = item.name;
-          if (item.instruments && item.instruments.length > 0) {
-            item.instruments.forEach((child: any) => {
-              child.label = child.name;
-              child.value = child.id;
-            });
-          }
-
-          const tempSi = {
-            value: item.id,
-            label: item.name,
-            id: item.id,
-            name: item.name,
-            instruments: [] as any
-          };
-          if (item.instruments) {
-            if (item.instruments.length == 1) {
-              tempSi.value = item.instruments[0].id;
-              tempSi.label = item.instruments[0].name;
-              tempSi.id = item.id;
-              tempSi.name = item.name;
-            } else if (item.instruments.length > 1) {
-              item.instruments.forEach((child: any) => {
-                child.label = child.name;
-                child.value = child.id;
-                tempSi.instruments.push({
-                  label: child.name,
-                  value: child.id,
-                  id: child.id,
-                  name: child.name
-                });
-              });
-            }
-          }
-          tempSubjectInstruments.push(tempSi);
-        });
-
-        this.setSubjects(tempSubjectList || []);
-        this.setSubjectInstruemnts(tempSubjectInstruments || []);
-        return Promise.resolve();
-      } catch (e) {
-        return Promise.reject(e);
-      }
-    },
-    /**
-     * 判断是否有教材分类数据,如不存在则获取教材分类列表
-     * @returns Promise
-     */
-    async getMusicSheetCategory() {
-      try {
-        // 判断是否存在声部数据
-        if (this.getMusicCategories && this.getMusicCategories.length > 0) {
-          return Promise.resolve();
-        }
-        const { data } = await getCategories({
-          enable: true,
-          page: 1,
-          rows: 999
-        });
-        this.setMusicCategories(data.rows || []);
-        return Promise.resolve();
-      } catch (e) {
-        return Promise.reject(e);
-      }
-    },
-    /**
-     * 获取乐器列表
-     * @returns Promise
-     */
-    async getMusicInstrument() {
-      try {
-        // 判断是否存在声部数据
-        if (this.getMusicInstruments && this.getMusicInstruments.length > 0) {
-          return Promise.resolve();
-        }
-        const { data } = await api_musicalInstrumentList({
-          enableFlag: true
-        });
-        console.log(data, 'data');
-        this.setMusicInstruments(data || []);
-        return Promise.resolve();
-      } catch (e) {
-        return Promise.reject(e);
-      }
-    }
-  }
-});
-
-// Need to be used outside the setup
-export function useCatchStoreWidthOut() {
-  return useCatchStore(store);
-}
+import { defineStore } from 'pinia';
+import { store } from '@/store';
+import {
+  getSubjectList,
+  getSubjectList2,
+  getCategories,
+  api_musicalInstrumentList
+} from '@/api/user';
+
+export const useCatchStore = defineStore('catch-store', {
+  state: () => ({
+    bookVersionList: [] as any[], // 其它类型
+    musicTypeList: [] as any[], // 乐谱分类
+    subjectList: [] as any[], // 声部列表,
+    musicInstrumentList: [] as any[], // 乐器列表,
+    subjectInstruemnts: [] as any[] // 乐器列表,
+  }),
+  getters: {
+    getBookVersion(): any[] {
+      return this.bookVersionList;
+    },
+    getMusicCategories(): any[] {
+      return this.musicTypeList;
+    },
+    getMusicInstruments(): any[] {
+      return this.musicInstrumentList;
+    },
+    getAllMusicCategories(): any[] {
+      return [
+        {
+          name: '全部',
+          id: null
+        },
+        ...this.musicTypeList
+      ];
+    },
+    getSubjectList(): any[] {
+      return this.subjectList;
+    },
+    getSubjectAllList(): any[] {
+      return [
+        {
+          name: '全部',
+          id: null
+        },
+        ...this.subjectList
+      ];
+    },
+    /**
+     * 获取所有启用的声部
+     */
+    getEnableSubjects(): any[] {
+      const temp: any[] = [];
+      this.subjectList.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);
+              }
+            });
+
+            temp.push({ ...r, instruments: tempChild });
+          }
+        }
+      });
+      return temp;
+    },
+    getSubjectInstruments(): any[] {
+      return [
+        {
+          name: '全部',
+          id: null,
+          label: '全部',
+          value: null
+        },
+        ...this.subjectInstruemnts
+      ];
+    }
+  },
+  actions: {
+    setBookVersion(books: any[]) {
+      this.bookVersionList = books;
+    },
+    setMusicCategories(musics: any[]) {
+      this.musicTypeList = musics;
+    },
+    setSubjects(subjects: any[]) {
+      this.subjectList = subjects;
+    },
+    setSubjectInstruemnts(subjects: any[]) {
+      this.subjectInstruemnts = subjects;
+    },
+    setMusicInstruments(instruments: any[]) {
+      this.musicInstrumentList = instruments;
+    },
+    /**
+     * 判断是否有声部数据,如不存在则获取声部列表
+     * @returns Promise
+     */
+    async getSubjects() {
+      try {
+        // 判断是否存在声部数据
+        if (this.getSubjectList && this.getSubjectList.length > 0) {
+          return Promise.resolve();
+        }
+        const { data } = await getSubjectList2({
+          // enableFlag: true,
+          delFlag: 0,
+          page: 1,
+          rows: 999
+        });
+
+        const tempSubjectList = data || [];
+
+        const tempSubjectInstruments: any = [];
+        tempSubjectList.forEach((item: any) => {
+          if (item.instruments && item.instruments.length > 0) {
+            item.value = item.id;
+            item.label = item.name;
+            item.instruments.forEach((child: any) => {
+              child.label = child.name;
+              child.value = child.id;
+            });
+
+            const tempSi = {
+              value: item.id,
+              label: item.name,
+              id: item.id,
+              name: item.name,
+              instruments: [] as any
+            };
+            if (item.instruments) {
+              if (item.instruments.length == 1) {
+                tempSi.value = item.instruments[0].id;
+                tempSi.label = item.instruments[0].name;
+                tempSi.id = item.id;
+                tempSi.name = item.name;
+              } else if (item.instruments.length > 1) {
+                item.instruments.forEach((child: any) => {
+                  child.label = child.name;
+                  child.value = child.id;
+                  tempSi.instruments.push({
+                    label: child.name,
+                    value: child.id,
+                    id: child.id,
+                    name: child.name
+                  });
+                });
+              }
+            }
+            tempSubjectInstruments.push(tempSi);
+          }
+        });
+
+        this.setSubjects(
+          tempSubjectList.filter(
+            (item: any) => item.instruments && item.instruments.length > 0
+          ) || 0
+        );
+        this.setSubjectInstruemnts(tempSubjectInstruments || []);
+
+        return Promise.resolve();
+      } catch (e) {
+        return Promise.reject(e);
+      }
+    },
+    /**
+     * 判断是否有教材分类数据,如不存在则获取教材分类列表
+     * @returns Promise
+     */
+    async getMusicSheetCategory() {
+      try {
+        // 判断是否存在声部数据
+        if (this.getMusicCategories && this.getMusicCategories.length > 0) {
+          return Promise.resolve();
+        }
+        const { data } = await getCategories({
+          enable: true,
+          page: 1,
+          rows: 999
+        });
+        this.setMusicCategories(data.rows || []);
+        return Promise.resolve();
+      } catch (e) {
+        return Promise.reject(e);
+      }
+    },
+    /**
+     * 获取乐器列表
+     * @returns Promise
+     */
+    async getMusicInstrument() {
+      try {
+        // 判断是否存在声部数据
+        if (this.getMusicInstruments && this.getMusicInstruments.length > 0) {
+          return Promise.resolve();
+        }
+        const { data } = await api_musicalInstrumentList({
+          enableFlag: true
+        });
+        console.log(data, 'data');
+        this.setMusicInstruments(data || []);
+        return Promise.resolve();
+      } catch (e) {
+        return Promise.reject(e);
+      }
+    }
+  }
+});
+
+// Need to be used outside the setup
+export function useCatchStoreWidthOut() {
+  return useCatchStore(store);
+}

+ 2402 - 0
src/views/attend-class/index.tsx

@@ -1,3 +1,4 @@
+<<<<<<< Updated upstream
 import {
   defineComponent,
   onMounted,
@@ -2096,3 +2097,2404 @@ export default defineComponent({
     );
   }
 });
+=======
+import {
+  defineComponent,
+  onMounted,
+  reactive,
+  onUnmounted,
+  ref,
+  Transition,
+  computed,
+  nextTick,
+  watch,
+  toRef
+} from 'vue';
+import styles from './index.module.less';
+import 'plyr/dist/plyr.css';
+import MusicScore from './component/musicScore';
+// import iconChange from './image/icon-change.png';
+// import iconMenu from './image/icon-menu.png';
+// import iconUp from './image/icon-up.png';
+// import iconDown from './image/icon-down.png';
+// import iconNote from './image/icon-note.png';
+// import iconWhiteboard from './image/icon-whiteboard.png';
+// import iconAssignHomework from './image/icon-assignHomework.png';
+// import iconClose from './image/icon-close.png';
+// import iconOverPreivew from './image/icon-over-preview.png';
+import { Vue3Lottie } from 'vue3-lottie';
+import playLoadData from './datas/data.json';
+// import Moveable from 'moveable';
+import VideoPlay from './component/video-play';
+import {
+  useMessage,
+  NDrawer,
+  NDrawerContent,
+  NModal,
+  NSpace,
+  NButton,
+  NCollapse,
+  NCollapseItem,
+  NTooltip
+} from 'naive-ui';
+import CardType from '@/components/card-type';
+import Pen from './component/tools/pen';
+import AudioPay from './component/audio-pay';
+import TrainSettings from './model/train-settings';
+import { useRoute } from 'vue-router';
+import {
+  api_teacherChapterLessonCoursewareDetail,
+  courseScheduleUpdate,
+  lessonCoursewareDetail,
+  lessonPreTrainingPage,
+  queryCourseware
+} from '../prepare-lessons/api';
+import { vaildUrl } from '/src/utils/urlUtils';
+import TimerMeter from '/src/components/timerMeter';
+import { iframeDislableKeyboard, px2vw } from '/src/utils';
+import PlaceholderTone from '/src/components/layout/modals/placeholderTone';
+import { state as globalState } from '/src/state';
+import Chapter from './model/chapter';
+import { useRouter } from 'vue-router';
+import { useUserStore } from '@/store/modules/users';
+import iconNote from './new-image/icon-note.png';
+import iconWhite from './new-image/icon-white.png';
+
+import rightIconEnd from './image/right_icon1.png';
+import rightIconArrange from './image/right_icon2.png';
+import rightIconPostil from './image/right_icon3.png';
+import rightIconWhiteboard from './image/right_icon4.png';
+import rightIconMetronome from './image/right_icon5.png';
+import rightIconTuner from './image/right_icon6.png';
+import rightIconTimer from './image/right_icon7.png';
+import rightIconCall from './image/right_icon10.png';
+import rightIconPackUp from './image/right_icon11.png';
+import leftIconPackUp from './image/right_icon8.png';
+import rightIconMusic from './image/right_icon9.png';
+import bottomIconSwitch from './image/bottom_icon1.png';
+import bottomIconResource from './image/bottom_icon2.png';
+import bottomIconPre from './image/bottom_icon3.png';
+import bottomIconNext from './image/bottom_icon4.png';
+import rightIconTool from './image/right_icon12.png';
+import rightHideIcon from './image/right_hide_icon.png';
+import leftHideIcon from './image/left_hide_icon.png';
+import SelectResources from '../prepare-lessons/model/select-resources';
+import { getStudentAfterWork, getStudentList } from '../studentList/api';
+import TheNoticeBar from '/src/components/TheNoticeBar';
+import ClassWork from './model/class-work';
+import SelectClass from './model/select-class';
+import SourceList from './model/source-list';
+import RhythmModal from './component/rhythm-modal';
+import InstruemntDetail from '/src/views/prepare-lessons/model/source-instrument/detail';
+import TheotyDetail from '/src/views/prepare-lessons/model/source-knowledge/detail';
+import MusicDetail from '/src/views/prepare-lessons/model/source-music/detail';
+import ListenModal from '/src/components/card-preview/listen-modal';
+import Train from '../prepare-lessons/components/lesson-main/train';
+import ResourceMain from '../prepare-lessons/components/resource-main';
+import { useResizeObserver } from '@vueuse/core';
+import { storage } from '/src/utils/storage';
+import { ACCESS_TOKEN_ADMIN } from '/src/store/mutation-types';
+import useDrag from '@/hooks/useDrag';
+import Dragbom from '@/hooks/useDrag/dragbom';
+
+export type ToolType = 'init' | 'pen' | 'whiteboard' | 'call';
+export type ToolItem = {
+  type: ToolType;
+  name: string;
+  icon: string;
+};
+
+export default defineComponent({
+  name: 'CoursewarePlay',
+  props: {
+    type: {
+      type: String,
+      default: ''
+    },
+    courseId: {
+      type: String,
+      default: ''
+    },
+    instrumentId: {
+      type: [String, Number],
+      default: ''
+    },
+    // 教材编号
+    lessonCourseId: {
+      type: [String, Number],
+      default: ''
+    },
+    detailId: {
+      type: String,
+      default: ''
+    },
+    // 班级编号
+    classGroupId: {
+      type: String,
+      default: ''
+    },
+    // 上课记录编号
+    classId: {
+      type: String,
+      defaault: ''
+    },
+    preStudentNum: {
+      type: [String, Number],
+      default: ''
+    }
+  },
+  emits: ['close'],
+  setup(props, { emit }) {
+    const message = useMessage();
+    const route = useRoute();
+    const router = useRouter();
+    const users = useUserStore();
+    /** 设置播放容器 16:9 */
+    const parentContainer = reactive({
+      width: '100vw'
+    });
+    // const NPopoverRef = ref();
+    // 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();
+    };
+    handleInit();
+    onUnmounted(() => {
+      handleInit(1);
+    });
+
+    const data = reactive({
+      type: 'class' as '' | 'preview' | 'class', // 预览类型
+      courseId: '' as any, // 课件编号
+      instrumentId: '' as any, // 声部编号
+      lessonCourseId: '' as any, // 教材编号
+      lessonCoursewareDetailId: '' as any, // 章节
+      lessonCoursewareSubjectList: [] as any, // 教材上的声部
+      detailId: '' as any, // 编号 - 课程编号
+      classGroupId: '' as any, // 上课时需要 班级编号
+      classId: '' as any, // 上课编号
+      preStudentNum: '' as any, // 班上学生
+      // detail: null,
+      knowledgePointList: [] as any,
+      itemList: [] as any,
+      // showHead: true,
+      // isCourse: false,
+      // isRecordPlay: false,
+      videoRefs: {} as any[],
+      audioRefs: {} as any[],
+      modelAttendStatus: false, // 布置作业提示弹窗
+      modalAttendMessage: '本节课未设置课后作业,是否继续?',
+      modelTrainStatus: false, // 训练设置
+      selectClassStatus: false, // 选择课件
+      homeworkStatus: true, // 布置作业完成时
+      removeVisiable: false,
+      nextEndShow: false,
+      removeTitle: '',
+      removeContent: '',
+      removeCourseStatus: false, // 是否布置作业
+
+      teacherChapterName: '',
+      lessonPreTrainingId: null,
+      selectResourceStatus: false,
+      videoState: 'init' as 'init' | 'play',
+      videoItemRef: null as any,
+      animationState: 'start' as 'start' | 'end'
+    });
+    const activeData = reactive({
+      isAutoPlay: false, // 是否自动播放
+      nowTime: 0,
+      model: true, // 遮罩
+      isAnimation: true, // 是否动画
+      // videoBtns: true, // 视频
+      // currentTime: 0,
+      // duration: 0,
+      timer: null as any,
+      item: null as any
+    });
+
+    // 键盘事件监听状态
+    const listenerKeyUpState = ref(false);
+
+    const getDetail = async () => {
+      try {
+        const res = await api_teacherChapterLessonCoursewareDetail(
+          data.courseId
+        );
+
+        data.teacherChapterName = res.data.name || '';
+        // 布置的作业编号
+        data.lessonPreTrainingId = res.data.lessonPreTrainingId;
+        // activeData.isAutoPlay = res.data.autoPlay || false; // 自动播放
+        const tempRows = res.data.chapterKnowledgeList || [];
+        const temp: any = [];
+        const allItem: any = [];
+        tempRows.forEach((row: any, index: number) => {
+          if (!Array.isArray(row.chapterKnowledgeMaterialList)) {
+            return;
+          }
+          const childList: any[] = [];
+          row.chapterKnowledgeMaterialList.forEach((child: any) => {
+            if (!child.removeFlag) {
+              childList.push({
+                id: child.id,
+                materialId: child.bizId,
+                coverImg: child.bizInfo.coverImg,
+                type: child.type,
+                title: child.bizInfo.name,
+                dataJson: child.dataJson,
+                isCollect: !!child.favoriteFlag,
+                isSelected: child.source === 'PLATFORM' ? true : false,
+                content: child.bizInfo.content,
+                parentIndex: index
+              });
+            }
+          });
+          temp.push({
+            title: row.name,
+            list: childList
+          });
+          allItem.push(...childList);
+        });
+
+        console.log(temp, 'temp', tempRows);
+        data.knowledgePointList = temp;
+        data.itemList = allItem?.map((m: any) => {
+          return {
+            ...m,
+            iframeRef: null,
+            videoEle: null,
+            audioEle: null,
+            autoPlay: res.data.autoPlay || false, //加载完成是否自动播放
+            isprepare: false, // 视频是否加载完成
+            isRender: false // 是否渲染了
+          };
+        });
+        setTimeout(() => {
+          data.animationState = 'end';
+        }, 500);
+      } catch (e) {
+        //
+        console.log(e);
+      }
+    };
+
+    const showModalBeat = ref(false);
+    const showModalTone = ref(false);
+    const showModalTime = ref(false);
+    // ifram事件处理
+    const iframeHandle = (ev: MessageEvent) => {
+      // console.log(ev.data?.api, ev.data, 'ev.data');
+      if (ev.data?.api === 'headerTogge') {
+        activeData.model =
+          ev.data.show || (ev.data.playState == 'play' ? false : true);
+      }
+
+      //
+      if (ev.data?.api === 'onAttendToggleMenu') {
+        activeData.model = !activeData.model;
+      }
+
+      if (ev.data?.api === 'api_fingerPreView') {
+        clearInterval(activeData.timer);
+        activeData.model = !ev.data.state;
+      }
+      //
+      if (ev.data?.api === 'documentBodyKeyup') {
+        if (ev.data?.code === 'ArrowLeft') {
+          setModalOpen();
+          handlePreAndNext('up');
+        }
+
+        if (ev.data?.code === 'ArrowRight') {
+          setModalOpen();
+          handlePreAndNext('down');
+        }
+      }
+
+      // 点名返回
+      if (ev.data?.api === 'callBack') {
+        closeStudyTool();
+      }
+
+      if (ev.data?.api === 'onLogin') {
+        const documentDom: any = document;
+        documentDom.exitFullscreen
+          ? documentDom.exitFullscreen()
+          : documentDom.mozCancelFullScreen
+          ? documentDom.mozCancelFullScreen()
+          : documentDom.webkitExitFullscreen
+          ? documentDom.webkitExitFullscreen()
+          : '';
+        users.logout();
+        router.replace('/login');
+      }
+    };
+
+    onMounted(() => {
+      // initMoveable();
+      const query = route.query;
+      console.log(query, props.preStudentNum, '学生人数');
+      // 先取参数,
+      data.type = props.type || (query.type as any);
+      data.courseId = props.courseId || query.courseId;
+      data.instrumentId = props.instrumentId || query.instrumentId;
+      data.detailId = props.detailId || query.detailId;
+      data.lessonCourseId = props.lessonCourseId || query.lessonCourseId;
+      data.classGroupId = props.classGroupId || query.classGroupId;
+      data.classId = props.classId || query.classId;
+      data.preStudentNum = props.preStudentNum || query.preStudentNum;
+      window.addEventListener('message', iframeHandle);
+      getDetail();
+      getLessonCoursewareDetail();
+      if (data.type === 'preview') {
+        // 预览隐藏点名和布置作业
+        const hideListIds = [2, 10];
+        let index = rightList.length - 1;
+        while (index >= 0) {
+          if (hideListIds.includes(rightList[index].id)) {
+            console.log(index);
+            rightList.splice(index, 1);
+          }
+          index--;
+        }
+      }
+      rollCallStudentList();
+    });
+
+    // const onFullScreen = () => {
+    //   if (data.type === 'preview') {
+    //     const el: any = document.querySelector('#app');
+
+    //     if (el.mozRequestFullScreen) {
+    //       el.mozRequestFullScreen();
+    //     } else if (el.webkitRequestFullscreen) {
+    //       el.webkitRequestFullscreen();
+    //     } else if (el.requestFullScreen) {
+    //       el.requestFullscreen();
+    //     }
+    //   }
+    // };
+
+    const popupData = reactive({
+      open: false,
+      activeIndex: 0,
+      courseActiveIndex: 0, // 课件选择的第几个
+      toolOpen: false, // 工具弹窗控制
+      chapterOpen: false, // 切换章节
+      chapterDetails: [] as any,
+      courseId: null as any, // 章节编号
+      chapterLoading: false // 加载数据
+    });
+
+    watch(
+      () => [popupData.open, popupData.chapterOpen],
+      val => {
+        // 为了处理window电脑滑动时的问题 - pointr-events
+        setTimeout(() => {
+          const drawers = document.querySelectorAll('.n-drawer-container');
+          if (val[0] || val[1]) {
+            drawers?.forEach(drawer => {
+              drawer.classList.remove('n-drawer-container-relative');
+            });
+          } else {
+            drawers?.forEach(drawer => {
+              drawer.classList.add('n-drawer-container-relative');
+            });
+          }
+        }, 200);
+      }
+    );
+    const formatParentId = (id: any, list: any, ids = [] as any) => {
+      for (const item of list) {
+        if (item.knowledgeList && item.knowledgeList.length > 0) {
+          const cIds: any = formatParentId(id, item.knowledgeList, [
+            ...ids,
+            item.id
+          ]);
+          if (cIds.includes(id)) {
+            return cIds;
+          }
+        }
+        if (item.id === id) {
+          return [...ids, id];
+        }
+      }
+      return ids;
+    };
+
+    /** 获取章节 */
+    const getLessonCoursewareDetail = async () => {
+      try {
+        const res = await lessonCoursewareDetail({
+          id: data.lessonCourseId,
+          instrumentId: data.instrumentId
+        });
+
+        popupData.chapterDetails = res.data.lessonList || [];
+
+        const ids = formatParentId(data.detailId, popupData.chapterDetails);
+        data.lessonCoursewareDetailId = ids[0];
+        console.log(res.data, 'data');
+        data.lessonCoursewareSubjectList = res.data.instrumentList || [];
+      } catch {
+        //
+      }
+    };
+    /** 更新上课记录 */
+    const classCourseScheduleUpdate = async () => {
+      try {
+        if (!data.classId) return;
+        await courseScheduleUpdate({
+          lessonCoursewareKnowledgeDetailId: data.detailId,
+          id: data.classId
+        });
+      } catch {
+        //
+      }
+    };
+
+    const activeName = computed(() => {
+      let name = '';
+      popupData.chapterDetails.forEach((chapter: any) => {
+        if (chapter.id === data.lessonCoursewareDetailId) {
+          // name = chapter.name;
+          chapter.knowledgeList?.forEach((know: any) => {
+            if (know.id === data.detailId) {
+              name = know.name;
+            }
+          });
+        }
+      });
+      return name;
+    });
+
+    /**停止所有的播放 */
+    const handleStop = (isStop = true) => {
+      // console.log(isStop, 'stop');
+      for (let i = 0; i < data.itemList.length; i++) {
+        const activeItem = data.itemList[i];
+        if (activeItem.type === 'VIDEO' && activeItem.videoEle) {
+          try {
+            if (isStop) {
+              activeItem.videoEle?.currentTime(0);
+            }
+            activeItem.videoEle?.pause();
+          } catch (e: any) {
+            // console.log(e, 'e');
+          }
+        }
+        if (activeItem.type === 'SONG' && activeItem.audioEle) {
+          activeItem.audioEle?.stop();
+        }
+        // console.log('🚀 ~ activeItem:', activeItem)
+        // 停止曲谱的播放
+        if (activeItem.type === 'MUSIC') {
+          activeItem.iframeRef?.contentWindow?.postMessage(
+            { api: 'setPlayState' },
+            '*'
+          );
+        }
+
+        if (
+          activeItem.type === 'INSTRUMENT' ||
+          activeItem.type === 'MUSICIAN' ||
+          activeItem.type === 'MUSIC_WIKI'
+        ) {
+          activeItem.iframeRef?.handleChangeAudio('pause');
+        }
+
+        // console.log(activeItem.type, 'activeItem.type');
+        if (activeItem.type === 'RHYTHM') {
+          activeItem.iframeRef?.contentWindow?.postMessage(
+            { api: 'setPlayState', data: false },
+            '*'
+          );
+        }
+
+        if (activeItem.type === 'LISTEN') {
+          activeItem.iframeRef?.contentWindow?.postMessage(
+            { api: 'setPlayState' },
+            '*'
+          );
+        }
+      }
+    };
+    // 切换素材
+    const toggleMaterial = (itemActive: any) => {
+      const index = data.itemList.findIndex((n: any) => n.id == itemActive);
+      if (index > -1) {
+        handleSwipeChange(index);
+      }
+    };
+    /** 延迟收起模态框 */
+    const setModelOpen = () => {
+      clearTimeout(activeData.timer);
+      message.destroyAll();
+      activeData.timer = setTimeout(() => {
+        activeData.model = false;
+        Object.values(data.videoRefs).map((n: any) =>
+          n?.toggleHideControl(false)
+        );
+
+        Object.values(data.audioRefs).map((n: any) =>
+          n?.toggleHideControl(false)
+        );
+      }, 4000);
+    };
+
+    /** 立即收起所有的模态框 */
+    const clearModel = () => {
+      clearTimeout(activeData.timer);
+      message.destroyAll();
+      activeData.model = false;
+      Object.values(data.videoRefs).map((n: any) =>
+        n?.toggleHideControl(false)
+      );
+      Object.values(data.audioRefs).map((n: any) =>
+        n?.toggleHideControl(false)
+      );
+    };
+    const toggleModel = (type = true) => {
+      activeData.model = type;
+      Object.values(data.videoRefs).map((n: any) => n?.toggleHideControl(type));
+      Object.values(data.audioRefs).map((n: any) => n?.toggleHideControl(type));
+    };
+
+    // 双击
+    const handleDbClick = (item: any) => {
+      if (item && item.type === 'VIDEO') {
+        const videoEle: HTMLVideoElement = item.videoEle;
+        if (videoEle) {
+          if (videoEle.paused) {
+            message.destroyAll();
+            videoEle.play();
+          } else {
+            message.warning('已暂停');
+            videoEle.pause();
+          }
+        }
+      }
+    };
+
+    // ppt iframe 点击事件
+    // const iframeClick = () => {
+    // 	if(document.all) {
+    // 		document.getElementById("iframe-ppt")?.attachEvent("click", () => {
+    //       activeData.model = !activeData.model
+    //     });
+    // 	} else {
+    // 		document.getElementById("iframe-ppt")?.contentWindow?.postMessage({
+    //       api: 'onAttendToggleMenu'
+    //     }, '*');
+    // 	}
+    // }
+
+    // 切换播放
+    // const togglePlay = (m: any, isPlay: boolean) => {
+    //   if (isPlay) {
+    //     m.videoEle?.play();
+    //   } else {
+    //     m.videoEle?.pause();
+    //   }
+    // };
+
+    // const showIndex = ref(-4);
+    const effectIndex = ref(3);
+    const effects = [
+      {
+        prev: {
+          transform: 'translate3d(0, 0, -800px) rotateX(180deg)'
+        },
+        next: {
+          transform: 'translate3d(0, 0, -800px) rotateX(-180deg)'
+        }
+      },
+      {
+        prev: {
+          transform: 'translate3d(-100%, 0, -800px)'
+        },
+        next: {
+          transform: 'translate3d(100%, 0, -800px)'
+        }
+      },
+      {
+        prev: {
+          transform: 'translate3d(-50%, 0, -800px) rotateY(80deg)'
+        },
+        next: {
+          transform: 'translate3d(50%, 0, -800px) rotateY(-80deg)'
+        }
+      },
+      {
+        prev: {
+          transform: 'translate3d(-100%, 0, -800px) rotateY(-120deg)'
+        },
+        next: {
+          transform: 'translate3d(100%, 0, -800px) rotateY(120deg)'
+        }
+      },
+      // 风车4
+      {
+        prev: {
+          transform: 'translate3d(-50%, 50%, -800px) rotateZ(-14deg)',
+          opacity: 0
+        },
+        next: {
+          transform: 'translate3d(50%, 50%, -800px) rotateZ(14deg)',
+          opacity: 0
+        }
+      },
+      // 翻页5
+      {
+        prev: {
+          transform: 'translateZ(-800px) rotate3d(0, -1, 0, 90deg)',
+          opacity: 0
+        },
+        next: {
+          transform: 'translateZ(-800px) rotate3d(0, 1, 0, 90deg)',
+          opacity: 0
+        },
+        current: { transitionDelay: '700ms' }
+      }
+    ];
+
+    const acitveTimer = ref();
+    // 轮播切换
+    const handleSwipeChange = (index: number) => {
+      // 如果是当前正在播放 或者是视频最后一个
+      if (popupData.activeIndex == index) return;
+      data.animationState = 'start';
+      data.videoState = 'init';
+      handleStop();
+      clearTimeout(acitveTimer.value);
+      activeData.model = true;
+      checkedAnimation(popupData.activeIndex, index);
+      popupData.activeIndex = index;
+
+      // 处理资源列表滚动
+      nextTick(() => {
+        scrollResourceSection();
+      });
+
+      acitveTimer.value = setTimeout(
+        () => {
+          const item = data.itemList[index];
+
+          if (item) {
+            if (item.type == 'MUSIC') {
+              activeData.model = true;
+            }
+            if (item.type === 'SONG') {
+              // 自动播放下一个音频
+              clearTimeout(activeData.timer);
+              message.destroyAll();
+              // item.autoPlay = false;
+              // nextTick(() => {
+              //   item.audioEle?.onPlay();
+              // });
+            }
+            if (item.type === 'VIDEO') {
+              // 自动播放下一个视频
+              clearTimeout(activeData.timer);
+              message.destroyAll();
+              nextTick(() => {
+                if (item.error) {
+                  // console.log(item, 'item error');
+                  item.videoEle?.src(item.content);
+                  item.error = false;
+                  //   item.videoEle?.onPlay();
+                }
+                data.animationState = 'end';
+              });
+            }
+            if (item.type === 'PPT') {
+              //
+            }
+          }
+        },
+        activeData.isAnimation ? 800 : 0
+      );
+    };
+
+    /** 是否有转场动画 */
+    const checkedAnimation = (index: number, nextIndex?: number) => {
+      const item = data.itemList[index];
+      const nextItem = data.itemList[nextIndex!];
+      if (nextItem) {
+        if (nextItem.knowledgePointId != item.knowledgePointId) {
+          activeData.isAnimation = true;
+          return;
+        }
+        const videoEle = item.videoEle;
+        const nextVideo = nextItem.videoEle;
+        if (videoEle && videoEle.duration < 8 && index < nextIndex!) {
+          activeData.isAnimation = false;
+        } else if (nextVideo && nextVideo.duration < 8 && index > nextIndex!) {
+          activeData.isAnimation = false;
+        } else {
+          activeData.isAnimation = true;
+        }
+      } else {
+        activeData.isAnimation = item?.adviseStudyTimeSecond < 8 ? false : true;
+      }
+    };
+
+    // 上一个知识点, 下一个知识点
+    const handlePreAndNext = async (type: string) => {
+      if (type === 'up') {
+        // 判断上面是否还有章节
+        if (popupData.activeIndex > 0) {
+          handleSwipeChange(popupData.activeIndex - 1);
+          return;
+        }
+
+        // 获取当前是哪个章节
+        let detailIndex = popupData.chapterDetails.findIndex(
+          (item: any) => item.id == data.lessonCoursewareDetailId
+        );
+        const detailItem =
+          popupData.chapterDetails[detailIndex]?.knowledgeList || [];
+        let lessonIndex = detailItem.findIndex(
+          (item: any) => item.id == data.detailId
+        );
+
+        let lessonStatus = false; // 当前章节上面是否有内容
+        let lessonCoursewareDetailId = '';
+        let coursewareDetailKnowledgeId = '';
+        while (lessonIndex >= 0) {
+          lessonIndex--;
+
+          if (lessonIndex >= 0) {
+            if (detailItem[lessonIndex].coursewareNum > 0) {
+              lessonStatus = true;
+              lessonCoursewareDetailId =
+                detailItem[lessonIndex].lessonCoursewareDetailId;
+              coursewareDetailKnowledgeId = detailItem[lessonIndex].id;
+            }
+          }
+
+          if (lessonStatus) {
+            break;
+          }
+        }
+        // 判断当前章节下面课程是否有内容,否则往上一个章节走
+        if (lessonStatus) {
+          popupData.courseId = coursewareDetailKnowledgeId;
+          data.selectClassStatus = true;
+          return;
+        }
+
+        let prevLessonStatus = false;
+        while (detailIndex >= 0) {
+          detailIndex--;
+          const tempDetail =
+            popupData.chapterDetails[detailIndex]?.knowledgeList || [];
+          let tempLessonLength = tempDetail.length;
+          while (tempLessonLength > 0) {
+            if (tempDetail[tempLessonLength - 1].coursewareNum > 0) {
+              prevLessonStatus = true;
+              lessonCoursewareDetailId =
+                tempDetail[tempLessonLength - 1].lessonCoursewareDetailId;
+              coursewareDetailKnowledgeId = tempDetail[tempLessonLength - 1].id;
+            }
+            tempLessonLength--;
+            if (prevLessonStatus) {
+              break;
+            }
+          }
+
+          if (prevLessonStatus) {
+            break;
+          }
+        }
+
+        // 判断当前章节下面课程是否有内容,否则往上一个章节走
+        if (prevLessonStatus) {
+          popupData.courseId = coursewareDetailKnowledgeId;
+          data.selectClassStatus = true;
+          return;
+        }
+      } else {
+        if (popupData.activeIndex < data.itemList.length - 1) {
+          handleSwipeChange(popupData.activeIndex + 1);
+          return;
+        }
+        data.nextEndShow = true;
+      }
+    };
+    // 当前课件结束之后选择下一个课件
+    function handleNextEnd() {
+      // 获取当前是哪个章节
+      let detailIndex = popupData.chapterDetails.findIndex(
+        (item: any) => item.id == data.lessonCoursewareDetailId
+      );
+      const detailItem =
+        popupData.chapterDetails[detailIndex]?.knowledgeList || [];
+      let lessonIndex = detailItem.findIndex(
+        (item: any) => item.id == data.detailId
+      );
+
+      let lessonStatus = false; // 当前章节下面是否有内容
+      let lessonCoursewareDetailId = '';
+      let coursewareDetailKnowledgeId = '';
+      while (lessonIndex < detailItem.length - 1) {
+        lessonIndex++;
+        if (lessonIndex >= 0) {
+          if (detailItem[lessonIndex].coursewareNum > 0) {
+            lessonStatus = true;
+            lessonCoursewareDetailId =
+              detailItem[lessonIndex].lessonCoursewareDetailId;
+            coursewareDetailKnowledgeId = detailItem[lessonIndex].id;
+          }
+        }
+        if (lessonStatus) {
+          break;
+        }
+      }
+      // 判断当前章节下面课程是否有内容,否则往下一个章节走
+      if (lessonStatus) {
+        popupData.courseId = coursewareDetailKnowledgeId;
+        data.selectClassStatus = true;
+        return;
+      }
+
+      let nextLessonStatus = false;
+      while (detailIndex <= popupData.chapterDetails.length - 1) {
+        detailIndex++;
+        const tempDetail =
+          popupData.chapterDetails[detailIndex]?.knowledgeList || [];
+        let tempLessonLength = 0;
+        while (tempLessonLength <= tempDetail.length - 1) {
+          if (tempDetail[tempLessonLength].coursewareNum > 0) {
+            nextLessonStatus = true;
+            lessonCoursewareDetailId =
+              tempDetail[tempLessonLength].lessonCoursewareDetailId;
+            coursewareDetailKnowledgeId = tempDetail[tempLessonLength].id;
+          }
+          tempLessonLength++;
+          if (nextLessonStatus) {
+            break;
+          }
+        }
+
+        if (nextLessonStatus) {
+          break;
+        }
+      }
+
+      // 判断当前章节下面课程是否有内容,否则往上一个章节走
+      if (nextLessonStatus) {
+        popupData.courseId = coursewareDetailKnowledgeId;
+        data.selectClassStatus = true;
+        return;
+      }
+    }
+    /** 弹窗关闭 */
+    const handleClosePopup = () => {
+      const item = data.itemList[popupData.activeIndex];
+      if (item?.type == 'VIDEO' && !item.videoEle?.paused) {
+        setModelOpen();
+      }
+
+      if (item?.type == 'SONG' && !item.audioEle?.paused) {
+        setModelOpen();
+      }
+    };
+    document.body.addEventListener('keyup', (e: KeyboardEvent) => {
+      if (e.code === 'ArrowUp') {
+        // if (popupData.activeIndex === 0) return;
+        setModalOpen();
+        handlePreAndNext('up');
+      } else if (e.code === 'ArrowDown') {
+        // if (popupData.activeIndex === data.itemList.length - 1) return;
+        setModalOpen();
+        handlePreAndNext('down');
+      } else if (e.code === 'Space') {
+        // const activeItem = data.itemList[popupData.activeIndex];
+        // console.log(activeItem, activeItem.videoEle);
+        // // 暂停视频和曲谱的播放
+        // if (activeItem.type === 'VIDEO' && activeItem.videoEle) {
+        //   activeItem.videoEle?.play();
+        // }
+        // if (activeItem.type === 'SONG' && activeItem.audioEle) {
+        //   activeItem.audioEle?.play();
+        // }
+        // if (activeItem.type === 'MUSIC') {
+        //   activeItem.iframeRef?.contentWindow?.postMessage(
+        //     { api: 'setPlayState' },
+        //     '*'
+        //   );
+        // }
+      }
+    });
+
+    // const toggleListenerKeyUp = (type: string) => {
+    //   if (type === 'remove') {
+    //     document.body.removeEventListener('keyup', () => {
+    //       listenerKeyUpState.value = false;
+    //     });
+    //   } else {
+    //     // 监听页面键盘事件 - 上下切换
+    //     document.body.addEventListener('keyup', (e: KeyboardEvent) => {
+    //       // console.log(e, 'e');
+    //       if (e.code === 'ArrowLeft') {
+    //         // if (popupData.activeIndex === 0) return;
+    //         setModalOpen();
+    //         handlePreAndNext('up');
+    //       } else if (e.code === 'ArrowRight') {
+    //         // if (popupData.activeIndex === data.itemList.length - 1) return;
+    //         setModalOpen();
+    //         handlePreAndNext('down');
+    //       }
+    //     });
+    //     listenerKeyUpState.value = true;
+    //   }
+    // };
+
+    // 监听切换到ppt课件时,手动移除键盘监听器
+    // watch(() => popupData.activeIndex, () => {
+    //   const activeItem = data.itemList[popupData.activeIndex];
+    //   if (activeItem?.type === 'PPT') {
+    //     toggleListenerKeyUp('remove')
+    //   } else {
+    //     !listenerKeyUpState.value && toggleListenerKeyUp('add')
+    //   }
+    // })
+    watch(
+      () => popupData.activeIndex,
+      () => {
+        const item = data.itemList[popupData.activeIndex];
+        popupData.courseActiveIndex = item.parentIndex;
+      }
+    );
+
+    const setModalOpen = (status = true) => {
+      clearTimeout(activeData.timer);
+      activeData.model = status;
+      Object.values(data.videoRefs).map((n: any) =>
+        n?.toggleHideControl(status)
+      );
+      Object.values(data.audioRefs).map((n: any) =>
+        n?.toggleHideControl(status)
+      );
+    };
+
+    /** 教学数据 */
+    const studyData = reactive({
+      type: '' as ToolType,
+      penShow: false,
+      whiteboardShow: false,
+      callShow: false,
+      callStudentList: [] as any // 学生列表
+    });
+
+    /** 打开教学工具 */
+    const openStudyTool = (item: ToolItem) => {
+      handleStop(false);
+      clearModel();
+      popupData.toolOpen = false;
+      studyData.type = item.type;
+
+      switch (item.type) {
+        case 'pen':
+          studyData.penShow = true;
+          break;
+        case 'whiteboard':
+          studyData.whiteboardShow = true;
+          break;
+        case 'call':
+          studyData.callShow = true;
+          break;
+      }
+    };
+
+    /** 关闭教学工具 */
+    const closeStudyTool = () => {
+      studyData.type = 'init';
+      toggleModel();
+      setModelOpen();
+    };
+
+    const startShowModal = (
+      val: 'setTimeIcon' | 'beatIcon' | 'toneIcon' | 'iconNote2'
+    ) => {
+      if (val == 'setTimeIcon') {
+        showModalTime.value = true;
+      }
+      if (val == 'beatIcon') {
+        showModalBeat.value = true;
+      }
+      if (val == 'toneIcon') {
+        showModalTone.value = true;
+      }
+    };
+
+    // 是否允许上一页
+    const isUpArrow = computed(() => {
+      /**
+       * 1,判断当前课程中是否处在第一个资源;
+       * 2,判断当前课程是否在当前章节的第一个;
+       * 3,判断当前章节,当前课程上面还没有其它课程,是否有资源;
+       * 4,判断当前章节上面还没有其它章节;
+       * 5,判断上面章节里面课程是否有资源;
+       */
+      if (popupData.activeIndex > 0) {
+        return true;
+      }
+
+      // 获取当前是哪个章节
+      let detailIndex = popupData.chapterDetails.findIndex(
+        (item: any) => item.id == data.lessonCoursewareDetailId
+      );
+      const detailItem =
+        popupData.chapterDetails[detailIndex]?.knowledgeList || [];
+      let lessonIndex = detailItem.findIndex(
+        (item: any) => item.id == data.detailId
+      );
+
+      // 说明已经是第一单元,第一课
+      if (detailIndex <= 0 && lessonIndex <= 0) {
+        return false;
+      }
+
+      let lessonStatus = false; // 当前章节上面是否有内容
+      while (lessonIndex >= 0) {
+        lessonIndex--;
+
+        if (lessonIndex >= 0) {
+          if (detailItem[lessonIndex].coursewareNum > 0) {
+            lessonStatus = true;
+          }
+        }
+      }
+      // 判断当前章节下面课程是否有内容,否则往上一个章节走
+      if (lessonStatus) {
+        return true;
+      }
+
+      // 已经是第一个章节了
+      if (detailIndex <= 0) {
+        return false;
+      }
+
+      let prevLessonStatus = false;
+      while (detailIndex >= 0) {
+        detailIndex--;
+        const tempDetail =
+          popupData.chapterDetails[detailIndex]?.knowledgeList || [];
+        let tempLessonLength = tempDetail.length;
+        while (tempLessonLength > 0) {
+          if (tempDetail[tempLessonLength - 1].coursewareNum > 0) {
+            prevLessonStatus = true;
+          }
+          tempLessonLength--;
+        }
+
+        if (prevLessonStatus) {
+          return true;
+        }
+      }
+
+      return false;
+    });
+
+    // 是否允许下一页
+    const isDownArrow = computed(() => {
+      if (popupData.activeIndex < data.itemList.length - 1) {
+        return true;
+      }
+
+      // 获取当前是哪个章节
+      let detailIndex = popupData.chapterDetails.findIndex(
+        (item: any) => item.id == data.lessonCoursewareDetailId
+      );
+
+      const detailItem =
+        popupData.chapterDetails[detailIndex]?.knowledgeList || [];
+      let lessonIndex = detailItem.findIndex(
+        (item: any) => item.id == data.detailId
+      );
+
+      // 说明已经是最后-单元,最后一课
+      if (
+        detailIndex >= popupData.chapterDetails.length - 1 &&
+        lessonIndex >= detailItem.length - 1
+      ) {
+        return false;
+      }
+
+      let lessonStatus = false; // 当前章节下面是否有内容
+      while (lessonIndex < detailItem.length - 1) {
+        lessonIndex++;
+        if (lessonIndex >= 0) {
+          if (detailItem[lessonIndex].coursewareNum > 0) {
+            lessonStatus = true;
+          }
+        }
+      }
+      // 判断当前章节下面课程是否有内容,否则往下一个章节走
+      if (lessonStatus) {
+        return true;
+      }
+
+      // 已经是最后一个章节了
+      if (detailIndex >= popupData.chapterDetails.length - 1) {
+        return false;
+      }
+
+      let nextLessonStatus = false;
+      while (detailIndex < popupData.chapterDetails.length - 1) {
+        detailIndex++;
+        const tempDetail =
+          popupData.chapterDetails[detailIndex]?.knowledgeList || [];
+        let tempLessonLength = 0;
+        while (tempLessonLength <= tempDetail.length - 1) {
+          if (tempDetail[tempLessonLength].coursewareNum > 0) {
+            nextLessonStatus = true;
+          }
+          tempLessonLength++;
+        }
+
+        if (nextLessonStatus) {
+          return true;
+        }
+      }
+
+      return false;
+    });
+    const activeVideoItem = computed(() => {
+      const item = data.itemList[popupData.activeIndex];
+      if (item && item.type && item.type.toLocaleUpperCase() === 'VIDEO') {
+        return item;
+      }
+      return {};
+    });
+
+    // 右侧菜单栏
+    const rightList = reactive([
+      {
+        name: '上一张',
+        icon: bottomIconPre,
+        id: 11
+      },
+      {
+        name: '下一张',
+        icon: bottomIconNext,
+        id: 12
+      },
+      {
+        name: '切换章节',
+        icon: bottomIconSwitch,
+        id: 13
+      },
+      {
+        name: '资源列表',
+        icon: bottomIconResource,
+        id: 14
+      },
+      {
+        name: '曲目资源',
+        icon: rightIconMusic,
+        id: 9
+      },
+      {
+        name: '点名',
+        icon: rightIconCall,
+        id: 10
+      },
+      {
+        name: '布置作业',
+        icon: rightIconArrange,
+        id: 2
+      },
+      {
+        name: '工具箱',
+        icon: rightIconTool,
+        id: 15
+      },
+      {
+        name: '结束课程',
+        name2: '结束预览',
+        icon: rightIconEnd,
+        id: 1
+      },
+      {
+        name: '收起',
+        icon: leftIconPackUp,
+        id: 8
+      }
+    ]);
+    const tooltipList = [
+      {
+        name: '节拍器',
+        icon: rightIconMetronome,
+        id: 5
+      },
+      {
+        name: '计时器',
+        icon: rightIconTimer,
+        id: 7
+      },
+      {
+        name: '批注',
+        icon: rightIconPostil,
+        id: 3
+      },
+      {
+        name: '白板',
+        icon: rightIconWhiteboard,
+        id: 4
+      }
+      // {
+      //   name: '调音器',
+      //   icon: rightIconTuner,
+      //   id: 6
+      // }
+    ];
+    // 默认收起菜单
+    const columnShow = ref(true);
+    // 菜单位置
+    const columnPos = ref<'left' | 'right'>('left');
+    watch(columnPos, () => {
+      for (let i = 0; i < data.itemList.length; i++) {
+        const activeItem = data.itemList[i];
+        if (['RHYTHM', 'MUSIC'].includes(activeItem.type)) {
+          activeItem.iframeRef?.contentWindow?.postMessage(
+            { api: 'imagePos', data: columnPos.value },
+            '*'
+          );
+        }
+      }
+    });
+    // 右边栏操作
+    const operateRightBtn = async (id: number) => {
+      if (![8, 11, 12, 13, 14].includes(id)) {
+        handleStop(false);
+      }
+
+      switch (id) {
+        case 1:
+          if (data.type === 'preview') {
+            data.removeVisiable = true;
+            data.removeTitle = '结束预览';
+            data.removeContent = '请确认是否结束预览?';
+          } else {
+            const res = await getStudentAfterWork({
+              courseScheduleId: data.classId,
+              page: 1,
+              rows: 99
+            });
+            if (res.data.rows && res.data.rows.length) {
+              data.removeContent = '请确认是否结束课程?';
+              data.removeCourseStatus = false;
+            } else {
+              data.removeContent = '本次课堂尚未布置作业,是否结束课程?';
+              data.removeCourseStatus = true;
+            }
+            data.removeVisiable = true;
+            data.removeTitle = '结束课程';
+          }
+          break;
+        case 2:
+          // 学生人数必须大于0,才可以布置作业
+          if (data.preStudentNum <= 0) return;
+          // const res = await lessonPreTrainingPage({
+          //   coursewareKnowledgeDetailId: data.detailId,
+          //   instrumentId: data.instrumentId,
+          //   page: 1,
+          //   rows: 99
+          // });
+          // if (res.data.rows && res.data.rows.length) {
+          //   data.modalAttendMessage = '本节课已设置课后作业,是否布置?';
+          // }
+          // data.modelAttendStatus = true;
+          const res = await getStudentAfterWork({
+            courseScheduleId: data.classId,
+            page: 1,
+            rows: 99
+          });
+          if (res.data.rows && res.data.rows.length) {
+            // data.modalAttendMessage = '请确认是否结束课程?';
+            data.modalAttendMessage = '本次课程已布置作业,是否继续?';
+            data.modelAttendStatus = true;
+          } else {
+            data.modelTrainStatus = true;
+            nextTick(() => {
+              getModalHeight();
+            });
+            data.modelAttendStatus = false;
+          }
+          break;
+        case 3:
+          openStudyTool({
+            type: 'pen',
+            icon: iconNote,
+            name: '批注'
+          });
+          break;
+        case 4:
+          openStudyTool({
+            type: 'whiteboard',
+            icon: iconWhite,
+            name: '白板'
+          });
+          break;
+        case 5:
+          startShowModal('beatIcon');
+          break;
+        case 6:
+          startShowModal('toneIcon');
+          break;
+        case 7:
+          startShowModal('setTimeIcon');
+          break;
+        case 8:
+          columnShow.value = false;
+          break;
+        case 9:
+          // 选择曲目时需要暂停所有播放
+          handleStop(false);
+          data.selectResourceStatus = true;
+          break;
+        case 10:
+          //  点名
+          // await rollCallStudentList();
+          if (studyData.callStudentList.length > 0) {
+            openStudyTool({
+              type: 'call',
+              icon: iconWhite,
+              name: '点名'
+            });
+            return;
+          }
+          break;
+        case 11:
+          if (!isUpArrow.value) return;
+          handlePreAndNext('up');
+          break;
+        case 12:
+          if (!isDownArrow.value) return;
+          handlePreAndNext('down');
+          break;
+        case 13:
+          popupData.chapterOpen = true;
+          break;
+        case 14:
+          popupData.open = true;
+          nextTick(() => {
+            scrollResourceSection();
+          });
+          break;
+        default:
+          break;
+      }
+    };
+
+    // 点名学生列表
+    const rollCallStudentList = async () => {
+      //
+      if (!data.classId) return;
+      try {
+        const res = await getStudentList({
+          classGroupId: data.classGroupId,
+          page: 1,
+          rows: 999
+        });
+        const result = res.data || {};
+        if (Array.isArray(result.rows) && result.rows.length > 0) {
+          const tempStudents: any = [];
+          result.rows.forEach((row: any) => {
+            tempStudents.push({
+              name: row.nickname,
+              img: row.avatar
+            });
+          });
+          studyData.callStudentList = [...tempStudents];
+        }
+      } catch {
+        //
+      }
+    };
+
+    // 滚动到某个元素的位置
+    const scrollResourceSection = () => {
+      const drawerCardItemRefs =
+        document.querySelectorAll('.drawerCardItemRef');
+      if (
+        popupData.activeIndex >= 0 &&
+        drawerCardItemRefs[popupData.activeIndex]
+      ) {
+        drawerCardItemRefs[popupData.activeIndex].scrollIntoView();
+      }
+    };
+
+    const getModalHeight = () => {
+      const dom: any = document.querySelector('#model-homework-height');
+      if (dom) {
+        useResizeObserver(dom as HTMLElement, (entries: any) => {
+          const entry = entries[0];
+          const { height } = entry.contentRect;
+          dom.style.setProperty('--window-page-lesson-height', height + 'px');
+        });
+      }
+    };
+
+    /* 弹窗加拖动 */
+    // 选择课件弹窗
+    const selCourBoxClass = 'selCourBoxClass_drag';
+    const selCourDragData = useDrag(
+      [`${selCourBoxClass}>.n-card-header`, `${selCourBoxClass} .bom_drag`],
+      selCourBoxClass,
+      toRef(data, 'selectClassStatus'),
+      users.info.id
+    );
+    // 选择资源弹窗
+    const selResourBoxClass = 'selResourBoxClass_drag';
+    const selResourDragData = useDrag(
+      [
+        `${selResourBoxClass} .select-resource>.n-tabs>.n-tabs-nav--top.n-tabs-nav`,
+        `${selResourBoxClass} .bom_drag`
+      ],
+      selResourBoxClass,
+      toRef(data, 'selectResourceStatus'),
+      users.info.id
+    );
+    // 结束预览  结束课程确认弹窗
+    const removeResourBoxClass = 'removeResourBoxClass_drag';
+    const removeResourDragData = useDrag(
+      [
+        `${removeResourBoxClass}>.n-card-header`,
+        `${removeResourBoxClass} .bom_drag`
+      ],
+      removeResourBoxClass,
+      toRef(data, 'removeVisiable'),
+      users.info.id
+    );
+    // 章节next弹窗
+    const nextEndBoxClass = 'nextEndBoxClass_drag';
+    const nextEndBoxDragData = useDrag(
+      [`${nextEndBoxClass}>.n-card-header`, `${nextEndBoxClass} .bom_drag`],
+      nextEndBoxClass,
+      toRef(data, 'nextEndShow'),
+      users.info.id
+    );
+    // 章节切换弹窗
+    const chapterConBoxClass = 'chapterConBoxClass_drag';
+    const chapterConBoxDragData = useDrag(
+      [
+        `${chapterConBoxClass}>.n-card-header`,
+        `${chapterConBoxClass} .bom_drag`
+      ],
+      chapterConBoxClass,
+      toRef(popupData, 'chapterOpen'),
+      users.info.id
+    );
+    // 资源列表弹窗
+    const resourcesConBoxClass = 'resourcesConBoxClass_drag';
+    const resourcesConDragData = useDrag(
+      [
+        `${resourcesConBoxClass}>.n-card-header`,
+        `${resourcesConBoxClass} .bom_drag`
+      ],
+      resourcesConBoxClass,
+      toRef(popupData, 'open'),
+      users.info.id
+    );
+    // 计时器
+    const timerMeterConBoxClass = 'timerMeterConBoxClass_drag';
+    const timerMeterConDragData = useDrag(
+      [
+        `${timerMeterConBoxClass}>.n-card-header`,
+        `${timerMeterConBoxClass} .bom_drag`
+      ],
+      timerMeterConBoxClass,
+      showModalTime,
+      users.info.id
+    );
+    // 节拍器
+    const metronomeConBoxClass = 'metronomeConBoxClass_drag';
+    const metronomeConBoxDragData = useDrag(
+      [
+        `${metronomeConBoxClass}>.n-card-header`,
+        `${metronomeConBoxClass} .bom_drag`
+      ],
+      metronomeConBoxClass,
+      showModalBeat,
+      users.info.id
+    );
+    // 布置作业弹窗
+    const modelTrainStatusConBoxClass = 'modelTrainStatusConBoxClass_drag';
+    const modelTrainStatusConBoxDragData = useDrag(
+      [
+        `${modelTrainStatusConBoxClass}>.n-card-header`,
+        `${modelTrainStatusConBoxClass} .bom_drag`
+      ],
+      modelTrainStatusConBoxClass,
+      toRef(data, 'modelTrainStatus'),
+      users.info.id
+    );
+    // 布置作业课后作业
+    const modelTrainHomeWordConBoxClass =
+      'modelTrainHomeWordConBoxClassBoxClass_drag';
+    const modelTrainHomeWordConBoxDragData = useDrag(
+      [
+        `${modelTrainHomeWordConBoxClass}>.n-card-header`,
+        `${modelTrainHomeWordConBoxClass} .bom_drag`
+      ],
+      modelTrainHomeWordConBoxClass,
+      toRef(data, 'modelAttendStatus'),
+      users.info.id
+    );
+    return () => (
+      <div id="playContent" class={[styles.playContent, 'wrap']}>
+        <div
+          onClick={() => {
+            clearTimeout(activeData.timer);
+            activeData.model = !activeData.model;
+            Object.values(data.videoRefs).map((n: any) =>
+              n?.toggleHideControl(activeData.model)
+            );
+            Object.values(data.audioRefs).map((n: any) =>
+              n?.toggleHideControl(activeData.model)
+            );
+          }}>
+          <div
+            class={styles.coursewarePlay}
+            style={{ width: parentContainer.width }}>
+            {!popupData.chapterLoading ? (
+              <div class={styles.wraps}>
+                <div
+                  style={
+                    activeVideoItem.value.type &&
+                    data.animationState === 'end' &&
+                    data.videoState === 'play'
+                      ? {
+                          zIndex: 15,
+                          opacity: 1
+                        }
+                      : { opacity: 0, zIndex: -1 }
+                  }
+                  class={styles.itemDiv}>
+                  <VideoPlay
+                    imagePos={columnPos.value}
+                    ref={(el: any) => (data.videoItemRef = el)}
+                    item={activeVideoItem.value}
+                    showModel={activeData.model}
+                    onClose={setModelOpen}
+                    onLoadedmetadata={(videoItem: any) => {
+                      if (data.itemList[popupData.activeIndex]) {
+                        data.itemList[popupData.activeIndex].videoEle =
+                          videoItem;
+                      }
+                    }}
+                    onCanplay={() => {
+                      data.videoState = 'play';
+                      // activeVideoItem.value.videoEle = videoItem;
+                    }}
+                    onPause={() => {
+                      clearTimeout(activeData.timer);
+                      activeData.model = true;
+                    }}
+                    onEnded={() => {
+                      // const _index = popupData.activeIndex + 1;
+                      // if (_index < data.itemList.length) {
+                      //   handleSwipeChange(_index);
+                      // }
+                    }}
+                  />
+                </div>
+                {data.itemList.map((m: any, mIndex: number) => {
+                  const isRender = Math.abs(popupData.activeIndex - mIndex) < 2;
+                  const isEmtry = Math.abs(popupData.activeIndex - mIndex) > 4;
+                  // if (isRender && m.type === 'PPT') {
+                  //   setTimeout(() => iframeClick() ,500)
+                  // }
+                  // if (isRender) {
+                  //   m.isRender = true;
+                  // }
+
+                  // const isRender =
+                  //   m.isRender || Math.abs(popupData.activeIndex - mIndex) < 2;
+                  // const isEmtry = Math.abs(popupData.activeIndex - mIndex) > 4;
+                  // if (isRender) {
+                  //   m.isRender = true;
+                  // }
+
+                  return isRender ? (
+                    <div
+                      key={'index' + mIndex}
+                      class={[
+                        styles.itemDiv,
+                        popupData.activeIndex === mIndex && styles.itemActive,
+                        activeData.isAnimation && styles.acitveAnimation,
+                        Math.abs(popupData.activeIndex - mIndex) < 2
+                          ? styles.show
+                          : styles.hide
+                      ]}
+                      style={
+                        mIndex < popupData.activeIndex
+                          ? effects[effectIndex.value].prev
+                          : mIndex > popupData.activeIndex
+                          ? effects[effectIndex.value].next
+                          : {}
+                      }
+                      onClick={(e: Event) => {
+                        e.stopPropagation();
+                        clearTimeout(activeData.timer);
+                        if (Date.now() - activeData.nowTime < 300) {
+                          handleDbClick(m);
+                          return;
+                        }
+                        activeData.nowTime = Date.now();
+                        activeData.timer = setTimeout(() => {
+                          activeData.model = !activeData.model;
+                          Object.values(data.videoRefs).map((n: any) =>
+                            n?.toggleHideControl(activeData.model)
+                          );
+                          Object.values(data.audioRefs).map((n: any) =>
+                            n?.toggleHideControl(activeData.model)
+                          );
+                          if (activeData.model) {
+                            setModelOpen();
+                          }
+                        }, 300);
+                      }}>
+                      {m.type === 'VIDEO' ? (
+                        <>
+                          <img
+                            src={m.coverImg}
+                            onLoad={() => {
+                              m.isprepare = true;
+                            }}
+                          />
+                          {/* <VideoPlay
+                            ref={(v: any) => (data.videoRefs[mIndex] = v)}
+                            item={m}
+                            isEmtry={isEmtry}
+                            onLoadedmetadata={(videoItem: any) => {
+                              m.videoEle = videoItem;
+                              m.isprepare = true;
+                            }}
+                            onTogglePlay={(paused: boolean) => {
+                              m.autoPlay = false;
+                              if (paused || popupData.open) {
+                                clearTimeout(activeData.timer);
+                              } else {
+                                setModelOpen();
+                              }
+                            }}
+                            onReset={() => {
+                              if (!m.videoEle?.paused) {
+                                setModelOpen();
+                              }
+                            }}
+                            onError={() => {
+                              console.log('video error');
+                              m.error = true;
+                            }}
+                          /> */}
+                          <Transition name="van-fade">
+                            {
+                              <div class={styles.loadWrap}>
+                                <Vue3Lottie
+                                  animationData={playLoadData}></Vue3Lottie>
+                              </div>
+                            }
+                          </Transition>
+                        </>
+                      ) : m.type === 'IMG' ? (
+                        <img src={m.content} />
+                      ) : m.type === 'SONG' ? (
+                        <AudioPay
+                          imagePos={columnPos.value}
+                          item={m}
+                          activeStatus={popupData.activeIndex === mIndex}
+                          ref={(v: any) => (data.audioRefs[mIndex] = v)}
+                          onLoadedmetadata={(audioItem: any) => {
+                            m.audioEle = audioItem;
+                            m.isprepare = true;
+                          }}
+                          onTogglePlay={(paused: boolean) => {
+                            // m.autoPlay = false;
+                            if (paused || popupData.open) {
+                              clearTimeout(activeData.timer);
+                            } else {
+                              setModelOpen();
+                            }
+                          }}
+                          onEnded={() => {
+                            // const _index = popupData.activeIndex + 1;
+                            // if (_index < data.itemList.length) {
+                            //   handleSwipeChange(_index);
+                            // }
+                          }}
+                          onReset={() => {
+                            if (!m.audioEle?.paused) {
+                              setModelOpen();
+                            }
+                          }}
+                        />
+                      ) : // : m.type === 'PPT' ? <div class={styles.iframePpt}>
+                      //   <div class={styles.pptBox}></div>
+                      //   <iframe src={`https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(m.content)}`} width='100%' height='100%' frameborder='1'></iframe>
+                      // </div>
+                      m.type === 'PPT' ? (
+                        <iframe
+                          src={`https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(
+                            m.content
+                          )}`}
+                          width="100%"
+                          height="100%"
+                          frameborder="1"></iframe>
+                      ) : m.type === 'RHYTHM' ? (
+                        <RhythmModal
+                          item={m}
+                          activeStatus={popupData.activeIndex === mIndex}
+                          imagePos={columnPos.value}
+                          onSetIframe={(el: any) => {
+                            m.iframeRef = el;
+                          }}
+                        />
+                      ) : m.type === 'LISTEN' ? (
+                        <ListenModal
+                          item={m}
+                          data-vid={m.id}
+                          activeStatus={popupData.activeIndex === mIndex}
+                          onSetIframe={(el: any) => {
+                            m.iframeRef = el;
+                          }}
+                        />
+                      ) : m.type === 'INSTRUMENT' || m.type === 'MUSICIAN' ? (
+                        <InstruemntDetail
+                          type="preview"
+                          id={m.content}
+                          contentType={m.type}
+                          activeStatus={popupData.activeIndex === mIndex}
+                          ref={(el: any) => (m.iframeRef = el)}
+                        />
+                      ) : m.type === 'MUSIC_WIKI' ? (
+                        <MusicDetail
+                          type="preview"
+                          id={m.content}
+                          contentType={m.type}
+                          activeStatus={popupData.activeIndex === mIndex}
+                          ref={(el: any) => (m.iframeRef = el)}
+                        />
+                      ) : m.type === 'THEORY' ? (
+                        <TheotyDetail
+                          type="preview"
+                          id={m.content}
+                          activeStatus={popupData.activeIndex === mIndex}
+                          ref={(el: any) => (m.iframeRef = el)}
+                        />
+                      ) : (
+                        <MusicScore
+                          activeModel={activeData.model}
+                          activeStatus={popupData.activeIndex === mIndex}
+                          data-vid={m.id}
+                          music={m}
+                          imagePos={columnPos.value}
+                          onSetIframe={(el: any) => {
+                            m.iframeRef = el;
+                          }}
+                        />
+                      )}
+                    </div>
+                  ) : null;
+                })}
+              </div>
+            ) : (
+              ''
+            )}
+          </div>
+        </div>
+
+        {/* 右边操作栏 */}
+        <div
+          class={[
+            styles.rightColumn,
+            columnShow.value && columnPos.value === 'right'
+              ? ''
+              : styles.rightColumnHide
+          ]}>
+          {rightList.map((item: any) => (
+            <div class={styles.columnItemBox}>
+              <div
+                class={[
+                  styles.columnItem,
+                  (item.id === 2 && data.preStudentNum <= 0) ||
+                  (item.id === 10 && studyData.callStudentList.length <= 0) ||
+                  (item.id === 11 && !isUpArrow.value) ||
+                  (item.id === 12 && !isDownArrow.value)
+                    ? styles.itemDisabled
+                    : ''
+                ]}
+                onClick={() => operateRightBtn(item.id)}>
+                <NTooltip
+                  showArrow={false}
+                  placement="left"
+                  class={[
+                    item.id === 15
+                      ? 'columnItemTooltip rightColumnItemTooltip'
+                      : ''
+                  ]}>
+                  {{
+                    trigger: () => (
+                      <img src={item.id === 8 ? rightIconPackUp : item.icon} />
+                    ),
+                    default: () =>
+                      item.id === 15 ? (
+                        <div class="tools">
+                          {tooltipList.map(i => (
+                            <div onClick={() => operateRightBtn(i.id)}>
+                              <img src={i.icon} />
+                              <div class="tit">{i.name}</div>
+                            </div>
+                          ))}
+                        </div>
+                      ) : item.id === 1 && data.type === 'preview' ? (
+                        item.name2
+                      ) : (
+                        item.name
+                      )
+                  }}
+                </NTooltip>
+              </div>
+            </div>
+          ))}
+        </div>
+        <img
+          class={[
+            styles.rightHideIcon,
+            !(columnShow.value && columnPos.value === 'right')
+              ? styles.rightIconShow
+              : ''
+          ]}
+          src={rightHideIcon}
+          onClick={() => {
+            columnPos.value = 'right';
+            columnShow.value = true;
+          }}
+        />
+        {/* 左边操作栏 */}
+        <div
+          class={[
+            styles.leftColumn,
+            columnShow.value && columnPos.value === 'left'
+              ? ''
+              : styles.leftColumnHide
+          ]}>
+          {rightList.map((item: any) => (
+            <div class={styles.columnItemBox}>
+              <div
+                class={[
+                  styles.columnItem,
+                  (item.id === 2 && data.preStudentNum <= 0) ||
+                  (item.id === 10 && studyData.callStudentList.length <= 0) ||
+                  (item.id === 11 && !isUpArrow.value) ||
+                  (item.id === 12 && !isDownArrow.value)
+                    ? styles.itemDisabled
+                    : ''
+                ]}
+                onClick={() => operateRightBtn(item.id)}>
+                <NTooltip
+                  showArrow={false}
+                  placement="right"
+                  class={[item.id === 15 ? 'columnItemTooltip' : '']}>
+                  {{
+                    trigger: () => <img src={item.icon} />,
+                    default: () =>
+                      item.id === 15 ? (
+                        <div class="tools">
+                          {tooltipList.map(i => (
+                            <div onClick={() => operateRightBtn(i.id)}>
+                              <img src={i.icon} />
+                              <div class="tit">{i.name}</div>
+                            </div>
+                          ))}
+                        </div>
+                      ) : item.id === 1 && data.type === 'preview' ? (
+                        item.name2
+                      ) : (
+                        item.name
+                      )
+                  }}
+                </NTooltip>
+              </div>
+            </div>
+          ))}
+        </div>
+        <img
+          class={[
+            styles.leftHideIcon,
+            !(columnShow.value && columnPos.value === 'left')
+              ? styles.leftIconShow
+              : ''
+          ]}
+          src={leftHideIcon}
+          onClick={() => {
+            columnPos.value = 'left';
+            columnShow.value = true;
+          }}
+        />
+
+        {/* 显示列表 */}
+        {/* <NDrawer
+          v-model:show={popupData.open}
+          class={[styles.drawerContainer, styles.drawerContainerSource]}
+          onAfterLeave={handleClosePopup}
+          showMask={false}
+          blockScroll={false}
+          trapFocus={false}>
+          <NDrawerContent closable>
+            {{
+              header: () => (
+                <TheNoticeBar text={activeName.value || '资源列表'} />
+              ),
+              default: () => (
+                <SourceList
+                  teacherChapterName={data.teacherChapterName}
+                  knowledgePointList={data.knowledgePointList}
+                  courseActiveIndex={popupData.courseActiveIndex}
+                  activeItem={data.itemList[popupData.activeIndex]}
+                  onConfirm={(item: any) => {
+                    popupData.open = false;
+                    toggleMaterial(item.id);
+                  }}
+                />
+              )
+            }}
+          </NDrawerContent>
+        </NDrawer> */}
+        <NModal
+          transformOrigin="center"
+          v-model:show={popupData.open}
+          preset="card"
+          class={[
+            'modalTitle background',
+            styles.drawerContainer,
+            resourcesConBoxClass
+          ]}
+          style={resourcesConDragData.styleDrag.value}
+          title={activeName.value || '资源列表'}>
+          <SourceList
+            teacherChapterName={data.teacherChapterName}
+            knowledgePointList={data.knowledgePointList}
+            courseActiveIndex={popupData.courseActiveIndex}
+            activeItem={data.itemList[popupData.activeIndex]}
+            onConfirm={(item: any) => {
+              popupData.open = false;
+              toggleMaterial(item.id);
+            }}
+          />
+          <Dragbom></Dragbom>
+        </NModal>
+        {/* 章节切换 */}
+        {/* <NDrawer
+          v-model:show={popupData.chapterOpen}
+          class={styles.drawerContainer}
+          onAfterLeave={handleClosePopup}
+          showMask={false}
+          maskClosable={data.selectClassStatus ? false : true}
+          blockScroll={false}
+          trapFocus={false}>
+          <NDrawerContent title="切换章节" closable>
+            <Chapter
+              treeList={popupData.chapterDetails}
+              itemActive={data.detailId as any}
+              onHandleSelect={async (val: any) => {
+                // itemActive: child.id,
+                // itemName: child.name
+                popupData.courseId = val.itemActive;
+                data.selectClassStatus = true;
+              }}
+            />
+          </NDrawerContent>
+        </NDrawer> */}
+        <NModal
+          transformOrigin="center"
+          v-model:show={popupData.chapterOpen}
+          preset="card"
+          class={[
+            'modalTitle background',
+            styles.drawerContainer,
+            chapterConBoxClass
+          ]}
+          style={chapterConBoxDragData.styleDrag.value}
+          title={'切换章节'}>
+          <Chapter
+            treeList={popupData.chapterDetails}
+            itemActive={data.detailId as any}
+            onHandleSelect={async (val: any) => {
+              // itemActive: child.id,
+              // itemName: child.name
+              popupData.courseId = val.itemActive;
+              data.selectClassStatus = true;
+            }}
+          />
+          <Dragbom></Dragbom>
+        </NModal>
+        {/* 批注 */}
+        {studyData.penShow && (
+          <Pen
+            isDrag={true}
+            show={studyData.type === 'pen'}
+            type={studyData.type}
+            close={() => closeStudyTool()}
+          />
+        )}
+
+        {studyData.whiteboardShow && (
+          <Pen
+            isDrag={true}
+            show={studyData.type === 'whiteboard'}
+            type={studyData.type}
+            close={() => closeStudyTool()}
+          />
+        )}
+
+        {studyData.callShow && (
+          <Pen
+            isDrag={true}
+            imagePos={columnPos.value}
+            callStudents={studyData.callStudentList}
+            show={studyData.type === 'call'}
+            type={studyData.type}
+            close={() => closeStudyTool()}
+          />
+        )}
+
+        {/* 选择课件 */}
+        <NModal
+          transformOrigin="center"
+          v-model:show={data.selectClassStatus}
+          preset="card"
+          class={[
+            'modalTitle background',
+            // styles.attendClassModal,
+            styles.selectClassModal,
+            selCourBoxClass
+          ]}
+          style={selCourDragData.styleDrag.value}
+          title={'选择课件'}>
+          <SelectClass
+            classId={data.classId}
+            courseId={popupData.courseId}
+            instrumentId={data.instrumentId}
+            lessonCoursewareSubjectList={data.lessonCoursewareSubjectList}
+            onConfirm={async (val: any) => {
+              popupData.chapterLoading = true;
+              try {
+                data.selectClassStatus = false;
+                data.detailId = val.itemActive;
+                data.courseId = val.chapterId;
+                const ids = formatParentId(
+                  val.itemActive,
+                  popupData.chapterDetails
+                );
+                data.lessonCoursewareDetailId = ids[0];
+                // 更新上课记录 上课的时候才更新
+                if (data.type !== 'preview') {
+                  await classCourseScheduleUpdate();
+                }
+                await getDetail();
+                popupData.activeIndex = 0;
+                popupData.chapterOpen = false;
+              } catch {
+                //
+              }
+              popupData.chapterLoading = false;
+            }}
+          />
+          <Dragbom></Dragbom>
+        </NModal>
+
+        {/* 布置作业 */}
+        <NModal
+          transformOrigin="center"
+          v-model:show={data.modelAttendStatus}
+          preset="card"
+          title={'课后作业'}
+          style={modelTrainHomeWordConBoxDragData.styleDrag.value}
+          class={[
+            'modalTitle',
+            styles.removeVisiable,
+            modelTrainHomeWordConBoxClass
+          ]}>
+          <div class={styles.studentRemove}>
+            <p>{data.modalAttendMessage}</p>
+            <NSpace class={styles.btnGroupModal} justify="center">
+              <NButton
+                type="default"
+                round
+                onClick={() => {
+                  data.modelTrainStatus = true;
+                  nextTick(() => {
+                    getModalHeight();
+                  });
+                  data.modelAttendStatus = false;
+                }}>
+                布置作业
+              </NButton>
+              <NButton
+                type="primary"
+                round
+                onClick={() => {
+                  handleStop();
+                  data.modelAttendStatus = false;
+                }}>
+                取消
+              </NButton>
+            </NSpace>
+          </div>
+          <Dragbom class={styles.dragbom}></Dragbom>
+        </NModal>
+
+        {/* 训练设置 */}
+        {/* <NModal
+          transformOrigin="center"
+          v-model:show={data.modelTrainStatus}
+          preset="card"
+          class={[styles.attendClassModal, styles.trainClassModal]}
+          title={'作业设置'}>
+          <ClassWork
+            detailId={data.detailId}
+            instrumentId={data.instrumentId}
+            courseScheduleId={data.classId}
+            activeName={activeName.value}
+            classGroupId={data.classGroupId}
+            onClose={() => (data.modelTrainStatus = false)}
+          />
+        </NModal> */}
+        <NModal
+          v-model:show={data.modelTrainStatus}
+          preset="card"
+          class={[
+            'modalTitle background',
+            styles.workVisiable,
+            modelTrainStatusConBoxClass
+          ]}
+          style={modelTrainStatusConBoxDragData.styleDrag.value}
+          title={'布置作业'}>
+          <div id="model-homework-height" class={styles.workContainer}>
+            <div class={styles.workTrain}>
+              <Train
+                from={'class'}
+                cardType="homeworkRecord"
+                lessonPreTraining={{
+                  title: data.lessonPreTrainingId
+                    ? ''
+                    : data.teacherChapterName + '-课后作业',
+                  chapterId: data.courseId, // 课件编号
+                  id: data.lessonPreTrainingId // 作业编号
+                }}
+                classGroupId={data.classGroupId}
+                courseScheduleId={data.classId}
+                onChange={async (val: any) => {
+                  data.modelTrainStatus = val.status;
+                  // getCoursewareList();
+                  if (val.saveWork) {
+                    try {
+                      const res =
+                        await api_teacherChapterLessonCoursewareDetail(
+                          data.courseId
+                        );
+
+                      data.lessonPreTrainingId = res.data.lessonPreTrainingId;
+                    } catch {
+                      //
+                    }
+                  }
+                }}
+              />
+            </div>
+            <div class={styles.resourceMain}>
+              <ResourceMain from={'class'} cardType="homerowk-record" />
+            </div>
+          </div>
+          <Dragbom class={styles.dragbom}></Dragbom>
+        </NModal>
+
+        <NModal
+          transformOrigin="center"
+          class={['modalTitle background', metronomeConBoxClass]}
+          title={'节拍器'}
+          preset="card"
+          v-model:show={showModalBeat.value}
+          style={{
+            width: '687px',
+            ...metronomeConBoxDragData.styleDrag.value
+          }}>
+          <div class={styles.modeWrap}>
+            <iframe
+              src={`${vaildUrl()}/metronome/?id=${new Date().getTime()}`}
+              scrolling="no"
+              frameborder="0"
+              width="100%"
+              onLoad={(val: any) => {
+                iframeDislableKeyboard(val.target);
+              }}
+              height={'650px'}></iframe>
+            <Dragbom class={styles.dragbom}></Dragbom>
+          </div>
+        </NModal>
+
+        <NModal
+          transformOrigin="center"
+          class={['background']}
+          v-model:show={showModalTone.value}>
+          <div>
+            <PlaceholderTone
+              onClose={() => {
+                showModalTone.value = false;
+              }}></PlaceholderTone>
+          </div>
+        </NModal>
+        <NModal
+          transformOrigin="center"
+          v-model:show={showModalTime.value}
+          class={['modalTitle background', timerMeterConBoxClass]}
+          title={'计时器'}
+          preset="card"
+          style={{
+            width: px2vw(772),
+            ...timerMeterConDragData.styleDrag.value
+          }}>
+          <div>
+            <TimerMeter></TimerMeter>
+            <Dragbom class={styles.dragbom}></Dragbom>
+          </div>
+        </NModal>
+
+        <NModal
+          v-model:show={data.selectResourceStatus}
+          class={['modalTitle', styles.selectMusicModal, selResourBoxClass]}
+          style={selResourDragData.styleDrag.value}
+          preset="card"
+          title={'选择资源'}>
+          <SelectResources from="class" />
+          <Dragbom></Dragbom>
+        </NModal>
+        <NModal
+          transformOrigin="center"
+          v-model:show={data.removeVisiable}
+          preset="card"
+          class={['modalTitle', styles.removeVisiable, removeResourBoxClass]}
+          style={removeResourDragData.styleDrag.value}
+          title={data.removeTitle}>
+          <div class={styles.studentRemove}>
+            <p>{data.removeContent}</p>
+
+            <NSpace class={styles.btnGroupModal} justify="center">
+              <NButton
+                round
+                onClick={() => {
+                  if (data.removeCourseStatus) {
+                    if (globalState.application) {
+                      document.exitFullscreen
+                        ? document.exitFullscreen()
+                        : document.mozCancelFullScreen
+                        ? document.mozCancelFullScreen()
+                        : document.webkitExitFullscreen
+                        ? document.webkitExitFullscreen()
+                        : '';
+                      emit('close');
+                    } else {
+                      window.close();
+                    }
+                  } else {
+                    data.removeVisiable = false;
+                  }
+                }}>
+                {data.removeCourseStatus ? '结束课程' : '取消'}
+              </NButton>
+              <NButton
+                round
+                type="primary"
+                onClick={() => {
+                  //
+                  if (data.removeCourseStatus) {
+                    data.modelTrainStatus = true;
+                    data.removeVisiable = false;
+                    nextTick(() => {
+                      getModalHeight();
+                    });
+                  } else {
+                    if (globalState.application) {
+                      document.exitFullscreen
+                        ? document.exitFullscreen()
+                        : document.mozCancelFullScreen
+                        ? document.mozCancelFullScreen()
+                        : document.webkitExitFullscreen
+                        ? document.webkitExitFullscreen()
+                        : '';
+                      emit('close');
+                    } else {
+                      window.close();
+
+                      if (route.query.source === 'admin') {
+                        storage.remove(ACCESS_TOKEN_ADMIN);
+                        window.parent.postMessage(
+                          {
+                            api: 'iframe_exit'
+                          },
+                          '*'
+                        );
+                      }
+                    }
+                  }
+                }}>
+                {data.removeCourseStatus ? '布置作业' : '确定'}
+              </NButton>
+            </NSpace>
+            <Dragbom></Dragbom>
+          </div>
+        </NModal>
+        <NModal
+          style={nextEndBoxDragData.styleDrag.value}
+          z-index={3000}
+          transformOrigin="center"
+          v-model:show={data.nextEndShow}
+          preset="card"
+          title={'提示'}
+          class={['modalTitle', styles.removeVisiable, nextEndBoxClass]}>
+          <div class={styles.studentRemove}>
+            <p>当前课件已结束,是否进入下一章节</p>
+            <NSpace class={styles.btnGroupModal} justify="center">
+              <NButton
+                type="default"
+                round
+                onClick={() => {
+                  data.nextEndShow = false;
+                }}>
+                取消
+              </NButton>
+              <NButton
+                type="primary"
+                round
+                onClick={() => {
+                  data.nextEndShow = false;
+                  handleNextEnd();
+                }}>
+                确认
+              </NButton>
+            </NSpace>
+            <Dragbom></Dragbom>
+          </div>
+        </NModal>
+      </div>
+    );
+  }
+});
+>>>>>>> Stashed changes

+ 165 - 160
src/views/attend-class/model/select-class/index.tsx

@@ -1,160 +1,165 @@
-import { PropType, defineComponent, onMounted, reactive } from 'vue';
-import styles from './index.module.less';
-import { teacherChapterLessonCoursewareList } from '/src/views/prepare-lessons/api';
-import { NCascader, NInput, NScrollbar, NSelect, NSpin } from 'naive-ui';
-import CoursewareType from '/src/views/prepare-lessons/model/courseware-type';
-import TheEmpty from '/src/components/TheEmpty';
-
-export default defineComponent({
-  name: 'select-class',
-  props: {
-    courseId: {
-      type: String as PropType<'' | null>,
-      default: ''
-    },
-    instrumentId: {
-      type: String,
-      default: ''
-    },
-    lessonCoursewareSubjectList: {
-      type: Array,
-      default: () => []
-    },
-    classId: {
-      type: String,
-      default: ''
-    }
-  },
-  emits: ['confirm', 'close'],
-  setup(props, { emit }) {
-    const forms = reactive({
-      loading: false,
-      instrumentId: props.instrumentId ? Number(props.instrumentId) : '',
-      tableList: [] as any
-    });
-
-    const getDetail = async () => {
-      forms.loading = true;
-      try {
-        // 如果是上课则查询班级声部,预览查询全部
-        // console.log(props.classId, props.instrumentId);
-        const { data } = await teacherChapterLessonCoursewareList({
-          coursewareDetailKnowledgeId: props.courseId,
-          instrumentId: props.classId ? forms.instrumentId : null
-        });
-
-        if (!Array.isArray(data)) {
-          return;
-        }
-        const tempList: any = [];
-        data.forEach((item: any) => {
-          const firstItem: any =
-            item.chapterKnowledgeList[0]?.chapterKnowledgeMaterialList[0];
-          tempList.push({
-            id: item.id,
-            openFlag: item.openFlag,
-            openFlagEnable: item.openFlagEnable,
-            subjectNames: item.subjectNames,
-            fromChapterLessonCoursewareId: item.fromChapterLessonCoursewareId,
-            name: item.name,
-            coverImg: firstItem?.bizInfo.coverImg,
-            type: firstItem?.bizInfo.type
-          });
-        });
-        forms.tableList = tempList;
-      } catch {
-        //
-      }
-      forms.loading = false;
-    };
-
-    onMounted(() => {
-      if (props.instrumentId) {
-        const s = Number(props.instrumentId);
-        let isE = false;
-        props.lessonCoursewareSubjectList.forEach((item: any) => {
-          if (item.id === s) {
-            isE = true;
-          }
-        });
-        if (!isE) {
-          forms.instrumentId = '';
-        }
-      }
-      getDetail();
-    });
-    return () => (
-      <div class={styles.selectClass}>
-        {props.classId && (
-          <div class={styles.searchGroup}>
-            <NSelect
-              options={[
-                { id: '', name: '全部乐器' },
-                ...(props.lessonCoursewareSubjectList as any)
-              ]}
-              valueField="id"
-              labelField="name"
-              style={{ width: '220px' }}
-              placeholder={'请选择乐器'}
-              v-model:value={forms.instrumentId}
-              onUpdate:value={() => {
-                getDetail();
-              }}
-            />
-            {/* <NCascader
-              options={[
-                { id: '', name: '全部声部' },
-                ...(props.lessonCoursewareSubjectList as any)
-              ]}
-              valueField="id"
-              labelField="name"
-              style={{ width: '220px' }}
-              placeholder={'请选择声部'}
-              v-model:value={forms.instrumentId}
-              onUpdate:value={() => {
-                getDetail();
-              }}
-              checkStrategy="child"
-              showPath
-              childrenField="instruments"
-              expandTrigger="hover"
-              clearable
-              filterable
-            /> */}
-          </div>
-        )}
-
-        <NSpin show={forms.loading}>
-          <NScrollbar class={styles.selectClassScroll}>
-            <div
-              class={[
-                styles.list,
-                !forms.loading &&
-                  forms.tableList.length <= 0 &&
-                  styles.listEmpty
-              ]}>
-              {forms.tableList.map((item: any) => (
-                <div class={[styles.itemWrap, styles.itemBlock, 'row-nav']}>
-                  <div class={styles.itemWrapBox}>
-                    <CoursewareType
-                      isShowPreviewBtn
-                      isShowOpenFlag={false}
-                      item={item}
-                      onClick={() => {
-                        emit('confirm', {
-                          itemActive: props.courseId,
-                          chapterId: item.id
-                        });
-                      }}
-                    />
-                  </div>
-                </div>
-              ))}
-              {!forms.loading && forms.tableList.length <= 0 && <TheEmpty />}
-            </div>
-          </NScrollbar>
-        </NSpin>
-      </div>
-    );
-  }
-});
+import { PropType, defineComponent, onMounted, reactive } from 'vue';
+import styles from './index.module.less';
+import { teacherChapterLessonCoursewareList } from '/src/views/prepare-lessons/api';
+import { NCascader, NInput, NScrollbar, NSelect, NSpin } from 'naive-ui';
+import CoursewareType from '/src/views/prepare-lessons/model/courseware-type';
+import TheEmpty from '/src/components/TheEmpty';
+
+export default defineComponent({
+  name: 'select-class',
+  props: {
+    courseId: {
+      type: String as PropType<'' | null>,
+      default: ''
+    },
+    instrumentId: {
+      type: String,
+      default: ''
+    },
+    lessonCoursewareSubjectList: {
+      type: Array,
+      default: () => []
+    },
+    classId: {
+      type: String,
+      default: ''
+    }
+  },
+  emits: ['confirm', 'close'],
+  setup(props, { emit }) {
+    const forms = reactive({
+      loading: false,
+      instrumentId: props.instrumentId ? Number(props.instrumentId) : '',
+      tableList: [] as any
+    });
+
+    const getDetail = async () => {
+      forms.loading = true;
+      try {
+        // 如果是上课则查询班级声部,预览查询全部
+        // console.log(props.classId, props.instrumentId);
+        const { data } = await teacherChapterLessonCoursewareList({
+          coursewareDetailKnowledgeId: props.courseId,
+          instrumentId: props.classId ? forms.instrumentId : null
+        });
+
+        if (!Array.isArray(data)) {
+          return;
+        }
+        const tempList: any = [];
+        data.forEach((item: any) => {
+          const firstItem: any =
+            item.chapterKnowledgeList[0]?.chapterKnowledgeMaterialList[0];
+          tempList.push({
+            id: item.id,
+            openFlag: item.openFlag,
+            openFlagEnable: item.openFlagEnable,
+            subjectNames: item.subjectNames,
+            fromChapterLessonCoursewareId: item.fromChapterLessonCoursewareId,
+            name: item.name,
+            coverImg: firstItem?.bizInfo.coverImg,
+            type: firstItem?.bizInfo.type
+          });
+        });
+        forms.tableList = tempList;
+      } catch {
+        //
+      }
+      forms.loading = false;
+    };
+
+    onMounted(() => {
+      console.log(
+        props.instrumentId,
+        props.lessonCoursewareSubjectList,
+        'props.lessonCoursewareSubjectList'
+      );
+      if (props.instrumentId) {
+        const s = Number(props.instrumentId);
+        let isE = false;
+        props.lessonCoursewareSubjectList.forEach((item: any) => {
+          if (item.id === s) {
+            isE = true;
+          }
+        });
+        if (!isE) {
+          forms.instrumentId = '';
+        }
+      }
+      getDetail();
+    });
+    return () => (
+      <div class={styles.selectClass}>
+        {props.classId && (
+          <div class={styles.searchGroup}>
+            <NSelect
+              options={[
+                { id: '', name: '全部乐器' },
+                ...(props.lessonCoursewareSubjectList as any)
+              ]}
+              valueField="id"
+              labelField="name"
+              style={{ width: '220px' }}
+              placeholder={'请选择乐器'}
+              v-model:value={forms.instrumentId}
+              onUpdate:value={() => {
+                getDetail();
+              }}
+            />
+            {/* <NCascader
+              options={[
+                { id: '', name: '全部声部' },
+                ...(props.lessonCoursewareSubjectList as any)
+              ]}
+              valueField="id"
+              labelField="name"
+              style={{ width: '220px' }}
+              placeholder={'请选择声部'}
+              v-model:value={forms.instrumentId}
+              onUpdate:value={() => {
+                getDetail();
+              }}
+              checkStrategy="child"
+              showPath
+              childrenField="instruments"
+              expandTrigger="hover"
+              clearable
+              filterable
+            /> */}
+          </div>
+        )}
+
+        <NSpin show={forms.loading}>
+          <NScrollbar class={styles.selectClassScroll}>
+            <div
+              class={[
+                styles.list,
+                !forms.loading &&
+                  forms.tableList.length <= 0 &&
+                  styles.listEmpty
+              ]}>
+              {forms.tableList.map((item: any) => (
+                <div class={[styles.itemWrap, styles.itemBlock, 'row-nav']}>
+                  <div class={styles.itemWrapBox}>
+                    <CoursewareType
+                      isShowPreviewBtn
+                      isShowOpenFlag={false}
+                      item={item}
+                      onClick={() => {
+                        emit('confirm', {
+                          itemActive: props.courseId,
+                          chapterId: item.id
+                        });
+                      }}
+                    />
+                  </div>
+                </div>
+              ))}
+              {!forms.loading && forms.tableList.length <= 0 && <TheEmpty />}
+            </div>
+          </NScrollbar>
+        </NSpin>
+      </div>
+    );
+  }
+});

+ 635 - 635
src/views/homework-record/index.tsx

@@ -1,635 +1,635 @@
-import { defineComponent, reactive, onMounted, ref } from 'vue';
-import styles from './index.module.less';
-import {
-  NAvatar,
-  NButton,
-  NDivider,
-  NForm,
-  NFormItem,
-  NImage,
-  NModal,
-  NSpace,
-  NSpin,
-  useMessage
-} from 'naive-ui';
-import SearchInput from '@/components/searchInput';
-import CDatePicker from '/src/components/CDatePicker';
-import CSelect from '@/components/CSelect';
-import add from '@/views/studentList/images/add.png';
-import { useRoute, useRouter } from 'vue-router';
-import { getGradeLevelList, getGradeYearList } from '../home/api';
-import { initCache, setCache } from '/src/hooks/use-async';
-import { classArray, getgradeNumList } from '../classList/contants';
-import teacherIcon from '@components/layout/images/teacherIcon.png';
-import Pagination from '/src/components/pagination';
-import { api_trainingList, api_withdrawTraining } from './api';
-import TheEmpty from '/src/components/TheEmpty';
-import { fscreen, getTimes } from '/src/utils';
-import dayjs from 'dayjs';
-import Train from '../prepare-lessons/components/lesson-main/train';
-import ResourceMain from '../prepare-lessons/components/resource-main';
-import { useResizeObserver } from '@vueuse/core';
-import { nextTick } from 'process';
-import PreviewWindow from '../preview-window';
-import { state as baseState } from '@/state';
-
-export const getCurrentMonth = () => {
-  return [dayjs().startOf('month').valueOf(), dayjs().endOf('month').valueOf()];
-};
-export default defineComponent({
-  name: 'homework-record',
-  setup() {
-    const state = reactive({
-      workVisiable: false,
-      resetVisiable: false,
-      resetItem: {} as any,
-      searchForm: {
-        keyword: null as any,
-        currentClass: '',
-        homeworkType: '',
-        currentGradeNum: '',
-        subjectId: '',
-        gradeYear: '',
-        gradeLevel: '',
-        homeworkObj: '',
-        status: '',
-        timer: getCurrentMonth() as any,
-        selfFlag: true
-      },
-      loading: false,
-      pagination: {
-        page: 1,
-        rows: 10,
-        pageTotal: 6
-      },
-      gradeNumList: [] as any,
-      tableList: [] as any,
-      studentVisible: false,
-      activeRow: null as any,
-      showaddClass: false,
-      popSelectYearList: [] as any,
-      popSelectLevelList: [] as any,
-      previewModal: false,
-      previewParams: {
-        type: '',
-        courseId: '',
-        subjectId: '',
-        detailId: ''
-      } as any
-    });
-    const formRef = ref();
-    const message = useMessage();
-    const router = useRouter();
-    const route = useRoute();
-    const search = () => {
-      state.pagination.page = 1;
-      getList();
-      setCache({ current: state.searchForm, saveKey: route.path });
-    };
-    state.gradeNumList = getgradeNumList();
-    const onReset = () => {
-      state.searchForm = {
-        keyword: null as any,
-        currentClass: '' as any,
-        currentGradeNum: '' as any,
-        subjectId: '' as any,
-        gradeYear: '' as any,
-        gradeLevel: '',
-        homeworkObj: '',
-        status: '',
-        timer: getCurrentMonth() as any,
-        selfFlag: true
-      };
-      if (state.popSelectYearList.length > 0) {
-        state.searchForm.gradeYear = state.popSelectYearList[2].id;
-      }
-      //
-      setCache({ current: state.searchForm, saveKey: route.path });
-      getList();
-    };
-
-    const getModalHeight = () => {
-      useResizeObserver(
-        document.querySelector('#model-homework-height') as HTMLElement,
-        (entries: any) => {
-          const entry = entries[0];
-          const { height } = entry.contentRect;
-          document.documentElement.style.setProperty(
-            '--window-page-lesson-height',
-            height + 'px'
-          );
-        }
-      );
-    };
-
-    const getList = async () => {
-      //   // classGroupList
-      state.loading = true;
-      try {
-        const res = await api_trainingList({
-          ...state.searchForm,
-          ...state.pagination,
-          ...getTimes(
-            state.searchForm.timer,
-            ['startTime', 'endTime'],
-            'YYYY-MM-DD'
-          )
-        });
-        const result = res.data.rows || [];
-        result.forEach((item: any) => {
-          let pTitle = '';
-          let eTitle = '';
-          if (
-            item.studentLessonTrainingDetails &&
-            item.studentLessonTrainingDetails.length > 0
-          ) {
-            item.studentLessonTrainingDetails.forEach((child: any) => {
-              if (child.trainingType === 'PRACTICE' && child.musicName) {
-                pTitle += pTitle
-                  ? '、《' + child.musicName + '》'
-                  : '练习曲目《' + child.musicName + '》';
-              }
-              if (child.trainingType === 'EVALUATION' && child.musicName) {
-                eTitle += eTitle
-                  ? '、《' + child.musicName + '》'
-                  : '评测曲目《' + child.musicName + '》';
-              }
-            });
-          }
-          item.pTitle = pTitle;
-          item.eTitle = eTitle;
-
-          let studentName = item.homeworkObjName;
-          if (item.homeworkObjName) {
-            const tempObjName = item.homeworkObjName.split(',');
-            if (tempObjName.length > 5) {
-              studentName =
-                tempObjName.slice(0, 5).join('、') +
-                `...等${tempObjName.length}${
-                  item.homeworkObj === 'CLASS' ? '个班级' : '人'
-                }`;
-            } else {
-              studentName = tempObjName.join('、');
-            }
-          }
-          item.studentName = studentName;
-        });
-        state.tableList = res.data.rows;
-        state.pagination.pageTotal = res.data.total;
-        state.loading = false;
-      } catch (e) {
-        state.loading = false;
-        console.log(e);
-      }
-    };
-
-    // 获取学年
-    const getYearList = async () => {
-      try {
-        const { data } = await getGradeYearList();
-        const temp = data || [];
-        temp.forEach((i: any) => {
-          i.name = i.name + '学年';
-        });
-        temp.unshift({
-          id: '',
-          name: '全部学年'
-        });
-        state.popSelectYearList = temp || [];
-        if (temp.length > 0 && !state.searchForm.gradeYear) {
-          state.searchForm.gradeYear = temp[2].id;
-        }
-      } catch {
-        //
-      }
-    };
-    // 获取学级
-    const getLevelList = async () => {
-      try {
-        const { data } = await getGradeLevelList();
-        const temp = data || [];
-        temp.forEach((i: any) => {
-          i.name = i.name + '级';
-        });
-        temp.unshift({
-          id: '',
-          name: '全部学级'
-        });
-        state.popSelectLevelList = temp || [];
-        if (temp.length > 0 && !state.searchForm.gradeLevel) {
-          state.searchForm.gradeLevel = temp[0].id;
-        }
-      } catch {
-        //
-      }
-    };
-
-    initCache({
-      current: state.searchForm,
-      callBack: (active: any) => {
-        state.searchForm = active;
-      }
-    });
-
-    const onResetRecord = async () => {
-      try {
-        await api_withdrawTraining({ lessonTrainingId: state.resetItem.id });
-        message.success('撤回成功');
-        state.resetVisiable = false;
-        search();
-      } catch {
-        //
-      }
-    };
-
-    // 预览上课
-    // courseId: '' as any, // 课件编号
-    //   subjectId: '' as any, // 声部编号
-    //   lessonCourseId: '' as any, // 教材编号
-    //   lessonCoursewareDetailId: '' as any, // 章节
-    //   detailId: '' as any, // 编号 - 课程编号
-    //   classGroupId: '' as any, // 上课时需要 班级编号
-    const onPreviewAttend = (item: any) => {
-      // 判断是否在应用里面
-      if (window.matchMedia('(display-mode: standalone)').matches) {
-        baseState.application = window.matchMedia(
-          '(display-mode: standalone)'
-        ).matches;
-        state.previewModal = true;
-        fscreen();
-        state.previewParams = {
-          type: 'preview',
-          courseId: item.chapterLessonCoursewareId,
-          subjectId: null,
-          detailId: item.lessonCoursewareKnowledgeDetailId,
-          lessonCourseId: item.lessonCoursewareId
-        };
-      } else {
-        const { href } = router.resolve({
-          path: '/attend-class',
-          query: {
-            type: 'preview',
-            courseId: item.chapterLessonCoursewareId,
-            subjectId: null,
-            detailId: item.lessonCoursewareKnowledgeDetailId,
-            lessonCourseId: item.lessonCoursewareId
-          }
-        });
-        window.open(href, +new Date() + '');
-      }
-    };
-
-    onMounted(async () => {
-      state.loading = true;
-      await getYearList();
-      await getLevelList();
-      await getList();
-      state.loading = false;
-    });
-    return () => (
-      <div class={styles.listWrap}>
-        <div class={styles.searchList}>
-          <NForm label-placement="left" inline ref={formRef}>
-            <NFormItem>
-              <SearchInput
-                {...{ placeholder: '请输入作业标题关键词' }}
-                class={styles.searchInput}
-                searchWord={state.searchForm.keyword}
-                onChangeValue={(val: string) =>
-                  (state.searchForm.keyword = val)
-                }></SearchInput>
-            </NFormItem>
-            <NFormItem>
-              <CSelect
-                {...({
-                  options: [
-                    { id: '', name: '全部类型' },
-                    { id: 'CLASSWORK', name: '课外作业' },
-                    { id: 'HOMEWORK', name: '课后作业' }
-                  ],
-                  placeholder: '选择类型',
-                  clearable: true,
-                  inline: true,
-                  labelField: 'name',
-                  valueField: 'id'
-                } as any)}
-                v-model:value={state.searchForm.homeworkType}></CSelect>
-            </NFormItem>
-            <NFormItem>
-              <CSelect
-                {...({
-                  options: [
-                    { id: '', name: '作业对象' },
-                    { id: 'PERSON', name: '个人' },
-                    { id: 'CLASS', name: '班级' }
-                  ],
-                  placeholder: '选择作业对象',
-                  clearable: true,
-                  inline: true,
-                  labelField: 'name',
-                  valueField: 'id'
-                } as any)}
-                v-model:value={state.searchForm.homeworkObj}></CSelect>
-            </NFormItem>
-            <NFormItem>
-              <CSelect
-                {...({
-                  options: state.popSelectYearList,
-                  placeholder: '选择学年',
-                  clearable: true,
-                  inline: true,
-                  labelField: 'name',
-                  valueField: 'id'
-                } as any)}
-                v-model:value={state.searchForm.gradeYear}></CSelect>
-            </NFormItem>
-            <NFormItem>
-              <CSelect
-                {...({
-                  options: state.popSelectLevelList,
-                  placeholder: '选择学级',
-                  clearable: true,
-                  inline: true,
-                  labelField: 'name',
-                  valueField: 'id'
-                } as any)}
-                v-model:value={state.searchForm.gradeLevel}></CSelect>
-            </NFormItem>
-
-            <NFormItem>
-              <CSelect
-                {...({
-                  options: state.gradeNumList,
-                  placeholder: '选择年级',
-                  clearable: true,
-                  inline: true
-                } as any)}
-                v-model:value={state.searchForm.currentGradeNum}></CSelect>
-            </NFormItem>
-            <NFormItem>
-              <CSelect
-                {...({
-                  options: classArray,
-                  placeholder: '选择班级',
-                  clearable: true,
-                  inline: true
-                } as any)}
-                v-model:value={state.searchForm.currentClass}></CSelect>
-            </NFormItem>
-            <NFormItem>
-              <CSelect
-                {...({
-                  options: [
-                    { value: '', label: '全部状态' },
-                    { value: 0, label: '进行中' },
-                    { value: 1, label: '已结束' }
-                  ],
-                  placeholder: '选择状态',
-                  clearable: true,
-                  inline: true
-                } as any)}
-                v-model:value={state.searchForm.status}></CSelect>
-            </NFormItem>
-            <NFormItem>
-              <CDatePicker
-                class={styles.CDatePickerItem}
-                separator={'-'}
-                type="daterange"
-                v-model:value={state.searchForm.timer}
-                timerValue={state.searchForm.timer}></CDatePicker>
-            </NFormItem>
-            <NFormItem>
-              <NSpace justify="end">
-                <NButton type="primary" class="searchBtn" onClick={search}>
-                  搜索
-                </NButton>
-                <NButton
-                  type="primary"
-                  ghost
-                  class="resetBtn"
-                  onClick={onReset}>
-                  重置
-                </NButton>
-              </NSpace>
-            </NFormItem>
-          </NForm>
-        </div>
-        <NButton
-          class={styles.addBtn}
-          type="primary"
-          onClick={() => {
-            state.workVisiable = true;
-            nextTick(() => {
-              getModalHeight();
-            });
-          }}
-          v-slots={{
-            icon: () => (
-              <>
-                <NImage
-                  class={styles.addBtnIcon}
-                  previewDisabled
-                  src={add}></NImage>
-              </>
-            )
-          }}>
-          布置作业
-        </NButton>
-        <div class={styles.tableWrap}>
-          <NSpin show={state.loading}>
-            <div style={{ minHeight: '40vh' }}>
-              <div class={styles.listSection}>
-                {state.tableList.map((item: any) => (
-                  <div
-                    class={styles.item}
-                    onClick={() => {
-                      router.push({
-                        path: '/homework-record-detail',
-                        query: {
-                          id: item.id,
-                          name: item.name
-                        }
-                      });
-                    }}>
-                    <div class={styles.header}>
-                      <NAvatar
-                        class={styles.navatar}
-                        round
-                        src={item.teacherAvatar || teacherIcon}
-                      />
-                      <div class={styles.userInfo}>
-                        <h2>{item.teacherName}</h2>
-                        <p>
-                          布置时间:
-                          {dayjs(item.createTime).format('YYYY-MM-DD HH:mm')}
-                          <span> | </span>
-                          <span>
-                            截止时间:
-                            {dayjs(item.expireDate).format('YYYY-MM-DD HH:mm')}
-                          </span>
-                        </p>
-                      </div>
-                      <div class={item.status ? styles.over : styles.ing}>
-                        {/* {item.status ? '已结束' : '进行中'} */}
-                      </div>
-                    </div>
-                    <div class={styles.content}>
-                      {/* <div> */}
-                      <div class={styles.homeTitle}>
-                        <p>
-                          <span class={styles[item.homeworkType]}>
-                            {item.homeworkType === 'CLASSWORK'
-                              ? '课外'
-                              : '课后'}
-                          </span>
-                          {item.name}
-                        </p>
-
-                        <NSpace>
-                          {item.chapterLessonCoursewareId && (
-                            <NButton
-                              class={styles.errorBtn}
-                              text
-                              color="#1677FF"
-                              onClick={(e: any) => {
-                                e.stopPropagation();
-                                // state.resetVisiable = true;
-                                // state.resetItem = item;
-                                onPreviewAttend(item);
-                              }}>
-                              查看课件
-                            </NButton>
-                          )}
-
-                          {!item.status && (
-                            <NButton
-                              class={styles.errorBtn}
-                              text
-                              color="#1677FF"
-                              onClick={(e: any) => {
-                                e.stopPropagation();
-                                state.resetVisiable = true;
-                                state.resetItem = item;
-                              }}>
-                              撤回
-                            </NButton>
-                          )}
-                        </NSpace>
-                      </div>
-                      <div class={styles.homeContent}>
-                        <span class={styles.title}>作业对象:</span>
-                        <span class={styles.text}>{item.studentName}</span>
-                      </div>
-                      <div class={[styles.homeContent, styles.homeworkText]}>
-                        <span class={styles.title}>作业内容:</span>
-                        <div class={styles.pSection}>
-                          {item.pTitle && (
-                            <p class={[styles.text, styles.p1]}>
-                              {item.pTitle}
-                            </p>
-                          )}
-                          {item.eTitle && (
-                            <p class={[styles.text, styles.p2]}>
-                              {item.eTitle}
-                            </p>
-                          )}
-                        </div>
-                      </div>
-                      <div class={styles.homeSubmit}>
-                        <span class={styles.title}>已提交:</span>
-                        <span class={styles.text}>
-                          {item.trainingNum || 0}/{item.expectNum || 0}人
-                        </span>
-                        <NDivider vertical />
-                        <span class={styles.title}>提交率:</span>
-                        <span class={styles.text}>
-                          {item.trainingRate || 0}%
-                        </span>
-                        <NDivider vertical />
-                        <span class={styles.title}>合格人数:</span>
-                        <span class={styles.text}>
-                          {item.standardNum || 0}人
-                        </span>
-                        <NDivider vertical />
-                        <span class={styles.title}>合格率:</span>
-                        <span class={styles.text}>
-                          {item.qualifiedRate || 0}%
-                        </span>
-                      </div>
-                      {/* </div> */}
-                    </div>
-                  </div>
-                ))}
-              </div>
-              {state.tableList.length <= 0 && !state.loading && (
-                <TheEmpty class={styles.nowEmpty} />
-              )}
-            </div>
-          </NSpin>
-
-          {state.tableList.length > 0 && (
-            <Pagination
-              v-model:page={state.pagination.page}
-              v-model:pageSize={state.pagination.rows}
-              v-model:pageTotal={state.pagination.pageTotal}
-              onList={getList}
-              sync
-            />
-          )}
-        </div>
-        <NModal
-          v-model:show={state.resetVisiable}
-          preset="card"
-          class={['modalTitle', styles.removeVisiable]}
-          title={'撤回作业'}>
-          <div class={styles.studentRemove}>
-            <p>
-              撤回作业后,此条作业将被删除,是否确认撤回【{state.resetItem.name}
-              】?
-            </p>
-
-            <NSpace class={styles.btnGroup} justify="center">
-              <NButton round onClick={() => (state.resetVisiable = false)}>
-                取消
-              </NButton>
-              <NButton round type="primary" onClick={onResetRecord}>
-                确定
-              </NButton>
-            </NSpace>
-          </div>
-        </NModal>
-
-        <NModal
-          v-model:show={state.workVisiable}
-          preset="card"
-          class={['modalTitle background', styles.workVisiable]}
-          title={'作业详情'}>
-          <div id="model-homework-height" class={styles.workContainer}>
-            <div class={styles.workTrain}>
-              <Train
-                lessonPreTraining={{
-                  title: dayjs().format('YYYY年MM月DD日') + '-课外作业'
-                }}
-                cardType={'homeworkRecord'}
-                onChange={(val: any) => {
-                  state.workVisiable = val.status;
-                  getList();
-                }}
-              />
-            </div>
-            <div class={styles.resourceMain}>
-              <ResourceMain cardType="homerowk-record" />
-            </div>
-          </div>
-        </NModal>
-
-        {/* 应用内预览或上课 */}
-        <PreviewWindow
-          v-model:show={state.previewModal}
-          type="attend"
-          params={state.previewParams}
-        />
-      </div>
-    );
-  }
-});
+import { defineComponent, reactive, onMounted, ref } from 'vue';
+import styles from './index.module.less';
+import {
+  NAvatar,
+  NButton,
+  NDivider,
+  NForm,
+  NFormItem,
+  NImage,
+  NModal,
+  NSpace,
+  NSpin,
+  useMessage
+} from 'naive-ui';
+import SearchInput from '@/components/searchInput';
+import CDatePicker from '/src/components/CDatePicker';
+import CSelect from '@/components/CSelect';
+import add from '@/views/studentList/images/add.png';
+import { useRoute, useRouter } from 'vue-router';
+import { getGradeLevelList, getGradeYearList } from '../home/api';
+import { initCache, setCache } from '/src/hooks/use-async';
+import { classArray, getgradeNumList } from '../classList/contants';
+import teacherIcon from '@components/layout/images/teacherIcon.png';
+import Pagination from '/src/components/pagination';
+import { api_trainingList, api_withdrawTraining } from './api';
+import TheEmpty from '/src/components/TheEmpty';
+import { fscreen, getTimes } from '/src/utils';
+import dayjs from 'dayjs';
+import Train from '../prepare-lessons/components/lesson-main/train';
+import ResourceMain from '../prepare-lessons/components/resource-main';
+import { useResizeObserver } from '@vueuse/core';
+import { nextTick } from 'process';
+import PreviewWindow from '../preview-window';
+import { state as baseState } from '@/state';
+
+export const getCurrentMonth = () => {
+  return [dayjs().startOf('month').valueOf(), dayjs().endOf('month').valueOf()];
+};
+export default defineComponent({
+  name: 'homework-record',
+  setup() {
+    const state = reactive({
+      workVisiable: false,
+      resetVisiable: false,
+      resetItem: {} as any,
+      searchForm: {
+        keyword: null as any,
+        currentClass: '',
+        homeworkType: '',
+        currentGradeNum: '',
+        subjectId: '',
+        gradeYear: '',
+        gradeLevel: '',
+        homeworkObj: '',
+        status: '',
+        timer: getCurrentMonth() as any,
+        selfFlag: true
+      },
+      loading: false,
+      pagination: {
+        page: 1,
+        rows: 10,
+        pageTotal: 6
+      },
+      gradeNumList: [] as any,
+      tableList: [] as any,
+      studentVisible: false,
+      activeRow: null as any,
+      showaddClass: false,
+      popSelectYearList: [] as any,
+      popSelectLevelList: [] as any,
+      previewModal: false,
+      previewParams: {
+        type: '',
+        courseId: '',
+        subjectId: '',
+        detailId: ''
+      } as any
+    });
+    const formRef = ref();
+    const message = useMessage();
+    const router = useRouter();
+    const route = useRoute();
+    const search = () => {
+      state.pagination.page = 1;
+      getList();
+      setCache({ current: state.searchForm, saveKey: route.path });
+    };
+    state.gradeNumList = getgradeNumList();
+    const onReset = () => {
+      state.searchForm = {
+        keyword: null as any,
+        currentClass: '' as any,
+        currentGradeNum: '' as any,
+        subjectId: '' as any,
+        gradeYear: '' as any,
+        gradeLevel: '',
+        homeworkObj: '',
+        status: '',
+        timer: getCurrentMonth() as any,
+        selfFlag: true
+      };
+      if (state.popSelectYearList.length > 0) {
+        state.searchForm.gradeYear = state.popSelectYearList[2].id;
+      }
+      //
+      setCache({ current: state.searchForm, saveKey: route.path });
+      getList();
+    };
+
+    const getModalHeight = () => {
+      useResizeObserver(
+        document.querySelector('#model-homework-height') as HTMLElement,
+        (entries: any) => {
+          const entry = entries[0];
+          const { height } = entry.contentRect;
+          document.documentElement.style.setProperty(
+            '--window-page-lesson-height',
+            height + 'px'
+          );
+        }
+      );
+    };
+
+    const getList = async () => {
+      //   // classGroupList
+      state.loading = true;
+      try {
+        const res = await api_trainingList({
+          ...state.searchForm,
+          ...state.pagination,
+          ...getTimes(
+            state.searchForm.timer,
+            ['startTime', 'endTime'],
+            'YYYY-MM-DD'
+          )
+        });
+        const result = res.data.rows || [];
+        result.forEach((item: any) => {
+          let pTitle = '';
+          let eTitle = '';
+          if (
+            item.studentLessonTrainingDetails &&
+            item.studentLessonTrainingDetails.length > 0
+          ) {
+            item.studentLessonTrainingDetails.forEach((child: any) => {
+              if (child.trainingType === 'PRACTICE' && child.musicName) {
+                pTitle += pTitle
+                  ? '、《' + child.musicName + '》'
+                  : '练习曲目《' + child.musicName + '》';
+              }
+              if (child.trainingType === 'EVALUATION' && child.musicName) {
+                eTitle += eTitle
+                  ? '、《' + child.musicName + '》'
+                  : '评测曲目《' + child.musicName + '》';
+              }
+            });
+          }
+          item.pTitle = pTitle;
+          item.eTitle = eTitle;
+
+          let studentName = item.homeworkObjName;
+          if (item.homeworkObjName) {
+            const tempObjName = item.homeworkObjName.split(',');
+            if (tempObjName.length > 5) {
+              studentName =
+                tempObjName.slice(0, 5).join('、') +
+                `...等${tempObjName.length}${
+                  item.homeworkObj === 'CLASS' ? '个班级' : '人'
+                }`;
+            } else {
+              studentName = tempObjName.join('、');
+            }
+          }
+          item.studentName = studentName;
+        });
+        state.tableList = res.data.rows;
+        state.pagination.pageTotal = res.data.total;
+        state.loading = false;
+      } catch (e) {
+        state.loading = false;
+        console.log(e);
+      }
+    };
+
+    // 获取学年
+    const getYearList = async () => {
+      try {
+        const { data } = await getGradeYearList();
+        const temp = data || [];
+        temp.forEach((i: any) => {
+          i.name = i.name + '学年';
+        });
+        temp.unshift({
+          id: '',
+          name: '全部学年'
+        });
+        state.popSelectYearList = temp || [];
+        if (temp.length > 0 && !state.searchForm.gradeYear) {
+          state.searchForm.gradeYear = temp[2].id;
+        }
+      } catch {
+        //
+      }
+    };
+    // 获取学级
+    const getLevelList = async () => {
+      try {
+        const { data } = await getGradeLevelList();
+        const temp = data || [];
+        temp.forEach((i: any) => {
+          i.name = i.name + '级';
+        });
+        temp.unshift({
+          id: '',
+          name: '全部学级'
+        });
+        state.popSelectLevelList = temp || [];
+        if (temp.length > 0 && !state.searchForm.gradeLevel) {
+          state.searchForm.gradeLevel = temp[0].id;
+        }
+      } catch {
+        //
+      }
+    };
+
+    initCache({
+      current: state.searchForm,
+      callBack: (active: any) => {
+        state.searchForm = active;
+      }
+    });
+
+    const onResetRecord = async () => {
+      try {
+        await api_withdrawTraining({ lessonTrainingId: state.resetItem.id });
+        message.success('撤回成功');
+        state.resetVisiable = false;
+        search();
+      } catch {
+        //
+      }
+    };
+
+    // 预览上课
+    // courseId: '' as any, // 课件编号
+    //   subjectId: '' as any, // 声部编号
+    //   lessonCourseId: '' as any, // 教材编号
+    //   lessonCoursewareDetailId: '' as any, // 章节
+    //   detailId: '' as any, // 编号 - 课程编号
+    //   classGroupId: '' as any, // 上课时需要 班级编号
+    const onPreviewAttend = (item: any) => {
+      // 判断是否在应用里面
+      if (window.matchMedia('(display-mode: standalone)').matches) {
+        baseState.application = window.matchMedia(
+          '(display-mode: standalone)'
+        ).matches;
+        state.previewModal = true;
+        fscreen();
+        state.previewParams = {
+          type: 'preview',
+          courseId: item.chapterLessonCoursewareId,
+          subjectId: null,
+          detailId: item.lessonCoursewareKnowledgeDetailId,
+          lessonCourseId: item.lessonCoursewareId
+        };
+      } else {
+        const { href } = router.resolve({
+          path: '/attend-class',
+          query: {
+            type: 'preview',
+            courseId: item.chapterLessonCoursewareId,
+            instrumentId: null,
+            detailId: item.lessonCoursewareKnowledgeDetailId,
+            lessonCourseId: item.lessonCoursewareId
+          }
+        });
+        window.open(href, +new Date() + '');
+      }
+    };
+
+    onMounted(async () => {
+      state.loading = true;
+      await getYearList();
+      await getLevelList();
+      await getList();
+      state.loading = false;
+    });
+    return () => (
+      <div class={styles.listWrap}>
+        <div class={styles.searchList}>
+          <NForm label-placement="left" inline ref={formRef}>
+            <NFormItem>
+              <SearchInput
+                {...{ placeholder: '请输入作业标题关键词' }}
+                class={styles.searchInput}
+                searchWord={state.searchForm.keyword}
+                onChangeValue={(val: string) =>
+                  (state.searchForm.keyword = val)
+                }></SearchInput>
+            </NFormItem>
+            <NFormItem>
+              <CSelect
+                {...({
+                  options: [
+                    { id: '', name: '全部类型' },
+                    { id: 'CLASSWORK', name: '课外作业' },
+                    { id: 'HOMEWORK', name: '课后作业' }
+                  ],
+                  placeholder: '选择类型',
+                  clearable: true,
+                  inline: true,
+                  labelField: 'name',
+                  valueField: 'id'
+                } as any)}
+                v-model:value={state.searchForm.homeworkType}></CSelect>
+            </NFormItem>
+            <NFormItem>
+              <CSelect
+                {...({
+                  options: [
+                    { id: '', name: '作业对象' },
+                    { id: 'PERSON', name: '个人' },
+                    { id: 'CLASS', name: '班级' }
+                  ],
+                  placeholder: '选择作业对象',
+                  clearable: true,
+                  inline: true,
+                  labelField: 'name',
+                  valueField: 'id'
+                } as any)}
+                v-model:value={state.searchForm.homeworkObj}></CSelect>
+            </NFormItem>
+            <NFormItem>
+              <CSelect
+                {...({
+                  options: state.popSelectYearList,
+                  placeholder: '选择学年',
+                  clearable: true,
+                  inline: true,
+                  labelField: 'name',
+                  valueField: 'id'
+                } as any)}
+                v-model:value={state.searchForm.gradeYear}></CSelect>
+            </NFormItem>
+            <NFormItem>
+              <CSelect
+                {...({
+                  options: state.popSelectLevelList,
+                  placeholder: '选择学级',
+                  clearable: true,
+                  inline: true,
+                  labelField: 'name',
+                  valueField: 'id'
+                } as any)}
+                v-model:value={state.searchForm.gradeLevel}></CSelect>
+            </NFormItem>
+
+            <NFormItem>
+              <CSelect
+                {...({
+                  options: state.gradeNumList,
+                  placeholder: '选择年级',
+                  clearable: true,
+                  inline: true
+                } as any)}
+                v-model:value={state.searchForm.currentGradeNum}></CSelect>
+            </NFormItem>
+            <NFormItem>
+              <CSelect
+                {...({
+                  options: classArray,
+                  placeholder: '选择班级',
+                  clearable: true,
+                  inline: true
+                } as any)}
+                v-model:value={state.searchForm.currentClass}></CSelect>
+            </NFormItem>
+            <NFormItem>
+              <CSelect
+                {...({
+                  options: [
+                    { value: '', label: '全部状态' },
+                    { value: 0, label: '进行中' },
+                    { value: 1, label: '已结束' }
+                  ],
+                  placeholder: '选择状态',
+                  clearable: true,
+                  inline: true
+                } as any)}
+                v-model:value={state.searchForm.status}></CSelect>
+            </NFormItem>
+            <NFormItem>
+              <CDatePicker
+                class={styles.CDatePickerItem}
+                separator={'-'}
+                type="daterange"
+                v-model:value={state.searchForm.timer}
+                timerValue={state.searchForm.timer}></CDatePicker>
+            </NFormItem>
+            <NFormItem>
+              <NSpace justify="end">
+                <NButton type="primary" class="searchBtn" onClick={search}>
+                  搜索
+                </NButton>
+                <NButton
+                  type="primary"
+                  ghost
+                  class="resetBtn"
+                  onClick={onReset}>
+                  重置
+                </NButton>
+              </NSpace>
+            </NFormItem>
+          </NForm>
+        </div>
+        <NButton
+          class={styles.addBtn}
+          type="primary"
+          onClick={() => {
+            state.workVisiable = true;
+            nextTick(() => {
+              getModalHeight();
+            });
+          }}
+          v-slots={{
+            icon: () => (
+              <>
+                <NImage
+                  class={styles.addBtnIcon}
+                  previewDisabled
+                  src={add}></NImage>
+              </>
+            )
+          }}>
+          布置作业
+        </NButton>
+        <div class={styles.tableWrap}>
+          <NSpin show={state.loading}>
+            <div style={{ minHeight: '40vh' }}>
+              <div class={styles.listSection}>
+                {state.tableList.map((item: any) => (
+                  <div
+                    class={styles.item}
+                    onClick={() => {
+                      router.push({
+                        path: '/homework-record-detail',
+                        query: {
+                          id: item.id,
+                          name: item.name
+                        }
+                      });
+                    }}>
+                    <div class={styles.header}>
+                      <NAvatar
+                        class={styles.navatar}
+                        round
+                        src={item.teacherAvatar || teacherIcon}
+                      />
+                      <div class={styles.userInfo}>
+                        <h2>{item.teacherName}</h2>
+                        <p>
+                          布置时间:
+                          {dayjs(item.createTime).format('YYYY-MM-DD HH:mm')}
+                          <span> | </span>
+                          <span>
+                            截止时间:
+                            {dayjs(item.expireDate).format('YYYY-MM-DD HH:mm')}
+                          </span>
+                        </p>
+                      </div>
+                      <div class={item.status ? styles.over : styles.ing}>
+                        {/* {item.status ? '已结束' : '进行中'} */}
+                      </div>
+                    </div>
+                    <div class={styles.content}>
+                      {/* <div> */}
+                      <div class={styles.homeTitle}>
+                        <p>
+                          <span class={styles[item.homeworkType]}>
+                            {item.homeworkType === 'CLASSWORK'
+                              ? '课外'
+                              : '课后'}
+                          </span>
+                          {item.name}
+                        </p>
+
+                        <NSpace>
+                          {item.chapterLessonCoursewareId && (
+                            <NButton
+                              class={styles.errorBtn}
+                              text
+                              color="#1677FF"
+                              onClick={(e: any) => {
+                                e.stopPropagation();
+                                // state.resetVisiable = true;
+                                // state.resetItem = item;
+                                onPreviewAttend(item);
+                              }}>
+                              查看课件
+                            </NButton>
+                          )}
+
+                          {!item.status && (
+                            <NButton
+                              class={styles.errorBtn}
+                              text
+                              color="#1677FF"
+                              onClick={(e: any) => {
+                                e.stopPropagation();
+                                state.resetVisiable = true;
+                                state.resetItem = item;
+                              }}>
+                              撤回
+                            </NButton>
+                          )}
+                        </NSpace>
+                      </div>
+                      <div class={styles.homeContent}>
+                        <span class={styles.title}>作业对象:</span>
+                        <span class={styles.text}>{item.studentName}</span>
+                      </div>
+                      <div class={[styles.homeContent, styles.homeworkText]}>
+                        <span class={styles.title}>作业内容:</span>
+                        <div class={styles.pSection}>
+                          {item.pTitle && (
+                            <p class={[styles.text, styles.p1]}>
+                              {item.pTitle}
+                            </p>
+                          )}
+                          {item.eTitle && (
+                            <p class={[styles.text, styles.p2]}>
+                              {item.eTitle}
+                            </p>
+                          )}
+                        </div>
+                      </div>
+                      <div class={styles.homeSubmit}>
+                        <span class={styles.title}>已提交:</span>
+                        <span class={styles.text}>
+                          {item.trainingNum || 0}/{item.expectNum || 0}人
+                        </span>
+                        <NDivider vertical />
+                        <span class={styles.title}>提交率:</span>
+                        <span class={styles.text}>
+                          {item.trainingRate || 0}%
+                        </span>
+                        <NDivider vertical />
+                        <span class={styles.title}>合格人数:</span>
+                        <span class={styles.text}>
+                          {item.standardNum || 0}人
+                        </span>
+                        <NDivider vertical />
+                        <span class={styles.title}>合格率:</span>
+                        <span class={styles.text}>
+                          {item.qualifiedRate || 0}%
+                        </span>
+                      </div>
+                      {/* </div> */}
+                    </div>
+                  </div>
+                ))}
+              </div>
+              {state.tableList.length <= 0 && !state.loading && (
+                <TheEmpty class={styles.nowEmpty} />
+              )}
+            </div>
+          </NSpin>
+
+          {state.tableList.length > 0 && (
+            <Pagination
+              v-model:page={state.pagination.page}
+              v-model:pageSize={state.pagination.rows}
+              v-model:pageTotal={state.pagination.pageTotal}
+              onList={getList}
+              sync
+            />
+          )}
+        </div>
+        <NModal
+          v-model:show={state.resetVisiable}
+          preset="card"
+          class={['modalTitle', styles.removeVisiable]}
+          title={'撤回作业'}>
+          <div class={styles.studentRemove}>
+            <p>
+              撤回作业后,此条作业将被删除,是否确认撤回【{state.resetItem.name}
+              】?
+            </p>
+
+            <NSpace class={styles.btnGroup} justify="center">
+              <NButton round onClick={() => (state.resetVisiable = false)}>
+                取消
+              </NButton>
+              <NButton round type="primary" onClick={onResetRecord}>
+                确定
+              </NButton>
+            </NSpace>
+          </div>
+        </NModal>
+
+        <NModal
+          v-model:show={state.workVisiable}
+          preset="card"
+          class={['modalTitle background', styles.workVisiable]}
+          title={'作业详情'}>
+          <div id="model-homework-height" class={styles.workContainer}>
+            <div class={styles.workTrain}>
+              <Train
+                lessonPreTraining={{
+                  title: dayjs().format('YYYY年MM月DD日') + '-课外作业'
+                }}
+                cardType={'homeworkRecord'}
+                onChange={(val: any) => {
+                  state.workVisiable = val.status;
+                  getList();
+                }}
+              />
+            </div>
+            <div class={styles.resourceMain}>
+              <ResourceMain cardType="homerowk-record" />
+            </div>
+          </div>
+        </NModal>
+
+        {/* 应用内预览或上课 */}
+        <PreviewWindow
+          v-model:show={state.previewModal}
+          type="attend"
+          params={state.previewParams}
+        />
+      </div>
+    );
+  }
+});

+ 797 - 795
src/views/prepare-lessons/components/lesson-main/courseware-presets/index.tsx

@@ -1,795 +1,797 @@
-import {
-  computed,
-  defineComponent,
-  onMounted,
-  reactive,
-  ref,
-  watch
-} from 'vue';
-import styles from './index.module.less';
-import {
-  NButton,
-  NTooltip,
-  NIcon,
-  NImage,
-  NModal,
-  NScrollbar,
-  NSpin,
-  NTabPane,
-  NTabs,
-  useMessage,
-  NPopselect
-} from 'naive-ui';
-import { usePrepareStore } from '/src/store/modules/prepareLessons';
-import add from '@/views/studentList/images/add.png';
-// import iconSlideRight from '../../../images/icon-slide-right.png';
-import CoursewareType from '../../../model/courseware-type';
-import TheEmpty from '/src/components/TheEmpty';
-import RelatedClass from '../../../model/related-class';
-import { state } from '/src/state';
-import { useResizeObserver } from '@vueuse/core';
-import AttendClass from '/src/views/prepare-lessons/model/attend-class';
-import {
-  api_addByOpenCourseware,
-  api_teacherChapterLessonCoursewareRemove,
-  teacherChapterLessonCoursewareList,
-  courseScheduleStart
-} from '../../../api';
-import { useRoute, useRouter } from 'vue-router';
-import TheMessageDialog from '/src/components/TheMessageDialog';
-import { eventGlobal, fscreen } from '/src/utils';
-import PreviewWindow from '/src/views/preview-window';
-import Related from './related';
-import Train from '../train';
-import ResourceMain from '../../resource-main';
-
-export default defineComponent({
-  name: 'courseware-presets',
-  props: {
-    addParam: {
-      type: Object,
-      default: () => ({})
-    }
-  },
-  emits: ['change'],
-  setup(props, { emit }) {
-    const prepareStore = usePrepareStore();
-    const message = useMessage();
-    const route = useRoute();
-    const router = useRouter();
-    const localStorageSubjectId = localStorage.getItem(
-      'prepareLessonSubjectId'
-    );
-
-    const forms = reactive({
-      // 选取参数带的,后取缓存
-      leftWidth: '100%',
-      rightWidth: '0',
-      messageLoading: false,
-      instrumentId: route.query.instrumentId
-        ? Number(route.query.instrumentId)
-        : localStorageSubjectId
-        ? Number(localStorageSubjectId)
-        : '',
-      courseScheduleSubjectId: route.query.courseScheduleSubjectId,
-      classGroupId: route.query.classGroupId,
-      preStudentNum: route.query.preStudentNum,
-      bodyWidth: '100%',
-      loading: false,
-      openLoading: false,
-      showRelatedClass: false,
-      tableList: [] as any,
-      openTableShow: true, // 是否显示
-      openTableList: [] as any,
-      selectItem: {} as any,
-      editTitleVisiable: false,
-      editTitle: null,
-      editBtnLoading: false,
-      preRemoveVisiable: false,
-      addVisiable: false, // 是否有添加的课件
-      carouselIndex: 0,
-      showAttendClass: false,
-      attendClassType: 'change', //
-      attendClassItem: {} as any,
-      previewModal: false,
-      previewParams: {
-        type: '',
-        courseId: '',
-        instrumentId: '',
-        detailId: ''
-      } as any,
-      workVisiable: false,
-      wikiCategoryIdChild: null
-    });
-
-    const getCoursewareList = async () => {
-      forms.loading = true;
-      try {
-        // 判断是否有选择对应的课件 或声部
-        if (!prepareStore.getSelectKey) return (forms.loading = false);
-
-        const { data } = await teacherChapterLessonCoursewareList({
-          instrumentId: prepareStore.getInstrumentId,
-          coursewareDetailKnowledgeId: prepareStore.getSelectKey
-        });
-        if (!Array.isArray(data)) {
-          return;
-        }
-        const tempList: any = [];
-        data.forEach((item: any) => {
-          const firstItem: any =
-            item.chapterKnowledgeList[0]?.chapterKnowledgeMaterialList[0];
-          tempList.push({
-            id: item.id,
-            lessonPreTrainingId: item.lessonPreTrainingId,
-            openFlag: item.openFlag,
-            openFlagEnable: item.openFlagEnable,
-            instrumentNames: item.instrumentNames,
-            fromChapterLessonCoursewareId: item.fromChapterLessonCoursewareId,
-            name: item.name,
-            coverImg: firstItem?.bizInfo.coverImg,
-            type: firstItem?.bizInfo.type,
-            isNotWork: item.lessonPreTrainingNum <= 0 ? true : false // 是否布置作业
-          });
-        });
-        forms.tableList = tempList;
-      } catch {
-        //
-      }
-      forms.loading = false;
-    };
-
-    // 监听选择的key 左侧选择了其它的课
-    watch(
-      () => [prepareStore.getSelectKey, prepareStore.getInstrumentId],
-      async () => {
-        eventGlobal.emit('openCoursewareChanged');
-        await getCoursewareList();
-        // await getOpenCoursewareList();
-
-        subjectRef.value?.syncBarPosition();
-      }
-    );
-
-    watch(
-      () => prepareStore.getInstrumentList,
-      () => {
-        checkInstrumentIds();
-      }
-    );
-
-    const checkInstrumentIds = () => {
-      const instrumentsList = prepareStore.getSingleInstrumentList;
-
-      // 并且没有声部时才会更新
-      if (instrumentsList.length > 0) {
-        const prepareLessonCourseWareSubjectIsNull = sessionStorage.getItem(
-          'prepareLessonCourseWareSubjectIsNull'
-        );
-        if (prepareLessonCourseWareSubjectIsNull === 'true') {
-          prepareStore.setInstrumentId('');
-          return;
-        }
-
-        // 并且声部在列表中
-        const localStorageSubjectId = localStorage.getItem(
-          'prepareLessonSubjectId'
-        );
-        // // 先取 上次上课声部,在取班级声部 最后取缓存
-        let instrumentId = null;
-        let index = -1;
-        if (forms.courseScheduleSubjectId) {
-          // 判断浏览器上面是否有
-          index = instrumentsList.findIndex(
-            (subject: any) => subject.id == forms.courseScheduleSubjectId
-          );
-          if (index >= 0) {
-            instrumentId = Number(forms.courseScheduleSubjectId);
-          }
-        }
-        // 判断班级上面声部 & 还没有声部
-        if (forms.instrumentId && !instrumentId) {
-          // 判断浏览器上面是否有
-          index = instrumentsList.findIndex(
-            (subject: any) => subject.id == forms.instrumentId
-          );
-          if (index >= 0) {
-            instrumentId = Number(forms.instrumentId);
-          }
-        }
-        // 缓存声部 & 还没有声部
-        if (localStorageSubjectId && !instrumentId) {
-          // 判断浏览器上面是否有
-          index = instrumentsList.findIndex(
-            (subject: any) => subject.id == localStorageSubjectId
-          );
-          if (index >= 0) {
-            instrumentId = Number(localStorageSubjectId);
-          }
-        }
-        // 判断是否选择为空
-        if (instrumentId && index >= 0) {
-          prepareStore.setSubjectId(instrumentId);
-          // forms.instrumentId = instrumentId;
-        } else {
-          // 判断是否有缓存
-          // prepareStore.setSubjectId(instrumentsList[0].id);
-          // forms.instrumentId = instrumentsList[0].id;
-        }
-
-        // 保存
-        localStorage.setItem(
-          'prepareLessonSubjectId',
-          prepareStore.getInstrumentId as any
-        );
-
-        subjectRef.value?.syncBarPosition();
-      }
-    };
-
-    const getInitInstrumentId = () => {
-      let instrumentId: any = '';
-      prepareStore.getInstrumentList.forEach((item: any) => {
-        if (Array.isArray(item.instruments)) {
-          item.instruments.forEach((child: any) => {
-            if (child.id === prepareStore.getInstrumentId) {
-              instrumentId = child.id;
-            }
-          });
-        }
-      });
-      if (instrumentId) {
-        forms.wikiCategoryIdChild = instrumentId;
-      }
-    };
-    const subjectRef = ref();
-    onMounted(async () => {
-      useResizeObserver(
-        document.querySelector('#presetsLeftRef') as HTMLElement,
-        (entries: any) => {
-          const entry = entries[0];
-          const { width } = entry.contentRect;
-          forms.leftWidth = width + 'px';
-        }
-      );
-      useResizeObserver(
-        document.querySelector('#presetsRightRef') as HTMLElement,
-        (entries: any) => {
-          const entry = entries[0];
-          const { width } = entry.contentRect;
-          forms.rightWidth = width + 'px';
-        }
-      );
-
-      prepareStore.setClassGroupId(route.query.classGroupId as any);
-      if (!prepareStore.getInstrumentId) {
-        // 获取教材分类列表
-        checkInstrumentIds();
-      } else {
-        getInitInstrumentId();
-      }
-
-      await getCoursewareList();
-
-      if (props.addParam.isAdd) {
-        forms.addVisiable = true;
-      }
-    });
-
-    // 删除
-    const onRemove = async () => {
-      forms.messageLoading = true;
-      try {
-        await api_teacherChapterLessonCoursewareRemove({
-          id: forms.selectItem.id
-        });
-        message.success('删除成功');
-        getCoursewareList();
-        // getOpenCoursewareList();
-        eventGlobal.emit('openCoursewareChanged');
-        forms.preRemoveVisiable = false;
-      } catch {
-        //
-      }
-      setTimeout(() => {
-        forms.messageLoading = false;
-      }, 100);
-    };
-
-    // 添加课件
-    const onAddCourseware = async (item: any) => {
-      if (forms.messageLoading) return;
-      forms.messageLoading = true;
-      try {
-        await api_addByOpenCourseware({ id: item.id });
-        message.success('添加成功');
-        getCoursewareList();
-        // getOpenCoursewareList();
-        eventGlobal.emit('openCoursewareChanged');
-      } catch {
-        //
-      }
-      setTimeout(() => {
-        forms.messageLoading = false;
-      }, 100);
-    };
-
-    // 预览上课
-    const onPreviewAttend = (id: string) => {
-      // 判断是否在应用里面
-      if (window.matchMedia('(display-mode: standalone)').matches) {
-        state.application = window.matchMedia(
-          '(display-mode: standalone)'
-        ).matches;
-        forms.previewModal = true;
-        fscreen();
-        forms.previewParams = {
-          type: 'preview',
-          courseId: id,
-          instrumentId: prepareStore.getInstrumentId,
-          detailId: prepareStore.getSelectKey,
-          lessonCourseId: prepareStore.getBaseCourseware.id
-        };
-      } else {
-        const { href } = router.resolve({
-          path: '/attend-class',
-          query: {
-            type: 'preview',
-            courseId: id,
-            instrumentId: prepareStore.getInstrumentId,
-            detailId: prepareStore.getSelectKey,
-            lessonCourseId: prepareStore.getBaseCourseware.id
-          }
-        });
-        window.open(href, +new Date() + '');
-      }
-    };
-
-    const onStartClass = async (
-      item: any,
-      classGroupId: any,
-      instrumentId?: any
-    ) => {
-      if (classGroupId) {
-        // 开始上课
-        const res = await courseScheduleStart({
-          lessonCoursewareKnowledgeDetailId: prepareStore.selectKey,
-          classGroupId: classGroupId,
-          useChapterLessonCoursewareId: item.id
-          // instrumentId: prepareStore.getInstrumentId
-        });
-        if (window.matchMedia('(display-mode: standalone)').matches) {
-          state.application = window.matchMedia(
-            '(display-mode: standalone)'
-          ).matches;
-          forms.previewModal = true;
-          fscreen();
-          forms.previewParams = {
-            type: 'class',
-            classGroupId: classGroupId,
-            courseId: item.id,
-            instrumentId: instrumentId || route.query.instrumentId,
-            detailId: prepareStore.getSelectKey,
-            classId: res.data,
-            lessonCourseId: prepareStore.getBaseCourseware.id,
-            preStudentNum: forms.preStudentNum
-          };
-        } else {
-          const { href } = router.resolve({
-            path: '/attend-class',
-            query: {
-              type: 'class',
-              classGroupId: classGroupId,
-              courseId: item.id,
-              instrumentId: prepareStore.getInstrumentId,
-              detailId: prepareStore.getSelectKey,
-              classId: res.data,
-              lessonCourseId: prepareStore.getBaseCourseware.id,
-              preStudentNum: forms.preStudentNum
-            }
-          });
-          window.open(href, +new Date() + '');
-        }
-      } else {
-        forms.showAttendClass = true;
-        forms.attendClassType = 'change';
-        forms.attendClassItem = item;
-      }
-    };
-
-    const selectChildObj = (item: any, index: number) => {
-      const obj: any = {};
-      item?.forEach((child: any) => {
-        if (child.id === forms.wikiCategoryIdChild) {
-          obj.selected = true;
-          obj.name = child.name;
-        }
-      });
-      return obj;
-    };
-
-    const tabInstrumentValue = computed(() => {
-      let instrumentId: any = prepareStore.getInstrumentId
-        ? prepareStore.getInstrumentId
-        : '';
-      prepareStore.getInstrumentList.forEach((item: any) => {
-        if (Array.isArray(item.instruments)) {
-          item.instruments.forEach((child: any) => {
-            if (child.id === prepareStore.getInstrumentId) {
-              instrumentId = item.id + '';
-            }
-          });
-        }
-      });
-      return instrumentId;
-    });
-    return () => (
-      <div
-        class={[
-          styles.coursewarePresetsContainer,
-          forms.openTableShow && styles.rightLineShow
-        ]}>
-        <div
-          class={styles.presetsLeft}
-          id="presetsLeftRef"
-          style={{ width: `calc(${forms.leftWidth} - ${forms.rightWidth})` }}>
-          <NTabs
-            ref={subjectRef}
-            defaultValue=""
-            paneClass={styles.paneTitle}
-            justifyContent="start"
-            paneWrapperClass={styles.paneWrapperContainer}
-            value={tabInstrumentValue.value}
-            onUpdate:value={(val: any) => {
-              prepareStore.getInstrumentList.forEach((item: any) => {
-                if (item.id.toString() === val.toString()) {
-                  prepareStore.setInstrumentId(val);
-                  // 保存
-                  forms.instrumentId = val;
-                  forms.wikiCategoryIdChild = null;
-                }
-              });
-
-              if (!val) {
-                prepareStore.setInstrumentId(val);
-                // 保存
-                forms.instrumentId = val;
-                forms.wikiCategoryIdChild = null;
-                sessionStorage.setItem(
-                  'prepareLessonCourseWareSubjectIsNull',
-                  val ? 'false' : 'true'
-                );
-              }
-            }}
-            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>
-              )
-            }}>
-            {[
-              { name: '全部乐器', id: '' },
-              ...prepareStore.getFormatInstrumentList
-            ].map((item: any, index: number) => (
-              <NTabPane
-                name={`${item.id}`}
-                tab={item.name}
-                disabled={item.instruments?.length > 0}
-                displayDirective="if">
-                {{
-                  tab: () =>
-                    item.instruments?.length > 0 ? (
-                      <NPopselect
-                        options={item.instruments}
-                        trigger="hover"
-                        v-model:value={forms.wikiCategoryIdChild}
-                        onUpdate:value={(val: any) => {
-                          // onSearch();
-                          prepareStore.setInstrumentId(val);
-                          // 保存
-                          forms.instrumentId = val;
-
-                          if (!val) {
-                            sessionStorage.setItem(
-                              'prepareLessonCourseWareSubjectIsNull',
-                              val ? 'false' : 'true'
-                            );
-                          }
-                        }}
-                        key={item.id}
-                        class={styles.popSelect}>
-                        <span
-                          class={[
-                            styles.textBtn,
-                            selectChildObj(item.instruments, index).selected &&
-                              styles.textBtnActive
-                          ]}>
-                          {selectChildObj(item.instruments, index).name ||
-                            item.name}
-                          <i class={styles.iconArrow}></i>
-                        </span>
-                      </NPopselect>
-                    ) : (
-                      item.name
-                    )
-                }}
-              </NTabPane>
-            ))}
-          </NTabs>
-          <NSpin show={forms.loading}>
-            <NScrollbar class={styles.coursewarePresets}>
-              <div style={{ overflow: 'hidden' }}>
-                <div
-                  class={[
-                    styles.list,
-                    !forms.loading &&
-                      forms.tableList.length <= 0 &&
-                      styles.listEmpty
-                  ]}>
-                  {forms.tableList.map((item: any) => (
-                    <div class={[styles.itemWrap, styles.itemBlock, 'row-nav']}>
-                      <div class={styles.itemWrapBox}>
-                        <CoursewareType
-                          operate
-                          isEditName
-                          item={item}
-                          onClick={() => onPreviewAttend(item.id)}
-                          // onEditName={() => {
-                          //   forms.selectItem = item;
-                          //   forms.editTitle = item.name;
-                          //   forms.editTitleVisiable = true;
-                          // }}
-                          onEdit={() => {
-                            //
-                            eventGlobal.emit('teacher-slideshow', true);
-                            emit('change', {
-                              status: true,
-                              type: 'update',
-                              groupItem: { id: item.id }
-                            });
-                          }}
-                          onStartClass={() =>
-                            onStartClass(item, forms.classGroupId)
-                          }
-                          onDelete={() => {
-                            forms.selectItem = item;
-                            forms.preRemoveVisiable = true;
-                          }}
-                          // 布置作业
-                          onWork={() => {
-                            forms.workVisiable = true;
-                            forms.selectItem = item;
-                          }}
-                        />
-                      </div>
-                    </div>
-                  ))}
-                  {!forms.loading && forms.tableList.length <= 0 && (
-                    <TheEmpty
-                      class={styles.empty1}
-                      description="当前章节暂无课件,快点击右上角创建课件吧"
-                    />
-                  )}
-                </div>
-              </div>
-            </NScrollbar>
-          </NSpin>
-        </div>
-
-        <div class={styles.presetsRight} id="presetsRightRef">
-          <NTooltip showArrow={false} animated={false} duration={0} delay={0}>
-            {{
-              trigger: () => (
-                <div
-                  class={[
-                    styles.presetsArrar,
-                    !forms.openTableShow && styles.presetsArrarActive
-                  ]}
-                  onClick={() => (forms.openTableShow = !forms.openTableShow)}>
-                  <NIcon>
-                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
-                      <path
-                        d="M16.62 2.99a1.25 1.25 0 0 0-1.77 0L6.54 11.3a.996.996 0 0 0 0 1.41l8.31 8.31c.49.49 1.28.49 1.77 0s.49-1.28 0-1.77L9.38 12l7.25-7.25c.48-.48.48-1.28-.01-1.76z"
-                        fill="currentColor"></path>
-                    </svg>
-                  </NIcon>
-                </div>
-              ),
-              default: () => <div>{forms.openTableShow ? '收起' : '展开'}</div>
-            }}
-          </NTooltip>
-
-          <Related
-            onMore={() => (forms.showRelatedClass = true)}
-            onAdd={(item: any) => {
-              onAddCourseware(item);
-            }}
-            onLook={(item: any) => {
-              onPreviewAttend(item.id);
-            }}
-          />
-        </div>
-        {/* )} */}
-
-        <NModal
-          v-model:show={forms.showRelatedClass}
-          preset="card"
-          showIcon={false}
-          class={['modalTitle background', styles.attendClassModal1]}
-          title={'相关课件'}
-          blockScroll={false}>
-          <RelatedClass
-            tableList={forms.tableList}
-            instrumentList={prepareStore.getInstrumentList}
-            instrumentId={prepareStore.getInstrumentId as any}
-            coursewareDetailKnowledgeId={prepareStore.getSelectKey}
-            onClose={() => (forms.showRelatedClass = false)}
-            onAdd={(item: any) => onAddCourseware(item)}
-            onClick={(item: any) => {
-              onPreviewAttend(item.id);
-              forms.showRelatedClass = false;
-            }}
-          />
-        </NModal>
-
-        {/* <NModal
-          v-model:show={forms.editTitleVisiable}
-          preset="card"
-          class={['modalTitle', styles.removeVisiable1]}
-          title={'课件重命名'}>
-          <div class={styles.studentRemove}>
-            <NInput
-              placeholder="请输入课件名称"
-              v-model:value={forms.editTitle}
-              maxlength={15}
-              onKeyup={(e: any) => {
-                if (e.code === 'ArrowLeft' || e.code === 'ArrowRight') {
-                  e.stopPropagation();
-                }
-              }}
-            />
-
-            <NSpace class={styles.btnGroupModal} justify="center">
-              <NButton round onClick={() => (forms.editTitleVisiable = false)}>
-                取消
-              </NButton>
-              <NButton
-                round
-                type="primary"
-                onClick={onEditTitleSubmit}
-                loading={forms.editBtnLoading}>
-                确定
-              </NButton>
-            </NSpace>
-          </div>
-        </NModal> */}
-
-        <NModal
-          v-model:show={forms.preRemoveVisiable}
-          preset="card"
-          class={['modalTitle', styles.removeVisiable1]}
-          title={'删除课件'}>
-          <TheMessageDialog
-            content={`<p style="text-align: left;">请确认是否删除【${forms.selectItem.name}】,删除后不可恢复</p>`}
-            cancelButtonText="取消"
-            confirmButtonText="确认"
-            loading={forms.messageLoading}
-            onClose={() => (forms.preRemoveVisiable = false)}
-            onConfirm={() => onRemove()}
-          />
-        </NModal>
-
-        <NModal
-          v-model:show={forms.addVisiable}
-          preset="card"
-          class={['modalTitle', styles.removeVisiable1]}
-          title={'保存成功'}>
-          <TheMessageDialog
-            content={`<p style="text-align: left;">【${props.addParam.name}】暂未设置课件作业,是否现在去设置课件作业</p>`}
-            cancelButtonText="稍后设置"
-            confirmButtonText="立即设置"
-            // loading={forms.messageLoading}
-            onClose={() => (forms.addVisiable = false)}
-            onConfirm={() => {
-              forms.addVisiable = false;
-              forms.workVisiable = true;
-              forms.selectItem = {
-                id: props.addParam.id,
-                name: props.addParam.name
-              };
-            }}
-          />
-        </NModal>
-
-        {/* 应用内预览或上课 */}
-        <PreviewWindow
-          v-model:show={forms.previewModal}
-          type="attend"
-          params={forms.previewParams}
-        />
-
-        <NModal
-          v-model:show={forms.showAttendClass}
-          preset="card"
-          showIcon={false}
-          class={['modalTitle background', styles.attendClassModal]}
-          title={'选择班级'}
-          blockScroll={false}>
-          <AttendClass
-            onClose={() => (forms.showAttendClass = false)}
-            type={forms.attendClassType}
-            onPreview={(item: any) => {
-              if (window.matchMedia('(display-mode: standalone)').matches) {
-                state.application = window.matchMedia(
-                  '(display-mode: standalone)'
-                ).matches;
-                forms.previewModal = true;
-                forms.previewParams = {
-                  ...item
-                };
-              } else {
-                const { href } = router.resolve({
-                  path: '/attend-class',
-                  query: {
-                    ...item
-                  }
-                });
-                window.open(href, +new Date() + '');
-              }
-            }}
-            onConfirm={async (item: any) => {
-              onStartClass(
-                forms.attendClassItem,
-                item.classGroupId,
-                item.instrumentId
-              );
-            }}
-          />
-        </NModal>
-
-        <NModal
-          v-model:show={forms.workVisiable}
-          preset="card"
-          class={['modalTitle background', styles.workVisiable]}
-          title={
-            forms.selectItem.lessonPreTrainingId ? '编辑作业' : '创建作业'
-          }>
-          <div id="model-homework-height" class={styles.workContainer}>
-            <div class={styles.workTrain}>
-              <Train
-                cardType="prepare"
-                lessonPreTraining={{
-                  title: forms.selectItem.name + '-课后作业',
-                  chapterId: forms.selectItem.id, // 课件编号
-                  id: forms.selectItem.lessonPreTrainingId // 作业编号
-                }}
-                onChange={(val: any) => {
-                  forms.workVisiable = val.status;
-                  getCoursewareList();
-                }}
-              />
-            </div>
-            <div class={styles.resourceMain}>
-              <ResourceMain cardType="prepare" />
-            </div>
-          </div>
-        </NModal>
-      </div>
-    );
-  }
-});
+import {
+  computed,
+  defineComponent,
+  onMounted,
+  reactive,
+  ref,
+  watch
+} from 'vue';
+import styles from './index.module.less';
+import {
+  NButton,
+  NTooltip,
+  NIcon,
+  NImage,
+  NModal,
+  NScrollbar,
+  NSpin,
+  NTabPane,
+  NTabs,
+  useMessage,
+  NPopselect
+} from 'naive-ui';
+import { usePrepareStore } from '/src/store/modules/prepareLessons';
+import add from '@/views/studentList/images/add.png';
+// import iconSlideRight from '../../../images/icon-slide-right.png';
+import CoursewareType from '../../../model/courseware-type';
+import TheEmpty from '/src/components/TheEmpty';
+import RelatedClass from '../../../model/related-class';
+import { state } from '/src/state';
+import { useResizeObserver } from '@vueuse/core';
+import AttendClass from '/src/views/prepare-lessons/model/attend-class';
+import {
+  api_addByOpenCourseware,
+  api_teacherChapterLessonCoursewareRemove,
+  teacherChapterLessonCoursewareList,
+  courseScheduleStart
+} from '../../../api';
+import { useRoute, useRouter } from 'vue-router';
+import TheMessageDialog from '/src/components/TheMessageDialog';
+import { eventGlobal, fscreen } from '/src/utils';
+import PreviewWindow from '/src/views/preview-window';
+import Related from './related';
+import Train from '../train';
+import ResourceMain from '../../resource-main';
+
+export default defineComponent({
+  name: 'courseware-presets',
+  props: {
+    addParam: {
+      type: Object,
+      default: () => ({})
+    }
+  },
+  emits: ['change'],
+  setup(props, { emit }) {
+    const prepareStore = usePrepareStore();
+    const message = useMessage();
+    const route = useRoute();
+    const router = useRouter();
+    const localStorageSubjectId = localStorage.getItem(
+      'prepareLessonSubjectId'
+    );
+
+    const forms = reactive({
+      // 选取参数带的,后取缓存
+      leftWidth: '100%',
+      rightWidth: '0',
+      messageLoading: false,
+      instrumentId: route.query.instrumentId
+        ? Number(route.query.instrumentId)
+        : localStorageSubjectId
+        ? Number(localStorageSubjectId)
+        : '',
+      courseScheduleSubjectId: route.query.courseScheduleSubjectId,
+      classGroupId: route.query.classGroupId,
+      preStudentNum: route.query.preStudentNum,
+      bodyWidth: '100%',
+      loading: false,
+      openLoading: false,
+      showRelatedClass: false,
+      tableList: [] as any,
+      openTableShow: true, // 是否显示
+      openTableList: [] as any,
+      selectItem: {} as any,
+      editTitleVisiable: false,
+      editTitle: null,
+      editBtnLoading: false,
+      preRemoveVisiable: false,
+      addVisiable: false, // 是否有添加的课件
+      carouselIndex: 0,
+      showAttendClass: false,
+      attendClassType: 'change', //
+      attendClassItem: {} as any,
+      previewModal: false,
+      previewParams: {
+        type: '',
+        courseId: '',
+        instrumentId: '',
+        detailId: ''
+      } as any,
+      workVisiable: false,
+      wikiCategoryIdChild: null
+    });
+
+    const getCoursewareList = async () => {
+      forms.loading = true;
+      try {
+        // 判断是否有选择对应的课件 或声部
+        if (!prepareStore.getSelectKey) return (forms.loading = false);
+
+        const { data } = await teacherChapterLessonCoursewareList({
+          instrumentId: prepareStore.getInstrumentId,
+          coursewareDetailKnowledgeId: prepareStore.getSelectKey
+        });
+        if (!Array.isArray(data)) {
+          return;
+        }
+        const tempList: any = [];
+        data.forEach((item: any) => {
+          const firstItem: any =
+            item.chapterKnowledgeList[0]?.chapterKnowledgeMaterialList[0];
+          tempList.push({
+            id: item.id,
+            lessonPreTrainingId: item.lessonPreTrainingId,
+            openFlag: item.openFlag,
+            openFlagEnable: item.openFlagEnable,
+            instrumentNames: item.instrumentNames,
+            fromChapterLessonCoursewareId: item.fromChapterLessonCoursewareId,
+            name: item.name,
+            coverImg: firstItem?.bizInfo.coverImg,
+            type: firstItem?.bizInfo.type,
+            isNotWork: item.lessonPreTrainingNum <= 0 ? true : false // 是否布置作业
+          });
+        });
+        forms.tableList = tempList;
+      } catch {
+        //
+      }
+      forms.loading = false;
+    };
+
+    // 监听选择的key 左侧选择了其它的课
+    watch(
+      () => [prepareStore.getSelectKey, prepareStore.getInstrumentId],
+      async () => {
+        eventGlobal.emit('openCoursewareChanged');
+        await getCoursewareList();
+        // await getOpenCoursewareList();
+
+        subjectRef.value?.syncBarPosition();
+      }
+    );
+
+    watch(
+      () => prepareStore.getInstrumentList,
+      () => {
+        checkInstrumentIds();
+      }
+    );
+
+    const checkInstrumentIds = () => {
+      const instrumentsList = prepareStore.getSingleInstrumentList;
+
+      // 并且没有声部时才会更新
+      if (instrumentsList.length > 0) {
+        const prepareLessonCourseWareSubjectIsNull = sessionStorage.getItem(
+          'prepareLessonCourseWareSubjectIsNull'
+        );
+        if (prepareLessonCourseWareSubjectIsNull === 'true') {
+          prepareStore.setInstrumentId('');
+          return;
+        }
+
+        // 并且声部在列表中
+        const localStorageSubjectId = localStorage.getItem(
+          'prepareLessonSubjectId'
+        );
+        // // 先取 上次上课声部,在取班级声部 最后取缓存
+        let instrumentId = null;
+        let index = -1;
+        if (forms.courseScheduleSubjectId) {
+          // 判断浏览器上面是否有
+          index = instrumentsList.findIndex(
+            (subject: any) => subject.id == forms.courseScheduleSubjectId
+          );
+          if (index >= 0) {
+            instrumentId = Number(forms.courseScheduleSubjectId);
+          }
+        }
+        // 判断班级上面声部 & 还没有声部
+        if (forms.instrumentId && !instrumentId) {
+          // 判断浏览器上面是否有
+          index = instrumentsList.findIndex(
+            (subject: any) => subject.id == forms.instrumentId
+          );
+          if (index >= 0) {
+            instrumentId = Number(forms.instrumentId);
+          }
+        }
+        // 缓存声部 & 还没有声部
+        if (localStorageSubjectId && !instrumentId) {
+          // 判断浏览器上面是否有
+          index = instrumentsList.findIndex(
+            (subject: any) => subject.id == localStorageSubjectId
+          );
+          if (index >= 0) {
+            instrumentId = Number(localStorageSubjectId);
+          }
+        }
+        // 判断是否选择为空
+        if (instrumentId && index >= 0) {
+          prepareStore.setSubjectId(instrumentId);
+          // forms.instrumentId = instrumentId;
+        } else {
+          // 判断是否有缓存
+          // prepareStore.setSubjectId(instrumentsList[0].id);
+          // forms.instrumentId = instrumentsList[0].id;
+        }
+
+        // 保存
+        localStorage.setItem(
+          'prepareLessonSubjectId',
+          prepareStore.getInstrumentId as any
+        );
+
+        subjectRef.value?.syncBarPosition();
+      }
+    };
+
+    const getInitInstrumentId = () => {
+      let instrumentId: any = '';
+      prepareStore.getInstrumentList.forEach((item: any) => {
+        if (Array.isArray(item.instruments)) {
+          item.instruments.forEach((child: any) => {
+            if (child.id === prepareStore.getInstrumentId) {
+              instrumentId = child.id;
+            }
+          });
+        }
+      });
+      if (instrumentId) {
+        forms.wikiCategoryIdChild = instrumentId;
+      }
+    };
+    const subjectRef = ref();
+    onMounted(async () => {
+      useResizeObserver(
+        document.querySelector('#presetsLeftRef') as HTMLElement,
+        (entries: any) => {
+          const entry = entries[0];
+          const { width } = entry.contentRect;
+          forms.leftWidth = width + 'px';
+        }
+      );
+      useResizeObserver(
+        document.querySelector('#presetsRightRef') as HTMLElement,
+        (entries: any) => {
+          const entry = entries[0];
+          const { width } = entry.contentRect;
+          forms.rightWidth = width + 'px';
+        }
+      );
+
+      prepareStore.setClassGroupId(route.query.classGroupId as any);
+      if (!prepareStore.getInstrumentId) {
+        // 获取教材分类列表
+        checkInstrumentIds();
+      } else {
+        getInitInstrumentId();
+      }
+
+      await getCoursewareList();
+
+      if (props.addParam.isAdd) {
+        forms.addVisiable = true;
+      }
+    });
+
+    // 删除
+    const onRemove = async () => {
+      forms.messageLoading = true;
+      try {
+        await api_teacherChapterLessonCoursewareRemove({
+          id: forms.selectItem.id
+        });
+        message.success('删除成功');
+        getCoursewareList();
+        // getOpenCoursewareList();
+        eventGlobal.emit('openCoursewareChanged');
+        forms.preRemoveVisiable = false;
+      } catch {
+        //
+      }
+      setTimeout(() => {
+        forms.messageLoading = false;
+      }, 100);
+    };
+
+    // 添加课件
+    const onAddCourseware = async (item: any) => {
+      if (forms.messageLoading) return;
+      forms.messageLoading = true;
+      try {
+        await api_addByOpenCourseware({ id: item.id });
+        message.success('添加成功');
+        getCoursewareList();
+        // getOpenCoursewareList();
+        eventGlobal.emit('openCoursewareChanged');
+      } catch {
+        //
+      }
+      setTimeout(() => {
+        forms.messageLoading = false;
+      }, 100);
+    };
+
+    // 预览上课
+    const onPreviewAttend = (id: string) => {
+      // 判断是否在应用里面
+      if (window.matchMedia('(display-mode: standalone)').matches) {
+        state.application = window.matchMedia(
+          '(display-mode: standalone)'
+        ).matches;
+        forms.previewModal = true;
+        fscreen();
+        forms.previewParams = {
+          type: 'preview',
+          courseId: id,
+          instrumentId: prepareStore.getInstrumentId,
+          detailId: prepareStore.getSelectKey,
+          lessonCourseId: prepareStore.getBaseCourseware.id
+        };
+      } else {
+        const { href } = router.resolve({
+          path: '/attend-class',
+          query: {
+            type: 'preview',
+            courseId: id,
+            instrumentId: prepareStore.getInstrumentId,
+            detailId: prepareStore.getSelectKey,
+            lessonCourseId: prepareStore.getBaseCourseware.id
+          }
+        });
+        window.open(href, +new Date() + '');
+      }
+    };
+
+    const onStartClass = async (
+      item: any,
+      classGroupId: any,
+      instrumentId?: any
+    ) => {
+      if (classGroupId) {
+        // 开始上课
+        const res = await courseScheduleStart({
+          lessonCoursewareKnowledgeDetailId: prepareStore.selectKey,
+          classGroupId: classGroupId,
+          useChapterLessonCoursewareId: item.id
+          // instrumentId: prepareStore.getInstrumentId
+        });
+        if (window.matchMedia('(display-mode: standalone)').matches) {
+          state.application = window.matchMedia(
+            '(display-mode: standalone)'
+          ).matches;
+          forms.previewModal = true;
+          fscreen();
+          forms.previewParams = {
+            type: 'class',
+            classGroupId: classGroupId,
+            courseId: item.id,
+            instrumentId: instrumentId || route.query.instrumentId,
+            detailId: prepareStore.getSelectKey,
+            classId: res.data,
+            lessonCourseId: prepareStore.getBaseCourseware.id,
+            preStudentNum: forms.preStudentNum
+          };
+        } else {
+          const { href } = router.resolve({
+            path: '/attend-class',
+            query: {
+              type: 'class',
+              classGroupId: classGroupId,
+              courseId: item.id,
+              // instrumentId: prepareStore.getInstrumentId,
+              instrumentId: instrumentId || route.query.instrumentId,
+              detailId: prepareStore.getSelectKey,
+              classId: res.data,
+              lessonCourseId: prepareStore.getBaseCourseware.id,
+              preStudentNum: forms.preStudentNum
+            }
+          });
+          window.open(href, +new Date() + '');
+        }
+      } else {
+        forms.showAttendClass = true;
+        forms.attendClassType = 'change';
+        forms.attendClassItem = item;
+      }
+    };
+
+    const selectChildObj = (item: any, index: number) => {
+      const obj: any = {};
+      item?.forEach((child: any) => {
+        if (child.id === forms.wikiCategoryIdChild) {
+          obj.selected = true;
+          obj.name = child.name;
+        }
+      });
+      return obj;
+    };
+
+    const tabInstrumentValue = computed(() => {
+      let instrumentId: any = prepareStore.getInstrumentId
+        ? prepareStore.getInstrumentId
+        : '';
+      prepareStore.getFormatInstrumentList.forEach((item: any) => {
+        if (Array.isArray(item.instruments)) {
+          item.instruments.forEach((child: any) => {
+            if (child.id === prepareStore.getInstrumentId) {
+              instrumentId = item.id + '';
+            }
+          });
+        }
+      });
+      return instrumentId;
+    });
+    return () => (
+      <div
+        class={[
+          styles.coursewarePresetsContainer,
+          forms.openTableShow && styles.rightLineShow
+        ]}>
+        <div
+          class={styles.presetsLeft}
+          id="presetsLeftRef"
+          style={{ width: `calc(${forms.leftWidth} - ${forms.rightWidth})` }}>
+          <NTabs
+            ref={subjectRef}
+            defaultValue=""
+            paneClass={styles.paneTitle}
+            justifyContent="start"
+            paneWrapperClass={styles.paneWrapperContainer}
+            value={tabInstrumentValue.value}
+            onUpdate:value={(val: any) => {
+              console.log(val, 'item.id', prepareStore.getFormatInstrumentList);
+              prepareStore.getFormatInstrumentList.forEach((item: any) => {
+                if (item.value.toString() === val.toString()) {
+                  prepareStore.setInstrumentId(val);
+                  // 保存
+                  forms.instrumentId = val;
+                  forms.wikiCategoryIdChild = null;
+                }
+              });
+
+              if (!val) {
+                prepareStore.setInstrumentId(val);
+                // 保存
+                forms.instrumentId = val;
+                forms.wikiCategoryIdChild = null;
+                sessionStorage.setItem(
+                  'prepareLessonCourseWareSubjectIsNull',
+                  val ? 'false' : 'true'
+                );
+              }
+            }}
+            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>
+              )
+            }}>
+            {[
+              { name: '全部乐器', id: '', value: '' },
+              ...prepareStore.getFormatInstrumentList
+            ].map((item: any, index: number) => (
+              <NTabPane
+                name={`${item.value}`}
+                tab={item.name}
+                disabled={item.instruments?.length > 0}
+                displayDirective="if">
+                {{
+                  tab: () =>
+                    item.instruments?.length > 0 ? (
+                      <NPopselect
+                        options={item.instruments}
+                        trigger="hover"
+                        v-model:value={forms.wikiCategoryIdChild}
+                        onUpdate:value={(val: any) => {
+                          // onSearch();
+                          prepareStore.setInstrumentId(val);
+                          // 保存
+                          forms.instrumentId = val;
+
+                          if (!val) {
+                            sessionStorage.setItem(
+                              'prepareLessonCourseWareSubjectIsNull',
+                              val ? 'false' : 'true'
+                            );
+                          }
+                        }}
+                        key={item.id}
+                        class={styles.popSelect}>
+                        <span
+                          class={[
+                            styles.textBtn,
+                            selectChildObj(item.instruments, index).selected &&
+                              styles.textBtnActive
+                          ]}>
+                          {selectChildObj(item.instruments, index).name ||
+                            item.name}
+                          <i class={styles.iconArrow}></i>
+                        </span>
+                      </NPopselect>
+                    ) : (
+                      item.name
+                    )
+                }}
+              </NTabPane>
+            ))}
+          </NTabs>
+          <NSpin show={forms.loading}>
+            <NScrollbar class={styles.coursewarePresets}>
+              <div style={{ overflow: 'hidden' }}>
+                <div
+                  class={[
+                    styles.list,
+                    !forms.loading &&
+                      forms.tableList.length <= 0 &&
+                      styles.listEmpty
+                  ]}>
+                  {forms.tableList.map((item: any) => (
+                    <div class={[styles.itemWrap, styles.itemBlock, 'row-nav']}>
+                      <div class={styles.itemWrapBox}>
+                        <CoursewareType
+                          operate
+                          isEditName
+                          item={item}
+                          onClick={() => onPreviewAttend(item.id)}
+                          // onEditName={() => {
+                          //   forms.selectItem = item;
+                          //   forms.editTitle = item.name;
+                          //   forms.editTitleVisiable = true;
+                          // }}
+                          onEdit={() => {
+                            //
+                            eventGlobal.emit('teacher-slideshow', true);
+                            emit('change', {
+                              status: true,
+                              type: 'update',
+                              groupItem: { id: item.id }
+                            });
+                          }}
+                          onStartClass={() =>
+                            onStartClass(item, forms.classGroupId)
+                          }
+                          onDelete={() => {
+                            forms.selectItem = item;
+                            forms.preRemoveVisiable = true;
+                          }}
+                          // 布置作业
+                          onWork={() => {
+                            forms.workVisiable = true;
+                            forms.selectItem = item;
+                          }}
+                        />
+                      </div>
+                    </div>
+                  ))}
+                  {!forms.loading && forms.tableList.length <= 0 && (
+                    <TheEmpty
+                      class={styles.empty1}
+                      description="当前章节暂无课件,快点击右上角创建课件吧"
+                    />
+                  )}
+                </div>
+              </div>
+            </NScrollbar>
+          </NSpin>
+        </div>
+
+        <div class={styles.presetsRight} id="presetsRightRef">
+          <NTooltip showArrow={false} animated={false} duration={0} delay={0}>
+            {{
+              trigger: () => (
+                <div
+                  class={[
+                    styles.presetsArrar,
+                    !forms.openTableShow && styles.presetsArrarActive
+                  ]}
+                  onClick={() => (forms.openTableShow = !forms.openTableShow)}>
+                  <NIcon>
+                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+                      <path
+                        d="M16.62 2.99a1.25 1.25 0 0 0-1.77 0L6.54 11.3a.996.996 0 0 0 0 1.41l8.31 8.31c.49.49 1.28.49 1.77 0s.49-1.28 0-1.77L9.38 12l7.25-7.25c.48-.48.48-1.28-.01-1.76z"
+                        fill="currentColor"></path>
+                    </svg>
+                  </NIcon>
+                </div>
+              ),
+              default: () => <div>{forms.openTableShow ? '收起' : '展开'}</div>
+            }}
+          </NTooltip>
+
+          <Related
+            onMore={() => (forms.showRelatedClass = true)}
+            onAdd={(item: any) => {
+              onAddCourseware(item);
+            }}
+            onLook={(item: any) => {
+              onPreviewAttend(item.id);
+            }}
+          />
+        </div>
+        {/* )} */}
+
+        <NModal
+          v-model:show={forms.showRelatedClass}
+          preset="card"
+          showIcon={false}
+          class={['modalTitle background', styles.attendClassModal1]}
+          title={'相关课件'}
+          blockScroll={false}>
+          <RelatedClass
+            tableList={forms.tableList}
+            instrumentList={prepareStore.getInstrumentList}
+            instrumentId={prepareStore.getInstrumentId as any}
+            coursewareDetailKnowledgeId={prepareStore.getSelectKey}
+            onClose={() => (forms.showRelatedClass = false)}
+            onAdd={(item: any) => onAddCourseware(item)}
+            onClick={(item: any) => {
+              onPreviewAttend(item.id);
+              forms.showRelatedClass = false;
+            }}
+          />
+        </NModal>
+
+        {/* <NModal
+          v-model:show={forms.editTitleVisiable}
+          preset="card"
+          class={['modalTitle', styles.removeVisiable1]}
+          title={'课件重命名'}>
+          <div class={styles.studentRemove}>
+            <NInput
+              placeholder="请输入课件名称"
+              v-model:value={forms.editTitle}
+              maxlength={15}
+              onKeyup={(e: any) => {
+                if (e.code === 'ArrowLeft' || e.code === 'ArrowRight') {
+                  e.stopPropagation();
+                }
+              }}
+            />
+
+            <NSpace class={styles.btnGroupModal} justify="center">
+              <NButton round onClick={() => (forms.editTitleVisiable = false)}>
+                取消
+              </NButton>
+              <NButton
+                round
+                type="primary"
+                onClick={onEditTitleSubmit}
+                loading={forms.editBtnLoading}>
+                确定
+              </NButton>
+            </NSpace>
+          </div>
+        </NModal> */}
+
+        <NModal
+          v-model:show={forms.preRemoveVisiable}
+          preset="card"
+          class={['modalTitle', styles.removeVisiable1]}
+          title={'删除课件'}>
+          <TheMessageDialog
+            content={`<p style="text-align: left;">请确认是否删除【${forms.selectItem.name}】,删除后不可恢复</p>`}
+            cancelButtonText="取消"
+            confirmButtonText="确认"
+            loading={forms.messageLoading}
+            onClose={() => (forms.preRemoveVisiable = false)}
+            onConfirm={() => onRemove()}
+          />
+        </NModal>
+
+        <NModal
+          v-model:show={forms.addVisiable}
+          preset="card"
+          class={['modalTitle', styles.removeVisiable1]}
+          title={'保存成功'}>
+          <TheMessageDialog
+            content={`<p style="text-align: left;">【${props.addParam.name}】暂未设置课件作业,是否现在去设置课件作业</p>`}
+            cancelButtonText="稍后设置"
+            confirmButtonText="立即设置"
+            // loading={forms.messageLoading}
+            onClose={() => (forms.addVisiable = false)}
+            onConfirm={() => {
+              forms.addVisiable = false;
+              forms.workVisiable = true;
+              forms.selectItem = {
+                id: props.addParam.id,
+                name: props.addParam.name
+              };
+            }}
+          />
+        </NModal>
+
+        {/* 应用内预览或上课 */}
+        <PreviewWindow
+          v-model:show={forms.previewModal}
+          type="attend"
+          params={forms.previewParams}
+        />
+
+        <NModal
+          v-model:show={forms.showAttendClass}
+          preset="card"
+          showIcon={false}
+          class={['modalTitle background', styles.attendClassModal]}
+          title={'选择班级'}
+          blockScroll={false}>
+          <AttendClass
+            onClose={() => (forms.showAttendClass = false)}
+            type={forms.attendClassType}
+            onPreview={(item: any) => {
+              if (window.matchMedia('(display-mode: standalone)').matches) {
+                state.application = window.matchMedia(
+                  '(display-mode: standalone)'
+                ).matches;
+                forms.previewModal = true;
+                forms.previewParams = {
+                  ...item
+                };
+              } else {
+                const { href } = router.resolve({
+                  path: '/attend-class',
+                  query: {
+                    ...item
+                  }
+                });
+                window.open(href, +new Date() + '');
+              }
+            }}
+            onConfirm={async (item: any) => {
+              onStartClass(
+                forms.attendClassItem,
+                item.classGroupId,
+                item.instrumentId
+              );
+            }}
+          />
+        </NModal>
+
+        <NModal
+          v-model:show={forms.workVisiable}
+          preset="card"
+          class={['modalTitle background', styles.workVisiable]}
+          title={
+            forms.selectItem.lessonPreTrainingId ? '编辑作业' : '创建作业'
+          }>
+          <div id="model-homework-height" class={styles.workContainer}>
+            <div class={styles.workTrain}>
+              <Train
+                cardType="prepare"
+                lessonPreTraining={{
+                  title: forms.selectItem.name + '-课后作业',
+                  chapterId: forms.selectItem.id, // 课件编号
+                  id: forms.selectItem.lessonPreTrainingId // 作业编号
+                }}
+                onChange={(val: any) => {
+                  forms.workVisiable = val.status;
+                  getCoursewareList();
+                }}
+              />
+            </div>
+            <div class={styles.resourceMain}>
+              <ResourceMain cardType="prepare" />
+            </div>
+          </div>
+        </NModal>
+      </div>
+    );
+  }
+});

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

@@ -1,959 +1,959 @@
-import { defineComponent, nextTick, onMounted, reactive, watch } from 'vue';
-import styles from './index.module.less';
-import {
-  NButton,
-  NModal,
-  NScrollbar,
-  NSelect,
-  NSpace,
-  NSpin,
-  useMessage,
-  useDialog
-} from 'naive-ui';
-import CardType from '/src/components/card-type';
-import AttendClass from '/src/views/prepare-lessons/model/attend-class';
-import { usePrepareStore } from '/src/store/modules/prepareLessons';
-import { useCatchStore } from '/src/store/modules/catchData';
-import TheEmpty from '/src/components/TheEmpty';
-import {
-  courseScheduleStart,
-  queryCourseware,
-  saveCourseware,
-  teacherKnowledgeMaterialDelete
-} from '../../../api';
-import Draggable from 'vuedraggable';
-import iconDelete from '../../../images/icon-delete.png';
-import iconAddMusic from '../../../images/icon-add-music.png';
-import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';
-import deepClone from '/src/helpers/deep-clone';
-import CardPreview from '/src/components/card-preview';
-import PreviewWindow from '/src/views/preview-window';
-import { state } from '/src/state';
-import SubjectSync from '../../../model/subject-sync';
-import { eventGlobal } from '/src/utils';
-import iconTips from '../../../images/icon-tips.png';
-import { useElementBounding } from '@vueuse/core';
-export default defineComponent({
-  name: 'courseware-modal',
-  setup() {
-    const catchStore = useCatchStore();
-    const prepareStore = usePrepareStore();
-    const route = useRoute();
-    const router = useRouter();
-    const dialog = useDialog();
-    const message = useMessage();
-
-    const localStorageSubjectId = localStorage.getItem(
-      'prepareLessonSubjectId'
-    );
-    const forms = reactive({
-      tipsStatus: localStorage.getItem('prepare-lesson-courseware-tip')
-        ? true
-        : false,
-      className: route.query.name as any,
-      classGroupId: route.query.classGroupId,
-      preStudentNum: route.query.preStudentNum,
-      courseScheduleSubjectId: route.query.courseScheduleSubjectId,
-      // 选取参数带的,后取缓存
-      subjectId: route.query.subjectId
-        ? Number(route.query.subjectId)
-        : localStorageSubjectId
-        ? Number(localStorageSubjectId)
-        : null,
-      coursewareList: [] as any,
-      loadingStatus: false,
-      showAttendClass: false,
-      attendClassType: 'change', //
-      removeIds: [] as any, // 临时删除的编号
-      drag: false,
-      isEdit: false, // 是否更新数据
-      editSubjectIds: '', // 声部编号
-      removeVisiable: false,
-      removeVisiable1: false,
-      subjectSyncVisiable: false, // 同步声部
-      show: false,
-      item: {} as any,
-      previewModal: false,
-      previewParams: {
-        type: '',
-        subjectId: '',
-        detailId: ''
-      } as any
-    });
-
-    // 获取列表
-    const getList = async () => {
-      forms.loadingStatus = true;
-      try {
-        // 判断是否有选择对应的课件 或声部
-        if (!prepareStore.getSelectKey || !prepareStore.getSubjectId)
-          return (forms.loadingStatus = false);
-        const { data } = await queryCourseware({
-          coursewareDetailKnowledgeId: prepareStore.getSelectKey,
-          subjectId: prepareStore.getSubjectId,
-          page: 1,
-          rows: 99
-        });
-        const tempRows = data.rows || [];
-        const temp: any = [];
-        tempRows.forEach((row: any) => {
-          temp.push({
-            id: row.id,
-            materialId: row.materialId,
-            coverImg: row.coverImg,
-            type: row.materialType,
-            title: row.materialName,
-            isCollect: !!row.favoriteFlag,
-            isSelected: row.source === 'PLATFORM' ? true : false,
-            content: row.content,
-            removeFlag: row.removeFlag
-          });
-        });
-
-        prepareStore.setCoursewareList(temp || []);
-
-        const tempCourse: any = [];
-        temp.forEach((item: any) => {
-          if (!forms.removeIds.includes(item.id)) {
-            tempCourse.push(item);
-          }
-        });
-        forms.coursewareList = tempCourse;
-      } catch {
-        //
-      }
-      forms.loadingStatus = false;
-    };
-
-    // 监听选择的key 左侧选择了其它的课
-    watch(
-      () => prepareStore.getSelectKey,
-      () => {
-        forms.drag = false;
-        prepareStore.setIsEditResource(false);
-        getList();
-      }
-    );
-    // 声部变化时
-    watch(
-      () => prepareStore.getSubjectId,
-      () => {
-        getList();
-      }
-    );
-    watch(
-      () => prepareStore.getIsAddResource,
-      (val: boolean) => {
-        if (val) {
-          getList();
-          prepareStore.setIsAddResource(false);
-        }
-      }
-    );
-    // 监听列表变化,如果变化了,则弹选择声部的
-    watch(
-      () => forms.coursewareList,
-      () => {
-        if (forms.drag) {
-          forms.isEdit = true;
-        }
-      },
-      {
-        deep: true
-      }
-    );
-
-    // 删除
-    const onDelete = (item: any) => {
-      //
-      forms.removeIds.push(item.id);
-      const index = forms.coursewareList.findIndex(
-        (c: any) => c.id === item.id
-      );
-      forms.coursewareList.splice(index, 1);
-      forms.isEdit = true;
-      // prepareStore.setCoursewareList(forms.coursewareList);
-      // console.log(prepareStore.getCoursewareList, 'getCourseware');
-    };
-
-    // 完成编辑
-    const onOverEdit = async () => {
-      try {
-        const temp: any = [];
-        forms.coursewareList.forEach((item: any) => {
-          temp.push({
-            materialName: item.title,
-            materialType: item.type,
-            materialId: item.materialId,
-            id: item.id
-          });
-        });
-        // 保存课件
-        // 判断是否编辑,如果编辑则取选择的声部
-        await saveCourseware({
-          coursewareDetailKnowledgeId: prepareStore.getSelectKey,
-          lessonCoursewareId: prepareStore.getLessonCoursewareId,
-          lessonCoursewareDetailId: prepareStore.getLessonCoursewareDetailId,
-          subjectId: forms.isEdit
-            ? forms.editSubjectIds
-            : prepareStore.getSubjectId,
-          materialList: [...temp]
-        });
-
-        forms.drag = false;
-        message.success('编辑成功');
-        forms.removeVisiable = false;
-        prepareStore.setIsEditResource(false);
-        // 重置临时删除编号
-        forms.removeIds = [];
-        await getList();
-      } catch {
-        //
-      }
-    };
-
-    // 预览上课
-    const onPreviewAttend = () => {
-      // 获取上架的数据
-      let count = 0;
-      forms.coursewareList.forEach((item: any) => {
-        if (!item.removeFlag) {
-          count++;
-        }
-      });
-      if (count <= 0) {
-        message.error('课件不能为空');
-        return;
-      }
-      // 判断是否在应用里面
-      if (window.matchMedia('(display-mode: standalone)').matches) {
-        state.application = window.matchMedia(
-          '(display-mode: standalone)'
-        ).matches;
-        forms.previewModal = true;
-        fscreen();
-        forms.previewParams = {
-          type: 'preview',
-          subjectId: prepareStore.getSubjectId,
-          detailId: prepareStore.getSelectKey,
-          lessonCourseId: prepareStore.getBaseCourseware.id
-        };
-      } else {
-        const { href } = router.resolve({
-          path: '/attend-class',
-          query: {
-            type: 'preview',
-            subjectId: prepareStore.getSubjectId,
-            detailId: prepareStore.getSelectKey,
-            lessonCourseId: prepareStore.getBaseCourseware.id
-          }
-        });
-        window.open(href, +new Date() + '');
-      }
-    };
-    const fscreen = () => {
-      const el: any = document.documentElement;
-      const documentDom: any = document;
-      const isFullscreen =
-        documentDom.fullScreen ||
-        documentDom.mozFullScreen ||
-        documentDom.webkitIsFullScreen;
-      if (!isFullscreen) {
-        //进入全屏
-        (el.requestFullscreen && el.requestFullscreen()) ||
-          (el.mozRequestFullScreen && el.mozRequestFullScreen()) ||
-          (el.webkitRequestFullscreen && el.webkitRequestFullscreen()) ||
-          (el.msRequestFullscreen && el.msRequestFullscreen());
-      }
-    };
-    // 单个删除
-    const onRemove = async (item: any) => {
-      try {
-        dialog.warning({
-          title: '提示',
-          content: '该资源已下架,是否删除?',
-          positiveText: '确定',
-          negativeText: '取消',
-          onPositiveClick: async () => {
-            forms.removeIds.push(item.id);
-            await teacherKnowledgeMaterialDelete({ ids: item.id });
-            message.success('删除成功');
-            getList();
-          }
-        });
-      } catch {
-        //
-      }
-    };
-
-    watch(
-      () => prepareStore.getSubjectList,
-      () => {
-        checkSubjectIds();
-      }
-    );
-
-    const checkSubjectIds = () => {
-      const subjectList = prepareStore.getSubjectList;
-
-      // 并且没有声部时才会更新
-      if (subjectList.length > 0) {
-        // 并且声部在列表中
-        const localStorageSubjectId = localStorage.getItem(
-          'prepareLessonSubjectId'
-        );
-        // // 先取 上次上课声部,在取班级声部 最后取缓存
-        let subjectId = null;
-        let index = -1;
-        if (forms.courseScheduleSubjectId) {
-          // 判断浏览器上面是否有
-          index = subjectList.findIndex(
-            (subject: any) => subject.id == forms.courseScheduleSubjectId
-          );
-          if (index >= 0) {
-            subjectId = Number(forms.courseScheduleSubjectId);
-          }
-        }
-        // 判断班级上面声部 & 还没有声部
-        if (forms.subjectId && !subjectId) {
-          // 判断浏览器上面是否有
-          index = subjectList.findIndex(
-            (subject: any) => subject.id == forms.subjectId
-          );
-          if (index >= 0) {
-            subjectId = Number(forms.subjectId);
-          }
-        }
-        // 缓存声部 & 还没有声部
-        if (localStorageSubjectId && !subjectId) {
-          // 判断浏览器上面是否有
-          index = subjectList.findIndex(
-            (subject: any) => subject.id == localStorageSubjectId
-          );
-          if (index >= 0) {
-            subjectId = Number(localStorageSubjectId);
-          }
-        }
-        if (subjectId && index >= 0) {
-          prepareStore.setSubjectId(subjectId);
-        } else {
-          // 判断是否有缓存
-          prepareStore.setSubjectId(subjectList[0].id);
-        }
-
-        // 保存
-        localStorage.setItem(
-          'prepareLessonSubjectId',
-          prepareStore.getSubjectId as any
-        );
-      }
-    };
-
-    watch(
-      () => route.query,
-      async () => {
-        forms.className = route.query.name as any;
-        forms.classGroupId = route.query.classGroupId as any;
-        forms.preStudentNum = route.query.preStudentNum as any;
-        forms.subjectId = route.query.subjectId
-          ? Number(route.query.subjectId)
-          : null;
-        prepareStore.setClassGroupId(forms.classGroupId as any);
-
-        checkSubjectIds();
-        await getList();
-      }
-    );
-
-    const isPointInsideElement = (element: any, x: number, y: number) => {
-      const rect = element.getBoundingClientRect();
-      return (
-        x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom
-      );
-    };
-    const isPointOnLeft = (element: any, x: number) => {
-      const rect = element.getBoundingClientRect();
-      const elementCenterX = rect.left + rect.width / 2;
-      return x < elementCenterX;
-    };
-    onMounted(async () => {
-      prepareStore.setClassGroupId(route.query.classGroupId as any);
-      // 获取教材分类列表
-      checkSubjectIds();
-
-      await getList();
-
-      // 动态添加数据
-      eventGlobal.on('onPrepareAddItem', (item: any, point?: any) => {
-        forms.drag = true;
-        forms.isEdit = true;
-        nextTick(() => {
-          if (point) {
-            const dom = document.querySelectorAll('.row-nav');
-            let isAdd = false;
-            dom.forEach((child: any, index: number) => {
-              const status = isPointInsideElement(child, point.x, point.y);
-              if (status) {
-                const array: any = forms.coursewareList;
-                const left = isPointOnLeft(child, point.x);
-                if (!left) {
-                  array.splice(index + 1, 0, item);
-                } else {
-                  array.splice(index, 0, item);
-                }
-                isAdd = true;
-                forms.coursewareList = array;
-                prepareStore.setCoursewareList(forms.coursewareList);
-              }
-            });
-            if (!isAdd) {
-              forms.coursewareList.push(item);
-              prepareStore.setCoursewareList(forms.coursewareList);
-            }
-          } else {
-            forms.coursewareList.push(item);
-            prepareStore.setCoursewareList(forms.coursewareList);
-          }
-        });
-      });
-    });
-
-    return () => (
-      <div class={styles.coursewareModal}>
-        <div class={styles.btnGroup}>
-          {forms.drag ? (
-            !forms.tipsStatus ? (
-              <div class={styles.tipsContainer}>
-                <div class={styles.tipsLeft}>
-                  <img src={iconTips} class={styles.iconTips} />
-                  <span class={styles.tips}>可以拖动资源排序哦</span>
-                </div>
-                <span
-                  class={styles.btnNoTips}
-                  onClick={() => {
-                    localStorage.setItem('prepare-lesson-courseware-tip', '1');
-                    forms.tipsStatus = true;
-                  }}>
-                  不再提醒
-                </span>
-              </div>
-            ) : (
-              <span></span>
-            )
-          ) : (
-            <NSpace>
-              {forms.classGroupId && (
-                <div class={styles.btnItem}>
-                  <span class={styles.btnTitle}>上课班级:</span>
-                  <div
-                    onClick={() => {
-                      forms.showAttendClass = true;
-                      forms.attendClassType = 'change';
-                    }}>
-                    <NSelect
-                      placeholder="选择班级"
-                      labelField="name"
-                      valueField="id"
-                      class={styles.btnClassList}
-                      value={forms.className}
-                      disabled
-                    />
-                  </div>
-                </div>
-              )}
-
-              <div class={styles.btnItem}>
-                <span class={styles.btnTitle}>声部:</span>
-                <NSelect
-                  placeholder="选择声部"
-                  class={styles.btnSubjectList}
-                  options={prepareStore.getSubjectList}
-                  labelField="name"
-                  valueField="id"
-                  value={prepareStore.getSubjectId}
-                  onUpdate:value={(val: any) => {
-                    prepareStore.setSubjectId(val);
-                    // 保存
-                    localStorage.setItem('prepareLessonSubjectId', val);
-                    getList();
-                  }}
-                />
-              </div>
-            </NSpace>
-          )}
-
-          {/* 编辑 */}
-          {!forms.drag ? (
-            <NSpace>
-              <NButton
-                type="default"
-                onClick={() => {
-                  forms.drag = true;
-                  prepareStore.setIsEditResource(true);
-
-                  // forms.subjectSyncVisiable = true;
-                }}>
-                编辑
-              </NButton>
-            </NSpace>
-          ) : (
-            <NSpace>
-              <NButton
-                type="error"
-                onClick={() => {
-                  forms.removeVisiable1 = true;
-                }}>
-                清空资源
-              </NButton>
-              <NButton
-                type="error"
-                onClick={() => {
-                  forms.drag = false;
-                  forms.isEdit = false;
-                  prepareStore.setIsEditResource(false);
-                  forms.removeIds = [];
-                  getList();
-                }}>
-                取消编辑
-              </NButton>
-              <NButton
-                type="default"
-                onClick={() => {
-                  if (forms.isEdit) {
-                    forms.subjectSyncVisiable = true;
-                  } else {
-                    forms.removeVisiable = true;
-                  }
-                }}>
-                完成编辑
-              </NButton>
-            </NSpace>
-          )}
-        </div>
-
-        <NScrollbar
-          class={[
-            styles.listContainer,
-            forms.drag ? styles.listContainerDrag : ''
-          ]}
-          {...{ id: 'lessons-2' }}>
-          <NSpin show={forms.loadingStatus}>
-            <div
-              class={[
-                styles.listSection
-                // !forms.loadingStatus && forms.coursewareList.length <= 0
-                //   ? styles.emptySection
-                //   : ''
-              ]}
-              onDragenter={(e: any) => {
-                e.preventDefault();
-              }}
-              onDragover={(e: any) => {
-                e.preventDefault();
-              }}
-              onDrop={(e: any) => {
-                console.log(e, 'event');
-                let dropItem = e.dataTransfer.getData('text');
-                dropItem = dropItem ? JSON.parse(dropItem) : {};
-                // 判断是否有数据
-                if (dropItem.id) {
-                  // 获取拖拽的目标元素
-
-                  eventGlobal.emit(
-                    'onPrepareAddItem',
-                    {
-                      materialId: dropItem.id,
-                      coverImg: dropItem.coverImg,
-                      type: dropItem.type,
-                      title: dropItem.title,
-                      isCollect: dropItem.isCollect,
-                      isSelected: dropItem.isSelected,
-                      content: dropItem.content,
-                      removeFlag: false
-                    },
-                    {
-                      x: e.clientX,
-                      y: e.clientY
-                    }
-                  );
-                }
-              }}>
-              {forms.coursewareList.length > 0 && (
-                <>
-                  {forms.drag ? (
-                    <Draggable
-                      v-model:modelValue={forms.coursewareList}
-                      itemKey="id"
-                      componentData={{
-                        itemKey: 'id',
-                        tag: 'div',
-                        animation: 200,
-                        group: 'description',
-                        disabled: false
-                      }}
-                      class={styles.list}>
-                      {{
-                        item: (element: any) => {
-                          const item = element.element;
-                          return (
-                            <div
-                              data-id={item.id}
-                              class={[
-                                styles.itemWrap,
-                                styles.itemBlock,
-                                'row-nav'
-                              ]}>
-                              <div class={styles.itemWrapBox}>
-                                <CardType
-                                  class={[styles.itemContent]}
-                                  isShowCollect={false}
-                                  offShelf={item.removeFlag ? true : false}
-                                  onOffShelf={() => onRemove(item)}
-                                  item={item}
-                                />
-                                <div class={styles.itemOperation}>
-                                  <img
-                                    src={iconDelete}
-                                    class={styles.iconDelete}
-                                    onClick={(e: MouseEvent) => {
-                                      e.stopPropagation();
-                                      onDelete(item);
-                                    }}
-                                  />
-                                </div>
-                              </div>
-                            </div>
-                          );
-                        }
-                      }}
-                    </Draggable>
-                  ) : (
-                    <div class={styles.list}>
-                      {forms.coursewareList.map((item: any) => (
-                        <div class={styles.itemWrap}>
-                          <div class={styles.itemWrapBox}>
-                            <CardType
-                              class={[styles.itemContent, 'handle']}
-                              isShowCollect={false}
-                              item={item}
-                              offShelf={item.removeFlag ? true : false}
-                              onOffShelf={() => onRemove(item)}
-                              disabledMouseHover={false}
-                              onClick={() => {
-                                if (item.type === 'IMG') return;
-                                forms.show = true;
-                                forms.item = item;
-                              }}
-                            />
-                          </div>
-                        </div>
-                      ))}
-                      <div class={styles.itemWrap}>
-                        <div class={styles.itemWrapBox}>
-                          <div
-                            class={[
-                              styles.itemContent,
-                              styles.addMusicItem,
-                              'handle'
-                            ]}
-                            onClick={() => {
-                              // 直接跳转到制谱页面 (临时存储数据)
-                              sessionStorage.setItem(
-                                'notation-open-create',
-                                '1'
-                              );
-                              router.push('/notation');
-                            }}>
-                            <img src={iconAddMusic} />
-
-                            <p class={styles.addMusicName}>开始制谱</p>
-                          </div>
-                        </div>
-                      </div>
-                    </div>
-                  )}
-                </>
-              )}
-
-              {/* {!forms.loadingStatus && forms.coursewareList.length <= 0 && (
-                <TheEmpty description="暂无课件" />
-              )} */}
-              {forms.coursewareList.length <= 0 && (
-                <div class={styles.list}>
-                  <div class={styles.itemWrap}>
-                    <div class={styles.itemWrapBox}>
-                      <div
-                        class={[
-                          styles.itemContent,
-                          styles.addMusicItem,
-                          'handle'
-                        ]}
-                        onClick={() => {
-                          // 直接跳转到制谱页面 (临时存储数据)
-                          sessionStorage.setItem('notation-open-create', '1');
-                          router.push('/notation');
-                        }}>
-                        <img src={iconAddMusic} />
-
-                        <p class={styles.addMusicName}>开始制谱</p>
-                      </div>
-                    </div>
-                  </div>
-                </div>
-              )}
-            </div>
-          </NSpin>
-        </NScrollbar>
-
-        {!forms.drag ? (
-          <div
-            class={[styles.btnGroup, styles.btnGroupClass]}
-            style={{ justifyContent: 'flex-end' }}>
-            <NSpace justify="end">
-              <NButton type="primary" onClick={onPreviewAttend}>
-                预览课件
-              </NButton>
-              <NButton
-                {...{ id: 'lessons-3' }}
-                type="error"
-                class={styles.btnClassStart}
-                onClick={async () => {
-                  let count = 0;
-                  forms.coursewareList.forEach((item: any) => {
-                    if (!item.removeFlag) {
-                      count++;
-                    }
-                  });
-                  if (count <= 0) {
-                    message.error('课件不能为空');
-                    return;
-                  }
-
-                  if (forms.classGroupId) {
-                    // 开始上课
-                    const res = await courseScheduleStart({
-                      lessonCoursewareKnowledgeDetailId: prepareStore.selectKey,
-                      classGroupId: forms.classGroupId,
-                      subjectId: prepareStore.getSubjectId
-                    });
-                    if (
-                      window.matchMedia('(display-mode: standalone)').matches
-                    ) {
-                      state.application = window.matchMedia(
-                        '(display-mode: standalone)'
-                      ).matches;
-                      forms.previewModal = true;
-                      fscreen();
-                      forms.previewParams = {
-                        type: 'class',
-                        classGroupId: forms.classGroupId,
-                        subjectId: prepareStore.getSubjectId,
-                        detailId: prepareStore.getSelectKey,
-                        classId: res.data,
-                        lessonCourseId: prepareStore.getBaseCourseware.id,
-                        preStudentNum: forms.preStudentNum
-                      };
-                    } else {
-                      const { href } = router.resolve({
-                        path: '/attend-class',
-                        query: {
-                          type: 'class',
-                          classGroupId: forms.classGroupId,
-                          subjectId: prepareStore.getSubjectId,
-                          detailId: prepareStore.getSelectKey,
-                          classId: res.data,
-                          lessonCourseId: prepareStore.getBaseCourseware.id,
-                          preStudentNum: forms.preStudentNum
-                        }
-                      });
-                      window.open(href, +new Date() + '');
-                    }
-                  } else {
-                    forms.showAttendClass = true;
-                    forms.attendClassType = 'change';
-                  }
-                }}>
-                开始上课
-              </NButton>
-            </NSpace>
-          </div>
-        ) : (
-          ''
-        )}
-
-        <NModal
-          v-model:show={forms.showAttendClass}
-          preset="card"
-          showIcon={false}
-          class={['modalTitle background', styles.attendClassModal]}
-          title={'选择班级'}
-          blockScroll={false}>
-          <AttendClass
-            onClose={() => (forms.showAttendClass = false)}
-            type={forms.attendClassType}
-            onPreview={(item: any) => {
-              if (window.matchMedia('(display-mode: standalone)').matches) {
-                state.application = window.matchMedia(
-                  '(display-mode: standalone)'
-                ).matches;
-                forms.previewModal = true;
-                forms.previewParams = {
-                  ...item
-                };
-              } else {
-                const { href } = router.resolve({
-                  path: '/attend-class',
-                  query: {
-                    ...item
-                  }
-                });
-                window.open(href, +new Date() + '');
-              }
-            }}
-            onConfirm={async (item: any) => {
-              if (forms.classGroupId) {
-                forms.className = item.name;
-                forms.classGroupId = item.classGroupId;
-                forms.preStudentNum = item.preStudentNum;
-                forms.subjectId = item.subjectId;
-                forms.courseScheduleSubjectId = item.courseScheduleSubjectId;
-                forms.showAttendClass = false;
-
-                prepareStore.setClassGroupId(item.classGroupId);
-                console.log(forms, 'forms', item);
-                checkSubjectIds();
-                // 声部切换时
-                eventGlobal.emit('onChangeClass', {
-                  lastUseCoursewareId: item.lastUseCoursewareId,
-                  unit: item.unit
-                });
-              } else {
-                const res = await courseScheduleStart({
-                  lessonCoursewareKnowledgeDetailId: prepareStore.selectKey,
-                  classGroupId: item.classGroupId,
-                  subjectId: prepareStore.getSubjectId
-                });
-                forms.showAttendClass = false;
-                if (window.matchMedia('(display-mode: standalone)').matches) {
-                  state.application = window.matchMedia(
-                    '(display-mode: standalone)'
-                  ).matches;
-                  forms.previewModal = true;
-                  forms.previewParams = {
-                    type: 'class',
-                    classId: res.data, // 上课编号
-                    classGroupId: item.classGroupId,
-                    preStudentNum: item.preStudentNum,
-                    subjectId: prepareStore.getSubjectId,
-                    detailId: prepareStore.getSelectKey,
-                    lessonCourseId: prepareStore.getBaseCourseware.id
-                  };
-                  setTimeout(() => {
-                    fscreen();
-                  }, 200);
-                } else {
-                  const { href } = router.resolve({
-                    path: '/attend-class',
-                    query: {
-                      type: 'class',
-                      classId: res.data, // 上课编号
-                      classGroupId: item.classGroupId,
-                      preStudentNum: item.preStudentNum,
-                      subjectId: prepareStore.getSubjectId,
-                      detailId: prepareStore.getSelectKey,
-                      lessonCourseId: prepareStore.getBaseCourseware.id
-                    }
-                  });
-                  window.open(href, +new Date() + '');
-                }
-              }
-            }}
-          />
-        </NModal>
-
-        {/* 弹窗查看 */}
-        <CardPreview v-model:show={forms.show} item={forms.item} />
-
-        <NModal
-          v-model:show={forms.removeVisiable}
-          preset="card"
-          class={['modalTitle', styles.removeVisiable]}
-          title={'提示'}>
-          <div class={styles.studentRemove}>
-            <p>是否完成编辑?</p>
-
-            <NSpace class={styles.btnGroupModal} justify="center">
-              <NButton round type="primary" onClick={onOverEdit}>
-                确定
-              </NButton>
-              <NButton round onClick={() => (forms.removeVisiable = false)}>
-                取消
-              </NButton>
-            </NSpace>
-          </div>
-        </NModal>
-
-        <NModal
-          v-model:show={forms.removeVisiable1}
-          preset="card"
-          class={['modalTitle', styles.removeVisiable1]}
-          title={'清空资源'}>
-          <div class={styles.studentRemove}>
-            <p>
-              请确认是否要清空资源?
-              <span>点击确认后所有的素材内容 将被清空掉。</span>
-            </p>
-
-            <NSpace class={styles.btnGroupModal} justify="center">
-              <NButton
-                round
-                type="primary"
-                onClick={() => {
-                  forms.coursewareList.forEach((item: any) => {
-                    forms.removeIds.push(item.id);
-                  });
-                  forms.coursewareList = [];
-                  forms.removeVisiable1 = false;
-                  forms.isEdit = true;
-                  // prepareStore.setCoursewareList([]);
-                }}>
-                确定
-              </NButton>
-              <NButton round onClick={() => (forms.removeVisiable1 = false)}>
-                取消
-              </NButton>
-            </NSpace>
-          </div>
-        </NModal>
-
-        <PreviewWindow
-          v-model:show={forms.previewModal}
-          type="attend"
-          params={forms.previewParams}
-        />
-
-        {/* 完成编辑时,选择声部 */}
-        <NModal
-          v-model:show={forms.subjectSyncVisiable}
-          preset="card"
-          class={['modalTitle background', styles.subjectSyncModal]}
-          title={'同步声部'}>
-          <SubjectSync
-            subjectId={prepareStore.getSubjectId as any}
-            onClose={() => (forms.subjectSyncVisiable = false)}
-            onConfirm={async (subjectIds: any) => {
-              //
-              try {
-                forms.editSubjectIds = subjectIds.join(',');
-                await onOverEdit();
-                forms.subjectSyncVisiable = false;
-              } catch {
-                //
-              }
-            }}
-          />
-        </NModal>
-      </div>
-    );
-  }
-});
+import { defineComponent, nextTick, onMounted, reactive, watch } from 'vue';
+import styles from './index.module.less';
+import {
+  NButton,
+  NModal,
+  NScrollbar,
+  NSelect,
+  NSpace,
+  NSpin,
+  useMessage,
+  useDialog
+} from 'naive-ui';
+import CardType from '/src/components/card-type';
+import AttendClass from '/src/views/prepare-lessons/model/attend-class';
+import { usePrepareStore } from '/src/store/modules/prepareLessons';
+import { useCatchStore } from '/src/store/modules/catchData';
+import TheEmpty from '/src/components/TheEmpty';
+import {
+  courseScheduleStart,
+  queryCourseware,
+  saveCourseware,
+  teacherKnowledgeMaterialDelete
+} from '../../../api';
+import Draggable from 'vuedraggable';
+import iconDelete from '../../../images/icon-delete.png';
+import iconAddMusic from '../../../images/icon-add-music.png';
+import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';
+import deepClone from '/src/helpers/deep-clone';
+import CardPreview from '/src/components/card-preview';
+import PreviewWindow from '/src/views/preview-window';
+import { state } from '/src/state';
+import SubjectSync from '../../../model/subject-sync';
+import { eventGlobal } from '/src/utils';
+import iconTips from '../../../images/icon-tips.png';
+import { useElementBounding } from '@vueuse/core';
+export default defineComponent({
+  name: 'courseware-modal',
+  setup() {
+    const catchStore = useCatchStore();
+    const prepareStore = usePrepareStore();
+    const route = useRoute();
+    const router = useRouter();
+    const dialog = useDialog();
+    const message = useMessage();
+
+    const localStorageSubjectId = localStorage.getItem(
+      'prepareLessonSubjectId'
+    );
+    const forms = reactive({
+      tipsStatus: localStorage.getItem('prepare-lesson-courseware-tip')
+        ? true
+        : false,
+      className: route.query.name as any,
+      classGroupId: route.query.classGroupId,
+      preStudentNum: route.query.preStudentNum,
+      courseScheduleSubjectId: route.query.courseScheduleSubjectId,
+      // 选取参数带的,后取缓存
+      subjectId: route.query.subjectId
+        ? Number(route.query.subjectId)
+        : localStorageSubjectId
+        ? Number(localStorageSubjectId)
+        : null,
+      coursewareList: [] as any,
+      loadingStatus: false,
+      showAttendClass: false,
+      attendClassType: 'change', //
+      removeIds: [] as any, // 临时删除的编号
+      drag: false,
+      isEdit: false, // 是否更新数据
+      editSubjectIds: '', // 声部编号
+      removeVisiable: false,
+      removeVisiable1: false,
+      subjectSyncVisiable: false, // 同步声部
+      show: false,
+      item: {} as any,
+      previewModal: false,
+      previewParams: {
+        type: '',
+        subjectId: '',
+        detailId: ''
+      } as any
+    });
+
+    // 获取列表
+    const getList = async () => {
+      forms.loadingStatus = true;
+      try {
+        // 判断是否有选择对应的课件 或声部
+        if (!prepareStore.getSelectKey || !prepareStore.getSubjectId)
+          return (forms.loadingStatus = false);
+        const { data } = await queryCourseware({
+          coursewareDetailKnowledgeId: prepareStore.getSelectKey,
+          subjectId: prepareStore.getSubjectId,
+          page: 1,
+          rows: 99
+        });
+        const tempRows = data.rows || [];
+        const temp: any = [];
+        tempRows.forEach((row: any) => {
+          temp.push({
+            id: row.id,
+            materialId: row.materialId,
+            coverImg: row.coverImg,
+            type: row.materialType,
+            title: row.materialName,
+            isCollect: !!row.favoriteFlag,
+            isSelected: row.source === 'PLATFORM' ? true : false,
+            content: row.content,
+            removeFlag: row.removeFlag
+          });
+        });
+
+        prepareStore.setCoursewareList(temp || []);
+
+        const tempCourse: any = [];
+        temp.forEach((item: any) => {
+          if (!forms.removeIds.includes(item.id)) {
+            tempCourse.push(item);
+          }
+        });
+        forms.coursewareList = tempCourse;
+      } catch {
+        //
+      }
+      forms.loadingStatus = false;
+    };
+
+    // 监听选择的key 左侧选择了其它的课
+    watch(
+      () => prepareStore.getSelectKey,
+      () => {
+        forms.drag = false;
+        prepareStore.setIsEditResource(false);
+        getList();
+      }
+    );
+    // 声部变化时
+    watch(
+      () => prepareStore.getSubjectId,
+      () => {
+        getList();
+      }
+    );
+    watch(
+      () => prepareStore.getIsAddResource,
+      (val: boolean) => {
+        if (val) {
+          getList();
+          prepareStore.setIsAddResource(false);
+        }
+      }
+    );
+    // 监听列表变化,如果变化了,则弹选择声部的
+    watch(
+      () => forms.coursewareList,
+      () => {
+        if (forms.drag) {
+          forms.isEdit = true;
+        }
+      },
+      {
+        deep: true
+      }
+    );
+
+    // 删除
+    const onDelete = (item: any) => {
+      //
+      forms.removeIds.push(item.id);
+      const index = forms.coursewareList.findIndex(
+        (c: any) => c.id === item.id
+      );
+      forms.coursewareList.splice(index, 1);
+      forms.isEdit = true;
+      // prepareStore.setCoursewareList(forms.coursewareList);
+      // console.log(prepareStore.getCoursewareList, 'getCourseware');
+    };
+
+    // 完成编辑
+    const onOverEdit = async () => {
+      try {
+        const temp: any = [];
+        forms.coursewareList.forEach((item: any) => {
+          temp.push({
+            materialName: item.title,
+            materialType: item.type,
+            materialId: item.materialId,
+            id: item.id
+          });
+        });
+        // 保存课件
+        // 判断是否编辑,如果编辑则取选择的声部
+        await saveCourseware({
+          coursewareDetailKnowledgeId: prepareStore.getSelectKey,
+          lessonCoursewareId: prepareStore.getLessonCoursewareId,
+          lessonCoursewareDetailId: prepareStore.getLessonCoursewareDetailId,
+          subjectId: forms.isEdit
+            ? forms.editSubjectIds
+            : prepareStore.getSubjectId,
+          materialList: [...temp]
+        });
+
+        forms.drag = false;
+        message.success('编辑成功');
+        forms.removeVisiable = false;
+        prepareStore.setIsEditResource(false);
+        // 重置临时删除编号
+        forms.removeIds = [];
+        await getList();
+      } catch {
+        //
+      }
+    };
+
+    // 预览上课
+    const onPreviewAttend = () => {
+      // 获取上架的数据
+      let count = 0;
+      forms.coursewareList.forEach((item: any) => {
+        if (!item.removeFlag) {
+          count++;
+        }
+      });
+      if (count <= 0) {
+        message.error('课件不能为空');
+        return;
+      }
+      // 判断是否在应用里面
+      if (window.matchMedia('(display-mode: standalone)').matches) {
+        state.application = window.matchMedia(
+          '(display-mode: standalone)'
+        ).matches;
+        forms.previewModal = true;
+        fscreen();
+        forms.previewParams = {
+          type: 'preview',
+          instrumentId: prepareStore.getInstrumentId,
+          detailId: prepareStore.getSelectKey,
+          lessonCourseId: prepareStore.getBaseCourseware.id
+        };
+      } else {
+        const { href } = router.resolve({
+          path: '/attend-class',
+          query: {
+            type: 'preview',
+            instrumentId: prepareStore.getInstrumentId,
+            detailId: prepareStore.getSelectKey,
+            lessonCourseId: prepareStore.getBaseCourseware.id
+          }
+        });
+        window.open(href, +new Date() + '');
+      }
+    };
+    const fscreen = () => {
+      const el: any = document.documentElement;
+      const documentDom: any = document;
+      const isFullscreen =
+        documentDom.fullScreen ||
+        documentDom.mozFullScreen ||
+        documentDom.webkitIsFullScreen;
+      if (!isFullscreen) {
+        //进入全屏
+        (el.requestFullscreen && el.requestFullscreen()) ||
+          (el.mozRequestFullScreen && el.mozRequestFullScreen()) ||
+          (el.webkitRequestFullscreen && el.webkitRequestFullscreen()) ||
+          (el.msRequestFullscreen && el.msRequestFullscreen());
+      }
+    };
+    // 单个删除
+    const onRemove = async (item: any) => {
+      try {
+        dialog.warning({
+          title: '提示',
+          content: '该资源已下架,是否删除?',
+          positiveText: '确定',
+          negativeText: '取消',
+          onPositiveClick: async () => {
+            forms.removeIds.push(item.id);
+            await teacherKnowledgeMaterialDelete({ ids: item.id });
+            message.success('删除成功');
+            getList();
+          }
+        });
+      } catch {
+        //
+      }
+    };
+
+    watch(
+      () => prepareStore.getSubjectList,
+      () => {
+        checkSubjectIds();
+      }
+    );
+
+    const checkSubjectIds = () => {
+      const subjectList = prepareStore.getSubjectList;
+
+      // 并且没有声部时才会更新
+      if (subjectList.length > 0) {
+        // 并且声部在列表中
+        const localStorageSubjectId = localStorage.getItem(
+          'prepareLessonSubjectId'
+        );
+        // // 先取 上次上课声部,在取班级声部 最后取缓存
+        let subjectId = null;
+        let index = -1;
+        if (forms.courseScheduleSubjectId) {
+          // 判断浏览器上面是否有
+          index = subjectList.findIndex(
+            (subject: any) => subject.id == forms.courseScheduleSubjectId
+          );
+          if (index >= 0) {
+            subjectId = Number(forms.courseScheduleSubjectId);
+          }
+        }
+        // 判断班级上面声部 & 还没有声部
+        if (forms.subjectId && !subjectId) {
+          // 判断浏览器上面是否有
+          index = subjectList.findIndex(
+            (subject: any) => subject.id == forms.subjectId
+          );
+          if (index >= 0) {
+            subjectId = Number(forms.subjectId);
+          }
+        }
+        // 缓存声部 & 还没有声部
+        if (localStorageSubjectId && !subjectId) {
+          // 判断浏览器上面是否有
+          index = subjectList.findIndex(
+            (subject: any) => subject.id == localStorageSubjectId
+          );
+          if (index >= 0) {
+            subjectId = Number(localStorageSubjectId);
+          }
+        }
+        if (subjectId && index >= 0) {
+          prepareStore.setSubjectId(subjectId);
+        } else {
+          // 判断是否有缓存
+          prepareStore.setSubjectId(subjectList[0].id);
+        }
+
+        // 保存
+        localStorage.setItem(
+          'prepareLessonSubjectId',
+          prepareStore.getSubjectId as any
+        );
+      }
+    };
+
+    watch(
+      () => route.query,
+      async () => {
+        forms.className = route.query.name as any;
+        forms.classGroupId = route.query.classGroupId as any;
+        forms.preStudentNum = route.query.preStudentNum as any;
+        forms.subjectId = route.query.subjectId
+          ? Number(route.query.subjectId)
+          : null;
+        prepareStore.setClassGroupId(forms.classGroupId as any);
+
+        checkSubjectIds();
+        await getList();
+      }
+    );
+
+    const isPointInsideElement = (element: any, x: number, y: number) => {
+      const rect = element.getBoundingClientRect();
+      return (
+        x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom
+      );
+    };
+    const isPointOnLeft = (element: any, x: number) => {
+      const rect = element.getBoundingClientRect();
+      const elementCenterX = rect.left + rect.width / 2;
+      return x < elementCenterX;
+    };
+    onMounted(async () => {
+      prepareStore.setClassGroupId(route.query.classGroupId as any);
+      // 获取教材分类列表
+      checkSubjectIds();
+
+      await getList();
+
+      // 动态添加数据
+      eventGlobal.on('onPrepareAddItem', (item: any, point?: any) => {
+        forms.drag = true;
+        forms.isEdit = true;
+        nextTick(() => {
+          if (point) {
+            const dom = document.querySelectorAll('.row-nav');
+            let isAdd = false;
+            dom.forEach((child: any, index: number) => {
+              const status = isPointInsideElement(child, point.x, point.y);
+              if (status) {
+                const array: any = forms.coursewareList;
+                const left = isPointOnLeft(child, point.x);
+                if (!left) {
+                  array.splice(index + 1, 0, item);
+                } else {
+                  array.splice(index, 0, item);
+                }
+                isAdd = true;
+                forms.coursewareList = array;
+                prepareStore.setCoursewareList(forms.coursewareList);
+              }
+            });
+            if (!isAdd) {
+              forms.coursewareList.push(item);
+              prepareStore.setCoursewareList(forms.coursewareList);
+            }
+          } else {
+            forms.coursewareList.push(item);
+            prepareStore.setCoursewareList(forms.coursewareList);
+          }
+        });
+      });
+    });
+
+    return () => (
+      <div class={styles.coursewareModal}>
+        <div class={styles.btnGroup}>
+          {forms.drag ? (
+            !forms.tipsStatus ? (
+              <div class={styles.tipsContainer}>
+                <div class={styles.tipsLeft}>
+                  <img src={iconTips} class={styles.iconTips} />
+                  <span class={styles.tips}>可以拖动资源排序哦</span>
+                </div>
+                <span
+                  class={styles.btnNoTips}
+                  onClick={() => {
+                    localStorage.setItem('prepare-lesson-courseware-tip', '1');
+                    forms.tipsStatus = true;
+                  }}>
+                  不再提醒
+                </span>
+              </div>
+            ) : (
+              <span></span>
+            )
+          ) : (
+            <NSpace>
+              {forms.classGroupId && (
+                <div class={styles.btnItem}>
+                  <span class={styles.btnTitle}>上课班级:</span>
+                  <div
+                    onClick={() => {
+                      forms.showAttendClass = true;
+                      forms.attendClassType = 'change';
+                    }}>
+                    <NSelect
+                      placeholder="选择班级"
+                      labelField="name"
+                      valueField="id"
+                      class={styles.btnClassList}
+                      value={forms.className}
+                      disabled
+                    />
+                  </div>
+                </div>
+              )}
+
+              <div class={styles.btnItem}>
+                <span class={styles.btnTitle}>声部:</span>
+                <NSelect
+                  placeholder="选择声部"
+                  class={styles.btnSubjectList}
+                  options={prepareStore.getSubjectList}
+                  labelField="name"
+                  valueField="id"
+                  value={prepareStore.getSubjectId}
+                  onUpdate:value={(val: any) => {
+                    prepareStore.setSubjectId(val);
+                    // 保存
+                    localStorage.setItem('prepareLessonSubjectId', val);
+                    getList();
+                  }}
+                />
+              </div>
+            </NSpace>
+          )}
+
+          {/* 编辑 */}
+          {!forms.drag ? (
+            <NSpace>
+              <NButton
+                type="default"
+                onClick={() => {
+                  forms.drag = true;
+                  prepareStore.setIsEditResource(true);
+
+                  // forms.subjectSyncVisiable = true;
+                }}>
+                编辑
+              </NButton>
+            </NSpace>
+          ) : (
+            <NSpace>
+              <NButton
+                type="error"
+                onClick={() => {
+                  forms.removeVisiable1 = true;
+                }}>
+                清空资源
+              </NButton>
+              <NButton
+                type="error"
+                onClick={() => {
+                  forms.drag = false;
+                  forms.isEdit = false;
+                  prepareStore.setIsEditResource(false);
+                  forms.removeIds = [];
+                  getList();
+                }}>
+                取消编辑
+              </NButton>
+              <NButton
+                type="default"
+                onClick={() => {
+                  if (forms.isEdit) {
+                    forms.subjectSyncVisiable = true;
+                  } else {
+                    forms.removeVisiable = true;
+                  }
+                }}>
+                完成编辑
+              </NButton>
+            </NSpace>
+          )}
+        </div>
+
+        <NScrollbar
+          class={[
+            styles.listContainer,
+            forms.drag ? styles.listContainerDrag : ''
+          ]}
+          {...{ id: 'lessons-2' }}>
+          <NSpin show={forms.loadingStatus}>
+            <div
+              class={[
+                styles.listSection
+                // !forms.loadingStatus && forms.coursewareList.length <= 0
+                //   ? styles.emptySection
+                //   : ''
+              ]}
+              onDragenter={(e: any) => {
+                e.preventDefault();
+              }}
+              onDragover={(e: any) => {
+                e.preventDefault();
+              }}
+              onDrop={(e: any) => {
+                console.log(e, 'event');
+                let dropItem = e.dataTransfer.getData('text');
+                dropItem = dropItem ? JSON.parse(dropItem) : {};
+                // 判断是否有数据
+                if (dropItem.id) {
+                  // 获取拖拽的目标元素
+
+                  eventGlobal.emit(
+                    'onPrepareAddItem',
+                    {
+                      materialId: dropItem.id,
+                      coverImg: dropItem.coverImg,
+                      type: dropItem.type,
+                      title: dropItem.title,
+                      isCollect: dropItem.isCollect,
+                      isSelected: dropItem.isSelected,
+                      content: dropItem.content,
+                      removeFlag: false
+                    },
+                    {
+                      x: e.clientX,
+                      y: e.clientY
+                    }
+                  );
+                }
+              }}>
+              {forms.coursewareList.length > 0 && (
+                <>
+                  {forms.drag ? (
+                    <Draggable
+                      v-model:modelValue={forms.coursewareList}
+                      itemKey="id"
+                      componentData={{
+                        itemKey: 'id',
+                        tag: 'div',
+                        animation: 200,
+                        group: 'description',
+                        disabled: false
+                      }}
+                      class={styles.list}>
+                      {{
+                        item: (element: any) => {
+                          const item = element.element;
+                          return (
+                            <div
+                              data-id={item.id}
+                              class={[
+                                styles.itemWrap,
+                                styles.itemBlock,
+                                'row-nav'
+                              ]}>
+                              <div class={styles.itemWrapBox}>
+                                <CardType
+                                  class={[styles.itemContent]}
+                                  isShowCollect={false}
+                                  offShelf={item.removeFlag ? true : false}
+                                  onOffShelf={() => onRemove(item)}
+                                  item={item}
+                                />
+                                <div class={styles.itemOperation}>
+                                  <img
+                                    src={iconDelete}
+                                    class={styles.iconDelete}
+                                    onClick={(e: MouseEvent) => {
+                                      e.stopPropagation();
+                                      onDelete(item);
+                                    }}
+                                  />
+                                </div>
+                              </div>
+                            </div>
+                          );
+                        }
+                      }}
+                    </Draggable>
+                  ) : (
+                    <div class={styles.list}>
+                      {forms.coursewareList.map((item: any) => (
+                        <div class={styles.itemWrap}>
+                          <div class={styles.itemWrapBox}>
+                            <CardType
+                              class={[styles.itemContent, 'handle']}
+                              isShowCollect={false}
+                              item={item}
+                              offShelf={item.removeFlag ? true : false}
+                              onOffShelf={() => onRemove(item)}
+                              disabledMouseHover={false}
+                              onClick={() => {
+                                if (item.type === 'IMG') return;
+                                forms.show = true;
+                                forms.item = item;
+                              }}
+                            />
+                          </div>
+                        </div>
+                      ))}
+                      <div class={styles.itemWrap}>
+                        <div class={styles.itemWrapBox}>
+                          <div
+                            class={[
+                              styles.itemContent,
+                              styles.addMusicItem,
+                              'handle'
+                            ]}
+                            onClick={() => {
+                              // 直接跳转到制谱页面 (临时存储数据)
+                              sessionStorage.setItem(
+                                'notation-open-create',
+                                '1'
+                              );
+                              router.push('/notation');
+                            }}>
+                            <img src={iconAddMusic} />
+
+                            <p class={styles.addMusicName}>开始制谱</p>
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                  )}
+                </>
+              )}
+
+              {/* {!forms.loadingStatus && forms.coursewareList.length <= 0 && (
+                <TheEmpty description="暂无课件" />
+              )} */}
+              {forms.coursewareList.length <= 0 && (
+                <div class={styles.list}>
+                  <div class={styles.itemWrap}>
+                    <div class={styles.itemWrapBox}>
+                      <div
+                        class={[
+                          styles.itemContent,
+                          styles.addMusicItem,
+                          'handle'
+                        ]}
+                        onClick={() => {
+                          // 直接跳转到制谱页面 (临时存储数据)
+                          sessionStorage.setItem('notation-open-create', '1');
+                          router.push('/notation');
+                        }}>
+                        <img src={iconAddMusic} />
+
+                        <p class={styles.addMusicName}>开始制谱</p>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              )}
+            </div>
+          </NSpin>
+        </NScrollbar>
+
+        {!forms.drag ? (
+          <div
+            class={[styles.btnGroup, styles.btnGroupClass]}
+            style={{ justifyContent: 'flex-end' }}>
+            <NSpace justify="end">
+              <NButton type="primary" onClick={onPreviewAttend}>
+                预览课件
+              </NButton>
+              <NButton
+                {...{ id: 'lessons-3' }}
+                type="error"
+                class={styles.btnClassStart}
+                onClick={async () => {
+                  let count = 0;
+                  forms.coursewareList.forEach((item: any) => {
+                    if (!item.removeFlag) {
+                      count++;
+                    }
+                  });
+                  if (count <= 0) {
+                    message.error('课件不能为空');
+                    return;
+                  }
+
+                  if (forms.classGroupId) {
+                    // 开始上课
+                    const res = await courseScheduleStart({
+                      lessonCoursewareKnowledgeDetailId: prepareStore.selectKey,
+                      classGroupId: forms.classGroupId,
+                      subjectId: prepareStore.getSubjectId
+                    });
+                    if (
+                      window.matchMedia('(display-mode: standalone)').matches
+                    ) {
+                      state.application = window.matchMedia(
+                        '(display-mode: standalone)'
+                      ).matches;
+                      forms.previewModal = true;
+                      fscreen();
+                      forms.previewParams = {
+                        type: 'class',
+                        classGroupId: forms.classGroupId,
+                        instrumentId: prepareStore.getInstrumentId,
+                        detailId: prepareStore.getSelectKey,
+                        classId: res.data,
+                        lessonCourseId: prepareStore.getBaseCourseware.id,
+                        preStudentNum: forms.preStudentNum
+                      };
+                    } else {
+                      const { href } = router.resolve({
+                        path: '/attend-class',
+                        query: {
+                          type: 'class',
+                          classGroupId: forms.classGroupId,
+                          instrumentId: prepareStore.getInstrumentId,
+                          detailId: prepareStore.getSelectKey,
+                          classId: res.data,
+                          lessonCourseId: prepareStore.getBaseCourseware.id,
+                          preStudentNum: forms.preStudentNum
+                        }
+                      });
+                      window.open(href, +new Date() + '');
+                    }
+                  } else {
+                    forms.showAttendClass = true;
+                    forms.attendClassType = 'change';
+                  }
+                }}>
+                开始上课
+              </NButton>
+            </NSpace>
+          </div>
+        ) : (
+          ''
+        )}
+
+        <NModal
+          v-model:show={forms.showAttendClass}
+          preset="card"
+          showIcon={false}
+          class={['modalTitle background', styles.attendClassModal]}
+          title={'选择班级'}
+          blockScroll={false}>
+          <AttendClass
+            onClose={() => (forms.showAttendClass = false)}
+            type={forms.attendClassType}
+            onPreview={(item: any) => {
+              if (window.matchMedia('(display-mode: standalone)').matches) {
+                state.application = window.matchMedia(
+                  '(display-mode: standalone)'
+                ).matches;
+                forms.previewModal = true;
+                forms.previewParams = {
+                  ...item
+                };
+              } else {
+                const { href } = router.resolve({
+                  path: '/attend-class',
+                  query: {
+                    ...item
+                  }
+                });
+                window.open(href, +new Date() + '');
+              }
+            }}
+            onConfirm={async (item: any) => {
+              if (forms.classGroupId) {
+                forms.className = item.name;
+                forms.classGroupId = item.classGroupId;
+                forms.preStudentNum = item.preStudentNum;
+                forms.subjectId = item.subjectId;
+                forms.courseScheduleSubjectId = item.courseScheduleSubjectId;
+                forms.showAttendClass = false;
+
+                prepareStore.setClassGroupId(item.classGroupId);
+                console.log(forms, 'forms', item);
+                checkSubjectIds();
+                // 声部切换时
+                eventGlobal.emit('onChangeClass', {
+                  lastUseCoursewareId: item.lastUseCoursewareId,
+                  unit: item.unit
+                });
+              } else {
+                const res = await courseScheduleStart({
+                  lessonCoursewareKnowledgeDetailId: prepareStore.selectKey,
+                  classGroupId: item.classGroupId,
+                  subjectId: prepareStore.getSubjectId
+                });
+                forms.showAttendClass = false;
+                if (window.matchMedia('(display-mode: standalone)').matches) {
+                  state.application = window.matchMedia(
+                    '(display-mode: standalone)'
+                  ).matches;
+                  forms.previewModal = true;
+                  forms.previewParams = {
+                    type: 'class',
+                    classId: res.data, // 上课编号
+                    classGroupId: item.classGroupId,
+                    preStudentNum: item.preStudentNum,
+                    subjectId: prepareStore.getSubjectId,
+                    detailId: prepareStore.getSelectKey,
+                    lessonCourseId: prepareStore.getBaseCourseware.id
+                  };
+                  setTimeout(() => {
+                    fscreen();
+                  }, 200);
+                } else {
+                  const { href } = router.resolve({
+                    path: '/attend-class',
+                    query: {
+                      type: 'class',
+                      classId: res.data, // 上课编号
+                      classGroupId: item.classGroupId,
+                      preStudentNum: item.preStudentNum,
+                      subjectId: prepareStore.getSubjectId,
+                      detailId: prepareStore.getSelectKey,
+                      lessonCourseId: prepareStore.getBaseCourseware.id
+                    }
+                  });
+                  window.open(href, +new Date() + '');
+                }
+              }
+            }}
+          />
+        </NModal>
+
+        {/* 弹窗查看 */}
+        <CardPreview v-model:show={forms.show} item={forms.item} />
+
+        <NModal
+          v-model:show={forms.removeVisiable}
+          preset="card"
+          class={['modalTitle', styles.removeVisiable]}
+          title={'提示'}>
+          <div class={styles.studentRemove}>
+            <p>是否完成编辑?</p>
+
+            <NSpace class={styles.btnGroupModal} justify="center">
+              <NButton round type="primary" onClick={onOverEdit}>
+                确定
+              </NButton>
+              <NButton round onClick={() => (forms.removeVisiable = false)}>
+                取消
+              </NButton>
+            </NSpace>
+          </div>
+        </NModal>
+
+        <NModal
+          v-model:show={forms.removeVisiable1}
+          preset="card"
+          class={['modalTitle', styles.removeVisiable1]}
+          title={'清空资源'}>
+          <div class={styles.studentRemove}>
+            <p>
+              请确认是否要清空资源?
+              <span>点击确认后所有的素材内容 将被清空掉。</span>
+            </p>
+
+            <NSpace class={styles.btnGroupModal} justify="center">
+              <NButton
+                round
+                type="primary"
+                onClick={() => {
+                  forms.coursewareList.forEach((item: any) => {
+                    forms.removeIds.push(item.id);
+                  });
+                  forms.coursewareList = [];
+                  forms.removeVisiable1 = false;
+                  forms.isEdit = true;
+                  // prepareStore.setCoursewareList([]);
+                }}>
+                确定
+              </NButton>
+              <NButton round onClick={() => (forms.removeVisiable1 = false)}>
+                取消
+              </NButton>
+            </NSpace>
+          </div>
+        </NModal>
+
+        <PreviewWindow
+          v-model:show={forms.previewModal}
+          type="attend"
+          params={forms.previewParams}
+        />
+
+        {/* 完成编辑时,选择声部 */}
+        <NModal
+          v-model:show={forms.subjectSyncVisiable}
+          preset="card"
+          class={['modalTitle background', styles.subjectSyncModal]}
+          title={'同步声部'}>
+          <SubjectSync
+            subjectId={prepareStore.getSubjectId as any}
+            onClose={() => (forms.subjectSyncVisiable = false)}
+            onConfirm={async (subjectIds: any) => {
+              //
+              try {
+                forms.editSubjectIds = subjectIds.join(',');
+                await onOverEdit();
+                forms.subjectSyncVisiable = false;
+              } catch {
+                //
+              }
+            }}
+          />
+        </NModal>
+      </div>
+    );
+  }
+});

+ 398 - 398
src/views/prepare-lessons/components/lesson-main/train/assign-student/index.tsx

@@ -1,398 +1,398 @@
-import { computed, defineComponent, onMounted, reactive } from 'vue';
-import styles from './index.module.less';
-import {
-  NAvatar,
-  NButton,
-  NCascader,
-  NCheckbox,
-  NCheckboxGroup,
-  NInput,
-  NScrollbar,
-  NSelect,
-  NSpace,
-  NSpin
-} from 'naive-ui';
-import defultHeade from '@/components/layout/images/teacherIcon.png';
-import SearchInput from '/src/components/searchInput';
-import { useCatchStore } from '/src/store/modules/catchData';
-import { getStudentList } from '/src/views/classList/api';
-import { useThrottleFn } from '@vueuse/core';
-import TheEmpty from '/src/components/TheEmpty';
-import { getGradeYearList } from '/src/views/home/api';
-import { api_getCurrentGradeYear } from '/src/views/studentList/api';
-
-export default defineComponent({
-  name: 'assign-student',
-  props: {
-    /** 班级列表 */
-    classList: {
-      type: Array,
-      default: () => []
-    },
-    /** 所选学生列表 */
-    studentList: {
-      type: Array,
-      default: () => []
-    },
-    /** 学年 */
-    currentGradeNum: {
-      type: [String || Number],
-      default: ''
-    },
-    selectIds: {
-      type: Array,
-      default: () => []
-    },
-    classGroupId: {
-      type: String,
-      default: ''
-    }
-  },
-  emits: ['close', 'confirm'],
-  setup(props, { emit }) {
-    const catchStore = useCatchStore();
-    const state = reactive({
-      studentName: '',
-      loading: false,
-      finshed: false, // 是否加载完
-      checkAllStatus: false,
-      indeterminate: false,
-      searchFrom: {
-        upgradeFlag: true,
-        currentGradeNum: props.currentGradeNum || '',
-        gradeYear: null,
-        classGroupId: props.classGroupId || '',
-        subjectId: '',
-        keyword: ''
-      },
-      pagination: {
-        page: 1,
-        rows: 20,
-        pageTotal: 0
-      },
-      tableList: [] as any,
-      checkboxIds: [] as any,
-      selectStudents: [] as any,
-      selectKeyword: '',
-      popSelectYearList: [] as any
-    });
-
-    // 获取学年
-    const getYearList = async () => {
-      try {
-        const { data } = await api_getCurrentGradeYear({});
-        state.searchFrom.gradeYear = data;
-        // const { data } = await getGradeYearList();
-        // const temp = data || [];
-        // temp.forEach((i: any) => {
-        //   i.name = i.name + '学年';
-        // });
-        // state.popSelectYearList = temp || [];
-        // if (temp.length > 0 && !state.searchFrom.gradeYear) {
-        //   state.searchFrom.gradeYear = temp[0].id;
-        // }
-      } catch {
-        //
-      }
-    };
-
-    const getStudentLists = async () => {
-      try {
-        if (state.pagination.page === 1) {
-          state.loading = true;
-          state.tableList = [];
-        }
-        const { data } = await getStudentList({
-          ...state.searchFrom,
-          ...state.pagination
-        });
-        state.loading = false;
-        const rows = data.rows || [];
-        state.tableList.push(...rows);
-        state.finshed = data.pages <= data.current ? true : false;
-
-        onCheckStudents();
-      } catch {
-        //
-        state.loading = false;
-      }
-    };
-
-    const onSearch = () => {
-      state.pagination.page = 1;
-      getStudentLists();
-    };
-
-    const selectStudentEmpty = computed(() => {
-      let status = true;
-      state.selectStudents.forEach((item: any) => {
-        if (!item.hide) {
-          status = false;
-        }
-      });
-      return status;
-    });
-
-    const throttledFn = useThrottleFn(() => {
-      state.pagination.page = state.pagination.page + 1;
-      getStudentLists();
-    }, 500);
-
-    // 切换学生状态
-    const onCheckStudents = () => {
-      // state.selectStudents = [];
-      if (state.checkboxIds.length <= 0 || state.tableList.length <= 0) {
-        state.indeterminate = false;
-        state.checkAllStatus = false;
-        return;
-      }
-      let count = 0;
-      // 右边数据
-      state.tableList.forEach((item: any) => {
-        if (state.checkboxIds.includes(item.id)) {
-          count++;
-          const index = state.selectStudents.findIndex(
-            (select: any) => select.id === item.id
-          );
-          if (index === -1) state.selectStudents.push(item);
-        }
-      });
-
-      if (count >= state.tableList.length) {
-        state.checkAllStatus = true;
-        state.indeterminate = false;
-      } else {
-        state.checkAllStatus = false;
-        state.indeterminate = true;
-      }
-    };
-
-    // 删除用户
-    const onRemove = (item: any) => {
-      const index = state.checkboxIds.findIndex((id: any) => id === item.id);
-      if (index !== -1) {
-        state.checkboxIds.splice(index, 1);
-        const sIndex = state.selectStudents.findIndex(
-          (select: any) => select.id === item.id
-        );
-        if (sIndex !== -1) {
-          state.selectStudents.splice(sIndex, 1);
-        }
-        onCheckStudents();
-      }
-    };
-
-    const onSave = () => {
-      const studentInfo: any[] = [];
-      state.selectStudents.forEach((item: any) => {
-        studentInfo.push({
-          id: item.id,
-          name: item.nickname,
-          avatar: item.avatar
-        });
-      });
-
-      emit('confirm', studentInfo);
-    };
-
-    onMounted(async () => {
-      state.checkboxIds = props.selectIds || [];
-      state.loading = true;
-      await catchStore.getSubjects();
-      await getYearList();
-      await getStudentLists();
-      // onCheckStudents();
-      // 重置选择的学生
-      state.selectStudents = props.studentList?.map((item: any) => {
-        return {
-          ...item,
-          nickname: item.name
-        };
-      });
-    });
-    return () => (
-      <div class={styles.assignStudent}>
-        <div class={styles.studentListGroup}>
-          <div class={styles.searchSection}>
-            <div class={styles.searchSpace}>
-              <NSelect
-                placeholder="全部班级"
-                disabled={props.classGroupId ? true : false}
-                v-model:value={state.searchFrom.classGroupId}
-                onUpdate:value={() => onSearch()}
-                options={
-                  [{ label: '全部班级', value: '' }, ...props.classList] as any
-                }
-              />
-              {/* <NSelect
-                options={[
-                  { label: '全部乐器', value: '' },
-                  ...catchStore.getEnableSubjects
-                ]}
-                placeholder="全部乐器"
-                v-model:value={state.searchFrom.subjectId}
-                onUpdate:value={() => onSearch()}
-              /> */}
-              <NCascader
-                options={[
-                  { name: '全部乐器', id: '' },
-                  ...catchStore.getSubjectList
-                ]}
-                placeholder="全部乐器"
-                v-model:value={state.searchFrom.subjectId}
-                onUpdate:value={() => onSearch()}
-                checkStrategy="child"
-                showPath
-                childrenField="instruments"
-                expandTrigger="hover"
-                labelField="name"
-                valueField="id"
-                clearable
-                filterable
-              />
-            </div>
-            <SearchInput
-              {...{ placeholder: '请输入学生姓名/手机号' }}
-              class={styles.searchInput}
-              searchWord={state.searchFrom.keyword}
-              onChangeValue={(val: string) => {
-                state.searchFrom.keyword = val;
-              }}
-              onClear={() => {
-                state.searchFrom.keyword = '';
-                onSearch();
-              }}
-              onKeyup={(e: KeyboardEvent) => {
-                if (e.code === 'Enter') {
-                  onSearch();
-                }
-              }}></SearchInput>
-          </div>
-
-          <div class={styles.studentSection}>
-            <div class={styles.checkboxAll}>
-              <NCheckbox
-                v-model:checked={state.checkAllStatus}
-                indeterminate={state.indeterminate}
-                onUpdate:checked={(val: any) => {
-                  if (val) {
-                    const ids: any = [];
-                    state.tableList.forEach((item: any) => {
-                      ids.push(item.id);
-                    });
-                    state.checkboxIds = ids;
-                  } else {
-                    state.checkboxIds = [];
-                    state.selectStudents = [];
-                    state.indeterminate = false;
-                  }
-                  onCheckStudents();
-                }}></NCheckbox>
-              <p>
-                全选 <span class={styles.nums}>({state.tableList.length})</span>{' '}
-                :
-              </p>
-            </div>
-          </div>
-          <NScrollbar
-            class={styles.student}
-            onScroll={(e: any) => {
-              const clientHeight = e.target?.clientHeight;
-              const scrollTop = e.target?.scrollTop;
-              const scrollHeight = e.target?.scrollHeight;
-              // 是否到底,是否加载完
-              if (
-                clientHeight + scrollTop + 20 >= scrollHeight &&
-                !state.finshed &&
-                !state.loading
-              ) {
-                throttledFn();
-              }
-            }}>
-            <NSpin show={state.loading} class={styles.loadingSection}>
-              <NCheckboxGroup
-                v-model:value={state.checkboxIds}
-                onUpdate:value={() => {
-                  state.selectStudents = [];
-                  onCheckStudents();
-                }}>
-                {state.tableList.map((item: any) => (
-                  <NCheckbox value={item.id} class={[styles.studentItem]}>
-                    <div class={styles.studentInfo}>
-                      <NAvatar
-                        src={item.avatar || defultHeade}
-                        class={styles.studentImg}
-                      />
-                      <div class={styles.studentValue}>
-                        <div class={styles.userInfo}>
-                          <span class={styles.name}>{item.nickname}</span>
-                          {item.membership && <i class={styles.iconMember}></i>}
-                          {item.classGroupName && (
-                            <span class={styles.className}>
-                              {item.classGroupName}
-                            </span>
-                          )}
-                        </div>
-                        <div class={styles.phone}>{item.phone}</div>
-                      </div>
-                    </div>
-                  </NCheckbox>
-                ))}
-              </NCheckboxGroup>
-              {state.tableList.length <= 0 && !state.loading && <TheEmpty />}
-            </NSpin>
-          </NScrollbar>
-        </div>
-
-        <div class={styles.selectStudentGroup}>
-          <div class={styles.selectCount}>
-            当前选中 <span>({state.selectStudents.length}) </span>:
-          </div>
-          <div class={styles.searchSection}>
-            <SearchInput
-              {...{ placeholder: '请输入学生姓名' }}
-              class={styles.searchInput}
-              searchWord={state.selectKeyword}
-              onChangeValue={(val: string) => {
-                state.selectKeyword = val;
-
-                state.selectStudents.forEach((item: any) => {
-                  if (item.nickname?.indexOf(val) === -1) {
-                    item.hide = true;
-                  } else {
-                    item.hide = false;
-                  }
-                });
-              }}></SearchInput>
-          </div>
-          <NScrollbar class={styles.student}>
-            {state.selectStudents.map((student: any) => (
-              <div class={[styles.studentItem, student.hide && styles.hide]}>
-                <div class={styles.studentInfo}>
-                  <NAvatar
-                    src={student.avatar || defultHeade}
-                    class={styles.studentImg}
-                  />
-                  <span class={styles.name}>{student.nickname}</span>
-                </div>
-                <i
-                  class={styles.iconClose}
-                  onClick={() => onRemove(student)}></i>
-              </div>
-            ))}
-            {selectStudentEmpty.value && <TheEmpty />}
-          </NScrollbar>
-
-          <NSpace justify="end" class={styles.btnGroup}>
-            <NButton type="default" onClick={() => emit('close')}>
-              取消
-            </NButton>
-            <NButton type="primary" onClick={onSave}>
-              保存
-            </NButton>
-          </NSpace>
-        </div>
-      </div>
-    );
-  }
-});
+import { computed, defineComponent, onMounted, reactive } from 'vue';
+import styles from './index.module.less';
+import {
+  NAvatar,
+  NButton,
+  NCascader,
+  NCheckbox,
+  NCheckboxGroup,
+  NInput,
+  NScrollbar,
+  NSelect,
+  NSpace,
+  NSpin
+} from 'naive-ui';
+import defultHeade from '@/components/layout/images/teacherIcon.png';
+import SearchInput from '/src/components/searchInput';
+import { useCatchStore } from '/src/store/modules/catchData';
+import { getStudentList } from '/src/views/classList/api';
+import { useThrottleFn } from '@vueuse/core';
+import TheEmpty from '/src/components/TheEmpty';
+import { getGradeYearList } from '/src/views/home/api';
+import { api_getCurrentGradeYear } from '/src/views/studentList/api';
+
+export default defineComponent({
+  name: 'assign-student',
+  props: {
+    /** 班级列表 */
+    classList: {
+      type: Array,
+      default: () => []
+    },
+    /** 所选学生列表 */
+    studentList: {
+      type: Array,
+      default: () => []
+    },
+    /** 学年 */
+    currentGradeNum: {
+      type: [String || Number],
+      default: ''
+    },
+    selectIds: {
+      type: Array,
+      default: () => []
+    },
+    classGroupId: {
+      type: String,
+      default: ''
+    }
+  },
+  emits: ['close', 'confirm'],
+  setup(props, { emit }) {
+    const catchStore = useCatchStore();
+    const state = reactive({
+      studentName: '',
+      loading: false,
+      finshed: false, // 是否加载完
+      checkAllStatus: false,
+      indeterminate: false,
+      searchFrom: {
+        upgradeFlag: true,
+        currentGradeNum: props.currentGradeNum || '',
+        gradeYear: null,
+        classGroupId: props.classGroupId || '',
+        classInstrumentId: '',
+        keyword: ''
+      },
+      pagination: {
+        page: 1,
+        rows: 20,
+        pageTotal: 0
+      },
+      tableList: [] as any,
+      checkboxIds: [] as any,
+      selectStudents: [] as any,
+      selectKeyword: '',
+      popSelectYearList: [] as any
+    });
+
+    // 获取学年
+    const getYearList = async () => {
+      try {
+        const { data } = await api_getCurrentGradeYear({});
+        state.searchFrom.gradeYear = data;
+        // const { data } = await getGradeYearList();
+        // const temp = data || [];
+        // temp.forEach((i: any) => {
+        //   i.name = i.name + '学年';
+        // });
+        // state.popSelectYearList = temp || [];
+        // if (temp.length > 0 && !state.searchFrom.gradeYear) {
+        //   state.searchFrom.gradeYear = temp[0].id;
+        // }
+      } catch {
+        //
+      }
+    };
+
+    const getStudentLists = async () => {
+      try {
+        if (state.pagination.page === 1) {
+          state.loading = true;
+          state.tableList = [];
+        }
+        const { data } = await getStudentList({
+          ...state.searchFrom,
+          ...state.pagination
+        });
+        state.loading = false;
+        const rows = data.rows || [];
+        state.tableList.push(...rows);
+        state.finshed = data.pages <= data.current ? true : false;
+
+        onCheckStudents();
+      } catch {
+        //
+        state.loading = false;
+      }
+    };
+
+    const onSearch = () => {
+      state.pagination.page = 1;
+      getStudentLists();
+    };
+
+    const selectStudentEmpty = computed(() => {
+      let status = true;
+      state.selectStudents.forEach((item: any) => {
+        if (!item.hide) {
+          status = false;
+        }
+      });
+      return status;
+    });
+
+    const throttledFn = useThrottleFn(() => {
+      state.pagination.page = state.pagination.page + 1;
+      getStudentLists();
+    }, 500);
+
+    // 切换学生状态
+    const onCheckStudents = () => {
+      // state.selectStudents = [];
+      if (state.checkboxIds.length <= 0 || state.tableList.length <= 0) {
+        state.indeterminate = false;
+        state.checkAllStatus = false;
+        return;
+      }
+      let count = 0;
+      // 右边数据
+      state.tableList.forEach((item: any) => {
+        if (state.checkboxIds.includes(item.id)) {
+          count++;
+          const index = state.selectStudents.findIndex(
+            (select: any) => select.id === item.id
+          );
+          if (index === -1) state.selectStudents.push(item);
+        }
+      });
+
+      if (count >= state.tableList.length) {
+        state.checkAllStatus = true;
+        state.indeterminate = false;
+      } else {
+        state.checkAllStatus = false;
+        state.indeterminate = true;
+      }
+    };
+
+    // 删除用户
+    const onRemove = (item: any) => {
+      const index = state.checkboxIds.findIndex((id: any) => id === item.id);
+      if (index !== -1) {
+        state.checkboxIds.splice(index, 1);
+        const sIndex = state.selectStudents.findIndex(
+          (select: any) => select.id === item.id
+        );
+        if (sIndex !== -1) {
+          state.selectStudents.splice(sIndex, 1);
+        }
+        onCheckStudents();
+      }
+    };
+
+    const onSave = () => {
+      const studentInfo: any[] = [];
+      state.selectStudents.forEach((item: any) => {
+        studentInfo.push({
+          id: item.id,
+          name: item.nickname,
+          avatar: item.avatar
+        });
+      });
+
+      emit('confirm', studentInfo);
+    };
+
+    onMounted(async () => {
+      state.checkboxIds = props.selectIds || [];
+      state.loading = true;
+      await catchStore.getSubjects();
+      await getYearList();
+      await getStudentLists();
+      // onCheckStudents();
+      // 重置选择的学生
+      state.selectStudents = props.studentList?.map((item: any) => {
+        return {
+          ...item,
+          nickname: item.name
+        };
+      });
+    });
+    return () => (
+      <div class={styles.assignStudent}>
+        <div class={styles.studentListGroup}>
+          <div class={styles.searchSection}>
+            <div class={styles.searchSpace}>
+              <NSelect
+                placeholder="全部班级"
+                disabled={props.classGroupId ? true : false}
+                v-model:value={state.searchFrom.classGroupId}
+                onUpdate:value={() => onSearch()}
+                options={
+                  [{ label: '全部班级', value: '' }, ...props.classList] as any
+                }
+              />
+              {/* <NSelect
+                options={[
+                  { label: '全部乐器', value: '' },
+                  ...catchStore.getEnableSubjects
+                ]}
+                placeholder="全部乐器"
+                v-model:value={state.searchFrom.classInstrumentId}
+                onUpdate:value={() => onSearch()}
+              /> */}
+              <NCascader
+                options={[
+                  { name: '全部乐器', id: '' },
+                  ...catchStore.getSubjectList
+                ]}
+                placeholder="全部乐器"
+                v-model:value={state.searchFrom.classInstrumentId}
+                onUpdate:value={() => onSearch()}
+                checkStrategy="child"
+                showPath
+                childrenField="instruments"
+                expandTrigger="hover"
+                labelField="name"
+                valueField="id"
+                clearable
+                filterable
+              />
+            </div>
+            <SearchInput
+              {...{ placeholder: '请输入学生姓名/手机号' }}
+              class={styles.searchInput}
+              searchWord={state.searchFrom.keyword}
+              onChangeValue={(val: string) => {
+                state.searchFrom.keyword = val;
+              }}
+              onClear={() => {
+                state.searchFrom.keyword = '';
+                onSearch();
+              }}
+              onKeyup={(e: KeyboardEvent) => {
+                if (e.code === 'Enter') {
+                  onSearch();
+                }
+              }}></SearchInput>
+          </div>
+
+          <div class={styles.studentSection}>
+            <div class={styles.checkboxAll}>
+              <NCheckbox
+                v-model:checked={state.checkAllStatus}
+                indeterminate={state.indeterminate}
+                onUpdate:checked={(val: any) => {
+                  if (val) {
+                    const ids: any = [];
+                    state.tableList.forEach((item: any) => {
+                      ids.push(item.id);
+                    });
+                    state.checkboxIds = ids;
+                  } else {
+                    state.checkboxIds = [];
+                    state.selectStudents = [];
+                    state.indeterminate = false;
+                  }
+                  onCheckStudents();
+                }}></NCheckbox>
+              <p>
+                全选 <span class={styles.nums}>({state.tableList.length})</span>{' '}
+                :
+              </p>
+            </div>
+          </div>
+          <NScrollbar
+            class={styles.student}
+            onScroll={(e: any) => {
+              const clientHeight = e.target?.clientHeight;
+              const scrollTop = e.target?.scrollTop;
+              const scrollHeight = e.target?.scrollHeight;
+              // 是否到底,是否加载完
+              if (
+                clientHeight + scrollTop + 20 >= scrollHeight &&
+                !state.finshed &&
+                !state.loading
+              ) {
+                throttledFn();
+              }
+            }}>
+            <NSpin show={state.loading} class={styles.loadingSection}>
+              <NCheckboxGroup
+                v-model:value={state.checkboxIds}
+                onUpdate:value={() => {
+                  state.selectStudents = [];
+                  onCheckStudents();
+                }}>
+                {state.tableList.map((item: any) => (
+                  <NCheckbox value={item.id} class={[styles.studentItem]}>
+                    <div class={styles.studentInfo}>
+                      <NAvatar
+                        src={item.avatar || defultHeade}
+                        class={styles.studentImg}
+                      />
+                      <div class={styles.studentValue}>
+                        <div class={styles.userInfo}>
+                          <span class={styles.name}>{item.nickname}</span>
+                          {item.membership && <i class={styles.iconMember}></i>}
+                          {item.classGroupName && (
+                            <span class={styles.className}>
+                              {item.classGroupName}
+                            </span>
+                          )}
+                        </div>
+                        <div class={styles.phone}>{item.phone}</div>
+                      </div>
+                    </div>
+                  </NCheckbox>
+                ))}
+              </NCheckboxGroup>
+              {state.tableList.length <= 0 && !state.loading && <TheEmpty />}
+            </NSpin>
+          </NScrollbar>
+        </div>
+
+        <div class={styles.selectStudentGroup}>
+          <div class={styles.selectCount}>
+            当前选中 <span>({state.selectStudents.length}) </span>:
+          </div>
+          <div class={styles.searchSection}>
+            <SearchInput
+              {...{ placeholder: '请输入学生姓名' }}
+              class={styles.searchInput}
+              searchWord={state.selectKeyword}
+              onChangeValue={(val: string) => {
+                state.selectKeyword = val;
+
+                state.selectStudents.forEach((item: any) => {
+                  if (item.nickname?.indexOf(val) === -1) {
+                    item.hide = true;
+                  } else {
+                    item.hide = false;
+                  }
+                });
+              }}></SearchInput>
+          </div>
+          <NScrollbar class={styles.student}>
+            {state.selectStudents.map((student: any) => (
+              <div class={[styles.studentItem, student.hide && styles.hide]}>
+                <div class={styles.studentInfo}>
+                  <NAvatar
+                    src={student.avatar || defultHeade}
+                    class={styles.studentImg}
+                  />
+                  <span class={styles.name}>{student.nickname}</span>
+                </div>
+                <i
+                  class={styles.iconClose}
+                  onClick={() => onRemove(student)}></i>
+              </div>
+            ))}
+            {selectStudentEmpty.value && <TheEmpty />}
+          </NScrollbar>
+
+          <NSpace justify="end" class={styles.btnGroup}>
+            <NButton type="default" onClick={() => emit('close')}>
+              取消
+            </NButton>
+            <NButton type="primary" onClick={onSave}>
+              保存
+            </NButton>
+          </NSpace>
+        </div>
+      </div>
+    );
+  }
+});

+ 261 - 247
src/views/prepare-lessons/model/attend-class/index.tsx

@@ -1,247 +1,261 @@
-import { defineComponent, onMounted, reactive, ref, toRef } from 'vue';
-import styles from './index.module.less';
-import { NInput, NModal, NScrollbar, NSelect, NSpin, NThing } from 'naive-ui';
-import { useRouter } from 'vue-router';
-import { BOOK_DATA } from '/src/views/natural-resources/model/add-teaching';
-import { classGroupPage, courseScheduleStart } from '../../api';
-import { useThrottleFn } from '@vueuse/core';
-import TheEmpty from '/src/components/TheEmpty';
-import { usePrepareStore } from '/src/store/modules/prepareLessons';
-import { state } from '/src/state';
-import { nextTick } from 'process';
-import UpdateSubject from '/src/views/classList/modals/updateSubject';
-const classList: any = [];
-for (let i = 1; i <= 40; i++) {
-  classList.push({ label: i + '班', value: i });
-}
-
-export default defineComponent({
-  name: 'attend-class',
-  props: {
-    // change 切换班级 select 直接进入上课
-    type: {
-      type: String,
-      default: 'change'
-    }
-  },
-  emits: ['close', 'preview', 'confirm'],
-  setup(props, { emit }) {
-    // const { type } = toRef(props);
-    const prepareStore = usePrepareStore();
-    const forms = reactive({
-      showSubjectClass: false,
-      activeRow: {} as any,
-      keyword: null,
-      currentGradeNum: null,
-      currentClass: null
-    });
-
-    const list = ref([] as any);
-    const loading = ref(false);
-    // 开始上课
-    const onAttendClass = async (item: any) => {
-      // console.log(item, 'onAttendClass');
-      try {
-        // 判断是否是切换班级
-        if (props.type == 'change') {
-          if (item.subjectId) {
-            emit('confirm', {
-              lastUseCoursewareId: item.lessonCoursewareId,
-              unit: item.lessonCoursewareKnowledgeDetailId,
-              subjectId: item.subjectId,
-              courseScheduleSubjectId: item.courseScheduleSubjectId,
-              name: item.name, // 班级名称
-              classGroupId: item.id, // 班级编号
-              preStudentNum: item.preStudentNum
-            });
-          } else {
-            forms.showSubjectClass = true;
-            forms.activeRow = item;
-          }
-          return;
-        }
-
-        const res = await courseScheduleStart({
-          lessonCoursewareKnowledgeDetailId: prepareStore.selectKey,
-          classGroupId: item.id,
-          subjectId: prepareStore.getSubjectId
-        });
-
-        emit('close');
-        emit('preview', {
-          type: 'class',
-          classId: res.data, // 上课编号
-          classGroupId: item.id,
-          subjectId: prepareStore.getSubjectId,
-          detailId: prepareStore.getSelectKey,
-          lessonCourseId: prepareStore.getBaseCourseware.id,
-          preStudentNum: item.preStudentNum
-        });
-        if (window.matchMedia('(display-mode: standalone)').matches) {
-          state.application = window.matchMedia(
-            '(display-mode: standalone)'
-          ).matches;
-          setTimeout(() => {
-            fscreen();
-          }, 200);
-        }
-      } catch {
-        //
-      }
-    };
-    const fscreen = () => {
-      const el: any = document.documentElement;
-      const documentDom: any = document;
-      const isFullscreen =
-        documentDom.fullScreen ||
-        documentDom.mozFullScreen ||
-        documentDom.webkitIsFullScreen;
-      if (!isFullscreen) {
-        //进入全屏
-        (el.requestFullscreen && el.requestFullscreen()) ||
-          (el.mozRequestFullScreen && el.mozRequestFullScreen()) ||
-          (el.webkitRequestFullscreen && el.webkitRequestFullscreen()) ||
-          (el.msRequestFullscreen && el.msRequestFullscreen());
-      } else {
-        //退出全屏
-        documentDom.exitFullscreen
-          ? documentDom.exitFullscreen()
-          : documentDom.mozCancelFullScreen
-          ? documentDom.mozCancelFullScreen()
-          : documentDom.webkitExitFullscreen
-          ? documentDom.webkitExitFullscreen()
-          : '';
-      }
-    };
-    const getList = async () => {
-      loading.value = true;
-      try {
-        const { data } = await classGroupPage({
-          page: 1,
-          rows: 99,
-          upgradeFlag: true,
-          ...forms
-        });
-        const result = data.rows || [];
-        const temp: any = [];
-        result.forEach((item: any) => {
-          // 判断班级里面有学生的
-          // if (item.preStudentNum > 0) {
-          temp.push(item);
-          // }
-        });
-        list.value = temp;
-      } catch {
-        //
-      }
-      loading.value = false;
-    };
-
-    const throttleFn = useThrottleFn(() => getList(), 500);
-
-    onMounted(() => {
-      getList();
-    });
-
-    return () => (
-      <div class={styles.attendClass}>
-        <div class={styles.attendClassSearch}>
-          <NInput
-            placeholder="请输入班级名称"
-            clearable
-            v-model:value={forms.keyword}
-            onKeyup={(e: KeyboardEvent) => {
-              if (e.code === 'Enter') {
-                throttleFn();
-              }
-            }}
-            onClear={() => throttleFn()}>
-            {{
-              prefix: () => (
-                <span
-                  class="icon-search-input"
-                  onClick={() => throttleFn()}></span>
-              )
-            }}
-          </NInput>
-          <NSelect
-            placeholder="全部年级"
-            clearable
-            options={
-              [{ label: '全部年级', value: null }, ...BOOK_DATA.grades] as any
-            }
-            v-model:value={forms.currentGradeNum}
-            onUpdate:value={() => throttleFn()}
-          />
-          <NSelect
-            placeholder="全部班级"
-            clearable
-            options={[{ label: '全部班级', value: null }, ...classList]}
-            v-model:value={forms.currentClass}
-            onUpdate:value={() => throttleFn()}
-          />
-        </div>
-        <NScrollbar class={styles.classList}>
-          <NSpin show={loading.value}>
-            <div
-              class={[
-                styles.listSection,
-                !loading.value && list.value.length <= 0
-                  ? styles.emptySection
-                  : ''
-              ]}>
-              {list.value.map((item: any) => (
-                <div onClick={() => onAttendClass(item)}>
-                  <NThing class={[styles.thingItem, 'isFull']}>
-                    {{
-                      header: () => (
-                        <>
-                          <div class={styles.title}>
-                            {item.name} {item.preStudentNum}人
-                          </div>
-                          <div
-                            class={[
-                              styles.subjects,
-                              item.instrumentName ? '' : styles.noSubjects
-                            ]}>
-                            {item.instrumentName
-                              ? item.instrumentName
-                              : '暂无乐器'}
-                          </div>
-                        </>
-                      ),
-                      default: () =>
-                        item.lastStudy && (
-                          <div class={styles.content}>{item.lastStudy}</div>
-                        )
-                    }}
-                  </NThing>
-                </div>
-              ))}
-              {!loading.value && list.value.length <= 0 && <TheEmpty />}
-            </div>
-          </NSpin>
-        </NScrollbar>
-
-        <NModal
-          v-model:show={forms.showSubjectClass}
-          style={{ width: '500px' }}
-          preset="card"
-          class={['modalTitle background']}
-          title={'修改乐器'}>
-          {forms.showSubjectClass ? (
-            <UpdateSubject
-              activeRow={forms.activeRow}
-              onGetList={() => getList()}
-              onConfirm={(item: any) => {
-                //
-                emit('confirm', item);
-              }}
-              onClose={() => (forms.showSubjectClass = false)}
-            />
-          ) : null}
-        </NModal>
-      </div>
-    );
-  }
-});
+import { defineComponent, onMounted, reactive, ref, toRef } from 'vue';
+import styles from './index.module.less';
+import { NInput, NModal, NScrollbar, NSelect, NSpin, NThing } from 'naive-ui';
+import { useRouter } from 'vue-router';
+import { BOOK_DATA } from '/src/views/natural-resources/model/add-teaching';
+import { classGroupPage, courseScheduleStart } from '../../api';
+import { useThrottleFn } from '@vueuse/core';
+import TheEmpty from '/src/components/TheEmpty';
+import { usePrepareStore } from '/src/store/modules/prepareLessons';
+import { state } from '/src/state';
+import { nextTick } from 'process';
+import UpdateSubject from '/src/views/classList/modals/updateSubject';
+import { api_getCurrentGradeYear } from '/src/views/studentList/api';
+const classList: any = [];
+for (let i = 1; i <= 40; i++) {
+  classList.push({ label: i + '班', value: i });
+}
+
+export default defineComponent({
+  name: 'attend-class',
+  props: {
+    // change 切换班级 select 直接进入上课
+    type: {
+      type: String,
+      default: 'change'
+    }
+  },
+  emits: ['close', 'preview', 'confirm'],
+  setup(props, { emit }) {
+    // const { type } = toRef(props);
+    const prepareStore = usePrepareStore();
+    const forms = reactive({
+      showSubjectClass: false,
+      activeRow: {} as any,
+      keyword: null,
+      currentGradeNum: null,
+      currentClass: null
+    });
+    const gradeYear = ref(null as any);
+
+    const list = ref([] as any);
+    const loading = ref(false);
+    // 开始上课
+    const onAttendClass = async (item: any) => {
+      // console.log(item, 'onAttendClass');
+      try {
+        // 判断是否是切换班级
+        if (props.type == 'change') {
+          if (item.instrumentId) {
+            emit('confirm', {
+              lastUseCoursewareId: item.lessonCoursewareId,
+              unit: item.lessonCoursewareKnowledgeDetailId,
+              instrumentId: item.instrumentId,
+              courseScheduleSubjectId: item.courseScheduleSubjectId,
+              name: item.name, // 班级名称
+              classGroupId: item.id, // 班级编号
+              preStudentNum: item.preStudentNum
+            });
+          } else {
+            forms.showSubjectClass = true;
+            forms.activeRow = item;
+          }
+          return;
+        }
+
+        const res = await courseScheduleStart({
+          lessonCoursewareKnowledgeDetailId: prepareStore.selectKey,
+          classGroupId: item.id,
+          instrumentId: prepareStore.getInstrumentId
+        });
+
+        emit('close');
+        emit('preview', {
+          type: 'class',
+          classId: res.data, // 上课编号
+          classGroupId: item.id,
+          instrumentId: prepareStore.getInstrumentId,
+          detailId: prepareStore.getSelectKey,
+          lessonCourseId: prepareStore.getBaseCourseware.id,
+          preStudentNum: item.preStudentNum
+        });
+        if (window.matchMedia('(display-mode: standalone)').matches) {
+          state.application = window.matchMedia(
+            '(display-mode: standalone)'
+          ).matches;
+          setTimeout(() => {
+            fscreen();
+          }, 200);
+        }
+      } catch {
+        //
+      }
+    };
+    const fscreen = () => {
+      const el: any = document.documentElement;
+      const documentDom: any = document;
+      const isFullscreen =
+        documentDom.fullScreen ||
+        documentDom.mozFullScreen ||
+        documentDom.webkitIsFullScreen;
+      if (!isFullscreen) {
+        //进入全屏
+        (el.requestFullscreen && el.requestFullscreen()) ||
+          (el.mozRequestFullScreen && el.mozRequestFullScreen()) ||
+          (el.webkitRequestFullscreen && el.webkitRequestFullscreen()) ||
+          (el.msRequestFullscreen && el.msRequestFullscreen());
+      } else {
+        //退出全屏
+        documentDom.exitFullscreen
+          ? documentDom.exitFullscreen()
+          : documentDom.mozCancelFullScreen
+          ? documentDom.mozCancelFullScreen()
+          : documentDom.webkitExitFullscreen
+          ? documentDom.webkitExitFullscreen()
+          : '';
+      }
+    };
+    const getList = async () => {
+      loading.value = true;
+      try {
+        const { data } = await classGroupPage({
+          page: 1,
+          rows: 99,
+          gradeYear: gradeYear.value,
+          upgradeFlag: true,
+          ...forms
+        });
+        const result = data.rows || [];
+        const temp: any = [];
+        result.forEach((item: any) => {
+          // 判断班级里面有学生的
+          // if (item.preStudentNum > 0) {
+          temp.push(item);
+          // }
+        });
+        list.value = temp;
+      } catch {
+        //
+      }
+      loading.value = false;
+    };
+
+    const throttleFn = useThrottleFn(() => getList(), 500);
+
+    const getCurrentGradeYears = async () => {
+      try {
+        const { data } = await api_getCurrentGradeYear({});
+        gradeYear.value = data;
+      } catch {
+        //
+      }
+    };
+
+    onMounted(async () => {
+      loading.value = true;
+      await getCurrentGradeYears();
+      getList();
+    });
+
+    return () => (
+      <div class={styles.attendClass}>
+        <div class={styles.attendClassSearch}>
+          <NInput
+            placeholder="请输入班级名称"
+            clearable
+            v-model:value={forms.keyword}
+            onKeyup={(e: KeyboardEvent) => {
+              if (e.code === 'Enter') {
+                throttleFn();
+              }
+            }}
+            onClear={() => throttleFn()}>
+            {{
+              prefix: () => (
+                <span
+                  class="icon-search-input"
+                  onClick={() => throttleFn()}></span>
+              )
+            }}
+          </NInput>
+          <NSelect
+            placeholder="全部年级"
+            clearable
+            options={
+              [{ label: '全部年级', value: null }, ...BOOK_DATA.grades] as any
+            }
+            v-model:value={forms.currentGradeNum}
+            onUpdate:value={() => throttleFn()}
+          />
+          <NSelect
+            placeholder="全部班级"
+            clearable
+            options={[{ label: '全部班级', value: null }, ...classList]}
+            v-model:value={forms.currentClass}
+            onUpdate:value={() => throttleFn()}
+          />
+        </div>
+        <NScrollbar class={styles.classList}>
+          <NSpin show={loading.value}>
+            <div
+              class={[
+                styles.listSection,
+                !loading.value && list.value.length <= 0
+                  ? styles.emptySection
+                  : ''
+              ]}>
+              {list.value.map((item: any) => (
+                <div onClick={() => onAttendClass(item)}>
+                  <NThing class={[styles.thingItem, 'isFull']}>
+                    {{
+                      header: () => (
+                        <>
+                          <div class={styles.title}>
+                            {item.name} {item.preStudentNum}人
+                          </div>
+                          <div
+                            class={[
+                              styles.subjects,
+                              item.instrumentName ? '' : styles.noSubjects
+                            ]}>
+                            {item.instrumentName
+                              ? item.instrumentName
+                              : '暂无乐器'}
+                          </div>
+                        </>
+                      ),
+                      default: () =>
+                        item.lastStudy && (
+                          <div class={styles.content}>{item.lastStudy}</div>
+                        )
+                    }}
+                  </NThing>
+                </div>
+              ))}
+              {!loading.value && list.value.length <= 0 && <TheEmpty />}
+            </div>
+          </NSpin>
+        </NScrollbar>
+
+        <NModal
+          v-model:show={forms.showSubjectClass}
+          style={{ width: '500px' }}
+          preset="card"
+          class={['modalTitle background']}
+          title={'修改乐器'}>
+          {forms.showSubjectClass ? (
+            <UpdateSubject
+              activeRow={forms.activeRow}
+              onGetList={() => getList()}
+              onConfirm={(item: any) => {
+                //
+                emit('confirm', item);
+              }}
+              onClose={() => (forms.showSubjectClass = false)}
+            />
+          ) : null}
+        </NModal>
+      </div>
+    );
+  }
+});

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

@@ -1,213 +1,213 @@
-import { defineComponent, onMounted, onUnmounted, reactive, watch } from 'vue';
-import styles from './index.module.less';
-import { NCascader, NInput, NScrollbar, NSelect, NSpin } from 'naive-ui';
-import { useThrottleFn } from '@vueuse/core';
-import CoursewareType from '../courseware-type';
-import TheEmpty from '/src/components/TheEmpty';
-import { api_queryOpenCoursewareByPage } from '../../api';
-import { eventGlobal } from '/src/utils';
-
-export default defineComponent({
-  name: 'related-class',
-  props: {
-    tableList: {
-      type: Array,
-      default: () => []
-    },
-    instrumentList: {
-      type: Array,
-      default: () => []
-    },
-    instrumentId: {
-      type: [String, Number],
-      default: ''
-    },
-    coursewareDetailKnowledgeId: {
-      type: [String, Number],
-      default: ''
-    }
-  },
-  emits: ['close', 'add', 'click'],
-  setup(props, { emit }) {
-    const forms = reactive({
-      loading: false,
-      finshed: false, // 是否加载完
-      pagination: {
-        page: 1,
-        rows: 20
-      },
-      tableList: [] as any,
-      searchGroup: {
-        instrumentId: props.instrumentId ? props.instrumentId : '',
-        keyword: null
-      }
-    });
-    const getList = async () => {
-      try {
-        if (forms.pagination.page === 1) {
-          forms.loading = true;
-        }
-        // 查询公开课件列表
-        const { data } = await api_queryOpenCoursewareByPage({
-          coursewareDetailKnowledgeId: props.coursewareDetailKnowledgeId,
-          ...forms.searchGroup,
-          ...forms.pagination
-        });
-        const result = data.rows || [];
-        const tempList: any = [];
-        result.forEach((item: any) => {
-          // const index = forms.tableList.findIndex(
-          //   (i: any) => i.fromChapterLessonCoursewareId === item.id
-          // );
-          const firstItem: any =
-            item.chapterKnowledgeList[0]?.chapterKnowledgeMaterialList[0];
-          tempList.push({
-            id: item.id,
-            openFlag: item.openFlag,
-            openFlagEnable: item.openFlagEnable,
-            instrumentNames: item.instrumentNames,
-            fromChapterLessonCoursewareId: item.fromChapterLessonCoursewareId,
-            name: item.name,
-            coverImg: firstItem?.bizInfo.coverImg,
-            type: firstItem?.bizInfo.type,
-            isAdd: item.addFlag,
-            isNotWork: item.lessonPreTrainingNum <= 0 ? true : false // 是否布置作业
-          });
-        });
-
-        forms.loading = false;
-        forms.tableList.push(...tempList);
-
-        forms.finshed = data.pages <= data.current ? true : false;
-      } catch {
-        forms.loading = false;
-      }
-    };
-
-    // 检测数据是否存在
-    // watch(
-    //   () => props.tableList,
-    //   () => {
-    //     // fromChapterLessonCoursewareId;
-    //     forms.tableList.forEach((item: any) => {
-    //       const index = props.tableList.findIndex(
-    //         (i: any) => i.fromChapterLessonCoursewareId === item.id
-    //       );
-    //       item.isAdd = index !== -1 ? true : false;
-    //     });
-    //   }
-    // );
-
-    const throttleFn = useThrottleFn(() => {
-      forms.pagination.page = 1;
-      forms.tableList = [];
-      getList();
-    }, 500);
-
-    onMounted(() => {
-      getList();
-      eventGlobal.on('openCoursewareChanged', throttleFn);
-    });
-
-    onUnmounted(() => {
-      eventGlobal.off('openCoursewareChanged', throttleFn);
-    });
-    return () => (
-      <div class={styles.relatedClass}>
-        <div class={styles.attendClassSearch}>
-          <NCascader
-            placeholder="全部声部"
-            clearable
-            options={[
-              { name: '全部声部', id: '' },
-              ...(props.instrumentList as any)
-            ]}
-            v-model:value={forms.searchGroup.instrumentId}
-            onUpdate:value={() => throttleFn()}
-            checkStrategy="child"
-            showPath
-            childrenField="instruments"
-            expandTrigger="hover"
-            labelField="name"
-            valueField="id"
-            filterable
-            style={{ width: '200px' }}
-          />
-          <NInput
-            placeholder="请输入课件标题关键词"
-            clearable
-            v-model:value={forms.searchGroup.keyword}
-            onKeyup={(e: KeyboardEvent) => {
-              if (e.code === 'Enter') {
-                throttleFn();
-              }
-            }}
-            onClear={() => throttleFn()}>
-            {{
-              prefix: () => (
-                <span
-                  class="icon-search-input"
-                  style={{ cursor: 'pointer' }}
-                  onClick={() => throttleFn()}></span>
-              )
-            }}
-          </NInput>
-        </div>
-
-        <NSpin show={forms.loading} size={'small'}>
-          <NScrollbar
-            class={styles.classList}
-            style={{
-              'max-height': `60vh`
-            }}
-            onScroll={(e: any) => {
-              const clientHeight = e.target?.clientHeight;
-              const scrollTop = e.target?.scrollTop;
-              const scrollHeight = e.target?.scrollHeight;
-              // 是否到底,是否加载完
-              if (
-                clientHeight + scrollTop + 20 >= scrollHeight &&
-                !forms.finshed &&
-                !forms.loading
-              ) {
-                throttleFn();
-              }
-            }}>
-            <div
-              style={{
-                'min-height': `60vh)`
-              }}
-              class={[
-                styles.listSection,
-                !forms.loading && forms.tableList.length <= 0
-                  ? styles.emptySection
-                  : ''
-              ]}>
-              {forms.tableList.length > 0 && (
-                <div class={[styles.list]}>
-                  {forms.tableList.map((item: any) => (
-                    <div class={[styles.itemWrap, styles.itemBlock, 'row-nav']}>
-                      <div class={styles.itemWrapBox}>
-                        <CoursewareType
-                          isHoverShowAdd={false}
-                          isShowOpenFlag={false}
-                          isShowAdd
-                          item={item}
-                          onAdd={() => {
-                            emit('add', item);
-                          }}
-                          onLook={() => emit('click', item)}
-                        />
-                      </div>
-                    </div>
-                  ))}
-                </div>
-              )}
-              {!forms.loading && forms.tableList.length <= 0 && <TheEmpty />}
-            </div>
-          </NScrollbar>
-        </NSpin>
-      </div>
-    );
-  }
-});
+import { defineComponent, onMounted, onUnmounted, reactive, watch } from 'vue';
+import styles from './index.module.less';
+import { NCascader, NInput, NScrollbar, NSelect, NSpin } from 'naive-ui';
+import { useThrottleFn } from '@vueuse/core';
+import CoursewareType from '../courseware-type';
+import TheEmpty from '/src/components/TheEmpty';
+import { api_queryOpenCoursewareByPage } from '../../api';
+import { eventGlobal } from '/src/utils';
+
+export default defineComponent({
+  name: 'related-class',
+  props: {
+    tableList: {
+      type: Array,
+      default: () => []
+    },
+    instrumentList: {
+      type: Array,
+      default: () => []
+    },
+    instrumentId: {
+      type: [String, Number],
+      default: ''
+    },
+    coursewareDetailKnowledgeId: {
+      type: [String, Number],
+      default: ''
+    }
+  },
+  emits: ['close', 'add', 'click'],
+  setup(props, { emit }) {
+    const forms = reactive({
+      loading: false,
+      finshed: false, // 是否加载完
+      pagination: {
+        page: 1,
+        rows: 20
+      },
+      tableList: [] as any,
+      searchGroup: {
+        instrumentId: props.instrumentId ? props.instrumentId : '',
+        keyword: null
+      }
+    });
+    const getList = async () => {
+      try {
+        if (forms.pagination.page === 1) {
+          forms.loading = true;
+        }
+        // 查询公开课件列表
+        const { data } = await api_queryOpenCoursewareByPage({
+          coursewareDetailKnowledgeId: props.coursewareDetailKnowledgeId,
+          ...forms.searchGroup,
+          ...forms.pagination
+        });
+        const result = data.rows || [];
+        const tempList: any = [];
+        result.forEach((item: any) => {
+          // const index = forms.tableList.findIndex(
+          //   (i: any) => i.fromChapterLessonCoursewareId === item.id
+          // );
+          const firstItem: any =
+            item.chapterKnowledgeList[0]?.chapterKnowledgeMaterialList[0];
+          tempList.push({
+            id: item.id,
+            openFlag: item.openFlag,
+            openFlagEnable: item.openFlagEnable,
+            instrumentNames: item.instrumentNames,
+            fromChapterLessonCoursewareId: item.fromChapterLessonCoursewareId,
+            name: item.name,
+            coverImg: firstItem?.bizInfo.coverImg,
+            type: firstItem?.bizInfo.type,
+            isAdd: item.addFlag,
+            isNotWork: item.lessonPreTrainingNum <= 0 ? true : false // 是否布置作业
+          });
+        });
+
+        forms.loading = false;
+        forms.tableList.push(...tempList);
+
+        forms.finshed = data.pages <= data.current ? true : false;
+      } catch {
+        forms.loading = false;
+      }
+    };
+
+    // 检测数据是否存在
+    // watch(
+    //   () => props.tableList,
+    //   () => {
+    //     // fromChapterLessonCoursewareId;
+    //     forms.tableList.forEach((item: any) => {
+    //       const index = props.tableList.findIndex(
+    //         (i: any) => i.fromChapterLessonCoursewareId === item.id
+    //       );
+    //       item.isAdd = index !== -1 ? true : false;
+    //     });
+    //   }
+    // );
+
+    const throttleFn = useThrottleFn(() => {
+      forms.pagination.page = 1;
+      forms.tableList = [];
+      getList();
+    }, 500);
+
+    onMounted(() => {
+      getList();
+      eventGlobal.on('openCoursewareChanged', throttleFn);
+    });
+
+    onUnmounted(() => {
+      eventGlobal.off('openCoursewareChanged', throttleFn);
+    });
+    return () => (
+      <div class={styles.relatedClass}>
+        <div class={styles.attendClassSearch}>
+          <NCascader
+            placeholder="全部声部"
+            clearable
+            options={[
+              { name: '全部声部', id: '' },
+              ...(props.instrumentList as any)
+            ]}
+            v-model:value={forms.searchGroup.instrumentId}
+            onUpdate:value={() => throttleFn()}
+            checkStrategy="child"
+            showPath
+            childrenField="instruments"
+            expandTrigger="hover"
+            labelField="name"
+            valueField="id"
+            filterable
+            style={{ width: '200px' }}
+          />
+          <NInput
+            placeholder="请输入课件标题关键词"
+            clearable
+            v-model:value={forms.searchGroup.keyword}
+            onKeyup={(e: KeyboardEvent) => {
+              if (e.code === 'Enter') {
+                throttleFn();
+              }
+            }}
+            onClear={() => throttleFn()}>
+            {{
+              prefix: () => (
+                <span
+                  class="icon-search-input"
+                  style={{ cursor: 'pointer' }}
+                  onClick={() => throttleFn()}></span>
+              )
+            }}
+          </NInput>
+        </div>
+
+        <NSpin show={forms.loading} size={'small'}>
+          <NScrollbar
+            class={styles.classList}
+            style={{
+              'max-height': `60vh`
+            }}
+            onScroll={(e: any) => {
+              const clientHeight = e.target?.clientHeight;
+              const scrollTop = e.target?.scrollTop;
+              const scrollHeight = e.target?.scrollHeight;
+              // 是否到底,是否加载完
+              if (
+                clientHeight + scrollTop + 20 >= scrollHeight &&
+                !forms.finshed &&
+                !forms.loading
+              ) {
+                throttleFn();
+              }
+            }}>
+            <div
+              style={{
+                'min-height': `60vh)`
+              }}
+              class={[
+                styles.listSection,
+                !forms.loading && forms.tableList.length <= 0
+                  ? styles.emptySection
+                  : ''
+              ]}>
+              {forms.tableList.length > 0 && (
+                <div class={[styles.list]}>
+                  {forms.tableList.map((item: any) => (
+                    <div class={[styles.itemWrap, styles.itemBlock, 'row-nav']}>
+                      <div class={styles.itemWrapBox}>
+                        <CoursewareType
+                          isHoverShowAdd={false}
+                          isShowOpenFlag={false}
+                          isShowAdd
+                          item={item}
+                          onAdd={() => {
+                            emit('add', item);
+                          }}
+                          onLook={() => emit('click', item)}
+                        />
+                      </div>
+                    </div>
+                  ))}
+                </div>
+              )}
+              {!forms.loading && forms.tableList.length <= 0 && <TheEmpty />}
+            </div>
+          </NScrollbar>
+        </NSpin>
+      </div>
+    );
+  }
+});

+ 427 - 425
src/views/xiaoku-ai/index.tsx

@@ -1,425 +1,427 @@
-import { defineComponent, onMounted, reactive } from 'vue';
-import styles from './index.module.less';
-import TheSearch from '@/components/TheSearch';
-import { NButton, NImage, NPopselect, NSpace, NSpin } from 'naive-ui';
-import { useRouter } from 'vue-router';
-import { api_musicSheetCategoriesPage, api_musicTagTree } from './api';
-import TheEmpty from '/src/components/TheEmpty';
-import { useCatchStore } from '/src/store/modules/catchData';
-
-export default defineComponent({
-  name: 'XiaokuAi',
-  setup() {
-    const catchStore = useCatchStore();
-    const router = useRouter();
-
-    const xiaokuAiSearch = localStorage.getItem('xiaoku-ai-search');
-    const xiaokuAi = xiaokuAiSearch ? JSON.parse(xiaokuAiSearch) : {};
-    const forms = reactive({
-      musicTagIds: xiaokuAi.musicTagIds ? xiaokuAi.musicTagIds : ([] as any[]),
-      enable: true,
-      instrumentId: xiaokuAi.instrumentId || null,
-      keyword: '',
-      page: 1,
-      rows: 9999
-    });
-    const data = reactive({
-      tags: [] as any[],
-      tagChildren: [] as any[],
-      tagActiveId: xiaokuAi.tagActiveId || '',
-      tagActive: {} as any,
-      tagIndex: xiaokuAi.instrumentId || 0,
-      list: [] as any,
-      loading: false
-    });
-    const getTags = async () => {
-      const res = await api_musicTagTree();
-      if (Array.isArray(res?.data) && res.data.length) {
-        data.tags = res.data || [];
-        const index = data.tags.findIndex(
-          (item: any) => item.id == data.tagActiveId
-        );
-        if (index > -1) {
-          data.tagActiveId = res.data[index].id;
-          const list: any[] = [];
-          renderTag(res.data[index].children, list);
-          data.tagChildren = list;
-        } else {
-          data.tagActiveId = res.data[0].id;
-          const list: any[] = [];
-          renderTag(res.data[0].children, list);
-          data.tagChildren = list;
-        }
-      }
-    };
-
-    const getList = async () => {
-      data.loading = true;
-      try {
-        const res = await api_musicSheetCategoriesPage({
-          ...forms,
-          musicTagIds: [data.tagActiveId, ...forms.musicTagIds].filter(Boolean)
-        });
-        if (Array.isArray(res?.data?.rows)) {
-          data.list = res.data.rows;
-        }
-      } catch {
-        //
-      }
-      data.loading = false;
-    };
-
-    // 递归渲染标签
-    const renderTag = (_data: any[], _list: any[]): any => {
-      if (!_data?.length) return;
-      const item = {
-        columnName: _data[0].columnName,
-        list: [] as any[]
-      };
-      const childrens = [];
-      for (let i = 0; i < _data.length; i++) {
-        item.list.push({
-          name: _data[i].name,
-          id: _data[i].id,
-          activeIndex: -1
-        });
-        if (_data[i].children) {
-          childrens.push(..._data[i].children);
-        }
-      }
-      _list.push(item);
-      if (childrens.length) {
-        renderTag(childrens, _list);
-      }
-    };
-    onMounted(async () => {
-      data.loading = true;
-      try {
-        await getTags();
-        await getList();
-        // 获取教材分类列表
-        await catchStore.getSubjects();
-
-        localStorage.setItem(
-          'xiaoku-ai-search',
-          JSON.stringify({
-            tagActiveId: data.tagActiveId,
-            instrumentId: forms.instrumentId,
-            musicTagIds: forms.musicTagIds
-          })
-        );
-        if (forms.instrumentId) {
-          let childInstruments: any[] = [];
-          catchStore.getSubjectInstruments.forEach((item: any) => {
-            if (Array.isArray(item.instruments)) {
-              item.instruments.forEach((child: any) => {
-                if (forms.instrumentId === child.value) {
-                  childInstruments = item.instruments || [];
-                }
-              });
-            }
-          });
-          if (childInstruments.length > 0) {
-            selectChildObj(childInstruments);
-          }
-        }
-      } catch {
-        //
-      }
-      data.loading = false;
-    });
-
-    /** 改变顶级分类 */
-    const changeTag = (item: any, index: number) => {
-      data.tagActiveId = item.id;
-      forms.musicTagIds = [];
-
-      localStorage.setItem(
-        'xiaoku-ai-search',
-        JSON.stringify({
-          tagActiveId: item.id,
-          instrumentId: forms.instrumentId,
-          musicTagIds: forms.musicTagIds
-        })
-      );
-
-      const list: any[] = [];
-      renderTag(data.tags[index].children, list);
-      data.tagChildren = list;
-      getList();
-    };
-
-    /** 选中子选项 */
-    const selectChildTag = (columnIndex: number, index: number) => {
-      const oldActiveItem =
-        data.tagChildren[columnIndex].list[
-          data.tagChildren[columnIndex].activeIndex
-        ];
-      const activeItem = data.tagChildren[columnIndex].list[index];
-      if (oldActiveItem && oldActiveItem.id !== activeItem.id) {
-        forms.musicTagIds = forms.musicTagIds.filter(
-          (item: any) => item !== oldActiveItem.id
-        );
-      }
-      if (forms.musicTagIds.includes(activeItem.id)) {
-        forms.musicTagIds = forms.musicTagIds.filter(
-          (item: any) => item !== activeItem.id
-        );
-        data.tagChildren[columnIndex].activeIndex = -1;
-      } else {
-        forms.musicTagIds.push(activeItem.id);
-        data.tagChildren[columnIndex].activeIndex = index;
-      }
-
-      localStorage.setItem(
-        'xiaoku-ai-search',
-        JSON.stringify({
-          tagActiveId: data.tagActiveId,
-          instrumentId: forms.instrumentId,
-          musicTagIds: forms.musicTagIds
-        })
-      );
-      getList();
-    };
-    const selectChildObj = (item: any) => {
-      const obj: any = {};
-
-      item?.forEach((child: any) => {
-        if (child.id === data.tagIndex) {
-          obj.selected = true;
-          obj.name = child.name;
-        }
-      });
-      return obj;
-    };
-    return () => (
-      <div class={styles.container}>
-        <div class={styles.tools}>
-          <div class={styles.tagWrap}>
-            <div class={styles.tags}>
-              <NSpace size={[20, 12]}>
-                <span class={styles.firstButton}>
-                  {data.tags?.[0]?.columnName}
-                </span>
-
-                {data.tags.map((item: any, index: number) => {
-                  return (
-                    <>
-                      <NButton
-                        round
-                        secondary={data.tagActiveId === item.id ? false : true}
-                        type={
-                          data.tagActiveId === item.id ? 'primary' : 'default'
-                        }
-                        onClick={() => changeTag(item, index)}>
-                        {item.name}
-                      </NButton>
-                    </>
-                  );
-                })}
-              </NSpace>
-            </div>
-
-            {data.tagChildren.map((column: any, columnIndex: number) => {
-              return (
-                <div class={styles.tags}>
-                  <NSpace size={[20, 12]}>
-                    <span class={styles.firstButton}>{column.columnName}</span>
-
-                    {column.list.map((item: any, index: number) => {
-                      return (
-                        <>
-                          <NButton
-                            round
-                            secondary={
-                              column.activeIndex === index ? false : true
-                            }
-                            type={
-                              column.activeIndex === index
-                                ? 'primary'
-                                : 'default'
-                            }
-                            onClick={() => selectChildTag(columnIndex, index)}>
-                            {item.name}
-                          </NButton>
-                        </>
-                      );
-                    })}
-                  </NSpace>
-                </div>
-              );
-            })}
-            <div class={styles.tags}>
-              <NSpace size={[20, 12]}>
-                <span class={styles.firstButton}>乐器</span>
-
-                {catchStore.getSubjectInstruments.map((item: any) =>
-                  item.instruments && item.instruments.length > 1 ? (
-                    <NPopselect
-                      options={item.instruments}
-                      trigger="hover"
-                      v-model:value={data.tagIndex}
-                      scrollable
-                      onUpdate:value={() => {
-                        forms.instrumentId = data.tagIndex;
-                        localStorage.setItem(
-                          'xiaoku-ai-search',
-                          JSON.stringify({
-                            tagActiveId: data.tagActiveId,
-                            instrumentId: data.tagIndex,
-                            musicTagIds: forms.musicTagIds
-                          })
-                        );
-                        getList();
-                      }}
-                      key={item.value}
-                      class={[styles.popSelect1]}>
-                      <NButton
-                        round
-                        textColor={
-                          selectChildObj(item.instruments).selected
-                            ? '#fff'
-                            : '#000'
-                        }
-                        color={
-                          selectChildObj(item.instruments).selected
-                            ? '#198CFE'
-                            : 'rgba(46, 51, 56, .05)'
-                        }
-                        type={
-                          selectChildObj(item.instruments).selected
-                            ? 'primary'
-                            : 'default'
-                        }
-                        class={[
-                          styles.textBtn,
-                          selectChildObj(item.instruments).selected &&
-                            styles.textBtnActive
-                        ]}>
-                        {selectChildObj(item.instruments).name || item.name}
-                        <i class={styles.iconArrow}></i>
-                      </NButton>
-                    </NPopselect>
-                  ) : (
-                    <NButton
-                      round
-                      textColor={
-                        data.tagIndex === (item.value || 0) ? '#fff' : '#000'
-                      }
-                      color={
-                        data.tagIndex === (item.value || 0)
-                          ? '#198CFE'
-                          : 'rgba(46, 51, 56, .05)'
-                      }
-                      type={
-                        data.tagIndex === (item.value || 0)
-                          ? 'primary'
-                          : 'default'
-                      }
-                      onClick={() => {
-                        data.tagIndex = item.value || 0;
-                        forms.instrumentId = item.value;
-                        localStorage.setItem(
-                          'xiaoku-ai-search',
-                          JSON.stringify({
-                            tagActiveId: data.tagActiveId,
-                            instrumentId: item.id,
-                            musicTagIds: forms.musicTagIds
-                          })
-                        );
-                        getList();
-                      }}>
-                      {item.name}
-                    </NButton>
-                  )
-                )}
-                {/* // {
-                //   return (
-                //     <>
-                //       <NButton
-                //         round
-                //         secondary={item.id === forms.instrumentId ? false : true}
-                //         type={
-                //           item.id === forms.instrumentId ? 'primary' : 'default'
-                //         }
-                //         onClick={() => {
-                //           forms.instrumentId = item.id;
-
-                //           localStorage.setItem(
-                //             'xiaoku-ai-search',
-                //             JSON.stringify({
-                //               tagActiveId: data.tagActiveId,
-                //               instrumentId: item.id,
-                //               musicTagIds: forms.musicTagIds
-                //             })
-                //           );
-                //           getList();
-                //         }}>
-                //         {item.name}
-                //       </NButton>
-                //     </>
-                //   );
-                // })} */}
-              </NSpace>
-            </div>
-          </div>
-          <TheSearch
-            round
-            onSearch={val => {
-              forms.keyword = val;
-              getList();
-            }}
-          />
-        </div>
-        <NSpin show={data.loading}>
-          <div
-            class={[styles.content, data.loading ? styles.loadingContent : '']}>
-            {data.list.length > 0
-              ? data.list.map((item: any, index: number) => {
-                  return (
-                    <div class={styles.itemWrap}>
-                      <div class={styles.itemWrapBox}>
-                        <div
-                          class={styles.item}
-                          key={`item-${index}`}
-                          onClick={() => {
-                            sessionStorage.setItem(
-                              'musicSubjectList',
-                              JSON.stringify(item.subjects)
-                            );
-                            router.push({
-                              path: '/xiaoku-music',
-                              query: {
-                                id: item.id,
-                                name: item.name
-                              }
-                            });
-                          }}>
-                          <div class={styles.cover}>
-                            <div class={styles.itemImg}>
-                              <div class={styles.itemBg}></div>
-                              <NImage
-                                objectFit="cover"
-                                src={item.coverImg}
-                                lazy
-                                previewDisabled={true}
-                                onLoad={e => {
-                                  (e.target as any).dataset.loaded = 'true';
-                                }}
-                              />
-                            </div>
-                          </div>
-                          <div class={styles.itemName}>{item.name}</div>
-                        </div>
-                      </div>
-                    </div>
-                  );
-                })
-              : ''}
-            {!data.loading && data.list.length <= 0 && <TheEmpty></TheEmpty>}
-          </div>
-        </NSpin>
-      </div>
-    );
-  }
-});
+import { defineComponent, onMounted, reactive } from 'vue';
+import styles from './index.module.less';
+import TheSearch from '@/components/TheSearch';
+import { NButton, NImage, NPopselect, NSpace, NSpin } from 'naive-ui';
+import { useRouter } from 'vue-router';
+import { api_musicSheetCategoriesPage, api_musicTagTree } from './api';
+import TheEmpty from '/src/components/TheEmpty';
+import { useCatchStore } from '/src/store/modules/catchData';
+
+export default defineComponent({
+  name: 'XiaokuAi',
+  setup() {
+    const catchStore = useCatchStore();
+    const router = useRouter();
+
+    const xiaokuAiSearch = localStorage.getItem('xiaoku-ai-search');
+    const xiaokuAi = xiaokuAiSearch ? JSON.parse(xiaokuAiSearch) : {};
+    const forms = reactive({
+      musicTagIds: xiaokuAi.musicTagIds ? xiaokuAi.musicTagIds : ([] as any[]),
+      enable: true,
+      instrumentId: xiaokuAi.instrumentId || null,
+      keyword: '',
+      page: 1,
+      rows: 9999
+    });
+    const data = reactive({
+      tags: [] as any[],
+      tagChildren: [] as any[],
+      tagActiveId: xiaokuAi.tagActiveId || '',
+      tagActive: {} as any,
+      tagIndex: xiaokuAi.instrumentId || 0,
+      list: [] as any,
+      loading: false
+    });
+    const getTags = async () => {
+      const res = await api_musicTagTree();
+      if (Array.isArray(res?.data) && res.data.length) {
+        data.tags = res.data || [];
+        const index = data.tags.findIndex(
+          (item: any) => item.id == data.tagActiveId
+        );
+        if (index > -1) {
+          data.tagActiveId = res.data[index].id;
+          const list: any[] = [];
+          renderTag(res.data[index].children, list);
+          data.tagChildren = list;
+        } else {
+          data.tagActiveId = res.data[0].id;
+          const list: any[] = [];
+          renderTag(res.data[0].children, list);
+          data.tagChildren = list;
+        }
+      }
+    };
+
+    const getList = async () => {
+      data.loading = true;
+      try {
+        const res = await api_musicSheetCategoriesPage({
+          ...forms,
+          musicTagIds: [data.tagActiveId, ...forms.musicTagIds].filter(Boolean)
+        });
+        if (Array.isArray(res?.data?.rows)) {
+          data.list = res.data.rows;
+        }
+      } catch {
+        //
+      }
+      data.loading = false;
+    };
+
+    // 递归渲染标签
+    const renderTag = (_data: any[], _list: any[]): any => {
+      if (!_data?.length) return;
+      const item = {
+        columnName: _data[0].columnName,
+        list: [] as any[]
+      };
+      const childrens = [];
+      for (let i = 0; i < _data.length; i++) {
+        item.list.push({
+          name: _data[i].name,
+          id: _data[i].id,
+          activeIndex: -1
+        });
+        if (_data[i].children) {
+          childrens.push(..._data[i].children);
+        }
+      }
+      _list.push(item);
+      if (childrens.length) {
+        renderTag(childrens, _list);
+      }
+    };
+    onMounted(async () => {
+      data.loading = true;
+      try {
+        await getTags();
+        await getList();
+        // 获取教材分类列表
+        await catchStore.getSubjects();
+
+        localStorage.setItem(
+          'xiaoku-ai-search',
+          JSON.stringify({
+            tagActiveId: data.tagActiveId,
+            instrumentId: forms.instrumentId,
+            musicTagIds: forms.musicTagIds
+          })
+        );
+        if (forms.instrumentId) {
+          let childInstruments: any[] = [];
+          catchStore.getSubjectInstruments.forEach((item: any) => {
+            if (Array.isArray(item.instruments)) {
+              item.instruments.forEach((child: any) => {
+                if (forms.instrumentId === child.value) {
+                  childInstruments = item.instruments || [];
+                }
+              });
+            }
+          });
+          if (childInstruments.length > 0) {
+            selectChildObj(childInstruments);
+          } else {
+            forms.instrumentId = '';
+          }
+        }
+      } catch {
+        //
+      }
+      data.loading = false;
+    });
+
+    /** 改变顶级分类 */
+    const changeTag = (item: any, index: number) => {
+      data.tagActiveId = item.id;
+      forms.musicTagIds = [];
+
+      localStorage.setItem(
+        'xiaoku-ai-search',
+        JSON.stringify({
+          tagActiveId: item.id,
+          instrumentId: forms.instrumentId,
+          musicTagIds: forms.musicTagIds
+        })
+      );
+
+      const list: any[] = [];
+      renderTag(data.tags[index].children, list);
+      data.tagChildren = list;
+      getList();
+    };
+
+    /** 选中子选项 */
+    const selectChildTag = (columnIndex: number, index: number) => {
+      const oldActiveItem =
+        data.tagChildren[columnIndex].list[
+          data.tagChildren[columnIndex].activeIndex
+        ];
+      const activeItem = data.tagChildren[columnIndex].list[index];
+      if (oldActiveItem && oldActiveItem.id !== activeItem.id) {
+        forms.musicTagIds = forms.musicTagIds.filter(
+          (item: any) => item !== oldActiveItem.id
+        );
+      }
+      if (forms.musicTagIds.includes(activeItem.id)) {
+        forms.musicTagIds = forms.musicTagIds.filter(
+          (item: any) => item !== activeItem.id
+        );
+        data.tagChildren[columnIndex].activeIndex = -1;
+      } else {
+        forms.musicTagIds.push(activeItem.id);
+        data.tagChildren[columnIndex].activeIndex = index;
+      }
+
+      localStorage.setItem(
+        'xiaoku-ai-search',
+        JSON.stringify({
+          tagActiveId: data.tagActiveId,
+          instrumentId: forms.instrumentId,
+          musicTagIds: forms.musicTagIds
+        })
+      );
+      getList();
+    };
+    const selectChildObj = (item: any) => {
+      const obj: any = {};
+
+      item?.forEach((child: any) => {
+        if (child.id === data.tagIndex) {
+          obj.selected = true;
+          obj.name = child.name;
+        }
+      });
+      return obj;
+    };
+    return () => (
+      <div class={styles.container}>
+        <div class={styles.tools}>
+          <div class={styles.tagWrap}>
+            <div class={styles.tags}>
+              <NSpace size={[20, 12]}>
+                <span class={styles.firstButton}>
+                  {data.tags?.[0]?.columnName}
+                </span>
+
+                {data.tags.map((item: any, index: number) => {
+                  return (
+                    <>
+                      <NButton
+                        round
+                        secondary={data.tagActiveId === item.id ? false : true}
+                        type={
+                          data.tagActiveId === item.id ? 'primary' : 'default'
+                        }
+                        onClick={() => changeTag(item, index)}>
+                        {item.name}
+                      </NButton>
+                    </>
+                  );
+                })}
+              </NSpace>
+            </div>
+
+            {data.tagChildren.map((column: any, columnIndex: number) => {
+              return (
+                <div class={styles.tags}>
+                  <NSpace size={[20, 12]}>
+                    <span class={styles.firstButton}>{column.columnName}</span>
+
+                    {column.list.map((item: any, index: number) => {
+                      return (
+                        <>
+                          <NButton
+                            round
+                            secondary={
+                              column.activeIndex === index ? false : true
+                            }
+                            type={
+                              column.activeIndex === index
+                                ? 'primary'
+                                : 'default'
+                            }
+                            onClick={() => selectChildTag(columnIndex, index)}>
+                            {item.name}
+                          </NButton>
+                        </>
+                      );
+                    })}
+                  </NSpace>
+                </div>
+              );
+            })}
+            <div class={styles.tags}>
+              <NSpace size={[20, 12]}>
+                <span class={styles.firstButton}>乐器</span>
+
+                {catchStore.getSubjectInstruments.map((item: any) =>
+                  item.instruments && item.instruments.length > 1 ? (
+                    <NPopselect
+                      options={item.instruments}
+                      trigger="hover"
+                      v-model:value={data.tagIndex}
+                      scrollable
+                      onUpdate:value={() => {
+                        forms.instrumentId = data.tagIndex;
+                        localStorage.setItem(
+                          'xiaoku-ai-search',
+                          JSON.stringify({
+                            tagActiveId: data.tagActiveId,
+                            instrumentId: data.tagIndex,
+                            musicTagIds: forms.musicTagIds
+                          })
+                        );
+                        getList();
+                      }}
+                      key={item.value}
+                      class={[styles.popSelect1]}>
+                      <NButton
+                        round
+                        textColor={
+                          selectChildObj(item.instruments).selected
+                            ? '#fff'
+                            : '#000'
+                        }
+                        color={
+                          selectChildObj(item.instruments).selected
+                            ? '#198CFE'
+                            : 'rgba(46, 51, 56, .05)'
+                        }
+                        type={
+                          selectChildObj(item.instruments).selected
+                            ? 'primary'
+                            : 'default'
+                        }
+                        class={[
+                          styles.textBtn,
+                          selectChildObj(item.instruments).selected &&
+                            styles.textBtnActive
+                        ]}>
+                        {selectChildObj(item.instruments).name || item.name}
+                        <i class={styles.iconArrow}></i>
+                      </NButton>
+                    </NPopselect>
+                  ) : (
+                    <NButton
+                      round
+                      textColor={
+                        data.tagIndex === (item.value || 0) ? '#fff' : '#000'
+                      }
+                      color={
+                        data.tagIndex === (item.value || 0)
+                          ? '#198CFE'
+                          : 'rgba(46, 51, 56, .05)'
+                      }
+                      type={
+                        data.tagIndex === (item.value || 0)
+                          ? 'primary'
+                          : 'default'
+                      }
+                      onClick={() => {
+                        data.tagIndex = item.value || 0;
+                        forms.instrumentId = item.value;
+                        localStorage.setItem(
+                          'xiaoku-ai-search',
+                          JSON.stringify({
+                            tagActiveId: data.tagActiveId,
+                            instrumentId: item.id,
+                            musicTagIds: forms.musicTagIds
+                          })
+                        );
+                        getList();
+                      }}>
+                      {item.name}
+                    </NButton>
+                  )
+                )}
+                {/* // {
+                //   return (
+                //     <>
+                //       <NButton
+                //         round
+                //         secondary={item.id === forms.instrumentId ? false : true}
+                //         type={
+                //           item.id === forms.instrumentId ? 'primary' : 'default'
+                //         }
+                //         onClick={() => {
+                //           forms.instrumentId = item.id;
+
+                //           localStorage.setItem(
+                //             'xiaoku-ai-search',
+                //             JSON.stringify({
+                //               tagActiveId: data.tagActiveId,
+                //               instrumentId: item.id,
+                //               musicTagIds: forms.musicTagIds
+                //             })
+                //           );
+                //           getList();
+                //         }}>
+                //         {item.name}
+                //       </NButton>
+                //     </>
+                //   );
+                // })} */}
+              </NSpace>
+            </div>
+          </div>
+          <TheSearch
+            round
+            onSearch={val => {
+              forms.keyword = val;
+              getList();
+            }}
+          />
+        </div>
+        <NSpin show={data.loading}>
+          <div
+            class={[styles.content, data.loading ? styles.loadingContent : '']}>
+            {data.list.length > 0
+              ? data.list.map((item: any, index: number) => {
+                  return (
+                    <div class={styles.itemWrap}>
+                      <div class={styles.itemWrapBox}>
+                        <div
+                          class={styles.item}
+                          key={`item-${index}`}
+                          onClick={() => {
+                            sessionStorage.setItem(
+                              'musicSubjectList',
+                              JSON.stringify(item.subjects)
+                            );
+                            router.push({
+                              path: '/xiaoku-music',
+                              query: {
+                                id: item.id,
+                                name: item.name
+                              }
+                            });
+                          }}>
+                          <div class={styles.cover}>
+                            <div class={styles.itemImg}>
+                              <div class={styles.itemBg}></div>
+                              <NImage
+                                objectFit="cover"
+                                src={item.coverImg}
+                                lazy
+                                previewDisabled={true}
+                                onLoad={e => {
+                                  (e.target as any).dataset.loaded = 'true';
+                                }}
+                              />
+                            </div>
+                          </div>
+                          <div class={styles.itemName}>{item.name}</div>
+                        </div>
+                      </div>
+                    </div>
+                  );
+                })
+              : ''}
+            {!data.loading && data.list.length <= 0 && <TheEmpty></TheEmpty>}
+          </div>
+        </NSpin>
+      </div>
+    );
+  }
+});