Bladeren bron

Merge branch 'startLogin'

mo 1 jaar geleden
bovenliggende
commit
6f3239c574

+ 1 - 1
src/store/modules/users.ts

@@ -33,7 +33,7 @@ export const useUserStore = defineStore('user-store', {
     getNickname(): string {
       return this.username;
     },
-    getUserInfo(): object {
+    getUserInfo(): any {
       return this.info;
     }
   },

+ 6 - 4
src/styles/index.less

@@ -167,11 +167,14 @@ body {
 // 给弹窗设置标题的基础样式
 .modalTitle {
   border-radius: 16px;
-  overflow: hidden;
-
+  .n-card-header {
+    border-radius: 16px 16px 0 0;
+  }
   &.background {
     .n-card-header {
       background: #f5f6fa;
+
+      overflow: hidden;
     }
   }
 
@@ -277,7 +280,6 @@ body {
   }
 }
 
-
 /* 列表动画 start */
 .list-move,
 /* 对移动中的元素应用的过渡 */
@@ -290,4 +292,4 @@ body {
 .list-leave-to {
   opacity: 0;
   transform: translateX(30px);
-}
+}

+ 17 - 0
src/utils/request.ts

@@ -24,6 +24,23 @@ request.interceptors.request.use(
     const userStore = useUserStore();
     const Authorization = userStore.getToken || '';
     const authHeaders: any = {};
+    console.log(userStore.getUserInfo, 'userStore');
+    // if (
+    //   userStore.getUserInfo &&
+    //   userStore.getUserInfo.schoolInfos &&
+    //   userStore.getUserInfo.schoolInfos[0]?.id &&
+    //   options.data
+    // ) {
+    //   // console.log(
+    //   //   userStore.getUserInfo && userStore.getUserInfo.schoolInfos[0]?.id,
+    //   //   ' userStore.getUserInfo && userStore.getUserInfo.schoolInfos[0]?.id',
+    //   //   options
+    //   // );
+
+    //   options.data['schoolId'] =
+    //     (userStore.getUserInfo && userStore.getUserInfo.schoolInfos[0]?.id) ||
+    //     '';
+    // }
     if (
       Authorization &&
       !['/api-oauth/userlogin', '/api-auth/open/sendSms'].includes(url)

+ 49 - 0
src/views/classList/api.ts

@@ -1 +1,50 @@
 import request from '@/utils/request';
+/**
+ * 班级管理 - 班级列表
+ */
+export const classGroupList = (params: any) => {
+  return request.post('/edu-app/classGroup/page', {
+    data: params
+    // requestType: 'form'
+  });
+};
+
+/**
+ * 获取班级里的学生
+ */
+export const getCLassStudent = (params: any) => {
+  return request.post('/edu-app/student/page', {
+    data: params
+    // requestType: 'form'
+  });
+};
+
+/**
+ * 学员调整
+ */
+export const adjustStudent = (params: any) => {
+  return request.post('/edu-app/classGroup/adjustStudent', {
+    data: params
+    // requestType: 'form'
+  });
+};
+
+/**
+ * 删除
+ *
+ */
+export const deleteClass = (params: any) => {
+  return request.post('/edu-app/classGroup/delete', {
+    data: params,
+    requestType: 'form'
+  });
+};
+
+/**
+ * 新建班级
+ */
+export const addClass = (params: any) => {
+  return request.post('/edu-app/classGroup/save', {
+    data: params
+  });
+};

+ 85 - 0
src/views/classList/contants.ts

@@ -0,0 +1,85 @@
+export const threeYearSystem = [
+  { label: '全部年级', value: null },
+  { label: '一年级', value: 1 },
+  { label: '二年级', value: 2 },
+  { label: '三年级', value: 3 }
+];
+export const foreYearSystem = [
+  { label: '选择年级', value: null },
+  { label: '一年级', value: 1 },
+  { label: '二年级', value: 2 },
+  { label: '三年级', value: 3 },
+  { label: '四年级', value: 4 }
+];
+export const fiveYearSystem = [
+  { label: '选择年级', value: null },
+  { label: '一年级', value: 1 },
+  { label: '二年级', value: 2 },
+  { label: '三年级', value: 3 },
+  { label: '四年级', value: 4 },
+  { label: '五年级', value: 5 }
+];
+export const sixYearSystem = [
+  { label: '全部年级', value: null },
+  { label: '一年级', value: 1 },
+  { label: '二年级', value: 2 },
+  { label: '三年级', value: 3 },
+  { label: '四年级', value: 4 },
+  { label: '五年级', value: 5 },
+  { label: '六年级', value: 6 }
+];
+export const nineYearSystem = [
+  { label: '选择年级', value: null },
+  { label: '一年级', value: 1 },
+  { label: '二年级', value: 2 },
+  { label: '三年级', value: 3 },
+  { label: '四年级', value: 4 },
+  { label: '五年级', value: 5 },
+  { label: '六年级', value: 6 },
+  { label: '七年级', value: 7 },
+  { label: '八年级', value: 8 },
+  { label: '九年级', value: 9 }
+];
+export const classArray = [
+  { value: null, label: '选择班级' },
+  { value: 1, label: '1班' },
+  { value: 2, label: '2班' },
+  { value: 3, label: '3班' },
+  { value: 4, label: '4班' },
+  { value: 5, label: '5班' },
+  { value: 6, label: '6班' },
+  { value: 7, label: '7班' },
+  { value: 8, label: '8班' },
+  { value: 9, label: '9班' },
+  { value: 10, label: '10班' },
+  { value: 11, label: '11班' },
+  { value: 12, label: '12班' },
+  { value: 13, label: '13班' },
+  { value: 14, label: '14班' },
+  { value: 15, label: '15班' },
+  { value: 16, label: '16班' },
+  { value: 17, label: '17班' },
+  { value: 18, label: '18班' },
+  { value: 19, label: '19班' },
+  { value: 20, label: '20班' },
+  { value: 21, label: '21班' },
+  { value: 22, label: '22班' },
+  { value: 23, label: '23班' },
+  { value: 24, label: '24班' },
+  { value: 25, label: '25班' },
+  { value: 26, label: '26班' },
+  { value: 27, label: '27班' },
+  { value: 28, label: '28班' },
+  { value: 29, label: '29班' },
+  { value: 30, label: '30班' },
+  { value: 31, label: '31班' },
+  { value: 32, label: '32班' },
+  { value: 33, label: '33班' },
+  { value: 34, label: '34班' },
+  { value: 35, label: '35班' },
+  { value: 36, label: '36班' },
+  { value: 37, label: '37班' },
+  { value: 38, label: '38班' },
+  { value: 39, label: '39班' },
+  { value: 40, label: '40班' }
+];

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


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


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


+ 264 - 0
src/views/classList/index.module.less

@@ -1,3 +1,4 @@
+@img: './images';
 .listWrap {
   padding: 32px;
   background-color: #fff;
@@ -22,3 +23,266 @@
     }
   }
 }
+.btnGroup {
+  padding: 40px 0;
+
+  :global {
+    .n-button {
+      height: 47px;
+      min-width: 156px;
+    }
+  }
+}
+.resetStudentWrap {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding-top: 40px;
+  .studentTransfer {
+    position: relative;
+    .smallArrow {
+      right: 166px;
+      top: 15px;
+      position: absolute;
+      width: 12px;
+      height: 12px;
+      cursor: pointer;
+      z-index: 1000;
+    }
+
+    :global {
+      .n-legacy-transfer {
+        width: 634px;
+        min-height: 340px;
+        .n-legacy-transfer-list {
+          &:nth-child(1) {
+            .n-legacy-transfer-list-header__header {
+              &::after {
+                content: '(当前班级)';
+                font-size: 12px;
+                color: #777;
+                font-weight: 400;
+              }
+            }
+          }
+        }
+      }
+      .n-legacy-transfer-list-item {
+        &:hover {
+          background-color: #fff !important;
+        }
+      }
+      .n-legacy-transfer-list__border {
+        border: none;
+      }
+      .n-legacy-transfer-list-header__extra {
+        display: none;
+      }
+      .n-legacy-transfer-list-header {
+        display: flex;
+        flex-direction: column;
+        background: #e8f2ff;
+        align-items: flex-start;
+        height: auto;
+      }
+      .n-legacy-transfer-list-header__checkbox {
+        order: 2;
+        padding: 0 !important;
+        &::after {
+          content: '全选';
+          margin-left: 5px;
+        }
+        margin-top: 8px;
+      }
+      .n-legacy-transfer-list-header__header {
+        width: 100%;
+        padding: 14px 0;
+        font-size: 16px;
+        font-weight: 600 !important;
+        color: #131415;
+        line-height: 22px;
+        order: 1;
+        border-bottom: 1px solid rgba(0, 0, 0, 0.06);
+      }
+      .n-legacy-transfer-list {
+        padding: 0 16px;
+        min-height: 340px;
+        background: #e8f2ff;
+        border-radius: 16px 16px 0 0;
+        width: 277px;
+        .n-legacy-transfer-filter {
+          background: #e8f2ff;
+          padding: 8px 0px 0px;
+          border-bottom: none;
+        }
+        .n-input {
+          border-radius: 8px;
+          .n-input-wrapper {
+            .n-input__border {
+              border-radius: 8px;
+            }
+            .n-input__input-el {
+              height: 41px;
+              line-height: 41px;
+              background: #ffffff;
+            }
+          }
+        }
+      }
+      .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;
+
+                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: 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%;
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      justify-content: space-between;
+
+      .bottom {
+        padding: 0 16px;
+
+        width: 277px;
+        background-color: #e8f2ff;
+
+        border-radius: 0 0 8px 8px;
+        .bottomWrap {
+          padding: 14px 0;
+          border-top: 1px solid rgba(0, 0, 0, 0.06);
+        }
+      }
+    }
+  }
+}
+.studentTransferList {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  .studentLeft,
+  .studentRight {
+    padding: 14px 16px;
+    width: 277px;
+
+    background: #e8f2ff;
+    border-radius: 16px;
+    .listTop {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      padding-bottom: 14px;
+      border-bottom: 1px solid rgba(0, 0, 0, 0.06);
+      font-size: 16px;
+      font-weight: 600;
+      color: #131415;
+      line-height: 22px;
+      span {
+        color: #777;
+        font-weight: 400;
+        font-size: 12px;
+      }
+    }
+    .chioseCheckBox {
+      padding: 2px 2px;
+      font-size: 16px;
+      font-weight: 400;
+      color: #131415;
+    }
+  }
+
+  .chioseBox {
+    width: 80px;
+    height: 389px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    .chioseBtn {
+      cursor: pointer;
+      width: 34px;
+      height: 34px;
+      border-radius: 8px;
+      background: url('@{img}/transArrrow.png') no-repeat;
+      background-size: 34px 34px;
+      &:hover {
+        background: url('@{img}/transArrowActive.png') no-repeat;
+        background-size: 34px 34px;
+      }
+    }
+    .chioseBtnRight {
+      transform: rotate(180deg);
+      margin-bottom: 23px;
+    }
+  }
+  .chioseCheckAllBox {
+    margin-top: 8px !important;
+    margin-bottom: 14px !important;
+  }
+  .bottom {
+    padding-top: 14px;
+    border-top: 1px solid rgba(0, 0, 0, 0.06);
+  }
+}
+.addClass {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding-top: 50px;
+}

+ 166 - 88
src/views/classList/index.tsx

@@ -1,4 +1,4 @@
-import { defineComponent, reactive } from 'vue';
+import { defineComponent, reactive, onMounted, ref } from 'vue';
 import styles from './index.module.less';
 import {
   NButton,
@@ -6,18 +6,38 @@ import {
   NForm,
   NFormItem,
   NImage,
+  NModal,
   NSelect,
-  NSpace
+  NSpace,
+  useDialog,
+  useMessage
 } from 'naive-ui';
 import SearchInput from '@/components/searchInput';
 import CSelect from '@/components/CSelect';
 import Pagination from '@/components/pagination';
-import add from './images/add.png';
+import { classGroupList, deleteClass } from './api';
+import { useUserStore } from '/src/store/modules/users';
+import CreateClass from './modals/createClass';
+import RestStudentBox from './modals/restStudentBox';
+import {
+  sixYearSystem,
+  fiveYearSystem,
+  threeYearSystem,
+  foreYearSystem,
+  nineYearSystem,
+  classArray
+} from './contants';
+import add from '@/views/studentList/images/add.png';
 export default defineComponent({
   name: 'class-classList',
   setup(props, { emit }) {
     const state = reactive({
-      searchWord: '',
+      searchForm: {
+        keyword: null as any,
+        currentClass: null,
+        currentGradeNum: null
+      },
+
       orchestraType: null,
       courseTypeCode: null,
       loading: false,
@@ -26,47 +46,79 @@ export default defineComponent({
         rows: 10,
         pageTotal: 6
       },
-      tableList: [
-        {
-          className: '三年级1班',
-          studentNum: '36',
-          lastStudy: '人教版二年级上册 | 第一单元 |【歌表演】如愿'
-        },
-        {
-          className: '三年级2班',
-          studentNum: '43',
-          lastStudy: '人教版二年级上册 | 第一单元 |【歌表演】欢乐颂'
-        },
-        {
-          className: '三年级3班',
-          studentNum: '56',
-          lastStudy: '人教版二年级上册 | 第一单元 |【歌表演】我和我的祖国'
-        },
-        {
-          className: '三年级4班',
-          studentNum: '35',
-          lastStudy: '人教版二年级上册 | 第一单元 |【歌表演】孤勇者'
-        },
-        {
-          className: '三年级5班',
-          studentNum: '42',
-          lastStudy: '人教版二年级上册 | 第一单元 |【歌表演】大雁'
-        },
-        {
-          className: '三年级1班',
-          studentNum: '38',
-          lastStudy: '人教版二年级上册 | 第一单元 |【歌表演】暗香'
-        }
-      ] as any
+      gradeNumList: [] as any,
+      tableList: [] as any,
+      studentVisible: false,
+      activeRow: null as any,
+      showaddClass: false
     });
+    const formRef = ref();
+    const dialog = useDialog();
+    const message = useMessage();
     const search = () => {
+      state.pagination.page = 1;
+      getList();
       console.log('search', state);
     };
-
+    const userInfo = useUserStore();
+    if (userInfo.getUserInfo.schoolInfos[0].gradeYear == 'THREE_YEAR_SYSTEM') {
+      state.gradeNumList = threeYearSystem;
+    } else if (
+      userInfo.getUserInfo.schoolInfos[0].gradeYear == 'FORE_YEAR_SYSTEM'
+    ) {
+      state.gradeNumList = foreYearSystem;
+    } else if (
+      userInfo.getUserInfo.schoolInfos[0].gradeYear == 'FIVE_YEAR_SYSTEM'
+    ) {
+      state.gradeNumList = fiveYearSystem;
+    } else if (
+      userInfo.getUserInfo.schoolInfos[0].gradeYear == 'SIX_YEAR_SYSTEM'
+    ) {
+      state.gradeNumList = sixYearSystem;
+    } else {
+      state.gradeNumList = nineYearSystem;
+    }
     const onReset = () => {
-      console.log('search');
+      state.searchForm = {
+        keyword: null as any,
+        currentClass: null,
+        currentGradeNum: null
+      };
+      getList();
+    };
+
+    const removeClass = async (row: any) => {
+      dialog.warning({
+        title: '警告',
+        content: `是否删除班级“${row.name}”?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          try {
+            await deleteClass({ ids: row.id });
+            getList();
+            message.success(`删除成功`);
+          } catch (e) {
+            console.log(e);
+          }
+        }
+      });
     };
-    const getList = () => {
+    const getList = async () => {
+      // classGroupList
+      state.loading = true;
+      try {
+        const res = await classGroupList({
+          ...state.searchForm,
+          ...state.pagination
+        });
+        state.tableList = res.data.rows;
+        state.pagination.pageTotal = res.data.total;
+        state.loading = false;
+      } catch (e) {
+        state.loading = false;
+        console.log(e);
+      }
       console.log('getList');
     };
 
@@ -74,15 +126,18 @@ export default defineComponent({
       return [
         {
           title: '班级名称',
-          key: 'className'
+          key: 'name'
         },
         {
           title: '学生人数',
-          key: 'studentNum'
+          key: 'preStudentNum'
         },
         {
           title: '上次学习',
-          key: 'lastStudy'
+          key: 'lastStudy',
+          render(row: any) {
+            return <p>{row.lastStudy ? row.lastStudy : '--'}</p>;
+          }
         },
         {
           title: '操作',
@@ -94,18 +149,26 @@ export default defineComponent({
                   <NButton type="primary" text>
                     详情
                   </NButton>
-                  <NButton type="primary" text>
-                    修改
-                  </NButton>
-                  <NButton type="primary" text>
+                  <NButton
+                    type="primary"
+                    text
+                    onClick={() => {
+                      startResetStudent(row);
+                    }}>
                     学生调整
                   </NButton>
                   <NButton type="primary" text>
                     开始上课
                   </NButton>
-                  <NButton type="primary" text textColor="#EA4132">
-                    删除
-                  </NButton>
+                  {!(row.preStudentNum > 0) ? (
+                    <NButton
+                      type="primary"
+                      text
+                      textColor="#EA4132"
+                      onClick={() => removeClass(row)}>
+                      删除
+                    </NButton>
+                  ) : null}
                 </NSpace>
               </div>
             );
@@ -113,57 +176,47 @@ export default defineComponent({
         }
       ];
     };
+
+    const startResetStudent = (row: any) => {
+      state.activeRow = row;
+      state.studentVisible = true;
+    };
+    onMounted(() => {
+      getList();
+    });
     return () => (
       <div class={styles.listWrap}>
         <div class={styles.searchList}>
-          <NForm label-placement="left" inline>
+          <NForm label-placement="left" inline ref={formRef}>
             <NFormItem>
               <SearchInput
                 {...{ placeholder: '请输入班级名称' }}
                 class={styles.searchInput}
-                searchWord={state.searchWord}
+                searchWord={state.searchForm.keyword}
                 onChangeValue={(val: string) =>
-                  (state.searchWord = val)
+                  (state.searchForm.keyword = val)
                 }></SearchInput>
             </NFormItem>
 
             <NFormItem>
               <CSelect
                 {...({
-                  options: [
-                    {
-                      label: '一年级',
-                      value: 'song0'
-                    },
-                    {
-                      label: '二年级',
-                      value: 'song1'
-                    }
-                  ],
-                  placeholder: '全部年级',
+                  options: state.gradeNumList,
+                  placeholder: '选择年级',
                   clearable: true,
                   inline: true
                 } as any)}
-                v-model:value={state.orchestraType}></CSelect>
+                v-model:value={state.searchForm.currentGradeNum}></CSelect>
             </NFormItem>
             <NFormItem>
               <CSelect
                 {...({
-                  options: [
-                    {
-                      label: '1班',
-                      value: 'song0'
-                    },
-                    {
-                      label: '2班',
-                      value: 'song1'
-                    }
-                  ],
-                  placeholder: '全部班级',
+                  options: classArray,
+                  placeholder: '选择班级',
                   clearable: true,
                   inline: true
                 } as any)}
-                v-model:value={state.courseTypeCode}></CSelect>
+                v-model:value={state.searchForm.currentClass}></CSelect>
             </NFormItem>
 
             <NFormItem>
@@ -182,18 +235,19 @@ export default defineComponent({
             </NFormItem>
           </NForm>
         </div>
-        {/* <NButton
-            class={styles.addBtn}
-            type="primary"
-            v-slots={{
-              icon: () => (
-                <>
-                  <NImage class={styles.addBtnIcon} src={add}></NImage>
-                </>
-              )
-            }}>
-            新增学生
-          </NButton> */}
+        <NButton
+          class={styles.addBtn}
+          type="primary"
+          onClick={() => (state.showaddClass = true)}
+          v-slots={{
+            icon: () => (
+              <>
+                <NImage class={styles.addBtnIcon} src={add}></NImage>
+              </>
+            )
+          }}>
+          创建班级
+        </NButton>
         <div class={styles.tableWrap}>
           <NDataTable
             class={styles.classTable}
@@ -209,6 +263,30 @@ export default defineComponent({
             saveKey="orchestraRegistration-key"
           />
         </div>
+        <NModal
+          v-model:show={state.studentVisible}
+          style={{ width: '707px' }}
+          preset="card"
+          class={['modalTitle background']}
+          title={'学员调整'}>
+          <RestStudentBox
+            activeRow={state.activeRow}
+            onClose={() => (state.studentVisible = false)}
+            onGetList={() => getList()}></RestStudentBox>
+        </NModal>
+        <NModal
+          v-model:show={state.showaddClass}
+          style={{ width: '500px' }}
+          preset="card"
+          class={['modalTitle background']}
+          title={'创建班级'}>
+          <CreateClass
+            gradeNumList={state.gradeNumList}
+            classArray={classArray}
+            onGetList={() => getList()}
+            onClose={() => (state.showaddClass = false)}
+          />
+        </NModal>
       </div>
     );
   }

+ 110 - 0
src/views/classList/modals/createClass.tsx

@@ -0,0 +1,110 @@
+import {
+  NButton,
+  NSpace,
+  useMessage,
+  NForm,
+  NFormItem,
+  NSelect
+} from 'naive-ui';
+import { defineComponent, onMounted, reactive, ref } from 'vue';
+import styles from '../index.module.less';
+import CSelect from '/src/components/CSelect';
+import { addClass } from '../api';
+export default defineComponent({
+  props: {
+    activeRow: {
+      type: Object,
+      default: () => ({ id: '' })
+    },
+    gradeNumList: {
+      type: Array,
+      default: () => []
+    },
+    classArray: {
+      type: Array,
+      default: () => []
+    }
+  },
+  name: 'resetStudent',
+  emits: ['close', 'getList'],
+  setup(props, { emit }) {
+    const data = reactive({
+      uploading: false
+    });
+    const message = useMessage();
+    const foemsRef = ref();
+    const createClassForm = reactive({
+      currentGradeNum: null,
+      currentClass: null
+    });
+    const submitForms = () => {
+      foemsRef.value.validate(async (error: any) => {
+        console.log(createClassForm);
+        console.log(error);
+        if (error) {
+          return;
+        }
+        try {
+          const res = await addClass({ ...createClassForm });
+          message.success('新增成功');
+          emit('close');
+          emit('getList');
+        } catch (e) {
+          console.log(e);
+        }
+      });
+    };
+    return () => (
+      <div class={[styles.addClass]}>
+        <NForm label-placement="left" model={createClassForm} ref={foemsRef}>
+          <NFormItem
+            path="currentGradeNum"
+            rule={[
+              {
+                required: true,
+                message: '请选择年级'
+              }
+            ]}>
+            <CSelect
+              {...({
+                style: { width: '400px' },
+                options: props.gradeNumList,
+                placeholder: '选择年级',
+                clearable: true
+              } as any)}
+              v-model:value={createClassForm.currentGradeNum}></CSelect>
+          </NFormItem>
+          <NFormItem
+            path="currentClass"
+            rule={[
+              {
+                required: true,
+                message: '请选择班级'
+              }
+            ]}>
+            <CSelect
+              {...({
+                style: { width: '400px' },
+                options: props.classArray,
+                placeholder: '选择班级',
+                clearable: true
+              } as any)}
+              v-model:value={createClassForm.currentClass}></CSelect>
+          </NFormItem>
+        </NForm>
+        <NSpace class={styles.btnGroup} justify="center">
+          <NButton round onClick={() => emit('close')}>
+            取消
+          </NButton>
+          <NButton
+            round
+            loading={data.uploading}
+            onClick={() => submitForms()}
+            type="primary">
+            保存
+          </NButton>
+        </NSpace>
+      </div>
+    );
+  }
+});

+ 161 - 0
src/views/classList/modals/resetStudent.tsx

@@ -0,0 +1,161 @@
+import {
+  NButton,
+  NLegacyTransfer,
+  NSpace,
+  useMessage,
+  NPopselect,
+  NImage,
+  NDropdown
+} from 'naive-ui';
+import { defineComponent, onMounted, reactive, ref } from 'vue';
+import styles from '../index.module.less';
+import smallArrow from '../images/smallArrow.png';
+import { getCLassStudent, classGroupList } from '../api';
+export default defineComponent({
+  props: {
+    activeRow: {
+      type: Object,
+      default: () => ({ id: '' })
+    }
+  },
+  name: 'resetStudent',
+  emits: ['close'],
+  setup(props, { emit }) {
+    const message = useMessage();
+    const data = reactive({
+      uploading: false
+    });
+    const options = ref([] as any);
+    const currentStudnetList = ref([] as any);
+    const chioseOptions = ref([] as any);
+    const formRef = ref();
+    const handleSubmit = async () => {
+      data.uploading = true;
+    };
+    const classList = ref([] as any);
+    console.log(props.activeRow, 'activeRow');
+    const targetClass = reactive({
+      name: '',
+      id: ''
+    });
+    //
+
+    /**
+     * 这里干3件事  1.获取当前班的学生
+     * 2.查询所有的班级列表  并且排查当前班级
+     * 3.默认选择第一个班级 并且查出此班的学生
+     */
+    const chioseStudnet = (val: any) => {
+      console.log(val);
+    };
+    const getAllClassList = async () => {
+      try {
+        const res = await classGroupList({ page: 1, rows: 9999 });
+        classList.value = res.data.rows.map((item: any) => {
+          return {
+            label: item.name,
+            key: item.id,
+            disabled: item.id == props.activeRow.id
+          };
+        });
+        if (classList.value[0].disabled) {
+          targetClass.name = classList.value[1].label;
+          targetClass.id = classList.value[1].id;
+        } else {
+          targetClass.name = classList.value[0].label;
+          targetClass.id = classList.value[0].id;
+        }
+
+        console.log(classList.value, ' classList.value');
+      } catch (e) {
+        console.log(e);
+      }
+    };
+    const getCLassStudentList = async (id: string | number) => {
+      return await getCLassStudent({
+        page: 1,
+        rows: 999,
+        classGroupId: id
+      });
+    };
+    const chioseClass = async (val: any) => {
+      classList.value.forEach((item: any) => {
+        if (item.key == val) {
+          targetClass.name = item.label;
+          targetClass.id = item.key;
+        }
+      });
+      console.log(targetClass);
+      const res = await getCLassStudentList(val);
+      chioseOptions.value = res.data.rows.map((item: any) => {
+        return item.id;
+      });
+      console.log(chioseOptions.value, 'chioseOptions.value');
+    };
+    onMounted(async () => {
+      console.log('onMounted');
+      getAllClassList();
+      const res = await getCLassStudentList(props.activeRow.id as string);
+      currentStudnetList.value = res.data.rows.map((item: any) => {
+        return {
+          label: item.nickname + '(' + item.id + ')',
+          value: item.id
+        };
+      });
+    });
+    return () => (
+      <div class={[styles.container, styles.resetStudentWrap]}>
+        <div class={styles.studentTransfer}>
+          <NDropdown
+            key="111"
+            v-model:value={targetClass.id}
+            options={classList.value}
+            onSelect={(value: any) => {
+              chioseClass(value);
+            }}
+            scrollable>
+            <NImage
+              class={styles.smallArrow}
+              src={smallArrow}
+              previewDisabled></NImage>
+          </NDropdown>
+          <NLegacyTransfer
+            source-title={props.activeRow.name}
+            target-title={targetClass.name}
+            size="large"
+            ref={formRef}
+            options={currentStudnetList.value}
+            source-filter-placeholder="请输入学生姓名"
+            target-filter-placeholder="请输入学生姓名"
+            v-model:value={chioseOptions.value}
+            virtual-scroll
+            onUpdate:value={(val: any) => {
+              chioseStudnet(val);
+            }}
+            filterable></NLegacyTransfer>
+          <div class={styles.studentTransferBottom}>
+            <div class={[styles.bottomLeft, styles.bottom]}>
+              <div class={styles.bottomWrap}>共0名学生</div>
+            </div>
+            <div class={[styles.bottomRight, styles.bottom]}>
+              <div class={styles.bottomWrap}>共0名学生</div>
+            </div>
+          </div>
+        </div>
+
+        <NSpace class={styles.btnGroup} justify="center">
+          <NButton round onClick={() => emit('close')}>
+            取消
+          </NButton>
+          <NButton
+            round
+            loading={data.uploading}
+            type="primary"
+            onClick={() => handleSave()}>
+            保存
+          </NButton>
+        </NSpace>
+      </div>
+    );
+  }
+});

+ 397 - 0
src/views/classList/modals/restStudentBox.tsx

@@ -0,0 +1,397 @@
+import {
+  NButton,
+  NSpace,
+  useMessage,
+  NCheckboxGroup,
+  NCheckbox,
+  NRow,
+  NImage,
+  NInput,
+  NScrollbar,
+  NDropdown
+} from 'naive-ui';
+import { computed, defineComponent, onMounted, reactive, ref } from 'vue';
+import styles from '../index.module.less';
+import SearchInput from '@/components/searchInput';
+import smallArrow from '../images/smallArrow.png';
+import transArrrow from '../images/transArrrow.png';
+import transArrowActive from '../images/transArrowActive.png';
+import { getCLassStudent, classGroupList, adjustStudent } from '../api';
+export default defineComponent({
+  props: {
+    activeRow: {
+      type: Object,
+      default: () => ({ id: '' })
+    }
+  },
+  name: 'RestStudentBox',
+  emits: ['close', 'getList'],
+  setup(props, { emit }) {
+    const message = useMessage();
+    const data = reactive({
+      uploading: false
+    });
+    const options = ref([] as any);
+
+    const chioseOptions = ref([] as any);
+    const formRef = ref();
+    const handleSubmit = async () => {
+      data.uploading = true;
+    };
+    const classList = ref([] as any);
+    console.log(props.activeRow, 'activeRow');
+    const targetClass = reactive({
+      name: '',
+      id: ''
+    });
+    const currentchioseStudent = ref([] as any);
+    const currentStudentList = ref([] as any);
+    const currentSearch = ref(null as any);
+
+    const targetchioseStudent = ref([] as any);
+    const targetStudentList = ref([] as any);
+    const targetSearch = ref(null as any);
+    //
+    const submitList = ref([] as any);
+    /**
+     * 这里干3件事  1.获取当前班的学生
+     * 2.查询所有的班级列表  并且排查当前班级
+     * 3.默认选择第一个班级 并且查出此班的学生
+     */
+    const chioseStudnet = (val: any) => {
+      console.log(val);
+    };
+    const getAllClassList = async () => {
+      try {
+        const res = await classGroupList({ page: 1, rows: 9999 });
+        classList.value = res.data.rows.map((item: any) => {
+          return {
+            label: item.name,
+            key: item.id,
+            disabled: item.id == props.activeRow.id
+          };
+        });
+
+        if (classList.value[0].disabled) {
+          targetClass.name = classList.value[1].label;
+          targetClass.id = classList.value[1].key;
+        } else {
+          targetClass.name = classList.value[0].label;
+          targetClass.id = classList.value[0].key;
+        }
+
+        const tarRes = await getCLassStudentList(targetClass.id);
+        targetStudentList.value = tarRes.data.rows.map((item: any) => {
+          return {
+            label: item.nickname + '(' + item.id + ')',
+            value: item.id
+          };
+        });
+      } catch (e) {
+        console.log(e);
+      }
+    };
+    const getCLassStudentList = async (id: string | number) => {
+      return await getCLassStudent({
+        page: 1,
+        rows: 999,
+        classGroupId: id
+      });
+    };
+    const chioseClass = async (val: any) => {
+      classList.value.forEach((item: any) => {
+        if (item.key == val) {
+          targetClass.name = item.label;
+          targetClass.id = item.key;
+        }
+      });
+      const res = await getCLassStudentList(val);
+      targetStudentList.value = res.data.rows.map((item: any) => {
+        return {
+          label: item.nickname + '(' + item.id + ')',
+          value: item.id
+        };
+      });
+      console.log(submitList.value, 'submitList.value');
+      // 判断一下 targetStudentList.value 和 submitList 对比
+      targetStudentList.value = targetStudentList.value.filter(
+        (item: any) =>
+          !submitList.value.some((ele: any) => ele.value === item.value)
+      );
+      // 如果 如果submitList 学生的toClassId 和targetClassId相同 则添加
+      submitList.value.forEach((ele: any) => {
+        if (ele.toClassId == targetClass.id) {
+          console.log(ele.toClassId, ele);
+          targetStudentList.value.push({
+            label: ele.label,
+            value: ele.value
+          });
+        }
+      });
+      // 有2下 如果submitList 学生 和 targetStudentList 学生id相同 则删除
+    };
+    const currentFitterList = computed(() => {
+      const oraginArr = currentStudentList.value || [];
+      const list = oraginArr.filter((item: any) => {
+        return item.label.indexOf(currentSearch.value || '') != -1;
+      });
+      return list;
+    });
+
+    const targetFitterList = computed(() => {
+      const oraginArr = targetStudentList.value || [];
+      const list = oraginArr.filter((item: any) => {
+        return item.label.indexOf(targetSearch.value || '') != -1;
+      });
+      return list;
+    });
+
+    const chioseAllCurrentStudent = () => {
+      if (
+        currentFitterList.value.length === currentchioseStudent.value.length
+      ) {
+        // 说明要取消全选
+        currentchioseStudent.value = [];
+      } else {
+        currentchioseStudent.value = currentFitterList.value.map(
+          (item: any) => {
+            return item.value;
+          }
+        );
+        // 全选
+      }
+    };
+
+    const chioseAllTargetStudent = () => {
+      if (targetFitterList.value.length === targetchioseStudent.value.length) {
+        // 说明要取消全选
+        targetchioseStudent.value = [];
+      } else {
+        targetchioseStudent.value = targetFitterList.value.map((item: any) => {
+          return item.value;
+        });
+        // 全选
+      }
+    };
+    const toTargetList = () => {
+      const subStudetn = currentStudentList.value.filter((item: any) => {
+        return currentchioseStudent.value.indexOf(item.value) != -1;
+      });
+      if (subStudetn.length > 0) {
+        const arr = subStudetn.map((item: any) => {
+          return {
+            ...item,
+            studentId: item.value,
+            toClassId: targetClass.id
+          };
+        });
+        submitList.value = submitList.value.filter(
+          (item: any) => !arr.some((ele: any) => ele.value === item.value)
+        );
+        submitList.value = submitList.value.concat(arr);
+      }
+      // 接下来 删除 currentStudentList里的这三个学生
+      currentStudentList.value = currentStudentList.value.filter(
+        (item: any) => !subStudetn.some((ele: any) => ele.value === item.value)
+      );
+      subStudetn.forEach((item: any) => {
+        targetStudentList.value.push(item);
+      });
+      currentchioseStudent.value = [];
+    };
+    const toCurrentList = () => {
+      const subStudetn = targetStudentList.value.filter((item: any) => {
+        return targetchioseStudent.value.indexOf(item.value) != -1;
+      });
+      if (subStudetn.length > 0) {
+        const arr = subStudetn.map((item: any) => {
+          return {
+            ...item,
+            studentId: item.value,
+            toClassId: props.activeRow.id
+          };
+        });
+        submitList.value = submitList.value.filter(
+          (item: any) => !arr.some((ele: any) => ele.value === item.value)
+        );
+        submitList.value = submitList.value.concat(arr);
+      }
+      targetStudentList.value = targetStudentList.value.filter(
+        (item: any) => !subStudetn.some((ele: any) => ele.value === item.value)
+      );
+      subStudetn.forEach((item: any) => {
+        currentStudentList.value.push(item);
+      });
+      targetchioseStudent.value = [];
+      // 过去 所以
+      console.log(submitList.value, ' submitList.value===>');
+    };
+
+    const submitStudent = async () => {
+      if (submitList.value < 1) {
+        emit('close');
+        return;
+      }
+      try {
+        const res = await adjustStudent(submitList.value);
+        emit('close');
+        emit('getList');
+      } catch (e) {
+        console.log(e);
+      }
+    };
+    onMounted(async () => {
+      getAllClassList();
+      const res = await getCLassStudentList(props.activeRow.id as string);
+      currentStudentList.value = res.data.rows.map((item: any) => {
+        return {
+          label: item.nickname + '(' + item.id + ')',
+          value: item.id
+        };
+      });
+    });
+    return () => (
+      <div class={[styles.container, styles.resetStudentWrap]}>
+        <div class={styles.studentTransfer}>
+          <div class={styles.studentTransferList}>
+            <div class={styles.studentLeft}>
+              <div class={styles.listTop}>
+                <p>{props.activeRow.name}</p>
+                <span>(当前班级)</span>
+              </div>
+              <div class={styles.listCore}>
+                <NRow class={styles.chioseCheckAllBox}>
+                  <NCheckbox
+                    onUpdateChecked={val => {
+                      chioseAllCurrentStudent();
+                    }}
+                    checked={
+                      currentFitterList.value.length ===
+                      currentchioseStudent.value.length
+                    }
+                    indeterminate={
+                      currentchioseStudent.value.length > 0 &&
+                      currentFitterList.value.length !==
+                        currentchioseStudent.value.length
+                    }
+                    label="全选"></NCheckbox>
+                </NRow>
+                <NRow>
+                  <SearchInput
+                    {...{ placeholder: '请输入学生姓名' }}
+                    class={styles.searchInput}
+                    searchWord={currentSearch.value}
+                    onChangeValue={(val: string) =>
+                      (currentSearch.value = val)
+                    }></SearchInput>
+                </NRow>
+                <NScrollbar style="max-height: 204px;min-height: 204px;margin-top:14px;">
+                  <NCheckboxGroup v-model:value={currentchioseStudent.value}>
+                    {currentFitterList.value.map((item: any) => (
+                      <NRow class={styles.chioseCheckBox}>
+                        <NCheckbox
+                          value={item.value}
+                          label={item.label}></NCheckbox>
+                      </NRow>
+                    ))}
+                  </NCheckboxGroup>
+                </NScrollbar>
+              </div>
+              <div class={[styles.bottomLeft, styles.bottom]}>
+                <div class={styles.bottomWrap}>
+                  共{currentStudentList.value.length}名学生
+                </div>
+              </div>
+            </div>
+            <div class={styles.chioseBox}>
+              <div
+                class={[styles.chioseBtn, styles.chioseBtnRight]}
+                onClick={() => toTargetList()}></div>
+              <div
+                class={styles.chioseBtn}
+                onClick={() => toCurrentList()}></div>
+            </div>
+            <div class={styles.studentRight}>
+              <div class={styles.listTop}>
+                <NDropdown
+                  key="111"
+                  v-model:value={targetClass.id}
+                  options={classList.value}
+                  onSelect={(value: any) => {
+                    chioseClass(value);
+                  }}
+                  scrollable>
+                  <div>
+                    {targetClass.name}
+                    <NImage
+                      class={styles.smallArrow}
+                      src={smallArrow}
+                      previewDisabled></NImage>
+                  </div>
+                </NDropdown>
+              </div>
+              <div class={styles.listCore}>
+                <NRow class={styles.chioseCheckAllBox}>
+                  <NCheckbox
+                    onUpdateChecked={val => {
+                      chioseAllTargetStudent();
+                    }}
+                    checked={
+                      targetFitterList.value.length ===
+                      targetchioseStudent.value.length
+                    }
+                    indeterminate={
+                      targetchioseStudent.value.length > 0 &&
+                      targetFitterList.value.length !==
+                        targetchioseStudent.value.length
+                    }
+                    label="全选"></NCheckbox>
+                </NRow>
+                <NRow>
+                  <SearchInput
+                    {...{ placeholder: '请输入学生姓名' }}
+                    class={styles.searchInput}
+                    searchWord={targetSearch.value}
+                    onChangeValue={(val: string) =>
+                      (targetSearch.value = val)
+                    }></SearchInput>
+                </NRow>
+                <NScrollbar style="max-height: 204px;min-height: 204px;margin-top:14px;">
+                  <NCheckboxGroup v-model:value={targetchioseStudent.value}>
+                    {targetFitterList.value.map((item: any) => (
+                      <NRow class={styles.chioseCheckBox}>
+                        <NCheckbox
+                          value={item.value}
+                          label={item.label}></NCheckbox>
+                      </NRow>
+                    ))}
+                  </NCheckboxGroup>
+                </NScrollbar>
+              </div>
+              <div class={[styles.bottomRight, styles.bottom]}>
+                <div class={styles.bottomWrap}>
+                  共{targetStudentList.value.length}名学生
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <NSpace class={styles.btnGroup} justify="center">
+          <NButton round onClick={() => emit('close')}>
+            取消
+          </NButton>
+          <NButton
+            round
+            loading={data.uploading}
+            type="primary"
+            onClick={() => {
+              submitStudent();
+            }}>
+            保存
+          </NButton>
+        </NSpace>
+      </div>
+    );
+  }
+});

+ 2 - 3
src/views/login/api.ts

@@ -14,8 +14,7 @@ export const sendSms = (params: any) => {
  * 修改密码-
  */
 export const updatePassword = (params: any) => {
-  return request.post('/edu-app/user/updatePassword', {
-    data: params,
-    requestType: 'form'
+  return request.post('/edu-app/open/user/updatePassword', {
+    data: params
   });
 };

+ 10 - 8
src/views/login/components/forgotPassword.tsx

@@ -19,7 +19,7 @@ import { storage } from '@/utils/storage';
 import { useUserStore } from '/src/store/modules/users';
 import { sendSms, updatePassword } from '../api';
 interface FormState {
-  username: string;
+  mobile: string;
   password: string;
   grant_type: string;
   loginType: string;
@@ -42,7 +42,7 @@ export default defineComponent({
     const showPwd2 = ref(false);
     const userStore = useUserStore();
     const formInline = reactive({
-      username: '',
+      mobile: '',
       password: '',
       password1: '',
       code: '',
@@ -72,12 +72,14 @@ export default defineComponent({
           loading.value = true;
           try {
             await updatePassword({
-              ...formInline
+              ...formInline,
+              clientType: 'TEACHER'
             });
             message.success('修改成功');
             loading.value = false;
+
+            emit('changType');
             return false;
-            // emit('changType');
           } catch (e: any) {
             loading.value = false;
             message.error(e.msg);
@@ -90,14 +92,14 @@ export default defineComponent({
     };
 
     const sendMessage = async () => {
-      if (!formInline.username) {
+      if (!formInline.mobile) {
         message.error('请输入手机号');
         return;
       }
       try {
         const res = await sendSms({
           clientId: 'cooleshow-teacher',
-          mobile: formInline.username,
+          mobile: formInline.mobile,
           type: 'PASSWORD'
         });
         checkTimeOut();
@@ -132,13 +134,13 @@ export default defineComponent({
           size="large"
           model={formInline}>
           <NFormItem
-            path="username"
+            path="mobile"
             rule={[
               { required: true, message: '请输入手机号', trigger: 'blur' }
             ]}>
             <NInput
               maxlength={11}
-              v-model:value={formInline.username}
+              v-model:value={formInline.mobile}
               placeholder="请输入手机号">
               {{
                 prefix: () => (