瀏覽代碼

添加作业

lex 1 年之前
父節點
當前提交
13dcd0bd24
共有 33 個文件被更改,包括 1335 次插入324 次删除
  1. 1 1
      public/version.json
  2. 11 0
      src/store/modules/users.ts
  3. 36 1
      src/views/attend-class/index.module.less
  4. 54 4
      src/views/attend-class/index.tsx
  5. 49 21
      src/views/attend-class/model/train-type/index.module.less
  6. 26 12
      src/views/attend-class/model/train-type/index.tsx
  7. 二進制
      src/views/homework-record/images/icon-ing.png
  8. 二進制
      src/views/homework-record/images/icon-over.png
  9. 59 14
      src/views/homework-record/index.module.less
  10. 154 60
      src/views/homework-record/index.tsx
  11. 2 3
      src/views/natural-resources/components/my-resources/upload-modal/index.tsx
  12. 43 2
      src/views/prepare-lessons/components/lesson-main/courseware-presets/index.module.less
  13. 102 104
      src/views/prepare-lessons/components/lesson-main/courseware-presets/index.tsx
  14. 11 12
      src/views/prepare-lessons/components/lesson-main/courseware-presets/select-related/index.tsx
  15. 29 0
      src/views/prepare-lessons/components/lesson-main/courseware/addCourseware.tsx
  16. 8 1
      src/views/prepare-lessons/components/lesson-main/train/assign-homework.tsx
  17. 1 1
      src/views/prepare-lessons/components/lesson-main/train/index.module.less
  18. 59 44
      src/views/prepare-lessons/components/lesson-main/train/index.tsx
  19. 5 2
      src/views/prepare-lessons/components/resource-main/components/select-music/index.tsx
  20. 2 2
      src/views/prepare-lessons/components/resource-main/index.tsx
  21. 二進制
      src/views/prepare-lessons/images/addSource/icon8.png
  22. 二進制
      src/views/prepare-lessons/images/protocol/check-active.png
  23. 二進制
      src/views/prepare-lessons/images/protocol/check-default.png
  24. 二進制
      src/views/prepare-lessons/images/protocol/closeAble.png
  25. 二進制
      src/views/prepare-lessons/images/protocol/dingPng.png
  26. 二進制
      src/views/prepare-lessons/images/protocol/moveTop.png
  27. 174 0
      src/views/prepare-lessons/model/add-courseware-protocol/index.module.less
  28. 230 0
      src/views/prepare-lessons/model/add-courseware-protocol/index.tsx
  29. 20 0
      src/views/prepare-lessons/model/add-other-source/index.module.less
  30. 104 1
      src/views/prepare-lessons/model/add-other-source/index.tsx
  31. 103 13
      src/views/prepare-lessons/model/courseware-type/index.module.less
  32. 48 20
      src/views/prepare-lessons/model/courseware-type/index.tsx
  33. 4 6
      src/views/prepare-lessons/model/related-class/index.tsx

+ 1 - 1
public/version.json

@@ -1 +1 @@
-{"version":1710852026507}
+{"version":1710898215962}

+ 11 - 0
src/store/modules/users.ts

