Browse Source

Merge branch 'startLogin'

mo 1 year ago
parent
commit
a087aeddcd

+ 53 - 15
src/views/attend-class/model/train-type/index.module.less

@@ -1,7 +1,7 @@
 .trainType {
   display: inline-block;
   width: 462px;
-  background: #ECF6FF;
+  background: #ecf6ff;
   border-radius: 16px;
   padding: 20px;
   position: relative;
@@ -45,10 +45,10 @@
   .btn {
     padding: 0 12px;
     height: 32px;
-    background: linear-gradient(270deg, #23C3FF 0%, #007AFE 100%);
+    background: linear-gradient(270deg, #23c3ff 0%, #007afe 100%);
     font-size: 16px;
     font-weight: 600;
-    color: #FFFFFF;
+    color: #ffffff;
     line-height: 22px;
     --n-border: 0 !important;
     --n-border-hover: 0 !important;
@@ -89,9 +89,9 @@
 .train-content {
   margin: 20px 0;
   height: 238px;
-  background: #FFFFFF;
+  background: #ffffff;
   border-radius: 11px;
-  border: 1px solid #74BAFF;
+  border: 1px solid #74baff;
   position: relative;
   overflow: hidden;
 
@@ -115,11 +115,11 @@
     left: 0;
     right: 0;
     bottom: 0;
-    background-color: rgba(0, 0, 0, .7);
+    background-color: rgba(0, 0, 0, 0.7);
     display: flex;
     align-items: center;
     justify-content: center;
-    transition: all .2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+    transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
 
     .previewBtn {
       background: #fff;
@@ -129,11 +129,49 @@
     }
   }
 
+  .disPreview {
+    position: absolute;
+    // opacity: 0;
+    // visibility: hidden;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.7);
+    display: flex;
+    align-items: center;
+    flex-direction: column;
+    justify-content: center;
+    transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+    .disPreviewDivide {
+      font-size: 15px;
+      color: #fff;
+    }
+    :global {
+      .n-progress-graph-circle-rail {
+        stroke: #8b8b8b !important;
+      }
+    }
+    .BProgress {
+      color: #fff;
+      h4 {
+        font-size: 28px;
+        font-family: 'DINA';
+        font-weight: bold;
+        text-align: center;
+        span {
+          font-size: 12px;
+          font-weight: 400;
+        }
+      }
+    }
+  }
+
   &:hover {
     .preview {
       opacity: 1;
       visibility: visible;
-      transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+      transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
     }
   }
 }
@@ -151,9 +189,9 @@
     .n-tag {
       font-size: 14px;
       font-weight: 500;
-      color: #0378EC;
+      color: #0378ec;
       line-height: 20px;
-      border: 1px solid #198CFE;
+      border: 1px solid #198cfe;
       border-radius: 6px;
       background-color: transparent;
       height: 28px;
@@ -173,10 +211,10 @@
 }
 
 .evaluationType {
-  background: #FFF0EB;
+  background: #fff0eb;
 
   .btn {
-    background: linear-gradient(270deg, #FF7B57 0%, #FF3460 100%);
+    background: linear-gradient(270deg, #ff7b57 0%, #ff3460 100%);
   }
 
   .train-content {
@@ -186,9 +224,9 @@
   .train-footer {
     :global {
       .n-tag {
-        color: #F92D53;
-        border: 1px solid #F92D53;
+        color: #f92d53;
+        border: 1px solid #f92d53;
       }
     }
   }
-}
+}

+ 94 - 33
src/views/attend-class/model/train-type/index.tsx

@@ -1,6 +1,14 @@
 import { PropType, defineComponent } from 'vue';
 import styles from './index.module.less';
-import { NButton, NEllipsis, NSpace, NImage, NTag, useDialog } from 'naive-ui';
+import {
+  NButton,
+  NEllipsis,
+  NSpace,
+  NImage,
+  NTag,
+  useDialog,
+  NProgress
+} from 'naive-ui';
 import pTag from './images/p-tag.svg';
 import eTag from './images/e-tag.svg';
 import pEdit from './images/p-edit.svg';
@@ -17,6 +25,8 @@ type ItemType = {
   coverImg: string;
   musicName: string;
   typeList: string[];
+  allTimes?: number;
+  trainingTimes?: number;
 };
 
 export default defineComponent({
@@ -33,6 +43,10 @@ export default defineComponent({
     isDelete: {
       type: Boolean,
       default: false
+    },
+    isDisabled: {
+      type: Boolean,
+      default: false
     }
   },
   emits: ['click', 'delete', 'edit'],
@@ -60,6 +74,10 @@ export default defineComponent({
       const src = `${origin}/instrument?platform=pc&modelType=practise`;
       window.open(src, '_blank');
     };
+    function rgba(arg0: number, arg1: number, arg2: number, arg3: number) {
+      throw new Error('Function not implemented.');
+    }
+
     return () => (
       <div
         class={[
@@ -91,25 +109,65 @@ export default defineComponent({
               <img src={iconDelete} />
             </NButton>
           ) : (
-            <NButton class={styles.btn} round onClick={onDetail}>
+            <NButton
+              class={styles.btn}
+              round
+              onClick={() => {
+                if (props.isDisabled) {
+                  return;
+                }
+                onDetail;
+              }}>
               {props.item.trainingType === 'EVALUATION'
                 ? '评测模式'
                 : '练习模式'}
-              <img src={iconPause} />
+              {props.isDisabled ? null : <img src={iconPause} />}
             </NButton>
           )}
         </div>
         <div class={styles['train-content']}>
           <NImage src={props.item.coverImg} previewDisabled objectFit="cover" />
-          <div class={styles.preview}>
-            <NButton
-              strong
-              secondary
-              class={styles.previewBtn}
-              onClick={onDetail}>
-              预览
-            </NButton>
-          </div>
+          {props.isDisabled ? (
+            <div class={styles.disPreview}>
+              <NProgress
+                percentage={
+                  Number(props.item.trainingTimes) / Number(props.item.allTimes)
+                }
+                offset-degree={180}
+                type="circle"
+                rail-color={'8b8b8b'}
+                color={
+                  props.item.trainingType === 'EVALUATION'
+                    ? '#FF7E65'
+                    : '#44B3FF'
+                }
+                style="width: 120px; margin: 0  0 10px;">
+                <div class={styles.BProgress}>
+                  <h4>
+                    {props.item.trainingTimes} <span>分钟</span>{' '}
+                  </h4>
+                  <p>实际练习 </p>
+                </div>
+              </NProgress>
+              <p class={styles.disPreviewDivide}>
+                {props.item.trainingType === 'EVALUATION'
+                  ? '合格分数'
+                  : '练习时长要求'}
+                {props.item.allTimes}
+                {props.item.trainingType === 'EVALUATION' ? '分' : '分钟'}
+              </p>
+            </div>
+          ) : (
+            <div class={styles.preview}>
+              <NButton
+                strong
+                secondary
+                class={styles.previewBtn}
+                onClick={onDetail}>
+                预览
+              </NButton>
+            </div>
+          )}
         </div>
         <div class={styles['train-footer']}>
           <NSpace class={styles.type}>
@@ -117,37 +175,40 @@ export default defineComponent({
               <NTag>{type}</NTag>
             ))}
           </NSpace>
-
-          <NSpace size={6}>
-            <n-button
-              quaternary
-              disabled={props.isDelete}
-              class={styles.operation}
-              onClick={(e: MouseEvent) => {
-                e.stopPropagation();
-                emit('edit', props.item);
-              }}>
-              <img
-                src={props.item.trainingType === 'EVALUATION' ? eEdit : pEdit}
-              />
-            </n-button>
-            {props.type === 'homework' && (
+          {props.isDisabled ? null : (
+            <NSpace size={6}>
               <n-button
                 quaternary
                 disabled={props.isDelete}
                 class={styles.operation}
                 onClick={(e: MouseEvent) => {
                   e.stopPropagation();
-                  onDelete();
+                  emit('edit', props.item);
                 }}>
                 <img
-                  src={
-                    props.item.trainingType === 'EVALUATION' ? eDelete : pDelete
-                  }
+                  src={props.item.trainingType === 'EVALUATION' ? eEdit : pEdit}
                 />
               </n-button>
-            )}
-          </NSpace>
+              {props.type === 'homework' && (
+                <n-button
+                  quaternary
+                  disabled={props.isDelete}
+                  class={styles.operation}
+                  onClick={(e: MouseEvent) => {
+                    e.stopPropagation();
+                    onDelete();
+                  }}>
+                  <img
+                    src={
+                      props.item.trainingType === 'EVALUATION'
+                        ? eDelete
+                        : pDelete
+                    }
+                  />
+                </n-button>
+              )}
+            </NSpace>
+          )}
         </div>
       </div>
     );

+ 28 - 1
src/views/classList/api.ts

@@ -87,7 +87,7 @@ export const getTrainingStudentList = (params: any) => {
 };
 
 /**
- * 练习记录
+ * 练习排行
  */
 export const getTestList = (params: any) => {
   return request.post('/edu-app/musicPracticeRecordStat/trainingRanking', {
@@ -96,6 +96,15 @@ export const getTestList = (params: any) => {
 };
 
 /**
+ * 练习记录
+ */
+export const getTestreCodeList = (params: any) => {
+  return request.post('/edu-app/musicPracticeRecordStat/trainingStat', {
+    data: params
+  });
+};
+
+/**
  * 获取学生详情
  */
 export const getStudentDetail = (params: any) => {
@@ -113,3 +122,21 @@ export const courseSchedulePage = (params: any) => {
     data: params
   });
 };
+
+/**
+ * 开始上课 获取章节
+ */
+export const getCourseChapter = (params: any) => {
+  return request.get(`/edu-app/lessonCourseware/detail/${params}`);
+};
+
+/**
+ * 获取学生训练详情
+ */
+
+export const getTrainingStudentDetail = (params: any) => {
+  return request.get(`/edu-app/lessonTraining/trainingStudentDetail`, {
+    params,
+    requestType: 'form'
+  });
+};

+ 51 - 7
src/views/classList/components/afterWorkDetail.tsx

@@ -6,6 +6,7 @@ import {
   NForm,
   NFormItem,
   NImage,
+  NModal,
   NSelect,
   NSpace
 } from 'naive-ui';
@@ -24,7 +25,9 @@ import {
   getTimes
 } from '/src/utils/dateFormat';
 import { trainingStatusArray } from '@/utils/searchArray';
+import TrainingDetails from '../modals/TrainingDetails';
 import dayjs from 'dayjs';
+import { lookup } from 'dns';
 export default defineComponent({
   name: 'student-studentList',
   setup(props, { emit }) {
@@ -42,12 +45,16 @@ export default defineComponent({
         expireDate: '',
         teacherAvatar: '',
         teacherName: ''
-      }
+      },
+      detailVisiable: false,
+      activeRow: null as any,
+      index: 0
     });
     const timer = ref<[number, number]>([
       getNowDateAndMonday(new Date().getTime()),
       getNowDateAndSunday(new Date().getTime())
     ]);
+    const TrainingDetailsRef = ref();
     const route = useRoute();
     const routerList = ref([
       { name: '班级管理', path: '/classList' },
@@ -75,8 +82,8 @@ export default defineComponent({
         const res = await getTrainingStudentList({
           trainingId: route.query.trainingId,
           ...state.searchForm,
-          ...state.pagination,
-          ...getTimes(timer.value, ['startTime', 'endTime'], 'YYYY-MM-DD')
+          ...state.pagination
+          // ...getTimes(timer.value, ['startTime', 'endTime'], 'YYYY-MM-DD')
         });
 
         state.tableList = res.data.rows;
@@ -97,6 +104,13 @@ export default defineComponent({
         console.log(e);
       }
     };
+
+    const lookDetail = (row: any, index: number) => {
+      console.log(index, 'index');
+      state.index = index + 1;
+      state.activeRow = row;
+      state.detailVisiable = true;
+    };
     onMounted(() => {
       getWorkInfo();
       getList();
@@ -138,9 +152,14 @@ export default defineComponent({
         {
           title: '操作',
           key: 'id',
-          render(row: any) {
+          render(row: any, index: number) {
             return (
-              <NButton text type="primary">
+              <NButton
+                text
+                type="primary"
+                onClick={() => {
+                  lookDetail(row, index);
+                }}>
                 详情
               </NButton>
             );
@@ -148,6 +167,17 @@ export default defineComponent({
         }
       ];
     };
+
+    const goToNext = () => {
+      state.index++;
+      state.activeRow = state.tableList[state.index - 1];
+      TrainingDetailsRef.value.getTrainingDetail();
+    };
+    const gotoPre = () => {
+      state.index--;
+      state.activeRow = state.tableList[state.index - 1];
+      TrainingDetailsRef.value.getTrainingDetail();
+    };
     return () => (
       <div>
         <CBreadcrumb list={routerList.value}></CBreadcrumb>
@@ -205,13 +235,13 @@ export default defineComponent({
                   } as any)}
                   v-model:value={state.searchForm.trainingStatus}></CSelect>
               </NFormItem>
-              <NFormItem>
+              {/* <NFormItem>
                 <CDatePicker
                   v-model:value={timer.value}
                   separator={'至'}
                   type="daterange"
                   timerValue={timer.value}></CDatePicker>
-              </NFormItem>
+              </NFormItem> */}
 
               <NFormItem>
                 <NSpace justify="end">
@@ -257,6 +287,20 @@ export default defineComponent({
             />
           </div>
         </div>
+        <NModal
+          v-model:show={state.detailVisiable}
+          preset="card"
+          class={['modalTitle background', styles.wordDetailModel]}
+          title={'训练详情'}>
+          <TrainingDetails
+            onNext={() => goToNext()}
+            onPre={() => gotoPre()}
+            ref={TrainingDetailsRef}
+            onClose={() => (state.detailVisiable = false)}
+            total={state.tableList.length}
+            current={state.index}
+            activeRow={state.activeRow}></TrainingDetails>
+        </NModal>
       </div>
     );
   }

+ 7 - 7
src/views/classList/contants.ts

@@ -1,15 +1,15 @@
 export const threeYearSystem = [
   { label: '全部年级', value: null },
-  { label: '七年级', value: 1 },
-  { label: '八年级', value: 2 },
-  { label: '九年级', value: 3 }
+  { label: '七年级', value: 7 },
+  { label: '八年级', value: 8 },
+  { label: '九年级', value: 9 }
 ];
 export const foreYearSystem = [
   { label: '选择年级', value: null },
-  { label: '六年级', value: 1 },
-  { label: '七年级', value: 2 },
-  { label: '八年级', value: 3 },
-  { label: '九年级', value: 4 }
+  { label: '六年级', value: 6 },
+  { label: '七年级', value: 7 },
+  { label: '八年级', value: 8 },
+  { label: '九年级', value: 9 }
 ];
 export const fiveYearSystem = [
   { label: '选择年级', value: null },

BIN
src/views/classList/images/nosub.png


BIN
src/views/classList/images/qualified.png


BIN
src/views/classList/images/unqualified.png


+ 229 - 60
src/views/classList/index.module.less

@@ -1,4 +1,5 @@
 @img: '../setting/images';
+@currentimg './images'
 .listWrap {
   padding: 32px;
   background-color: #fff;
@@ -129,66 +130,66 @@
           }
         }
       }
-      .n-legacy-transfer-gap {
-        width: 80px;
-        .n-button {
-          width: 34px;
-          height: 34px;
-          border-radius: 8px;
-          .n-button__state-border {
-            border: none !important;
-          }
-          &:nth-child(1) {
-            transform: rotate(180deg);
-            position: relative;
-            &:hover {
-              &::after {
-                background: url('@{img}/transArrowActive.png') no-repeat;
-                top: 0;
-                left: 0;
+      // .n-legacy-transfer-gap {
+      //   width: 80px;
+      //   .n-button {
+      //     width: 34px;
+      //     height: 34px;
+      //     border-radius: 8px;
+      //     .n-button__state-border {
+      //       border: none !important;
+      //     }
+      //     &:nth-child(1) {
+      //       transform: rotate(180deg);
+      //       position: relative;
+      //       &:hover {
+      //         &::after {
+      //           background: url('@{currentimg}/transArrowActive.png') no-repeat;
+      //           top: 0;
+      //           left: 0;
 
-                background-size: 34px 34px;
-              }
-            }
-            &::after {
-              position: absolute;
-              content: '';
-              width: 34px;
-              height: 34px;
-              background-color: black;
-              top: 0;
-              left: 0;
-              background: url('@{img}/transArrrow.png') no-repeat;
-              background-size: 34px 34px;
-              z-index: 100;
-            }
-          }
-          &:nth-child(2) {
-            position: relative;
-            &:hover {
-              &::after {
-                background: url('@{img}/transArrowActive.png') no-repeat;
-                top: 0;
-                left: 0;
+      //           background-size: 34px 34px;
+      //         }
+      //       }
+      //       &::after {
+      //         position: absolute;
+      //         content: '';
+      //         width: 34px;
+      //         height: 34px;
+      //         background-color: black;
+      //         top: 0;
+      //         left: 0;
+      //         background: url('@{currentimg}/transArrrow.png') no-repeat;
+      //         background-size: 34px 34px;
+      //         z-index: 100;
+      //       }
+      //     }
+      //     &:nth-child(2) {
+      //       position: relative;
+      //       &:hover {
+      //         &::after {
+      //           background: url('@{currentimg}/transArrowActive.png') no-repeat;
+      //           top: 0;
+      //           left: 0;
 
-                background-size: 34px 34px;
-              }
-            }
-            &::after {
-              position: absolute;
-              content: '';
-              width: 100%;
-              height: 100%;
-              background-color: black;
-              top: 0;
-              left: 0;
-              background: url('@{img}/transArrrow.png') no-repeat;
-              background-size: 34px 34px;
-              z-index: 100;
-            }
-          }
-        }
-      }
+      //           background-size: 34px 34px;
+      //         }
+      //       }
+      //       &::after {
+      //         position: absolute;
+      //         content: '';
+      //         width: 100%;
+      //         height: 100%;
+      //         background-color: black;
+      //         top: 0;
+      //         left: 0;
+      //         background: url('@{img}/transArrrow.png') no-repeat;
+      //         background-size: 34px 34px;
+      //         z-index: 100;
+      //       }
+      //     }
+      //   }
+      // }
     }
     .studentTransferBottom {
       width: 100%;
@@ -259,10 +260,10 @@
       width: 34px;
       height: 34px;
       border-radius: 8px;
-      background: url('@{img}/transArrrow.png') no-repeat;
+      background: url('./images/transArrrow.png') no-repeat;
       background-size: 34px 34px;
       &:hover {
-        background: url('@{img}/transArrowActive.png') no-repeat;
+        background: url('./images/transArrowActive.png') no-repeat;
         background-size: 34px 34px;
       }
     }
@@ -470,3 +471,171 @@
     height: 20px;
   }
 }
+
+.chioseModel {
+  width: 413px;
+
+  :global {
+    .n-select {
+      width: 100%;
+      min-width: 180px;
+
+      .n-base-selection-label {
+        height: 43px;
+        line-height: 43px;
+      }
+
+      .n-base-selection__border {
+        border-radius: 8px;
+        overflow: hidden;
+      }
+
+      .n-base-selection__state-border {
+        border-radius: 8px;
+        overflow: hidden;
+      }
+    }
+
+    .n-card-header {
+      position: relative;
+      padding: 20px 18px;
+      text-align: center;
+      // background: #F5F6FA;
+      font-size: 22px;
+      font-weight: 600;
+      color: #131415;
+      line-height: 30px;
+    }
+
+    .n-card-header__close {
+      position: absolute;
+      right: 18px;
+    }
+
+    .n-card__content {
+      // padding: 28px;
+      padding: 30px;
+    }
+  }
+
+  .updateBtnGroup {
+    padding: 0;
+    justify-content: center !important;
+
+    :global {
+      .n-button {
+        height: 48px !important;
+        min-width: 156px;
+      }
+    }
+  }
+}
+.wordDetailModel {
+  width: 1012px;
+}
+.trainingDetails {
+  padding: 24px 32px 32px;
+  .studentList {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    margin-bottom: 24px;
+    justify-content: space-between;
+    border-bottom: 1px solid #f2f2f2;
+    padding-bottom: 18px;
+    .studentHeaderWrap {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+
+      .studentHeader {
+        width: 66px;
+        height: 66px;
+        padding: 2px;
+        border-radius: 99px;
+        background: linear-gradient(
+          228deg,
+          rgba(2, 186, 255, 1),
+          rgba(0, 122, 254, 1)
+        );
+        margin-right: 16px;
+        .studentHeaderBorder {
+          width: 100%;
+          height: 100%;
+          background: #fff;
+          border-radius: 99px;
+          overflow: hidden;
+          display: flex;
+          flex-direction: row;
+          align-items: center;
+          justify-content: center;
+          padding: 4px;
+        }
+      }
+    }
+    .workStatus {
+      width: 87px;
+      height: 87px;
+    }
+    .studentHeaderImg {
+      width: 66px;
+      height: 66px;
+      border-radius: 50%;
+      overflow: hidden;
+    }
+    .workafterInfo {
+      h4 {
+        font-size: 22px;
+        line-height: 30px;
+        line-height: 30px;
+        font-weight: 600;
+        color: #131415;
+        margin-bottom: 12px;
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        .workafterInfoDot {
+          width: 52px;
+          height: 22px;
+          background: #ff8a32;
+          border-radius: 13px 4px 13px 4px;
+          font-size: 14px;
+          font-weight: 600;
+          color: #ffffff;
+          line-height: 22px;
+          text-align: center;
+          margin-left: 8px;
+        }
+      }
+      p {
+        font-size: 16px;
+        line-height: 22px;
+        color: #777;
+        span {
+          color: #ea4132;
+        }
+      }
+    }
+  }
+  .workList {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: space-between;
+  }
+  .allTotal {
+    font-size: 16px;
+    font-weight: 400;
+    color: #8b8b8b;
+  }
+  .btnGroups {
+    padding: 40px 0;
+    :global {
+      .n-button {
+        height: 47px;
+        min-width: 96px;
+        border-radius: 8px;
+      }
+    }
+  }
+}

+ 23 - 2
src/views/classList/index.tsx

@@ -19,6 +19,7 @@ import { classGroupList, deleteClass } from './api';
 import { useUserStore } from '/src/store/modules/users';
 import CreateClass from './modals/createClass';
 import RestStudentBox from './modals/restStudentBox';
+import TrainDetail from './modals/Gotoclass';
 import {
   sixYearSystem,
   fiveYearSystem,
@@ -29,6 +30,7 @@ import {
 } from './contants';
 import add from '@/views/studentList/images/add.png';
 import { useRouter } from 'vue-router';
+import { rowDark } from 'naive-ui/es/legacy-grid/styles';
 export default defineComponent({
   name: 'class-classList',
   setup(props, { emit }) {
@@ -51,7 +53,8 @@ export default defineComponent({
       tableList: [] as any,
       studentVisible: false,
       activeRow: null as any,
-      showaddClass: false
+      showaddClass: false,
+      goCourseVisiable: false
     });
     const formRef = ref();
     const dialog = useDialog();
@@ -167,7 +170,10 @@ export default defineComponent({
                     }}>
                     学生调整
                   </NButton>
-                  <NButton type="primary" text>
+                  <NButton
+                    type="primary"
+                    text
+                    onClick={() => classesBegin(row)}>
                     开始上课
                   </NButton>
                   {!(row.preStudentNum > 0) ? (
@@ -189,6 +195,12 @@ export default defineComponent({
       state.activeRow = row;
       state.studentVisible = true;
     };
+
+    const classesBegin = (row: any) => {
+      state.activeRow = row;
+      state.goCourseVisiable = true;
+      console.log('classesBegin');
+    };
     onMounted(() => {
       getList();
     });
@@ -295,6 +307,15 @@ export default defineComponent({
             onClose={() => (state.showaddClass = false)}
           />
         </NModal>
+
+        <NModal
+          v-model:show={state.goCourseVisiable}
+          preset="card"
+          class={['modalTitle background', styles.chioseModel]}
+          title={'选择课件'}>
+          <TrainDetail
+            onClose={() => (state.goCourseVisiable = false)}></TrainDetail>
+        </NModal>
       </div>
     );
   }

+ 268 - 0
src/views/classList/modals/Gotoclass.tsx

@@ -0,0 +1,268 @@
+import { defineComponent, onMounted, reactive, ref } from 'vue';
+import styles from '../index.module.less';
+import {
+  NButton,
+  NForm,
+  NFormItem,
+  NSelect,
+  NSpace,
+  useMessage
+} from 'naive-ui';
+import {
+  bookVersionPage,
+  lessonCoursewarePage,
+  queryCourseware
+} from '@/views/prepare-lessons/api';
+import { useRouter } from 'vue-router';
+import { useThrottleFn } from '@vueuse/core';
+import { getCourseChapter } from '../api';
+import { useCatchStore } from '/src/store/modules/catchData';
+export default defineComponent({
+  name: 'train-update',
+  emits: ['close'],
+  props: {
+    activeRow: {
+      type: Object,
+      default: () => ({ id: '', currentGradeNum: '' })
+    }
+  },
+  setup(props, { emit }) {
+    // 'practice' | 'evaluation'
+    const forms = reactive({
+      bookVersionId: null,
+      classGroupId: null,
+      category: null,
+      chapter: null,
+      subjectId: null,
+      musicTagList: [] as any,
+      loading: false,
+      list: [] as any,
+      chapterList: [] as any,
+      unit: null,
+      unitList: [],
+      subjectList: [] as any
+    });
+    const router = useRouter();
+    const catchStore = useCatchStore();
+    const message = useMessage();
+    const gotoClassPage = () => {
+      formsRef.value.validate(async (error: any) => {
+        if (error) return;
+        const { data } = await queryCourseware({
+          coursewareDetailKnowledgeId: forms.chapter,
+          subjectId: forms.subjectId,
+          page: 1,
+          rows: 99
+        });
+        console.log('gotoClassPage', data);
+        if (data.rows && data.rows.length > 0) {
+          const { href } = router.resolve({
+            path: '/attend-class',
+            query: {
+              type: 'class',
+              classGroupId: props.activeRow.id,
+              subjectId: forms.subjectId,
+              detailId: forms.chapter
+            }
+          });
+          emit('close');
+          window.open(href, +new Date() + '');
+        } else {
+          message.error('当前章节没有课件,请重新学则');
+        }
+      });
+
+      /**
+       *         query: {
+            type: 'class',
+            classGroupId: item.id,
+            subjectId: prepareStore.getSubjectId,
+            detailId: prepareStore.getSelectKey // 章节id
+          }
+       */
+    };
+
+    const formsRef = ref();
+    const throttledFn = useThrottleFn(() => getLessonCourseware(), 500);
+    const getLessonCourseware = async () => {
+      forms.category = null;
+      forms.unit = null;
+      forms.category = null;
+      forms.chapter = null;
+      forms.loading = true;
+
+      if (forms.bookVersionId) {
+        try {
+          const { data } = await lessonCoursewarePage({
+            page: 1,
+            rows: 99,
+            type: 'COURSEWARE',
+            enableFlag: 1,
+            bookVersionId: forms.bookVersionId,
+            currentGradeNum: props.activeRow.currentGradeNum
+          });
+
+          forms.list = data.rows.map((item: any) => {
+            return {
+              label: item.name,
+              value: item.id
+            };
+          });
+        } catch {
+          //
+        }
+      } else {
+        forms.list = [];
+      }
+
+      forms.loading = false;
+    };
+    const getVersion = async () => {
+      forms.unit = null;
+      forms.chapter = null;
+
+      try {
+        const { data } = await bookVersionPage({
+          page: 1,
+          rows: 99,
+          type: 'COURSEWARE'
+        });
+        const temp = data.rows || [];
+        temp.forEach((item: any) => {
+          forms.musicTagList.push({
+            id: item.id,
+            name: item.name
+          });
+        });
+      } catch {
+        //
+      }
+    };
+
+    const getunitList = async () => {
+      forms.unit = null;
+      forms.chapter = null;
+      try {
+        if (forms.category) {
+          const res = await getCourseChapter(forms.category);
+          forms.unitList = res.data.lessonList.map((item: any) => {
+            return { ...item, label: item.name, value: item.id };
+          });
+        } else {
+          forms.unitList = [];
+        }
+      } catch (e) {
+        console.log(e);
+      }
+    };
+    const getchapterList = () => {
+      forms.chapter = null;
+      if (forms.unit) {
+        const item: any = forms.unitList.find((item: any) => {
+          return item.id === forms.unit;
+        });
+        forms.chapterList = item.knowledgeList.map((know: any) => {
+          return { ...know, label: know.name, value: know.id };
+        });
+        console.log('getchapterList', item);
+      } else {
+        forms.chapterList = [];
+      }
+      console.log('getchapterList');
+    };
+    onMounted(async () => {
+      await catchStore.getSubjects();
+      forms.subjectList = catchStore.getSubjectList.map((item: any) => {
+        return {
+          label: item.name,
+          value: item.id
+        };
+      });
+      getVersion();
+    });
+    return () => (
+      <div class={styles.trainUpdate}>
+        <NForm
+          labelAlign="left"
+          labelPlacement="left"
+          ref={formsRef}
+          model={forms}>
+          <NFormItem
+            path="bookVersionId"
+            rule={[{ required: true, message: '选择教材版本' }]}>
+            <NSelect
+              placeholder="选择教材版本"
+              clearable
+              options={[...forms.musicTagList]}
+              labelField="name"
+              valueField="id"
+              v-model:value={forms.bookVersionId}
+              onUpdate:value={() => throttledFn()}
+            />
+          </NFormItem>
+          <NFormItem
+            path="category"
+            rule={[{ required: true, message: '请选择册别' }]}>
+            <NSelect
+              {...({
+                options: [...forms.list],
+                placeholder: '选择册别',
+                clearable: true
+              } as any)}
+              disabled={!forms.bookVersionId}
+              v-model:value={forms.category}
+              onUpdate:value={() => getunitList()}></NSelect>
+          </NFormItem>
+          <NFormItem
+            path="unit"
+            rule={[{ required: true, message: '请选择单元' }]}>
+            <NSelect
+              disabled={!forms.category}
+              {...({
+                options: [...forms.unitList],
+                placeholder: '选择单元',
+                clearable: true
+              } as any)}
+              v-model:value={forms.unit}
+              onUpdate:value={() => getchapterList()}></NSelect>
+          </NFormItem>
+          <NFormItem
+            path="chapter"
+            rule={[{ required: true, message: '请选择章节' }]}>
+            <NSelect
+              disabled={!forms.unit}
+              {...({
+                options: [...forms.chapterList],
+                placeholder: '选择章节',
+                clearable: true
+              } as any)}
+              v-model:value={forms.chapter}></NSelect>
+          </NFormItem>
+          <NFormItem
+            path="subjectId"
+            rule={[{ required: true, message: '请选择乐器' }]}>
+            <NSelect
+              {...({
+                options: [...forms.subjectList],
+                placeholder: '选择乐器',
+                clearable: true
+              } as any)}
+              v-model:value={forms.subjectId}></NSelect>
+          </NFormItem>
+          <NSpace class={styles.updateBtnGroup}>
+            <NButton strong type="default" round onClick={() => emit('close')}>
+              取消
+            </NButton>
+            <NButton
+              strong
+              type="primary"
+              round
+              onClick={() => gotoClassPage()}>
+              确认
+            </NButton>
+          </NSpace>
+        </NForm>
+      </div>
+    );
+  }
+});

+ 193 - 0
src/views/classList/modals/TrainingDetails.tsx

@@ -0,0 +1,193 @@
+import {
+  NButton,
+  NSpace,
+  useMessage,
+  NForm,
+  NFormItem,
+  NSelect,
+  NImage
+} from 'naive-ui';
+import { defineComponent, onMounted, reactive, ref } from 'vue';
+import { getTrainingStudentDetail } from '../api';
+import styles from '../index.module.less';
+import TrainType from '@/views/attend-class/model/train-type';
+import defultHeade from '@/components/layout/images/teacherIcon.png';
+import noSub from '../images/nosub.png';
+import qualified from '../images/qualified.png';
+import unqualified from '../images/unqualified.png';
+import { evaluateDifficult } from '/src/utils/contants';
+import dayjs from 'dayjs';
+export default defineComponent({
+  props: {
+    activeRow: {
+      type: Object,
+      default: () => ({ studentLessonTrainingId: '' })
+    },
+    total: {
+      type: Number,
+      default: 0
+    },
+    current: {
+      type: Number,
+      default: 0
+    }
+  },
+  name: 'TrainingDetails',
+  emits: ['close', 'next', 'pre'],
+
+  setup(props, { emit, expose }) {
+    const data = reactive({
+      uploading: false
+    });
+    const studnetInfo = ref({
+      studentName: '',
+      submitTime: '',
+      trainingStatus: '',
+      studentAvatar: '',
+      studentLessonTrainingDetails: [] as any
+    } as any);
+    const message = useMessage();
+    const foemsRef = ref();
+    const typeFormat = (trainingType: string, configJson: any) => {
+      let tList: string[] = [];
+
+      if (trainingType === 'EVALUATION') {
+        tList = [
+          `${evaluateDifficult[configJson.evaluateDifficult]}`,
+          '全部小节',
+          `速度${configJson.evaluateSpeed}`,
+          `${configJson.trainingTimes}分合格`
+        ];
+        console.log('configJson.evaluateDifficult--', tList);
+      } else {
+        tList = [
+          `${configJson.practiceChapterBegin}-${configJson.practiceChapterEnd}小节`,
+          `速度${configJson.practiceSpeed}`,
+          `${configJson.trainingTimes}分钟`
+        ];
+        console.log('configJson.evaluateDifficult', tList);
+      }
+      return tList;
+    };
+    const getTrainingDetail = async () => {
+      try {
+        const res = await getTrainingStudentDetail({
+          studentLessonTrainingId: props.activeRow.studentLessonTrainingId
+        });
+        const arr = res.data.studentLessonTrainingDetails.map((item: any) => {
+          const tList = typeFormat(
+            item.trainingType,
+            JSON.parse(item.trainingContent)
+          );
+          return {
+            ...item,
+            coverImg: item.titleImg,
+            allTimes: JSON.parse(item.trainingContent).trainingTimes,
+            typeList: tList || []
+          };
+        });
+        studnetInfo.value = {
+          ...res.data,
+
+          studentLessonTrainingDetails: arr
+        };
+        console.log(studnetInfo.value.studentLessonTrainingDetails);
+      } catch (e) {
+        console.log(e);
+      }
+    };
+    expose({ getTrainingDetail });
+    onMounted(() => {
+      getTrainingDetail();
+    });
+
+    return () => (
+      <div class={[styles.trainingDetails]}>
+        <div class={styles.studentList}>
+          <div class={styles.studentHeaderWrap}>
+            <div class={styles.studentHeader}>
+              <div class={styles.studentHeaderBorder}>
+                <NImage
+                  class={styles.studentHeaderImg}
+                  src={
+                    studnetInfo.value.studentAvatar
+                      ? studnetInfo.value.studentAvatar
+                      : defultHeade
+                  }
+                  previewDisabled></NImage>
+              </div>
+            </div>
+
+            <div class={styles.workafterInfo}>
+              <h4>
+                {studnetInfo.value.studentName}{' '}
+                <div class={styles.workafterInfoDot}>学生</div>
+              </h4>
+              <p>
+                提交时间:
+                {studnetInfo.value.submitTime
+                  ? dayjs(new Date(studnetInfo.value.submitTime)).format(
+                      'YYYY-MM-DD'
+                    )
+                  : '--'}
+              </p>
+            </div>
+          </div>
+          {studnetInfo.value.trainingStatus == 'UNSUBMITTED' ? (
+            <NImage
+              previewDisabled
+              class={styles.workStatus}
+              src={noSub}></NImage>
+          ) : null}
+          {studnetInfo.value.trainingStatus == 'SUBMITTED' ? (
+            <NImage
+              previewDisabled
+              class={styles.workStatus}
+              src={unqualified}></NImage>
+          ) : null}
+          {studnetInfo.value.trainingStatus == 'TARGET' ? (
+            <NImage
+              previewDisabled
+              class={styles.workStatus}
+              src={qualified}></NImage>
+          ) : null}
+        </div>
+        <div class={styles.workList}>
+          {studnetInfo.value.studentLessonTrainingDetails.map((item: any) => (
+            <TrainType
+              isDisabled={true}
+              isDelete={false}
+              item={item}></TrainType>
+          ))}
+        </div>
+        <NSpace class={styles.btnGroups} justify="space-between">
+          <div class={styles.allTotal}>
+            {props.current}/{props.total}名学生
+          </div>
+          <div>
+            <NSpace>
+              <NButton
+                disabled={props.current <= 1}
+                round
+                type="primary"
+                onClick={() => {
+                  emit('pre');
+                }}>
+                上一名
+              </NButton>
+              <NButton
+                disabled={props.current >= props.total}
+                round
+                type="primary"
+                onClick={() => {
+                  emit('next');
+                }}>
+                下一名
+              </NButton>
+            </NSpace>
+          </div>
+        </NSpace>
+      </div>
+    );
+  }
+});