lex-xin 8 mesiacov pred
rodič
commit
6e64a27a2b

+ 8 - 1
src/App.tsx

@@ -42,11 +42,18 @@ export default defineComponent({
       const appTheme = setting.appTheme;
       const lightenStr = lighten(setting.appTheme, 6);
 
+    //   errorColor: string;
+    // errorColorHover: string;
+    // errorColorPressed: string;
+    // errorColorSuppl: string;
       return {
         common: {
           primaryColor: appTheme,
           primaryColorHover: lightenStr,
-          primaryColorPressed: lightenStr
+          primaryColorPressed: lightenStr,
+          errorColor: '#F51C08',
+          errorColorHover: '#F51C08',
+          errorColorPressed: '#F51C08'
         },
         LoadingBar: {
           colorLoading: appTheme

+ 3 - 2
src/components/card-type/index.module.less

@@ -57,10 +57,11 @@
   &.isError {
     :global {
       .n-card--bordered {
-        border: 1Px solid #d03050 !important;
+        border: 1Px solid #F51C08 !important;
     
         &:hover {
-          border: 1Px solid #d03050 !important;
+          border: 1Px solid #F51C08 !important;
+          box-shadow: 0 0 0 2px rgba(245, 28, 8, 0.2);
         }
       }
     }

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

@@ -789,7 +789,7 @@ export default defineComponent({
           v-model:show={forms.instrumentErrorVisiable}
           preset="card"
           class={['modalTitle', styles.removeVisiable1]}
-          title={'提示'}>
+          title={'温馨提示'}>
           <TheMessageDialog
             content={forms.instrumentErrorContent}
             contentDirection="left"

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

@@ -397,7 +397,13 @@ export default defineComponent({
           materialList.forEach((m: any) => {
             forms.coursewareList[item.index || 0].list.push(m);
           });
-          message.success('添加成功');
+          console.log(item, '1212---------------')
+          if(item.isError) {
+            message.error('您添加的资源与课件乐器不符')
+          } else {
+            message.success('添加成功');
+          }
+          
         }
 
         timer = setTimeout(() => {
@@ -441,6 +447,10 @@ export default defineComponent({
         });
         forms.coursewareList[item.index || 0].list = array;
 
+        if(item.isError) {
+          message.error('您添加的资源与课件乐器不符')
+        }
+
         timer = setTimeout(() => {
           // 内容有更新 - 相关资源会刷新
           eventGlobal.emit('onCoursewareUpdate');
@@ -481,10 +491,10 @@ export default defineComponent({
           type: 'checkInstrument',
           loading: false,
           contentDirection: 'center',
-          title: '提示',
+          title: '温馨提示',
           content: '课件中含有不符合课件乐器的资源,是否继续保存?',
           cancelButtonText: '取消',
-          confirmButtonText: '保存',
+          confirmButtonText: '继续保存',
           index: 0
         };
       }
@@ -707,13 +717,21 @@ export default defineComponent({
     const onCourseWareSubjectChange = (subjects: any) => {
       forms.subjects = subjects
 
+      let isTips = false
       // 修改声部后重新检测状态
       forms.coursewareList.forEach((item: any) => {
         const childList = item.list || []
         childList.forEach((child: any) => {
           child.isError = checkCurrentIsInstrument(child.instrumentIds)
+          if(child.isError) {
+            isTips = true
+          }
         })
       })
+
+      if(isTips) {
+        message.error('您添加的资源与课件乐器不符')
+      }
     }
 
     onMounted(async () => {
@@ -849,7 +867,7 @@ export default defineComponent({
                       if (dropItem.sourceForm === 'resource-item') {
                         if(forms.subjects.length <= 0) {
                           list.splice(evt.newDraggableIndex, 1)
-                          message.error('请先选择乐器')
+                          message.error('请先选择课件乐器')
                           eventGlobal.emit('checkCoursewareForm', 'subject')
                           return
                         }

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

@@ -584,11 +584,11 @@ export default defineComponent({
           style={
             props.from === 'class'
               ? {
-                  width: '640px',
+                  width: '780px',
                   ...assignHomeworkStuBoxDragData.styleDrag.value
                 }
               : {
-                  width: '640px'
+                  width: '780px'
                 }
           }
           preset="card"

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

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