@@ -8,6 +8,7 @@ export interface IUserState {
   token: string;
   imToken: string;
   username: string;
+  readCoursewareOpenAgreement: boolean;
   avatar: string;
   info: any;
   imUserInfo: any;
@@ -20,6 +21,7 @@ export const useUserStore = defineStore('user-store', {
     imToken: storage.get(IM_TOKEN, ''),
     username: '',
     avatar: '',
+    readCoursewareOpenAgreement: true, // 是否阅读协议 备课
     noReadCount: 0, // 未读数量
     info: storage.get(CURRENT_USER, {}),
     imUserInfo: {} // IM
@@ -45,6 +47,9 @@ export const useUserStore = defineStore('user-store', {
     },
     getImUserInfo(): any {
       return this.imUserInfo;
+    },
+    getReadCoursewareOpenAgreement(): boolean {
+      return this.readCoursewareOpenAgreement;
     }
   },
   actions: {
@@ -69,6 +74,9 @@ export const useUserStore = defineStore('user-store', {
     setImUserInfo(info: any) {
       this.imUserInfo = info;
     },
+    setReadCoursewareOpenAgreement(info: any) {
+      this.readCoursewareOpenAgreement = info;
+    },
     // 登录
     async login(userInfo: any) {
       try {
@@ -95,6 +103,9 @@ export const useUserStore = defineStore('user-store', {
             this.setUserInfo(result);
             this.setAvatar(result.account.avatar);
             this.setUsername(result.nickname);
+            this.setReadCoursewareOpenAgreement(
+              result.readCoursewareOpenAgreement
+            );
             resolve(true);
           })
           .catch((error: any) => {

+ 36 - 1
src/views/attend-class/index.module.less

@@ -459,7 +459,7 @@
 }
 
 .workContainer {
-  padding: 20px 40px 40px;
+  // padding: 20px 40px 40px;
 
   h2 {
     font-size: 26px;
@@ -868,4 +868,39 @@
 
 .selectClassModal {
   width: 1000px;
+}
+
+.workVisiable {
+  width: 1258px;
+}
+
+.workContainer {
+  display: flex;
+  align-items: center;
+
+  .workTrain {
+    flex: 1;
+    height: 75vh;
+
+    &>div {
+      padding-top: 15px;
+    }
+  }
+
+  :global {
+    .train-container {
+      // max-height: calc(var(--window-page-lesson-height) - 135px) !important;
+      max-height: calc(var(--window-page-lesson-height) - 100px) !important;
+
+      .train-listSection {
+        min-height: calc(var(--window-page-lesson-height) - 100px) !important;
+      }
+    }
+  }
+
+  .resourceMain {
+    flex: 0 0 360px;
+    height: 75vh;
+    box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
+  }
 }

+ 54 - 4
src/views/attend-class/index.tsx

@@ -85,6 +85,9 @@ import InstruemntDetail from '/src/views/prepare-lessons/model/source-instrument
 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';
 
 export type ToolType = 'init' | 'pen' | 'whiteboard' | 'call';
 export type ToolItem = {
@@ -192,6 +195,7 @@ export default defineComponent({
       removeCourseStatus: false, // 是否布置作业
 
       teacherChapterName: '',
+      lessonPreTrainingId: null,
       selectResourceStatus: false,
       videoState: 'init' as 'init' | 'play',
       videoItemRef: null as any,
@@ -219,6 +223,8 @@ export default defineComponent({
         );
 
         data.teacherChapterName = res.data.name || '';
+        // 布置的作业编号
+        data.lessonPreTrainingId = res.data.lessonPreTrainingId;
         const tempRows = res.data.chapterKnowledgeList || [];
         const temp: any = [];
         const allItem: any = [];
@@ -326,7 +332,7 @@ export default defineComponent({
     onMounted(() => {
       // initMoveable();
       const query = route.query;
-      // console.log(query, props.preStudentNum, '学生人数');
+      console.log(query, props.preStudentNum, '学生人数');
       // 先取参数,
       data.type = props.type || (query.type as any);
       data.courseId = props.courseId || query.courseId;
@@ -1276,6 +1282,9 @@ export default defineComponent({
             data.modelAttendStatus = true;
           } else {
             data.modelTrainStatus = true;
+            nextTick(() => {
+              getModalHeight();
+            });
             data.modelAttendStatus = false;
           }
           break;
@@ -1390,6 +1399,17 @@ export default defineComponent({
       }
     };
 
+    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');
+        });
+      }
+    };
+
     return () => (
       <div id="playContent" class={[styles.playContent, 'wrap']}>
         <div
@@ -1853,6 +1873,9 @@ export default defineComponent({
                 round
                 onClick={() => {
                   data.modelTrainStatus = true;
+                  nextTick(() => {
+                    getModalHeight();
+                  });
                   data.modelAttendStatus = false;
                 }}>
                 布置作业
@@ -1871,7 +1894,7 @@ export default defineComponent({
         </NModal>
 
         {/* 训练设置 */}
-        <NModal
+        {/* <NModal
           transformOrigin="center"
           v-model:show={data.modelTrainStatus}
           preset="card"
@@ -1885,6 +1908,32 @@ export default defineComponent({
             classGroupId={data.classGroupId}
             onClose={() => (data.modelTrainStatus = false)}
           />
+        </NModal> */}
+        <NModal
+          v-model:show={data.modelTrainStatus}
+          preset="card"
+          class={['modalTitle background', styles.workVisiable]}
+          title={'布置作业'}>
+          <div id="model-homework-height" class={styles.workContainer}>
+            <div class={styles.workTrain}>
+              <Train
+                cardType="homeworkRecord"
+                lessonPreTraining={{
+                  title: '',
+                  chapterId: data.courseId, // 课件编号
+                  id: data.lessonPreTrainingId // 作业编号
+                }}
+                courseScheduleId={data.classId}
+                onChange={(val: any) => {
+                  data.modelTrainStatus = val.status;
+                  // getCoursewareList();
+                }}
+              />
+            </div>
+            <div class={styles.resourceMain}>
+              <ResourceMain cardType="homerowk-record" />
+            </div>
+          </div>
         </NModal>
 
         <NModal
@@ -1974,6 +2023,9 @@ export default defineComponent({
                   if (data.removeCourseStatus) {
                     data.modelTrainStatus = true;
                     data.removeVisiable = false;
+                    nextTick(() => {
+                      getModalHeight();
+                    });
                   } else {
                     if (globalState.application) {
                       document.exitFullscreen
@@ -1998,5 +2050,3 @@ export default defineComponent({
     );
   }
 });
-
-// roll-call/index.html

+ 49 - 21
src/views/attend-class/model/train-type/index.module.less

@@ -71,32 +71,34 @@
     }
   }
 
-  .iconDelete {
-    position: absolute;
-    right: 0px;
-    top: 0px;
-    z-index: 11;
-    display: flex;
-    height: 30px;
-    padding: 0;
-
-    img {
-      height: 30px;
-      width: 30px;
-    }
-  }
+  // .iconDelete {
+  //   position: absolute;
+  //   right: 0px;
+  //   top: 0px;
+  //   z-index: 11;
+  //   display: flex;
+  //   height: 30px;
+  //   padding: 0;
+
+  //   img {
+  //     height: 30px;
+  //     width: 30px;
+  //   }
+  // }
 }
 
 .train-content {
-  height: 238px;
+  height: 140px;
   background: #ffffff;
   position: relative;
   overflow: hidden;
+  transition: all 0.2s ease;
 
   :global {
     .n-image {
       width: 100%;
       height: inherit;
+      transition: all 0.2s ease;
 
       img {
         width: 100%;
@@ -188,6 +190,32 @@
       visibility: visible;
       transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
     }
+
+    .iconDelete {
+      opacity: 1;
+      visibility: visible;
+      transition: all .2s ease;
+    }
+
+    :global {
+      .n-image {
+        transform: scale(1.05);
+        transition: all 0.2s ease;
+      }
+    }
+  }
+
+  .iconDelete {
+    position: absolute;
+    top: 8px;
+    right: 10px;
+    z-index: 98;
+    opacity: 0;
+    visibility: hidden;
+    transition: all .2s ease;
+    width: 27px;
+    height: 27px;
+    cursor: pointer;
   }
 }
 
@@ -195,7 +223,7 @@
   display: flex;
   align-items: center;
   justify-content: space-between;
-  padding: 14px 13px;
+  padding: 8px;
 
   .type {
     gap: 8px 10px !important;
@@ -216,12 +244,12 @@
 }
 
 .trainInfo {
-  max-width: 60%;
+  max-width: 82%;
 
   .trainName {
     display: flex;
     align-items: center;
-    font-size: max(15px, 13Px);
+    font-size: max(13px, 12Px);
     font-family: PingFangSC, PingFang SC;
     font-weight: 600;
     color: #131415;
@@ -233,7 +261,7 @@
     display: inline-block;
     background-color: #ccc;
     border-radius: 5px;
-    font-size: max(12px, 11Px);
+    font-size: max(12px, 10Px);
     font-weight: 600;
     color: #FFFFFF;
     height: 18Px;
@@ -254,14 +282,14 @@
     display: flex;
     align-items: center;
     padding-top: 5px;
-    font-size: 12Px;
+    font-size: 11Px;
     font-weight: 500;
     color: rgba(0, 0, 0, 0.5);
 
     :global {
       .n-divider {
         --n-color: rgba(0, 0, 0, 0.5) !important;
-        height: 12Px;
+        height: 11Px;
         margin: 0 5px !important;
       }
     }

+ 26 - 12
src/views/attend-class/model/train-type/index.tsx

@@ -12,9 +12,9 @@ import {
   useMessage,
   NDivider
 } from 'naive-ui';
-
+import iconDelete from '@/views/prepare-lessons/images/icon-delete-default.png';
 import iconEdit from './images/icon-edit.png';
-import iconDelete from './images/icon-delete2.png';
+// import iconDelete from './images/icon-delete2.png';
 import iconBackLook from './images/icon-back-look.png';
 import iconReport from './images/icon-report.png';
 import { useUserStore } from '/src/store/modules/users';
@@ -175,8 +175,16 @@ export default defineComponent({
           props.item.trainingType === 'EVALUATION' ? styles.evaluationType : ''
         ]}
         onClick={() => emit('click', props.item)}>
-        <div class={styles['train-content']}>
-          <NImage src={props.item.coverImg} previewDisabled objectFit="cover" />
+        <div
+          class={[
+            styles['train-content'],
+            props.isDisabled && !props.isCLassWork && styles.trainDisabled
+          ]}>
+          <NImage
+            src={props.item.coverImg}
+            previewDisabled
+            objectFit="contain"
+          />
           {props.isDisabled && !props.isCLassWork ? (
             <div class={styles.disPreview}>
               <NProgress
@@ -226,13 +234,21 @@ export default defineComponent({
                 {props.item.trainingType === 'EVALUATION' ? '分' : '分钟'}
               </p>
             </div>
-          ) : (
-            <div class={styles.preview} onClick={onDetail}>
+          ) : null}
+
+          {/* <div class={styles.preview} onClick={onDetail}>
               <NButton strong secondary class={styles.previewBtn}>
                 预览
               </NButton>
-            </div>
-          )}
+            </div> */}
+          <img
+            src={iconDelete}
+            class={styles.iconDelete}
+            onClick={(e: MouseEvent) => {
+              e.stopPropagation();
+              emit('delete', props.item);
+            }}
+          />
         </div>
         <div class={styles['train-footer']}>
           <div class={styles.trainInfo}>
@@ -273,8 +289,7 @@ export default defineComponent({
                   }}
                 </NTooltip>
               </n-button>
-              {/* {props.type === 'homework' && ( */}
-              <n-button
+              {/* <n-button
                 quaternary
                 disabled={!props.isDelete}
                 class={styles.operation}
@@ -290,8 +305,7 @@ export default defineComponent({
                     default: '删除'
                   }}
                 </NTooltip>
-              </n-button>
-              {/* )} */}
+              </n-button> */}
             </NSpace>
           )}
 

二進制
src/views/homework-record/images/icon-ing.png


二進制
src/views/homework-record/images/icon-over.png


+ 59 - 14
src/views/homework-record/index.module.less

@@ -165,6 +165,7 @@
   background: #F7F9FF;
   border-radius: 13px;
   padding: 0 17px 17px;
+  position: relative;
 
   .header {
     display: flex;
@@ -206,21 +207,31 @@
       }
     }
 
+    .ing,
+    .over {
+      position: absolute;
+      top: 0;
+      right: 0;
+      width: 121px;
+      height: 38px;
+      display: inline-block;
+    }
+
     .ing {
-      font-weight: 500;
-      color: #1677FF;
+      background: url('./images/icon-ing.png') no-repeat center;
+      background-size: contain;
     }
 
     .over {
-      font-weight: 500;
-      color: #AAAAAA;
+      background: url('./images/icon-over.png') no-repeat center;
+      background-size: contain;
     }
   }
 
   .content {
-    display: flex;
-    justify-content: space-between;
-    align-items: flex-end;
+    // display: flex;
+    // justify-content: space-between;
+    // align-items: flex-end;
     padding: 13px;
     background: #FFFFFF;
     border-radius: 10px;
@@ -231,6 +242,40 @@
       font-weight: 600;
       color: #000000;
       padding-bottom: 5px;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+
+      :global {
+        .n-space {
+          flex-shrink: 0;
+        }
+      }
+
+      &>p {
+        display: flex;
+        align-items: center;
+      }
+
+      .CLASSWORK,
+      .HOMEWORK {
+        padding: 2px 8px 1px;
+        border-radius: 4px;
+        font-size: max(13px, 11Px);
+        line-height: 18px;
+        margin-right: 7px;
+      }
+
+      .CLASSWORK {
+        color: #E24F4F;
+        background: #FFD2D2;
+      }
+
+      .HOMEWORK {
+        color: #3F8ADF;
+        background: #D2E9FF;
+
+      }
     }
 
     .homeContent {
@@ -242,7 +287,7 @@
       align-items: flex-start;
 
       .pSection {
-        max-width: 500px;
+        max-width: 650px;
       }
 
       .p1,
@@ -288,14 +333,14 @@
     }
 
     .errorBtn {
-      min-width: 93px;
+      // min-width: 93px;
       // height: 30px;
-      --n-height: 36px !important;
+      --n-height: 24px !important;
       // background: #F94D50;
-      border-radius: 7px;
-      --n-font-size: max(13px, 12Px);
-      font-weight: 600;
-      color: #FFFFFF;
+      // border-radius: 7px;
+      --n-font-size: max(15px, 13Px);
+      font-weight: 500 !important;
+      // color: #FFFFFF;
       line-height: 18px;
     }
   }

+ 154 - 60
src/views/homework-record/index.tsx

@@ -24,12 +24,14 @@ 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 { getTimes } from '/src/utils';
+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()];
@@ -44,6 +46,7 @@ export default defineComponent({
       searchForm: {
         keyword: null as any,
         currentClass: '',
+        homeworkType: '',
         currentGradeNum: '',
         subjectId: '',
         gradeYear: '',
@@ -65,7 +68,14 @@ export default defineComponent({
       activeRow: null as any,
       showaddClass: false,
       popSelectYearList: [] as any,
-      popSelectLevelList: [] as any
+      popSelectLevelList: [] as any,
+      previewModal: false,
+      previewParams: {
+        type: '',
+        courseId: '',
+        subjectId: '',
+        detailId: ''
+      } as any
     });
     const formRef = ref();
     const message = useMessage();
@@ -213,6 +223,43 @@ export default defineComponent({
       }
     };
 
+    // 预览上课
+    // 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.lessonCoursewareDetailId
+        };
+      } else {
+        const { href } = router.resolve({
+          path: '/attend-class',
+          query: {
+            type: 'preview',
+            courseId: item.chapterLessonCoursewareId,
+            subjectId: null,
+            detailId: item.lessonCoursewareKnowledgeDetailId,
+            lessonCourseId: item.lessonCoursewareDetailId
+          }
+        });
+        window.open(href, +new Date() + '');
+      }
+    };
+
     onMounted(async () => {
       state.loading = true;
       await getYearList();
@@ -237,6 +284,22 @@ export default defineComponent({
               <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: '班级' }
@@ -381,76 +444,100 @@ export default defineComponent({
                           布置时间:
                           {dayjs(item.createTime).format('YYYY-MM-DD HH:mm')}
                           <span> | </span>
-                          <span style={{ color: '#EA4132' }}>
+                          <span>
                             截止时间:
                             {dayjs(item.expireDate).format('YYYY-MM-DD HH:mm')}
                           </span>
                         </p>
                       </div>
                       <div class={item.status ? styles.over : styles.ing}>
-                        {item.status ? '已结束' : '进行中'}
+                        {/* {item.status ? '已结束' : '进行中'} */}
                       </div>
                     </div>
                     <div class={styles.content}>
-                      <div>
-                        <div class={styles.homeTitle}>{item.name}</div>
-                        <div class={styles.homeContent}>
-                          <span class={styles.title}>作业对象:</span>
-                          <span class={styles.text}>
-                            {item.homeworkObjName}
-                          </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}%
+                      {/* <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.homeworkObjName}</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>
-
-                      {!item.status && (
-                        <NButton
-                          class={styles.errorBtn}
-                          type="error"
-                          color="#F94D50"
-                          onClick={(e: any) => {
-                            e.stopPropagation();
-                            state.resetVisiable = true;
-                            state.resetItem = item;
-                          }}>
-                          撤回
-                        </NButton>
-                      )}
+                      <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>
                 ))}
@@ -516,6 +603,13 @@ export default defineComponent({
             </div>
           </div>
         </NModal>
+
+        {/* 应用内预览或上课 */}
+        <PreviewWindow
+          v-model:show={state.previewModal}
+          type="attend"
+          params={state.previewParams}
+        />
       </div>
     );
   }

+ 2 - 3
src/views/natural-resources/components/my-resources/upload-modal/index.tsx

@@ -118,14 +118,13 @@ export default defineComponent({
               id: item.id || null
             });
           });
-          console.log(isUpdate.value, 'isUpdate.value', props.editStatus);
           if (isUpdate.value) {
             if (!props.editStatus) {
-              await materialUpdateAll(body);
+              const { data } = await materialUpdateAll(body);
               message.success('保存成功');
               uploadForms.list = [];
               emit('close', true);
-              emit('confirm');
+              emit('confirm', data);
             } else {
               emit('editAll', body);
             }

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

@@ -235,18 +235,24 @@
   }
 }
 
+.listLoading {}
+
 .list {
   display: flex;
   flex-flow: row wrap;
   justify-content: flex-start;
   padding: 10px 20px 12px;
   // padding: 0 20px 0px;
-  gap: 20px 0;
+  gap: 10px 0;
   margin: 0 -10px 0;
-  min-height: 313px;
+  min-height: calc(var(--window-page-lesson-height) - 100px);
   // height: 313px;
 
 
+  &.listEmpty {
+    align-items: center;
+  }
+
   &.listSame {
     margin-top: 0;
     padding-top: 0;
@@ -322,4 +328,39 @@
   width: 800px;
   border-radius: 16px;
   overflow: hidden;
+}
+
+.workVisiable {
+  width: 1258px;
+}
+
+.workContainer {
+  display: flex;
+  align-items: center;
+
+  .workTrain {
+    flex: 1;
+    height: 75vh;
+
+    &>div {
+      padding-top: 15px;
+    }
+  }
+
+  :global {
+    .train-container {
+      // max-height: calc(var(--window-page-lesson-height) - 135px) !important;
+      max-height: calc(var(--window-page-lesson-height) - 100px) !important;
+
+      .train-listSection {
+        min-height: calc(var(--window-page-lesson-height) - 100px) !important;
+      }
+    }
+  }
+
+  .resourceMain {
+    flex: 0 0 360px;
+    height: 75vh;
+    box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
+  }
 }

+ 102 - 104
src/views/prepare-lessons/components/lesson-main/courseware-presets/index.tsx

@@ -1,4 +1,11 @@
-import { defineComponent, onMounted, reactive, ref, watch } from 'vue';
+import {
+  defineComponent,
+  nextTick,
+  onMounted,
+  reactive,
+  ref,
+  watch
+} from 'vue';
 import styles from './index.module.less';
 import {
   NButton,
@@ -38,6 +45,8 @@ 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',
@@ -86,7 +95,8 @@ export default defineComponent({
         courseId: '',
         subjectId: '',
         detailId: ''
-      } as any
+      } as any,
+      workVisiable: false
     });
 
     const getCoursewareList = async () => {
@@ -107,13 +117,15 @@ export default defineComponent({
             item.chapterKnowledgeList[0]?.chapterKnowledgeMaterialList[0];
           tempList.push({
             id: item.id,
+            lessonPreTrainingId: item.lessonPreTrainingId,
             openFlag: item.openFlag,
             openFlagEnable: item.openFlagEnable,
             subjectNames: item.subjectNames,
             fromChapterLessonCoursewareId: item.fromChapterLessonCoursewareId,
             name: item.name,
             coverImg: firstItem?.bizInfo.coverImg,
-            type: firstItem?.bizInfo.type
+            type: firstItem?.bizInfo.type,
+            isNotWork: item.lessonPreTrainingNum <= 0 ? true : false // 是否布置作业
           });
         });
         forms.tableList = tempList;
@@ -123,54 +135,6 @@ export default defineComponent({
       forms.loading = false;
     };
 
-    const getOpenCoursewareList = async () => {
-      // 查询公开课件列表
-      forms.openLoading = true;
-      try {
-        // 判断是否有选择对应的课件 或声部
-        if (!prepareStore.getSelectKey) return (forms.openLoading = false);
-        const { data } = await api_queryOpenCoursewareByPage({
-          subjectId: prepareStore.getSubjectId,
-          coursewareDetailKnowledgeId: prepareStore.getSelectKey,
-          page: 1,
-          rows: 20
-        });
-        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,
-            subjectNames: item.subjectNames,
-            fromChapterLessonCoursewareId: item.fromChapterLessonCoursewareId,
-            name: item.name,
-            coverImg: firstItem?.bizInfo.coverImg,
-            type: firstItem?.bizInfo.type,
-            isAdd: item.addFlag
-          });
-        });
-
-        forms.openTableList = tempList || [];
-      } catch {
-        //
-      }
-      forms.openLoading = false;
-    };
-
-    // const chunkArray = (array: any, size: number) => {
-    //   const result = [];
-    //   for (let i = 0; i < array.length; i += size) {
-    //     result.push(array.slice(i, i + size));
-    //   }
-    //   return result;
-    // };
-
     // 监听选择的key 左侧选择了其它的课
     watch(
       () => [prepareStore.getSelectKey, prepareStore.getSubjectId],
@@ -284,35 +248,36 @@ export default defineComponent({
         checkSubjectIds();
       }
 
-      // useResizeObserver(
-      //   document.querySelector('#coursewarePresets') as HTMLElement,
-      //   (entries: any) => {
-      //     const entry = entries[0];
-      //     const { width } = entry.contentRect;
-      //     forms.bodyWidth = width + 'px';
-      //   }
-      // );
-
       await getCoursewareList();
-      // await getOpenCoursewareList();
     });
 
-    // 重命名
-    const onEditTitleSubmit = async () => {
-      try {
-        await api_updateCoursewareInfo({
-          id: forms.selectItem.id,
-          name: forms.editTitle
+    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');
         });
-        message.success('修改成功');
-        getCoursewareList();
-        // getOpenCoursewareList()
-        forms.editTitleVisiable = false;
-      } catch {
-        //
       }
     };
 
+    // 重命名
+    // const onEditTitleSubmit = async () => {
+    //   try {
+    //     await api_updateCoursewareInfo({
+    //       id: forms.selectItem.id,
+    //       name: forms.editTitle
+    //     });
+    //     message.success('修改成功');
+    //     getCoursewareList();
+    //     // getOpenCoursewareList()
+    //     forms.editTitleVisiable = false;
+    //   } catch {
+    //     //
+    //   }
+    // };
+
     // 删除
     const onRemove = async () => {
       forms.messageLoading = true;
@@ -430,14 +395,14 @@ export default defineComponent({
       }
     };
 
-    const carouselRef = ref();
-    const onChangeSlide = (type: 'left' | 'right') => {
-      if (type === 'left') {
-        carouselRef.value?.prev();
-      } else if (type === 'right') {
-        carouselRef.value?.next();
-      }
-    };
+    // const carouselRef = ref();
+    // const onChangeSlide = (type: 'left' | 'right') => {
+    //   if (type === 'left') {
+    //     carouselRef.value?.prev();
+    //   } else if (type === 'right') {
+    //     carouselRef.value?.next();
+    //   }
+    // };
     return () => (
       <div
         class={[
@@ -497,10 +462,16 @@ export default defineComponent({
               )
             )}
           </NTabs>
-          <NScrollbar class={styles.coursewarePresets}>
-            <div style={{ overflow: 'hidden' }}>
-              <NSpin show={forms.loading}>
-                <div class={styles.list}>
+          <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}>
@@ -509,11 +480,11 @@ export default defineComponent({
                           isEditName
                           item={item}
                           onClick={() => onPreviewAttend(item.id)}
-                          onEditName={() => {
-                            forms.selectItem = item;
-                            forms.editTitle = item.name;
-                            forms.editTitleVisiable = true;
-                          }}
+                          // onEditName={() => {
+                          //   forms.selectItem = item;
+                          //   forms.editTitle = item.name;
+                          //   forms.editTitleVisiable = true;
+                          // }}
                           onEdit={() => {
                             //
                             eventGlobal.emit('teacher-slideshow', true);
@@ -530,6 +501,14 @@ export default defineComponent({
                             forms.selectItem = item;
                             forms.preRemoveVisiable = true;
                           }}
+                          // 布置作业
+                          onWork={() => {
+                            forms.workVisiable = true;
+                            forms.selectItem = item;
+                            nextTick(() => {
+                              getModalHeight();
+                            });
+                          }}
                         />
                       </div>
                     </div>
@@ -538,24 +517,15 @@ export default defineComponent({
                     <TheEmpty class={styles.empty1} description="暂无课件" />
                   )}
                 </div>
-              </NSpin>
-            </div>
-          </NScrollbar>
+              </div>
+            </NScrollbar>
+          </NSpin>
         </div>
 
-        {/* {forms.openTableList.length > 0 && ( */}
         <div class={styles.presetsRight} id="presetsRightRef">
           <NTooltip showArrow={false}>
             {{
               trigger: () => (
-                // <i
-                //   class={[
-                //     styles.presetsArrar,
-                //     !forms.openTableShow && styles.presetsArrarActive
-                //   ]}
-                //   onClick={() =>
-                //     (forms.openTableShow = !forms.openTableShow)
-                //   }></i>
                 <div
                   class={[
                     styles.presetsArrar,
@@ -608,7 +578,7 @@ export default defineComponent({
           />
         </NModal>
 
-        <NModal
+        {/* <NModal
           v-model:show={forms.editTitleVisiable}
           preset="card"
           class={['modalTitle', styles.removeVisiable1]}
@@ -638,7 +608,7 @@ export default defineComponent({
               </NButton>
             </NSpace>
           </div>
-        </NModal>
+        </NModal> */}
 
         <NModal
           v-model:show={forms.preRemoveVisiable}
@@ -696,6 +666,34 @@ export default defineComponent({
             }}
           />
         </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: '',
+                  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>
     );
   }

+ 11 - 12
src/views/prepare-lessons/components/lesson-main/courseware-presets/select-related/index.tsx

@@ -32,6 +32,7 @@ export default defineComponent({
     });
     const getList = async () => {
       try {
+        if (!prepareStore.getSelectKey) return;
         if (state.pagination.page === 1) {
           state.loading = true;
         }
@@ -66,11 +67,7 @@ export default defineComponent({
         state.loading = false;
         state.tableList.push(...tempList);
         // console.log(result, 'result', data);
-        const pages = !data.total
-          ? 1
-          : Math.ceil(state.pagination.rows / data.total);
-        state.finshed = pages <= data.current ? true : false;
-        // state.finshed = data.pages <= data.current ? true : false;
+        state.finshed = data.pages <= data.current ? true : false;
       } catch {
         state.loading = false;
       }
@@ -84,12 +81,12 @@ export default defineComponent({
     };
 
     // 声部变化时
-    watch(
-      () => prepareStore.getSubjectId,
-      () => {
-        onSearch(state.searchGroup);
-      }
-    );
+    // watch(
+    //   () => prepareStore.getSubjectId,
+    //   () => {
+    //     onSearch(state.searchGroup);
+    //   }
+    // );
 
     const throttledFn = useThrottleFn(() => {
       state.pagination.page = state.pagination.page + 1;
@@ -98,7 +95,9 @@ export default defineComponent({
 
     onMounted(() => {
       getList();
-      // eventGlobal.on('openCoursewareChanged', onSearch);
+      eventGlobal.on('openCoursewareChanged', () =>
+        onSearch(state.searchGroup)
+      );
     });
     return () => (
       <div>

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

@@ -4,6 +4,7 @@ import {
   onMounted,
   onUnmounted,
   reactive,
+  ref,
   watch
 } from 'vue';
 import styles from './addCourseware.module.less';
@@ -50,6 +51,8 @@ import TheMessageDialog from '/src/components/TheMessageDialog';
 import AddItemModel from '../../../model/add-item-model';
 import AddOtherSource from '../../../model/add-other-source';
 import deepClone from '/src/helpers/deep-clone';
+import AddCoursewareProtocol from '../../../model/add-courseware-protocol';
+import { useUserStore } from '/src/store/modules/users';
 export default defineComponent({
   name: 'courseware-modal',
   props: {
@@ -61,6 +64,8 @@ export default defineComponent({
   emits: ['change'],
   setup(props, { emit }) {
     // const catchStore = useCatchStore();
+    const userStore = useUserStore();
+
     const prepareStore = usePrepareStore();
     // const route = useRoute();
     // const router = useRouter();
@@ -116,6 +121,7 @@ export default defineComponent({
       addOtherSource: false,
       addOtherIndex: 0 // 添加其它的索引
     });
+    const showModalMask = ref(false);
 
     // 获取列表
     const getList = async () => {
@@ -377,6 +383,11 @@ export default defineComponent({
           message.error('请至少添加一个资源');
           return;
         }
+
+        if (forms.openFlag && !userStore.getReadCoursewareOpenAgreement) {
+          showModalMask.value = true;
+          return;
+        }
         const resultStatus = await onSaveCourseWare();
 
         if (resultStatus) {
@@ -943,6 +954,24 @@ export default defineComponent({
             }}
           />
         </NModal>
+
+        <NModal v-model:show={showModalMask.value}>
+          <AddCoursewareProtocol
+            onClose={() => (showModalMask.value = false)}
+            onConfirm={async () => {
+              try {
+                const resultStatus = await onSaveCourseWare();
+                if (resultStatus) {
+                  userStore.setReadCoursewareOpenAgreement(true);
+                  emit('change', { status: false });
+                  eventGlobal.emit('teacher-slideshow', false);
+                }
+              } catch {
+                //
+              }
+            }}
+          />
+        </NModal>
       </div>
     );
   }

+ 8 - 1
src/views/prepare-lessons/components/lesson-main/train/assign-homework.tsx

@@ -33,6 +33,11 @@ export default defineComponent({
       type: String,
       default: ''
     },
+    /** 课件编号 */
+    chapterLessonCoursewareId: {
+      type: String,
+      default: ''
+    },
     item: {
       type: Object,
       default: () => ({})
@@ -60,6 +65,7 @@ export default defineComponent({
       uploading: false,
       title: props.item.title,
       courseScheduleId: props.courseScheduleId || null,
+      chapterLessonCoursewareId: props.chapterLessonCoursewareId || null,
       gradeList: [] as any,
       classList: [] as any,
       currentGradeNum: null,
@@ -150,7 +156,8 @@ export default defineComponent({
               ? forms.classGroupId.join(',')
               : null,
             studentIds: null as any,
-            courseScheduleId: forms.courseScheduleId
+            courseScheduleId: forms.courseScheduleId,
+            chapterLessonCoursewareId: forms.chapterLessonCoursewareId // 课件编号
           };
           if (forms.homeworkObj === 'PERSON') {
             params.classGroupId = '';

+ 1 - 1
src/views/prepare-lessons/components/lesson-main/train/index.module.less

@@ -154,7 +154,7 @@
   gap: 20px 2%;
 
   &>div {
-    width: 49% !important;
+    width: 32% !important;
   }
 
   .itemBlock {

+ 59 - 44
src/views/prepare-lessons/components/lesson-main/train/index.tsx

@@ -47,7 +47,7 @@ export default defineComponent({
       default: () => ({})
     },
     cardType: {
-      type: String as PropType<'' | 'homeworkRecord'>,
+      type: String as PropType<'' | 'homeworkRecord' | 'prepare'>,
       default: ''
     },
     /** 编辑编号  - 目前从上传传 */
@@ -68,6 +68,7 @@ export default defineComponent({
   },
   emits: ['change'],
   setup(props, { emit }) {
+    console.log(props.courseScheduleId, 'courseScheduleId');
     const catchStore = useCatchStore();
     const prepareStore = usePrepareStore();
     const dialog = useDialog();
@@ -84,7 +85,6 @@ export default defineComponent({
       editStatus: false,
       editItem: {} as any,
       removeIds: [] as any, // 临时删除的编号
-
       removeVisiable1: false,
       preSaveVisiable: false
     });
@@ -94,13 +94,14 @@ export default defineComponent({
       forms.loadingStatus = true;
       try {
         // 判断是否有选择对应的课件
-        console.log(props.lessonPreTraining, 'props.lessonPreTraining');
+        // console.log(props.lessonPreTraining, 'props.lessonPreTraining');
         if (!props.lessonPreTraining?.id) return (forms.loadingStatus = false);
         const { data } = await lessonPreTrainingV2Detail({
           id: props.lessonPreTraining?.id
         });
         const tempRows = data.lessonPreTrainingDetails || [];
         const temp: any = [];
+        forms.title = data.title;
         tempRows.forEach((row: any) => {
           let tList: string[] = [];
           const configJson = row.trainingConfigJson;
@@ -140,13 +141,6 @@ export default defineComponent({
       forms.loadingStatus = false;
     };
 
-    // // 声部变化时
-    // watch(
-    //   () => prepareStore.getSubjectId,
-    //   () => {
-    //     getList();
-    //   }
-    // );
     // 监听选择的key 左侧选择了其它的课
     watch(
       () => prepareStore.getSelectKey,
@@ -159,7 +153,6 @@ export default defineComponent({
     );
     // 删除
     const onDelete = (item: any) => {
-      //
       forms.removeIds.push(item.id);
       const index = forms.trainList.findIndex((c: any) => c.id === item.id);
       forms.trainList.splice(index, 1);
@@ -203,9 +196,10 @@ export default defineComponent({
           id: props.lessonPreTraining?.id,
           coursewareKnowledgeDetailId:
             props.coursewareKnowledgeDetailId || prepareStore.getSelectKey,
-          lessonPreTrainingDetails
+          lessonPreTrainingDetails,
+          chapterLessonCoursewareId: props.lessonPreTraining?.chapterId
         });
-        message.success('保存预设成功');
+        message.success('保存成功');
         prepareStore.setIsEditTrain(false);
         forms.removeIds = [];
         // getList();
@@ -261,7 +255,7 @@ export default defineComponent({
                 // forms.drag = false;
                 prepareStore.setIsEditTrain(false);
                 forms.removeIds = [];
-                prepareStore.setTrainList([]);
+                // prepareStore.setTrainList([]);
                 // getList();
                 emit('change', { status: false });
               }}>
@@ -273,6 +267,10 @@ export default defineComponent({
                 type="primary"
                 disabled={forms.trainList.length <= 0}
                 onClick={() => {
+                  if (!forms.title) {
+                    message.error('请输入标题');
+                    return;
+                  }
                   let count = 0;
                   forms.trainList.forEach((item: any) => {
                     if (!item.removeFlag) {
@@ -292,11 +290,26 @@ export default defineComponent({
                 type="default"
                 disabled={forms.trainList.length <= 0}
                 onClick={() => {
+                  if (!forms.title) {
+                    message.error('请输入标题');
+                    return;
+                  }
+                  let count = 0;
+                  forms.trainList.forEach((item: any) => {
+                    if (!item.removeFlag) {
+                      count++;
+                    }
+                  });
+                  if (count <= 0) {
+                    message.error('作业内容不能为空');
+                    return;
+                  }
+
                   forms.preSaveVisiable = true;
                 }}
                 // loading={forms.preBtnLoading}
               >
-                保存预设
+                保存
               </NButton>
             )}
           </NSpace>
@@ -415,34 +428,35 @@ export default defineComponent({
           </NSpin>
         </NScrollbar>
 
-        {props.cardType !== 'homeworkRecord' && (
-          <div
-            class={[styles.btnGroup, styles.btnGroupClass]}
-            style={{ justifyContent: 'flex-end' }}>
-            <NSpace justify="end">
-              <NButton
-                type="primary"
-                // {...{ id: 'train-0' }}
-                // disabled={forms.drag}
-                disabled={forms.trainList.length <= 0}
-                onClick={() => {
-                  let count = 0;
-                  forms.trainList.forEach((item: any) => {
-                    if (!item.removeFlag) {
-                      count++;
+        {props.cardType !== 'homeworkRecord' &&
+          props.cardType !== 'prepare' && (
+            <div
+              class={[styles.btnGroup, styles.btnGroupClass]}
+              style={{ justifyContent: 'flex-end' }}>
+              <NSpace justify="end">
+                <NButton
+                  type="primary"
+                  // {...{ id: 'train-0' }}
+                  // disabled={forms.drag}
+                  disabled={forms.trainList.length <= 0}
+                  onClick={() => {
+                    let count = 0;
+                    forms.trainList.forEach((item: any) => {
+                      if (!item.removeFlag) {
+                        count++;
+                      }
+                    });
+                    if (count <= 0) {
+                      message.error('作业内容不能为空');
+                      return;
                     }
-                  });
-                  if (count <= 0) {
-                    message.error('作业内容不能为空');
-                    return;
-                  }
-                  forms.assignHomeworkStatus = true;
-                }}>
-                立即布置
-              </NButton>
-            </NSpace>
-          </div>
-        )}
+                    forms.assignHomeworkStatus = true;
+                  }}>
+                  立即布置
+                </NButton>
+              </NSpace>
+            </div>
+          )}
 
         {/* 编辑 */}
         <NModal
@@ -491,6 +505,7 @@ export default defineComponent({
           <AssignHomework
             classGroupId={props.classGroupId}
             courseScheduleId={props.courseScheduleId}
+            chapterLessonCoursewareId={props.lessonPreTraining.chapterId}
             item={{
               title: forms.title,
               lessonPreTrainingDetails: forms.trainList
@@ -545,10 +560,10 @@ export default defineComponent({
           v-model:show={forms.preSaveVisiable}
           preset="card"
           class={['modalTitle', styles.removeVisiable1]}
-          title={'保存预设'}>
+          title={'保存'}>
           <TheMessageDialog
             content="是否保存当前页面编辑内容?"
-            cancelButtonText="不保存"
+            cancelButtonText="取消"
             confirmButtonText="保存"
             onClose={() => (forms.preSaveVisiable = false)}
             onConfirm={() => onPreSave()}

+ 5 - 2
src/views/prepare-lessons/components/resource-main/components/select-music/index.tsx

@@ -55,7 +55,7 @@ export default defineComponent({
     },
     /** 类型 */
     cardType: {
-      type: String as PropType<'' | 'homerowk-record'>,
+      type: String as PropType<'' | 'homerowk-record' | 'prepare'>,
       default: ''
     }
   },
@@ -85,7 +85,10 @@ export default defineComponent({
     });
     const getList = async () => {
       try {
-        if (!prepareStore.getSubjectId && props.cardType !== 'homerowk-record')
+        if (
+          !prepareStore.getSubjectId &&
+          !['homerowk-record', 'prepare'].includes(props.cardType)
+        )
           return;
         if (state.pagination.page === 1) {
           state.loading = true;

+ 2 - 2
src/views/prepare-lessons/components/resource-main/index.tsx

@@ -22,7 +22,7 @@ export default defineComponent({
   props: {
     /** 类型 */
     cardType: {
-      type: String as PropType<'' | 'homerowk-record'>,
+      type: String as PropType<'' | 'homerowk-record' | 'prepare'>,
       default: ''
     }
   },
@@ -92,7 +92,7 @@ export default defineComponent({
             : ''
         ]}>
         {prepareStore.getTabType === 'courseware' &&
-        props.cardType !== 'homerowk-record' ? (
+        !['homerowk-record', 'prepare'].includes(props.cardType) ? (
           <NTabs
             ref={tabRef}
             animated

二進制
src/views/prepare-lessons/images/addSource/icon8.png


二進制
src/views/prepare-lessons/images/protocol/check-active.png


二進制
src/views/prepare-lessons/images/protocol/check-default.png


二進制
src/views/prepare-lessons/images/protocol/closeAble.png


二進制
src/views/prepare-lessons/images/protocol/dingPng.png


二進制
src/views/prepare-lessons/images/protocol/moveTop.png


+ 174 - 0
src/views/prepare-lessons/model/add-courseware-protocol/index.module.less

@@ -0,0 +1,174 @@
+.protocolModal {
+  position: relative;
+
+  .dingPng {
+    width: 162px;
+    height: 98px;
+    position: absolute;
+    left: 50%;
+    margin-left: -81px;
+    top: -49px;
+    z-index: 100;
+  }
+}
+
+.downMove {
+  width: 413px;
+  // height: 309px;
+  background: #FFFFFF;
+  border-radius: 16px;
+  position: relative;
+  padding: 0 30px 35px;
+  overflow: hidden;
+
+  .downMoveBg {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 413px;
+    height: 101px;
+  }
+
+
+
+  .closeAble {
+    cursor: pointer;
+    width: 25px;
+    height: 25px;
+    position: absolute;
+    top: 18px;
+    right: 20px;
+  }
+
+  h2 {
+    font-size: 24px;
+    font-family: PingFangSC-Semibold, PingFang SC;
+    font-weight: 600;
+    color: #131415;
+    line-height: 33px;
+    text-align: center;
+    padding-top: 64px;
+    padding-bottom: 15px;
+  }
+
+  p {
+    font-size: 18px;
+    font-family: PingFangSC-Regular, PingFang SC;
+    font-weight: 400;
+    color: #777777;
+    line-height: 30px;
+  }
+
+  .submitAppBtn,
+  .cancelBtn {
+    min-width: 130px;
+    height: 42px;
+    line-height: 42px;
+    border-radius: 24px;
+    border: none;
+  }
+
+  .submitAppBtn {
+    background: linear-gradient(305deg, #40C8FF 0%, #3192FF 100%)
+  }
+}
+
+.protocolGroup {
+  padding-top: 17px;
+  display: flex;
+  align-items: flex-start;
+  font-size: 13px;
+  color: #333333;
+  line-height: 20px;
+  cursor: pointer;
+
+  .checkbox {
+    margin-top: 6px;
+    margin-right: 5px;
+    width: 14Px;
+    height: 14Px;
+    display: inline-block;
+    background: url('../../images/protocol/check-default.png') no-repeat center;
+    background-size: contain;
+  }
+
+  .checkboxActive {
+    background: url('../../images/protocol/check-active.png') no-repeat center;
+    background-size: contain;
+  }
+
+  span {
+    color: #1677FF;
+  }
+}
+
+.protocolSection {
+  width: 610px;
+  background: #FFFFFF;
+  border-radius: 16px;
+  position: relative;
+  padding: 0 30px 35px;
+  overflow: hidden;
+
+  .downMoveBg {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 101px;
+  }
+
+
+
+  .closeAble {
+    cursor: pointer;
+    width: 25px;
+    height: 25px;
+    position: absolute;
+    top: 18px;
+    right: 20px;
+  }
+
+  h2 {
+    font-size: 24px;
+    font-family: PingFangSC-Semibold, PingFang SC;
+    font-weight: 600;
+    color: #131415;
+    line-height: 33px;
+    text-align: center;
+    padding-top: 64px;
+    padding-bottom: 15px;
+  }
+
+  .protocolContent {
+    font-size: max(18px, 14Px);
+    line-height: 30px;
+    color: #777;
+    text-align: justify;
+
+    p {
+      font-weight: 600;
+      color: #333333;
+      padding-top: 20px;
+    }
+
+    .child {
+      padding-left: 20px;
+    }
+  }
+
+
+
+  .submitAppBtn,
+  .cancelBtn {
+    min-width: 150px;
+    height: 45px;
+    line-height: 45px;
+    border-radius: 24px;
+    border: none;
+  }
+
+  .submitAppBtn {
+    background: linear-gradient(305deg, #40C8FF 0%, #3192FF 100%)
+  }
+}

+ 230 - 0
src/views/prepare-lessons/model/add-courseware-protocol/index.tsx

@@ -0,0 +1,230 @@
+import { defineComponent, reactive } from 'vue';
+import styles from './index.module.less';
+import dingPng from '../../images/protocol/dingPng.png';
+import moveTop from '../../images/protocol/moveTop.png';
+import closeAble from '../../images/protocol/closeAble.png';
+import { NSpace, NButton, NScrollbar } from 'naive-ui';
+
+export default defineComponent({
+  name: 'add-courseware-protocol',
+  emits: ['close', 'confirm'],
+  setup(props, { emit }) {
+    const forms = reactive({
+      status: false,
+      protocolShow: false // 是否显示协议
+    });
+    return () => (
+      <div class={styles.protocolModal}>
+        <img src={dingPng} class={styles.dingPng} alt="" />
+        {!forms.protocolShow ? (
+          <div class={styles.downMove}>
+            <img src={moveTop} class={styles.downMoveBg} alt="" />
+            <img
+              src={closeAble}
+              class={styles.closeAble}
+              onClick={() => {
+                // showModalMask.value = false;
+                // checkAuthShow();
+                emit('close');
+              }}
+              alt=""
+            />
+            <h2>课件公开须知</h2>
+            <p>
+              公开课件后,您课件中的资源及作业都可被其他教师查看、使用,具体信息请查看服务协议
+            </p>
+
+            <div
+              class={styles.protocolGroup}
+              onClick={() => {
+                forms.status = !forms.status;
+              }}>
+              <i
+                class={[
+                  styles.checkbox,
+                  forms.status && styles.checkboxActive
+                ]}></i>
+              <p>
+                我已阅读并同意
+                <span
+                  onClick={(e: any) => {
+                    e.stopPropagation();
+                    forms.protocolShow = true;
+                  }}>
+                  《音乐数字课堂课件与作业公开服务协议》
+                </span>
+              </p>
+            </div>
+
+            <NSpace style={{ padding: '25px 0 0 0' }} justify="center">
+              <NButton class={styles.cancelBtn} round type="default">
+                取消
+              </NButton>
+              <NButton
+                class={styles.submitAppBtn}
+                bordered={false}
+                round
+                type="primary"
+                disabled={!forms.status}
+                onClick={() => {
+                  emit('confirm');
+                }}>
+                确定
+              </NButton>
+            </NSpace>
+          </div>
+        ) : (
+          <div class={styles.protocolSection}>
+            <img src={moveTop} class={styles.downMoveBg} alt="" />
+            <img
+              src={closeAble}
+              class={styles.closeAble}
+              onClick={() => {
+                // showModalMask.value = false;
+                // checkAuthShow();
+                emit('close');
+              }}
+              alt=""
+            />
+            <h2>《音乐数字课堂课件与作业公开服务协议》</h2>
+
+            <NScrollbar style={{ maxHeight: '45vh' }}>
+              <div class={styles.protocolContent}>
+                <p style={{ paddingTop: '0' }}>欢迎使用音乐数字课堂!</p>
+                <p>重要须知</p>
+                武汉酷乐秀网络科技有限公司(以下统称“平台方”,或称“我们”),在此特别提醒,为使用音乐数字课堂(包括手机端、网页端等,以下称“软件”或“平台”)与相关信息化教育产品、内容及服务,您务必仔细阅读、充分理解并遵守《音乐数字课堂课件与作业公开服务协议》(以下简称“本协议”)中各项条款,包括免除或者限制责任的条款,并选择接受或不接受。本协议所述服务条款构成您(个人或者单位、组织、团体等)使用平台方提供的相关服务(以下简称“该服务”)的先决条件。若您不接受本协议中所述服务条款或其后对协议条款的修改,您应不使用或主动取消平台方提供的相关服务。
+                您自愿使用平台方提供的网络存储空间进行培训课件与作业及相关智力成果的上传及传播服务。如果您未满18周岁,请在法定监护人的陪同下阅读本协议。
+                <br />
+                本协议是您(或称“用户”,指注册、登录、使用、浏览本服务的个人或组织)与平台方之间关于音乐数字课堂与相关信息化教育产品、内容及服务所订立的协议。
+                <br />
+                <p>1 权利声明</p>
+                音乐数字课堂由武汉酷乐秀网络科技有限公司(以下简称“酷乐秀”)独立开发,一切知识产权以及音乐数字课堂自有的所有信息内容包括但不限于:文字表述及其组合、图标、图饰、图像、图表、色彩、界面设计、版面框架、有关数据、附加程序、印刷材料或电子文档等均为酷乐秀所有,受著作权法和国际著作权条约以及其他知识产权法律法规的保护。
+                <br />
+                音乐数字课堂由武汉酷乐秀网络科技有限公司(以下简称“音乐数字课堂”)提供运营管理服务。
+                <br />
+                <p>2 服务说明 </p>
+                2.1
+                您可以通过音乐数字课堂主页【网址:https://kt.colexiu.com/classroom-admin/#/login】、手机客户端(及其他由音乐数字课堂运营的任何网站)、音乐数字课堂公众号,访问音乐数字课堂并使用相关服务。
+                <br />
+                2.2
+                您知悉并同意,在注册成为音乐数字课堂用户或使用本服务时,需提供一些必要信息,包括但不限于手机号码、头像等。若国家法律法规或政策有特殊规定的,平台方会根据相关特殊规定要求您提供相关信息,如真实的身份信息等,若您提供的信息不完整,您将无法使用本服务或本服务中的相关功能,由此为您带来不便或损失的,平台方完全免责。如个人信息发生变更,您有权随时与平台方联系并要求修改相关个人信息。在您向平台方提出前述删除请求前,平台方可在本协议约定范围内合理利用相关个人信息。
+                <br />
+                您应承诺合法使用平台方提供的服务,您使用该服务的行为应符合当地的法律法规及政策的要求,否则由此带来的责任由您自行承担。
+                <br />
+                <p>3 权利授予 </p>
+                3.1
+                您理解并同意,您将课件与作业及相关智力成果上传至音乐数字课堂,即视为您授予了平台方无期限限制的、全球范围内的、不可撤销的信息网络传播权和其他形式的使用权。为了更好地对课件与作业进行宣传和推广,平台方可以将上述权利转让或者转授予给其关联公司或者合作伙伴,而无须征得您的同意。您如果不同意上述条款,请不要将作品上传至音乐数字课堂。
+                <br />
+                3.2平台方仅对您提交的资料和信息进行审核,并不对您的主体资质和上传的课件与作业内容的真实性、正确性、合法性承担任何责任或提供任何担保。
+                <br />
+                3.3
+                如果任何第三方侵犯音乐数字课堂用户相关的权利,用户同意授权平台方或其指定的代理人代表平台方自身或用户对该第三方提出警告、投诉、发起行政执法、诉讼、进行上诉,或谈判和解,并且用户同意在平台方认为必要的情况下参与共同维权。
+                <br />
+                <p>4 权利限制 </p>
+                4.1
+                平台方通过音乐数字课堂所提供的服务,均限于在音乐数字课堂平台内使用,禁止任何以恶意破解等非法手段将音乐数字课堂内的服务与音乐数字课堂平台分离的行为,否则,由此引起的一切后果由行为人负责,平台方将保留依法追究行为人法律责任的权利。
+                <br />
+                4.2未经平台方书面同意,您不得将已上传至音乐数字课堂平台上的培训课件与作业的任何资料文件直接、间接或经修改后提供给任何第三方。
+                <br />
+                4.3
+                保留权利:本协议未明示许可的其他一切权利仍归平台方所有,您使用其他权利时必须获得平台方的书面同意。
+                <br />
+                4.4
+                除本协议有明确规定外,本协议并未对平台方其他服务规定相关的服务条款,对于这些服务可能有单独的服务条款加以规范,请您在使用有关服务时另行了解与确认。如您使用该服务,视为对相关服务条款的接受。
+                <br />
+                <p>5 用户使用须知</p>
+                5.1您承诺您具有履行本协议义务的权利能力及资格,因您自身职务或职业要求导致本协议无法履行或合同目的无法实现的,您应当及时通知平台方,并共同协商解决办法,以保证将事件影响性降到最低。
+                <br />
+                5.2您保证,您上传的课件与作业所涉的创意、脚本、资料、课件与作业等全部文件资料不违反国家相关法律法规、不侵犯第三方权益,且平台方按照约定行使授权内容的相关权利不会侵犯任何第三方的合法权益,也无须另行取得任何第三方的同意,更无须对任何第三方承担责任。如您违反前述保证,平台方有权采取包括但不限于删除相关课件与作业内容、中止或终止向您提供服务等措施。如您上传的课件与作业侵犯了第三方的合法权利,第三方向平台方提出举报,平台方有权删除相关的内容。当权利人发现音乐数字课堂上相关课件与作业侵犯其合法权益时,权利人可向平台方举报,平台方将根据中国法律法规和规范性文件的规定采取移除相关内容等合理措施。
+                <br />
+                5.3您保证上传的课件与作业中不含以下内容:
+                <br />
+                <div class={styles.child}>
+                  1.反对宪法所确定的基本原则;
+                  <br />
+                  2.危害国家安全,泄漏国家秘密,颠覆国家政权,破坏国家统一;
+                  <br />
+                  3.损害国家荣誉和利益; <br />
+                  4.煽动民族仇恨、民族歧视,破坏民族团结;
+                  <br />
+                  5.破坏国家宗教政策,宣扬邪教和封建迷信;
+                  <br />
+                  6.散布谣言,扰乱社会秩序,破坏社会稳定;
+                  <br />
+                  7.散布淫秽、色情、赌博、暴力、凶杀、恐怖或教唆犯罪;
+                  <br />
+                  8.侮辱或者诽谤他人,侵害他人合法权益;
+                  <br />
+                  9.含有法律、行政法规严令禁止的其他内容。
+                  <br />
+                </div>
+                5.4上述承诺与保证不受本协议期限的限制,您违反上述任一的保证与承诺的,平台方有权即时解除本协议并要求您承担由此产生的全部责任。
+                <br />
+                <p>6 隐私政策 </p>
+                6.1 目的
+                为改善平台方服务,提升用户体验,在您使用音乐数字课堂时,平台方可能对您使用音乐数字课堂的使用信息进行统计与分析,例如:平台方会根据您上传并通过审核的某单元的课件与作业数量显示您在该单元全国范围内的排名,同时显示您的头像、昵称信息及通过审核的课件与作业数量。平台方将采取必要的保护措施,以保护您的相关信息。您可以选择不提供或只提供部分信息,但平台方可能将无法为您提供完整的产品功能或服务。
+                <p>7 免责与责任限制</p>
+                7.1
+                音乐数字课堂不含有任何旨在破坏您计算机数据和获取您隐私信息的恶意代码。音乐数字课堂经过详细的测试,但不能保证与所有的软硬件系统完全兼容,不能保证音乐数字课堂完全没有错误。如果出现不兼容及软件错误的情况,您可拨打技术支持电话将情况报告平台方,以获得技术支持。如果无法解决兼容性问题,您可以删除音乐数字课堂。由此给您造成损失的,您同意平台方免责。
+                <br />
+                7.2
+                在适用法律允许的最大范围内,对因使用或不能使用音乐数字课堂所产生的损害及风险,包括但不限于直接或间接的个人损害、商业赢利的丧失、贸易中断、商业信息的丢失或任何其它经济损失,平台方不承担任何责任。
+                <br />
+                7.3
+                对于因电信系统或互联网网络故障、计算机故障或病毒、信息损坏或丢失、计算机系统问题或其它任何不可抗力原因而产生损失,平台方不承担任何责任。
+                <br />
+                7.4您知悉并同意,为实现部分软件功能,平台方有权将您在使用该服务过程当中产生的部分或全部数据信息,上传、保存至第三方云服务存储器,并根据您发出的功能指令需求,自行调取相关数据信息。因第三方云服务发生中断等功能障碍事故导致平台方无法正常提供服务的,平台方会尽其商业上的合理努力负责协调解决,但由此给您造成损失的,您同意平台方免责。
+                <br />
+                7.5
+                您违反本协议规定,对平台方造成损害的。平台方有权采取包括但不限于中断使用许可、停止提供服务、限制使用、法律追究等措施。
+                <br />
+                <p>8 法律及争议解决</p>
+                8.1 本协议适用中华人民共和国法律。
+                <br /> 8.2
+                因本协议引起的或与本协议有关的任何争议,各方应友好协商解决;协商不成的,任何一方均可将有关争议提交至平台方所在地有管辖权的人民法院管辖。
+                <br />
+                <p>9 其他条款</p>
+                9.1
+                如果本协议中的任何条款无论因何种原因完全或部分无效或不具有执行力,或违反任何适用的法律,则该条款被视为删除,但本协议的其余条款仍有效并且具有约束力。
+                <br />
+                9.2
+                如果本协议中的任何条款与音乐数字课堂中某具体软件的协议条款相矛盾的,以该具体软件的协议条款为准。
+                <br />
+                平台方有权随时根据有关法律、法规的变化以及公司经营状况和经营策略的调整等修改本协议。修改后的协议会在平台方指定网站上公布,并随附于新版音乐数字课堂。当发生有关争议时,以最新的协议文本为准。如果不同意改动的内容,您可以自行删除音乐数字课堂。如果您继续使用音乐数字课堂,则视为您接受本协议的变动。
+                <br />
+                至此,用户已经详细阅读并已理解本协议,并同意严格遵守各条款和条件。如果用户对本《协议》有任何疑问或者希望获得与本软件相关的任何信息,请按下列地址和方式与酷乐秀联系,酷乐秀将在15日内答复用户。
+                <br />
+                技术支持方:武汉酷乐秀网络科技有限公司
+                <br />
+                运营方:武汉酷乐秀网络科技有限公司
+              </div>
+            </NScrollbar>
+
+            <NSpace style={{ padding: '25px 0 0 0' }} justify="center">
+              <NButton
+                class={styles.cancelBtn}
+                round
+                type="default"
+                onClick={() => {
+                  forms.protocolShow = false;
+                }}>
+                取消授权
+              </NButton>
+              <NButton
+                class={styles.submitAppBtn}
+                bordered={false}
+                round
+                type="primary"
+                onClick={() => {
+                  forms.protocolShow = false;
+                  forms.status = true;
+                }}>
+                同意授权
+              </NButton>
+            </NSpace>
+          </div>
+        )}
+      </div>
+    );
+  }
+});

+ 20 - 0
src/views/prepare-lessons/model/add-other-source/index.module.less

@@ -70,4 +70,24 @@
 
 .subjectSyncModal {
   width: 1070px;
+}
+
+.attendClassModal {
+  width: 1100px;
+
+  :global {
+    .n-select-menu {
+      --n-height: calc(var(--n-option-height) * 5.6) !important;
+    }
+  }
+}
+
+.attendClassSaveModal {
+  width: 600px;
+
+  :global {
+    .n-select-menu {
+      --n-height: calc(var(--n-option-height) * 5.6) !important;
+    }
+  }
 }

+ 104 - 1
src/views/prepare-lessons/model/add-other-source/index.tsx

@@ -8,6 +8,7 @@ import icon4 from '../../images/addSource/icon4.png';
 import icon5 from '../../images/addSource/icon5.png';
 import icon6 from '../../images/addSource/icon6.png';
 import icon7 from '../../images/addSource/icon7.png';
+import icon8 from '../../images/addSource/icon8.png';
 import { useRouter } from 'vue-router';
 import SourceRhythm from '../source-rhythm';
 import SourceInstrument from '../source-instrument';
@@ -17,6 +18,10 @@ import SourceMusic from '../source-music';
 import { eventGlobal } from '/src/utils';
 import SubjectSync from '../subject-sync';
 import { usePrepareStore } from '/src/store/modules/prepareLessons';
+import UploadModal, {
+  formatUrlType
+} from '/src/views/natural-resources/components/my-resources/upload-modal';
+import SaveModal from '/src/views/natural-resources/components/my-resources/save-modal';
 
 export default defineComponent({
   name: 'add-other-source',
@@ -26,6 +31,11 @@ export default defineComponent({
     const router = useRouter();
     const sourceList = ref([
       {
+        image: icon8,
+        name: '上传资源',
+        index: 7
+      },
+      {
         image: icon1,
         name: '听音练习',
         index: 0
@@ -55,6 +65,7 @@ export default defineComponent({
         name: '乐理知识',
         index: 5
       }
+
       // {
       //   image: icon7,
       //   name: '制作曲谱',
@@ -67,8 +78,16 @@ export default defineComponent({
       theoryStatus: false, //
       musicStatus: false, //
       instrumentStatus: false, //
-      musicianStatus: false //
+      musicianStatus: false, //
+
+      uploadStatus: false,
+      saveStatus: false,
+      editStatus: false, // 是否编辑
+      editList: [] as any, // TOD
+      editIds: [] as any, // 编辑的
+      editOverIds: [] as any // 确认修改的数据
     });
+
     // LISTEN:听音,RHYTHM:节奏,THEORY:乐理知识,MUSIC_WIKI:曲目 INSTRUMENT:乐器 MUSICIAN:音乐家)
 
     const onDetail = (item: any) => {
@@ -98,6 +117,14 @@ export default defineComponent({
             router.push('/notation');
           });
           break;
+        case 7:
+          // eventGlobal.emit('pageBeforeLeave', () => {
+          //   // 直接跳转到制谱页面 (临时存储数据)
+          //   sessionStorage.setItem('notation-open-create', '1');
+          //   router.push('/notation');
+          // });
+          state.saveStatus = true;
+          break;
         default:
           break;
       }
@@ -304,6 +331,82 @@ export default defineComponent({
             }}
           />
         </NModal>
+
+        <NModal
+          v-model:show={state.uploadStatus}
+          preset="card"
+          showIcon={false}
+          class={['modalTitle background', styles.attendClassModal]}
+          title={state.editStatus ? '修改资源' : '上传资源'}
+          blockScroll={false}>
+          <UploadModal
+            editStatus={state.editStatus}
+            onClose={() => {
+              state.uploadStatus = false;
+            }}
+            onConfirm={(item: any) => {
+              state.editIds = [];
+              state.editList = [];
+              state.editOverIds = [];
+              state.saveStatus = false;
+
+              try {
+                state.musicStatus = false;
+                const value = item || [];
+                const temp: any[] = [];
+                value.forEach((item: any) => {
+                  temp.push({
+                    materialId: item.id,
+                    coverImg: item.coverImg,
+                    dataJson: null,
+                    title: item.name,
+                    isCollect: false,
+                    isSelected: false,
+                    content: item.content,
+                    type: item.type
+                  });
+                });
+                // state.listenStatus = false;
+                emit('comfirm', temp);
+                emit('close');
+              } catch {
+                //
+              }
+            }}
+            list={state.editList}
+          />
+        </NModal>
+
+        <NModal
+          v-model:show={state.saveStatus}
+          preset="card"
+          showIcon={false}
+          class={['modalTitle background', styles.attendClassSaveModal]}
+          title={'上传资源'}
+          blockScroll={false}>
+          <SaveModal
+            onClose={() => (state.saveStatus = false)}
+            onConfrim={(val: any) => {
+              const list = val || [];
+              const temp: any = [];
+              list.forEach((item: any) => {
+                temp.push({
+                  subjectIds: null,
+                  openFlag: false,
+                  coverImg: item.coverImg,
+                  title: item.name || '',
+                  type: formatUrlType(item.content),
+                  enableFlag: 1,
+                  content: item.content,
+                  id: null
+                });
+              });
+              state.editList = temp;
+              state.uploadStatus = true;
+              state.editStatus = false;
+            }}
+          />
+        </NModal>
       </>
     );
   }

+ 103 - 13
src/views/prepare-lessons/model/courseware-type/index.module.less

@@ -61,6 +61,58 @@
     overflow: hidden;
     background-color: #fff;
     border: 1px solid #EFF0F2;
+    transition: all .2s ease;
+
+    &:hover {
+      :global {
+        .n-image {
+          transform: scale(1.05);
+          transition: all 0.2s ease;
+          // &:hover {
+          // }
+        }
+      }
+
+      .defaultLook {
+        opacity: 1;
+        visibility: visible;
+      }
+    }
+
+    .defaultLook {
+      position: absolute;
+      opacity: 0;
+      visibility: hidden;
+      inset: 0;
+      background-color: rgba(0, 0, 0, 0.3);
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      cursor: pointer;
+      transition: all 0.2s ease;
+
+      &::before {
+        display: inline-block;
+        content: '';
+        width: 25px;
+        height: 25px;
+        background: url('../../images/icon-look.png') no-repeat center;
+        background-size: contain;
+      }
+    }
+
+    // 布置作业
+    &.isShowAdd:hover {
+      .defaultLook {
+        display: none;
+      }
+
+      .function {
+        opacity: 1;
+        visibility: visible;
+        transition: all .2s ease;
+      }
+    }
 
     .iconNoWork {
       position: absolute;
@@ -90,19 +142,7 @@
       .n-image {
         width: 100%;
         height: 100%;
-        transition: all .2s ease;
-
-        &:hover {
-          transform: scale(1.05);
-          transition: all 0.2s ease;
-
-          // &::after {
-          //   content: '';
-          //   position: absolute;
-          //   inset: 0;
-          //   background-color: rgba(0, 0, 0, 0.3);
-          // }
-        }
+        transition: all 0.2s ease;
       }
     }
 
@@ -398,4 +438,54 @@
       padding: 9px 7px !important;
     }
   }
+}
+
+.function {
+  position: absolute;
+  inset: 0;
+  background: rgba(0, 0, 0, .3);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  opacity: 0;
+  visibility: hidden;
+  transition: opacity 0.2s ease;
+
+  .iconLook,
+  .iconAdd {
+    cursor: pointer;
+    width: 38px;
+    height: 38px;
+    border-radius: 50%;
+    background: rgba(0, 0, 0, .4);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin: 0 16px;
+
+  }
+
+  .iconLook {
+    &::before {
+      display: inline-block;
+      content: '';
+      width: 25px;
+      height: 25px;
+      background: url('../../images/icon-look.png') no-repeat center;
+      background-size: contain;
+    }
+  }
+
+
+  .iconAdd {
+    &::before {
+      display: inline-block;
+      content: '';
+      width: 18px;
+      height: 18px;
+      background: url('../../images/icon-add.png') no-repeat center;
+      background-size: contain;
+    }
+  }
+
 }

+ 48 - 20
src/views/prepare-lessons/model/courseware-type/index.tsx

@@ -43,7 +43,16 @@ export default defineComponent({
     }
   },
   /** add */
-  emits: ['add', 'editName', 'edit', 'delete', 'startClass', 'click'],
+  emits: [
+    'add',
+    'editName',
+    'edit',
+    'delete',
+    'startClass',
+    'click',
+    'work',
+    'look'
+  ],
   setup(props, { emit }) {
     return () => (
       <div
@@ -53,27 +62,20 @@ export default defineComponent({
             ? styles.coursewareTypeHover
             : styles.coursewareTypeHocoursewareTypeShow
         ]}>
-        {/* {props.isShowAdd && (
-          <NButton
-            type="primary"
-            class={[styles.addBtn]}
-            disabled={props.item.isAdd ? true : false}
-            onClick={(e: MouseEvent) => {
-              e.stopPropagation();
-              e.preventDefault();
-              emit('add');
-            }}>
-            {props.item.isAdd ? '已添加' : '添加'}
-          </NButton>
-        )} */}
         <div
-          class={[styles.cover, props.isShowPreviewBtn && styles.hideP]}
+          class={[
+            styles.cover,
+            props.isShowPreviewBtn && styles.hideP,
+            props.isShowAdd && styles.isShowAdd
+          ]}
           onClick={() => emit('click')}>
           {props.item.openFlag && props.isShowOpenFlag && (
             <span class={styles.status}>公开</span>
           )}
           <NImage objectFit="cover" previewDisabled src={props.item.coverImg} />
 
+          <i class={styles.defaultLook}></i>
+
           {props.isShowPreviewBtn && (
             <div class={styles.preview}>
               <NButton strong secondary class={styles.previewBtn}>
@@ -82,15 +84,37 @@ export default defineComponent({
             </div>
           )}
 
-          <i class={styles.iconNoWork}></i>
+          {/* 是否布置作业 */}
+          {props.item.isNotWork && <i class={styles.iconNoWork}></i>}
+          {/* 是否有添加逻辑 */}
+          {props.isShowAdd && (
+            <div class={styles.function}>
+              <NTooltip showArrow={false}>
+                {{
+                  trigger: () => (
+                    <i class={styles.iconLook} onClick={() => emit('look')}></i>
+                  ),
+                  default: () => '预览课件'
+                }}
+              </NTooltip>
+              <NTooltip showArrow={false}>
+                {{
+                  trigger: () => (
+                    <i class={styles.iconAdd} onClick={() => emit('add')}></i>
+                  ),
+                  default: () => '添加到我的课件'
+                }}
+              </NTooltip>
+            </div>
+          )}
         </div>
         <div class={styles.operationBottom}>
           <div class={styles.coursewareText}>
-            <div class={[styles.name, props.isEditName && styles.editName]}>
+            <div class={[styles.name]}>
               <span>{props.item.name}</span>
-              <i
+              {/* , props.isEditName && styles.editName <i
                 class={styles.iconEditName}
-                onClick={() => emit('editName')}></i>
+                onClick={() => emit('editName')}></i> */}
             </div>
             <div class={styles.subjectName}>{props.item.subjectNames}</div>
           </div>
@@ -104,7 +128,11 @@ export default defineComponent({
               </div>
 
               <NSpace>
-                <div class={[styles.actionClass, styles.actionWork]}>作业</div>
+                <div
+                  class={[styles.actionClass, styles.actionWork]}
+                  onClick={() => emit('work')}>
+                  作业
+                </div>
                 <NPopover trigger="hover" showArrow={false} to={false}>
                   {{
                     trigger: () => <div class={[styles.menu]}></div>,

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

@@ -69,17 +69,15 @@ export default defineComponent({
             name: item.name,
             coverImg: firstItem?.bizInfo.coverImg,
             type: firstItem?.bizInfo.type,
-            isAdd: item.addFlag
+            isAdd: item.addFlag,
+            isNotWork: item.lessonPreTrainingNum <= 0 ? true : false // 是否布置作业
           });
         });
 
         forms.loading = false;
         forms.tableList.push(...tempList);
 
-        const pages = !data.total
-          ? 1
-          : Math.ceil(forms.pagination.rows / data.total);
-        forms.finshed = pages <= data.current ? true : false;
+        forms.finshed = data.pages <= data.current ? true : false;
       } catch {
         forms.loading = false;
       }
@@ -185,7 +183,7 @@ export default defineComponent({
                           onAdd={() => {
                             emit('add', item);
                           }}
-                          onClick={() => emit('click', item)}
+                          onLook={() => emit('click', item)}
                         />
                       </div>
                     </div>