lex 1 anno fa
parent
commit
80dbc21dd8
33 ha cambiato i file con 655 aggiunte e 165 eliminazioni
  1. 5 0
      src/api/user.ts
  2. BIN
      src/common/images/icon-download.png
  3. 21 5
      src/components/card-type/index.module.less
  4. 124 35
      src/components/card-type/index.tsx
  5. 1 1
      src/components/layout/index.tsx
  6. 38 22
      src/components/layout/layoutTop.tsx
  7. 2 2
      src/views/classList/api.ts
  8. 5 6
      src/views/classList/components/afterWork.tsx
  9. 3 3
      src/views/classList/components/afterWorkDetail.tsx
  10. 64 27
      src/views/classList/components/classStudent.tsx
  11. 4 4
      src/views/classList/components/testRecode.tsx
  12. 4 0
      src/views/classList/index.module.less
  13. 1 1
      src/views/home/components/practiceData.tsx
  14. 24 1
      src/views/login/components/codeLogin.tsx
  15. 11 0
      src/views/login/components/forgotPassword.tsx
  16. 24 3
      src/views/login/components/pwdLogin.tsx
  17. 4 1
      src/views/login/index.tsx
  18. 1 1
      src/views/natural-resources/components/my-collect/index.tsx
  19. 5 5
      src/views/natural-resources/components/my-collect/search-group-resources.tsx
  20. 1 0
      src/views/natural-resources/components/my-resources/index.tsx
  21. 1 1
      src/views/notation/index.tsx
  22. 1 4
      src/views/prepare-lessons/components/resource-main/components/resource-item/index.tsx
  23. 7 7
      src/views/prepare-lessons/components/resource-main/components/resource-item/resource-search-group/index.tsx
  24. 4 4
      src/views/prepare-lessons/model/select-resources/index.tsx
  25. 1 4
      src/views/prepare-lessons/model/select-resources/select-item/index.tsx
  26. 7 7
      src/views/prepare-lessons/model/select-resources/select-item/resource-search-group/index.tsx
  27. 5 0
      src/views/studentList/components/baseInfo.tsx
  28. 3 3
      src/views/studentList/components/practiceData.tsx
  29. 9 5
      src/views/studentList/components/studentAfterWork.tsx
  30. 4 0
      src/views/studentList/index.module.less
  31. 51 13
      src/views/studentList/index.tsx
  32. 16 0
      src/views/studentList/modals/update-student/index.module.less
  33. 204 0
      src/views/studentList/modals/update-student/index.tsx

+ 5 - 0
src/api/user.ts

@@ -55,3 +55,8 @@ export const suggestMessageUnread = (params?: any) => {
     params
   });
 };
+
+/** 曲谱详情 */
+export const api_musicSheetDetail = (data: any) => {
+  return request.get(`/edu-app/musicSheet/detail/${data}`);
+};

BIN
src/common/images/icon-download.png


+ 21 - 5
src/components/card-type/index.module.less

@@ -104,7 +104,7 @@
     display: flex;
     align-items: center;
     justify-content: space-between;
-
+    padding: 3px 0;
   }
 
   .title {
@@ -119,7 +119,7 @@
     .titleContent {
       padding-left: 6px;
       font-size: 16px;
-      max-width: 180px;
+      max-width: 160px;
       color: #131415;
       font-weight: 600 !important;
       flex: 1;
@@ -127,15 +127,32 @@
   }
 
   // 收藏按钮
+  .btnGroup {
+    position: absolute;
+    right: 12px;
+    display: flex;
+    align-items: center;
+
+    :global {
+      .n-spin-content {
+        display: flex;
+        align-items: center;
+      }
+    }
+  }
 
 
+  .btnItem+.btnItem {
+    margin-left: 12px;
+  }
+
   .iconCollect {
     width: 34px;
     height: 34px;
     // background: url('../../common/images/icon-collect-default.png') no-repeat center;
     // background-size: contain;
-    position: absolute;
-    right: 0;
+    // position: absolute;
+    // right: 0;
     transition: transform .2s ease;
 
     &:hover {
@@ -146,7 +163,6 @@
     &.isCollect {
       cursor: pointer;
     }
-
   }
 
   .iconDiv {

+ 124 - 35
src/components/card-type/index.tsx

@@ -1,6 +1,6 @@
 import { PropType, Transition, defineComponent, ref } from 'vue';
 import styles from './index.module.less';
-import { NButton, NCard, NImage, NModal } from 'naive-ui';
+import { NButton, NCard, NImage, NModal, NSpin, useMessage } from 'naive-ui';
 import iconImage from '@common/images/icon-image.png';
 import iconVideo from '@common/images/icon-video.png';
 import iconAudio from '@common/images/icon-audio.png';
@@ -8,10 +8,12 @@ import iconMusic from '@common/images/icon-music.png';
 import iconPPT from '@common/images/icon-ppt.png';
 import iconCollectDefault from '@common/images/icon-collect-default.png';
 import iconCollectActive from '@common/images/icon-collect-active.png';
+import iconDownload from '@common/images/icon-download.png';
 import TheNoticeBar from '../TheNoticeBar';
 import AudioPlayer from './audio-player';
 import VideoPlayer from './video-player';
 import { PageEnum } from '/src/enums/pageEnum';
+import { api_musicSheetDetail } from '/src/api/user';
 
 type itemType = {
   id: string | number;
@@ -75,6 +77,11 @@ export default defineComponent({
     offShelf: {
       type: Boolean,
       default: false
+    },
+    /** 是否可以下载 */
+    isDownload: {
+      type: Boolean,
+      default: false
     }
   },
   /**
@@ -85,7 +92,9 @@ export default defineComponent({
    */
   emits: ['click', 'collect', 'add', 'offShelf'],
   setup(props, { emit }) {
+    const message = useMessage();
     const isAnimation = ref(false);
+    const downloadStatus = ref(false);
     const formatType = (type: string) => {
       let typeImg = iconImage;
       switch (type) {
@@ -108,6 +117,71 @@ export default defineComponent({
       return typeImg;
     };
 
+    const downloadFile = (filename: string, fileUrl: string) => {
+      // 发起Fetch请求
+      fetch(fileUrl)
+        .then(response => response.blob())
+        .then(blob => {
+          // 创建一个Blob URL
+          const blobUrl = URL.createObjectURL(blob);
+
+          // 创建一个链接元素
+          const link = document.createElement('a');
+
+          // 设置链接的href属性为Blob URL
+          link.href = blobUrl;
+
+          // 设置下载时文件的名称
+          link.download = filename;
+
+          // 将链接元素添加到文档中
+          document.body.appendChild(link);
+
+          // 模拟点击链接以触发文件下载
+          link.click();
+
+          // 移除链接元素
+          document.body.removeChild(link);
+
+          // 释放Blob URL
+          URL.revokeObjectURL(blobUrl);
+
+          setTimeout(() => {
+            downloadStatus.value = false;
+          }, 100);
+        })
+        .catch(error => {
+          console.error('文件下载失败', error);
+          message.error('下载失败');
+        });
+
+      downloadStatus.value = false;
+    };
+
+    const onDownload = async (e: MouseEvent) => {
+      e.stopPropagation();
+      e.preventDefault();
+      const item = props.item;
+      if (!item.content) {
+        message.error('下载失败');
+        return;
+      }
+      if (downloadStatus.value) return false;
+      downloadStatus.value = true;
+      if (item.type === 'MUSIC') {
+        const { data } = await api_musicSheetDetail(item.content);
+        console.log(data, '1212');
+        // setTimeout(() => {
+        //   downloadStatus.value = false;
+        // }, 1000);
+      } else {
+        // const link = document.createElement('a');
+        const suffix: any = item.content?.split('.');
+        const fileName = item.title + '.' + suffix[suffix?.length - 1];
+        downloadFile(fileName, item.content);
+      }
+    };
+
     return () => (
       <div
         onClick={() => emit('click', props.item)}
@@ -217,40 +291,55 @@ export default defineComponent({
                   </span>
                 </div>
                 {/* 收藏 */}
-                {props.isShowCollect && (
-                  <div
-                    class={[styles.iconCollect, styles.iconDiv]}
-                    onClick={(e: MouseEvent) => {
-                      e.stopPropagation();
-                      e.preventDefault();
-                      // 判断是否可以收藏
-                      if (props.isCollect) {
-                        emit('collect', props.item);
-                      }
-                    }}>
-                    <Transition name="favitor" mode="out-in">
-                      {props.item.isCollect ? (
-                        <img
-                          src={iconCollectActive}
-                          key="1"
-                          class={[
-                            styles.iconCollect,
-                            props.isCollect ? styles.isCollect : ''
-                          ]}
-                        />
-                      ) : (
-                        <img
-                          src={iconCollectDefault}
-                          key="2"
-                          class={[
-                            styles.iconCollect,
-                            props.isCollect ? styles.isCollect : ''
-                          ]}
-                        />
-                      )}
-                    </Transition>
-                  </div>
-                )}
+                <div class={styles.btnGroup}>
+                  {props.isDownload && (
+                    <NSpin
+                      show={downloadStatus.value}
+                      class={styles.btnItem}
+                      size={'small'}>
+                      <img
+                        src={iconDownload}
+                        key="3"
+                        class={[styles.iconCollect]}
+                        onClick={onDownload}
+                      />
+                    </NSpin>
+                  )}
+                  {props.isShowCollect && (
+                    <div
+                      class={[styles.iconCollect, styles.btnItem]}
+                      onClick={(e: MouseEvent) => {
+                        e.stopPropagation();
+                        e.preventDefault();
+                        // 判断是否可以收藏
+                        if (props.isCollect) {
+                          emit('collect', props.item);
+                        }
+                      }}>
+                      <Transition name="favitor" mode="out-in">
+                        {props.item.isCollect ? (
+                          <img
+                            src={iconCollectActive}
+                            key="1"
+                            class={[
+                              styles.iconCollect,
+                              props.isCollect ? styles.isCollect : ''
+                            ]}
+                          />
+                        ) : (
+                          <img
+                            src={iconCollectDefault}
+                            key="2"
+                            class={[
+                              styles.iconCollect,
+                              props.isCollect ? styles.isCollect : ''
+                            ]}
+                          />
+                        )}
+                      </Transition>
+                    </div>
+                  )}
+                </div>
 
                 {/* 精选 */}
                 {props.item.isSelected && (

+ 1 - 1
src/components/layout/index.tsx

@@ -705,7 +705,7 @@ export default defineComponent({
                   startShowModal('iconNote');
                 }}>
                 <img src={iconNote} alt="" />
-                帮助指引
+                功能引导
               </div>
 
               <div

+ 38 - 22
src/components/layout/layoutTop.tsx

@@ -159,14 +159,23 @@ export default defineComponent({
               displayDirective="show"
               v-slots={{
                 trigger: () => (
-                  <div class={styles.optons}>
-                    <NImage src={classHistoryIcon} previewDisabled></NImage>
-                  </div>
+                  <NTooltip showArrow={false}>
+                    {{
+                      trigger: () => (
+                        <div class={styles.optons}>
+                          <NImage
+                            src={classHistoryIcon}
+                            previewDisabled></NImage>
+                        </div>
+                      ),
+                      default: '上课记录'
+                    }}
+                  </NTooltip>
                 )
               }}>
               <ClassModal />
             </NPopover>
-            <NTooltip>
+            <NTooltip showArrow={false}>
               {{
                 trigger: () => (
                   <div class={styles.optons} onClick={showOption}>
@@ -180,24 +189,31 @@ export default defineComponent({
             </NTooltip>
             {/* </div> */}
             <div onClick={() => (showImGroup.value = true)}>
-              <NBadge
-                value={noReadCount.value}
-                max={99}
-                class={[
-                  noReadCount.value > 0 ? '' : styles.messageBadgeHide,
-                  styles.messageBadge,
-                  noReadCount.value > 0 ? '' : styles.messageBadgeNo
-                ]}
-                {...{ id: 'home-2' }}
-                color={'#FF1036'}>
-                <NImage
-                  class={[
-                    styles.messageIcon,
-                    noReadCount.value > 0 ? styles.animation : ''
-                  ]}
-                  preview-disabled
-                  src={messageIcon}></NImage>
-              </NBadge>
+              <NTooltip showArrow={false}>
+                {{
+                  trigger: () => (
+                    <NBadge
+                      value={noReadCount.value}
+                      max={99}
+                      class={[
+                        noReadCount.value > 0 ? '' : styles.messageBadgeHide,
+                        styles.messageBadge,
+                        noReadCount.value > 0 ? '' : styles.messageBadgeNo
+                      ]}
+                      {...{ id: 'home-2' }}
+                      color={'#FF1036'}>
+                      <NImage
+                        class={[
+                          styles.messageIcon,
+                          noReadCount.value > 0 ? styles.animation : ''
+                        ]}
+                        preview-disabled
+                        src={messageIcon}></NImage>
+                    </NBadge>
+                  ),
+                  default: '聊天'
+                }}
+              </NTooltip>
             </div>
 
             <div class={styles.line}></div>

+ 2 - 2
src/views/classList/api.ts

@@ -131,7 +131,7 @@ export const getCourseChapter = (params: any) => {
 };
 
 /**
- * 获取学生训练详情
+ * 获取学生作业详情
  */
 
 export const getTrainingStudentDetail = (params: any) => {
@@ -151,7 +151,7 @@ export const getTrainingStat = (params: any) => {
 };
 
 /**
- * 获取班级训练详情
+ * 获取班级作业详情
  */
 export const getTrainingClassDetail = (params: any) => {
   return request.get(`/edu-app/lessonTraining/trainingDetail`, {

+ 5 - 6
src/views/classList/components/afterWork.tsx

@@ -40,7 +40,6 @@ export default defineComponent({
       getNowDateAndMonday(new Date().getTime()),
       getNowDateAndSunday(new Date().getTime())
     ]);
-    console.log(route.query, 'query');
     const state = reactive({
       upgradeFlag: props.upgradeFlag == 0 ? true : false, // 是否为历史班
       searchForm: {
@@ -126,7 +125,7 @@ export default defineComponent({
           }
         },
         {
-          title: '训练状态',
+          title: '作业状态',
           key: 'status',
           render(row: any) {
             return row.status == 0 ? (
@@ -190,7 +189,7 @@ export default defineComponent({
                   text
                   type="primary"
                   onClick={() => lookWorkDetail(row)}>
-                  训练详情
+                  作业详情
                 </NButton>
               </NSpace>
             );
@@ -231,7 +230,7 @@ export default defineComponent({
                 {...({
                   options: [
                     {
-                      label: '训练状态',
+                      label: '作业状态',
                       value: null
                     },
                     {
@@ -243,7 +242,7 @@ export default defineComponent({
                       value: 0
                     }
                   ],
-                  placeholder: '训练状态',
+                  placeholder: '作业状态',
                   clearable: true,
                   inline: true
                 } as any)}
@@ -309,7 +308,7 @@ export default defineComponent({
           v-model:show={state.detailVisiable}
           preset="card"
           class={['modalTitle background', styles.wordDetailModel]}
-          title={'训练详情'}>
+          title={'作业详情'}>
           <ClassTrainingDetails
             onClose={() => (state.detailVisiable = false)}
             activeRow={state.activeRow}></ClassTrainingDetails>

+ 3 - 3
src/views/classList/components/afterWorkDetail.tsx

@@ -280,8 +280,8 @@ export default defineComponent({
         </NButton> */}
           <div class={styles.tableWrap}>
             <NDataTable
-               v-slots={{
-                empty:()=><TheEmpty></TheEmpty>
+              v-slots={{
+                empty: () => <TheEmpty></TheEmpty>
               }}
               class={styles.classTable}
               loading={state.loading}
@@ -300,7 +300,7 @@ export default defineComponent({
           v-model:show={state.detailVisiable}
           preset="card"
           class={['modalTitle background', styles.wordDetailModel]}
-          title={'训练详情'}>
+          title={'作业详情'}>
           <TrainingDetails
             onNext={() => goToNext()}
             onPre={() => gotoPre()}

+ 64 - 27
src/views/classList/components/classStudent.tsx

@@ -5,18 +5,18 @@ import {
   NDataTable,
   NForm,
   NFormItem,
-  NImage,
-  NSelect,
+  NModal,
   NSpace,
+  NTooltip,
   useMessage
 } from 'naive-ui';
 import SearchInput from '@/components/searchInput';
 import CSelect from '@/components/CSelect';
 import Pagination from '@/components/pagination';
-import { classGroupDetail, getStudentList } from '../api';
-import add from './images/add.png';
+import { getStudentList } from '../api';
 import { useRoute, useRouter } from 'vue-router';
 import TheEmpty from '/src/components/TheEmpty';
+import UpdateStudent from '../../studentList/modals/update-student';
 export default defineComponent({
   name: 'student-studentList',
   props: {
@@ -24,7 +24,7 @@ export default defineComponent({
       type: Number
     }
   },
-  setup(props, { emit }) {
+  setup(props) {
     const message = useMessage();
     const route = useRoute();
     const router = useRouter();
@@ -38,7 +38,9 @@ export default defineComponent({
         rows: 10,
         pageTotal: 4
       },
-      tableList: [] as any
+      tableList: [] as any,
+      editStatus: false,
+      activeRow: {} as any
     });
 
     watch(
@@ -108,11 +110,18 @@ export default defineComponent({
           key: 'nickname',
           render: (row: any) => {
             return (
-              <div
-                style={{ userSelect: 'all', cursor: 'pointer' }}
-                onClick={() => copyTo(row.nickname)}>
-                {row.nickname}
-              </div>
+              <NTooltip showArrow={false} placement="top-start">
+                {{
+                  trigger: () => (
+                    <div
+                      style={{ userSelect: 'all', cursor: 'pointer' }}
+                      onClick={() => copyTo(row.nickname)}>
+                      {row.nickname}
+                    </div>
+                  ),
+                  default: '点击复制'
+                }}
+              </NTooltip>
             );
           }
         },
@@ -121,11 +130,18 @@ export default defineComponent({
           key: 'phone',
           render: (row: any) => {
             return (
-              <div
-                style={{ userSelect: 'all', cursor: 'pointer' }}
-                onClick={() => copyTo(row.phone)}>
-                {row.phone}
-              </div>
+              <NTooltip showArrow={false} placement="top-start">
+                {{
+                  trigger: () => (
+                    <div
+                      style={{ userSelect: 'all', cursor: 'pointer' }}
+                      onClick={() => copyTo(row.phone)}>
+                      {row.phone}
+                    </div>
+                  ),
+                  default: '点击复制'
+                }}
+              </NTooltip>
             );
           }
         },
@@ -144,27 +160,36 @@ export default defineComponent({
             );
           }
         },
-
-        // {
-        //   title: '学生类型',
-        //   key: 'studentType',
-        //   render(row: any) {
-        //     return <>{row.studentType == 'member' ? '会员' : '普通'}</>;
-        //   }
-        // },
+        {
+          title: '学生类型',
+          key: 'vipMember',
+          render(row: any) {
+            return <>{row.vipMember ? '会员' : '普通'}</>;
+          }
+        },
         {
           title: '操作',
           key: 'id',
           render(row: any) {
             return (
-              <NButton text type="primary" onClick={() => gotoDetail(row)}>
-                详情
-              </NButton>
+              <NSpace>
+                <NButton text type="primary" onClick={() => gotoDetail(row)}>
+                  详情
+                </NButton>
+                <NButton text type="primary" onClick={() => onUpdate(row)}>
+                  修改
+                </NButton>
+              </NSpace>
             );
           }
         }
       ];
     };
+    // 修改
+    const onUpdate = (row: any) => {
+      state.editStatus = true;
+      state.activeRow = row;
+    };
     return () => (
       <div>
         <div class={styles.searchList}>
@@ -248,6 +273,18 @@ export default defineComponent({
             sync
           />
         </div>
+
+        <NModal
+          v-model:show={state.editStatus}
+          class={['modalTitle background', styles.updateStudent]}
+          preset="card"
+          title="修改信息">
+          <UpdateStudent
+            onClose={() => (state.editStatus = false)}
+            onConfirm={() => getList()}
+            row={state.activeRow}
+          />
+        </NModal>
       </div>
     );
   }

+ 4 - 4
src/views/classList/components/testRecode.tsx

@@ -128,7 +128,7 @@ export default defineComponent({
     const columns = () => {
       return [
         {
-          title: '姓名',
+          title: '学生姓名',
           key: 'studentName'
         },
         {
@@ -165,7 +165,7 @@ export default defineComponent({
           }
         },
         {
-          title: '练时长',
+          title: '练时长',
           key: 'studentType',
           render(row: any) {
             return (
@@ -177,7 +177,7 @@ export default defineComponent({
                       getSecend(row.practiceDuration) +
                       '秒'
                     : getSecend(row.practiceDuration) + '秒'
-                  : 0}
+                  : 0 + '秒'}
               </>
             );
           }
@@ -318,7 +318,7 @@ export default defineComponent({
                   </div>
                 </p>
-                <p class={styles.TrainDataItemsubTitle}>平均练习时长</p>
+                <p class={styles.TrainDataItemsubTitle}>平均每天练习时长</p>
               </div>
             </NGi>
           </NGrid>

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

@@ -755,4 +755,8 @@
 
 .nextWrap {
   padding: 30px 32px 0 !important;
+}
+
+.updateStudent {
+  width: 480px;
 }

+ 1 - 1
src/views/home/components/practiceData.tsx

@@ -61,7 +61,7 @@ export default defineComponent({
           }
         },
         {
-          title: '平均练习时长(分钟)',
+          title: '平均练习时长',
           key: 'practiceDuration',
           render(row: any) {
             return (

+ 24 - 1
src/views/login/components/codeLogin.tsx

@@ -30,6 +30,13 @@ interface FormState {
 
 export default defineComponent({
   name: 'codeLogin',
+  props: {
+    phone: {
+      type: String,
+      default: ''
+    }
+  },
+  emits: ['update:phone'],
   setup(props, { emit }) {
     const router = useRouter();
     const route = useRoute();
@@ -52,6 +59,19 @@ export default defineComponent({
     if (formInlineHistory) {
       formInline.username = JSON.parse(formInlineHistory).username;
     }
+
+    if (formInline.username) {
+      if (formInline.username !== props.phone && props.phone) {
+        formInline.username = props.phone;
+      } else {
+        emit('update:phone', formInline.username);
+      }
+    } else {
+      if (props.phone) {
+        formInline.username = props.phone;
+      }
+    }
+
     const handleSubmit = async () => {
       formRef.value.validate(async (errors: any) => {
         if (!errors) {
@@ -152,7 +172,10 @@ export default defineComponent({
             <NInput
               maxlength={11}
               v-model:value={formInline.username}
-              placeholder="请输入手机号">
+              placeholder="请输入手机号"
+              onInput={(val: any) => {
+                emit('update:phone', val);
+              }}>
               {{
                 prefix: () => (
                   <img src={useIcon} class={styles.prefixIcon} alt="" />

+ 11 - 0
src/views/login/components/forgotPassword.tsx

@@ -29,6 +29,12 @@ interface FormState {
 
 export default defineComponent({
   name: 'forgotPassword',
+  props: {
+    phone: {
+      type: String,
+      default: ''
+    }
+  },
   emits: ['changType'],
   setup(props, { emit }) {
     const router = useRouter();
@@ -65,6 +71,11 @@ export default defineComponent({
       }
     };
 
+    // 初始化手机号
+    if (props.phone) {
+      formInline.mobile = props.phone;
+    }
+
     const handleSubmit = async () => {
       formRef.value.validate(async (errors: any) => {
         if (!errors) {

+ 24 - 3
src/views/login/components/pwdLogin.tsx

@@ -30,7 +30,13 @@ interface FormState {
 
 export default defineComponent({
   name: 'codeLogin',
-  emits: ['changType'],
+  props: {
+    phone: {
+      type: String,
+      default: ''
+    }
+  },
+  emits: ['changType', 'update:phone'],
   setup(props, { emit }) {
     const router = useRouter();
     const route = useRoute();
@@ -51,6 +57,19 @@ export default defineComponent({
     if (formInlineHistory) {
       formInline = reactive({ ...JSON.parse(formInlineHistory) });
     }
+
+    if (formInline.username) {
+      if (formInline.username !== props.phone && props.phone) {
+        formInline.username = props.phone;
+      } else {
+        emit('update:phone', formInline.username);
+      }
+    } else {
+      if (props.phone) {
+        formInline.username = props.phone;
+      }
+    }
+
     const handleSubmit = async () => {
       formRef.value.validate(async (errors: any) => {
         if (!errors) {
@@ -111,7 +130,10 @@ export default defineComponent({
             <NInput
               maxlength={11}
               v-model:value={formInline.username}
-              placeholder="请输入用户名">
+              placeholder="请输入用户名"
+              onInput={(val: any) => {
+                emit('update:phone', val);
+              }}>
               {{
                 prefix: () => (
                   <img src={useIcon} class={styles.prefixIcon} alt="" />
@@ -130,7 +152,6 @@ export default defineComponent({
               inputProps={{ autocomplete: 'off' }}
               class={[showPwd.value ? '' : styles['no-pwd']]}
               onKeydown={(e: KeyboardEvent) => {
-                console.log(e.code);
                 if (e.code === 'Enter' || e.code === 'NumpadEnter') {
                   handleSubmit();
                 }

+ 4 - 1
src/views/login/index.tsx

@@ -37,6 +37,7 @@ export default defineComponent({
     const forgotPasswordRef = ref();
     const popEvent = ref();
     const dialog = useDialog();
+    const userPhone = ref(); // 用户手机号
     const showModalMask = ref(false);
     const checkInstall = async (event: any) => {
       event.preventDefault();
@@ -143,6 +144,7 @@ export default defineComponent({
               justify-content="center">
               <NTabPane name="forgotPassword" tab="重置密码">
                 <ForgotPassword
+                  v-model:phone={userPhone.value}
                   onChangType={() => {
                     isForgot.value = false;
                     NavsValue.value = 'pwdLogin';
@@ -159,6 +161,7 @@ export default defineComponent({
               justify-content="center">
               <NTabPane name="pwdLogin" tab="密码登录">
                 <PwdLogin
+                  v-model:phone={userPhone.value}
                   onChangType={() => {
                     isForgot.value = true;
                     NavsValue.value = 'forgotPassword';
@@ -166,7 +169,7 @@ export default defineComponent({
                   }}></PwdLogin>
               </NTabPane>
               <NTabPane name="codeLogin" tab="短信验证">
-                <CodeLogin></CodeLogin>
+                <CodeLogin v-model:phone={userPhone.value}></CodeLogin>
               </NTabPane>
             </NTabs>
           )}

+ 1 - 1
src/views/natural-resources/components/my-collect/index.tsx

@@ -22,7 +22,7 @@ export default defineComponent({
         rows: 20
       },
       searchGroup: {
-        type: '', //
+        type: 'MUSIC', //
         name: '',
         bookVersionId: null,
         subjectId: null,

+ 5 - 5
src/views/natural-resources/components/my-collect/search-group-resources.tsx

@@ -13,7 +13,7 @@ export default defineComponent({
     const catchStore = useCatchStore();
     const resourceList = ref([] as any[]);
     const forms = reactive({
-      type: '', //
+      type: 'MUSIC', //
       name: '',
       bookVersionId: null,
       subjectId: null
@@ -70,10 +70,10 @@ export default defineComponent({
 
     onMounted(async () => {
       resourceList.value = [
-        {
-          label: '全部',
-          value: ''
-        },
+        // {
+        //   label: '全部',
+        //   value: ''
+        // },
         ...resourceTypeArray
       ];
 

+ 1 - 0
src/views/natural-resources/components/my-resources/index.tsx

@@ -212,6 +212,7 @@ export default defineComponent({
                 <div class={styles.itemWrapBox}>
                   <CardType
                     item={item}
+                    isDownload
                     disabledMouseHover={false}
                     offShelf={item.enableFlag ? false : true}
                     onOffShelf={() => {

+ 1 - 1
src/views/notation/index.tsx

@@ -27,7 +27,7 @@ export default defineComponent({
             'https://test.lexiaoya.cn'
           : // 'http://localhost:3050'
             location.origin
-      }/notation/#/create?v=${Date.now()}&Authorization=${Authorization}${openCreateUrl}`
+      }/notation/?t=${Date.now()}#/create?v=${Date.now()}&Authorization=${Authorization}${openCreateUrl}`
       //   src: `http://localhost:3050/#/create?Authorization=${Authorization}`
     });
     const fscreen = () => {

+ 1 - 4
src/views/prepare-lessons/components/resource-main/components/resource-item/index.tsx

@@ -40,10 +40,7 @@ export default defineComponent({
         rows: 20
       },
       searchGroup: {
-        type:
-          props.type === 'shareResources' || props.type === 'myResources'
-            ? 'MUSIC'
-            : '', //
+        type: 'MUSIC', //
         name: '',
         bookVersionId: null,
         subjectId: null,

+ 7 - 7
src/views/prepare-lessons/components/resource-main/components/resource-item/resource-search-group/index.tsx

@@ -32,13 +32,13 @@ export default defineComponent({
     onMounted(async () => {
       // 获取教材分类列表
       await catchStore.getMusicSheetCategory();
-      if (props.type === 'myCollect') {
-        resourceType.value.push({
-          label: '全部',
-          value: ''
-        });
-        forms.type = ''; // 默认全部
-      }
+      // if (props.type === 'myCollect') {
+      //   resourceType.value.push({
+      //     label: '全部',
+      //     value: ''
+      //   });
+      //   forms.type = ''; // 默认全部
+      // }
       resourceTypeArray.forEach((item: any) => {
         // if (props.type === 'myResources') {
         //   item.value !== 'MUSIC' && resourceType.value.push(item);

+ 4 - 4
src/views/prepare-lessons/model/select-resources/index.tsx

@@ -18,10 +18,10 @@ export default defineComponent({
     const tabType = ref(type.value);
 
     onMounted(() => {
-      console.log(
-        document.querySelector('.select-resource .n-tabs-nav--top'),
-        ''
-      );
+      // console.log(
+      //   document.querySelector('.select-resource .n-tabs-nav--top'),
+      //   ''
+      // );
       useResizeObserver(
         document.querySelector(
           '.select-resource .n-tabs-nav--top'

+ 1 - 4
src/views/prepare-lessons/model/select-resources/select-item/index.tsx

@@ -50,10 +50,7 @@ export default defineComponent({
         rows: 20
       },
       searchGroup: {
-        type:
-          type.value === 'shareResources' || type.value === 'myResources'
-            ? 'MUSIC'
-            : '', //
+        type: 'MUSIC', //
         name: '',
         bookVersionId: null,
         subjectId: prepareStore.getSubjectId,

+ 7 - 7
src/views/prepare-lessons/model/select-resources/select-item/resource-search-group/index.tsx

@@ -92,13 +92,13 @@ export default defineComponent({
       }
     };
     onMounted(async () => {
-      if (props.type === 'myCollect') {
-        resourceType.value.push({
-          label: '全部',
-          value: ''
-        });
-        forms.type = ''; // 默认全部
-      }
+      // if (props.type === 'myCollect') {
+      //   resourceType.value.push({
+      //     label: '全部',
+      //     value: ''
+      //   });
+      //   forms.type = ''; // 默认全部
+      // }
       resourceTypeArray.forEach((item: any) => {
         // if (props.type === 'myResources') {
         //   item.value !== 'MUSIC' && resourceType.value.push(item);

+ 5 - 0
src/views/studentList/components/baseInfo.tsx

@@ -109,6 +109,8 @@ export default defineComponent({
       studentForm.currentClass = props.studentInfo.currentClass;
       data.disabled = true;
     };
+
+    const onlyAllowNumber = (value: string) => !value || /^\d+$/.test(value);
     return () => (
       <div class={styles.infoWrap}>
         <div class={styles.setInfo}>
@@ -124,6 +126,7 @@ export default defineComponent({
                     trigger: 'blur'
                   }}>
                   <NInput
+                    maxlength={15}
                     bordered={!data.disabled}
                     placeholder="请填写学生姓名"
                     v-model:value={studentForm.nickname}></NInput>
@@ -146,6 +149,8 @@ export default defineComponent({
                     }
                   ]}>
                   <NInput
+                    maxlength={11}
+                    allowInput={onlyAllowNumber}
                     bordered={!data.disabled}
                     placeholder="请填写学生手机号"
                     v-model:value={studentForm.phone}></NInput>

+ 3 - 3
src/views/studentList/components/practiceData.tsx

@@ -348,7 +348,7 @@ export default defineComponent({
                     <i style={{ width: '4px', display: 'inline-block' }}></i>秒
                   </div>
                 </p>
-                <p class={styles.TrainDataItemsubTitle}>平均练习时长</p>
+                <p class={styles.TrainDataItemsubTitle}>平均每天练习时长</p>
               </div>
               <div class={styles.TrainDataItem}>
                 <p class={styles.TrainDataItemTitle}>
@@ -390,8 +390,8 @@ export default defineComponent({
           </div>
           <div class={styles.tableWrap}>
             <NDataTable
-               v-slots={{
-                empty:()=><TheEmpty></TheEmpty>
+              v-slots={{
+                empty: () => <TheEmpty></TheEmpty>
               }}
               class={styles.classTable}
               loading={state.loading}

+ 9 - 5
src/views/studentList/components/studentAfterWork.tsx

@@ -156,10 +156,14 @@ export default defineComponent({
             return (
               <div>
                 {row.trainingStatus == 'UNSUBMITTED' ? (
-                  <p class={styles.nosub} style={{color:'#aaa'}}>未提交</p>
+                  <p class={styles.nosub} style={{ color: '#aaa' }}>
+                    未提交
+                  </p>
                 ) : null}
                 {row.trainingStatus == 'SUBMITTED' ? (
-                  <p style={{color:'#EA4132'}} class={styles.ison}>不合格</p>
+                  <p style={{ color: '#EA4132' }} class={styles.ison}>
+                    不合格
+                  </p>
                 ) : null}
                 {row.trainingStatus == 'TARGET' ? (
                   <p class={styles.isok}>合格</p>
@@ -250,8 +254,8 @@ export default defineComponent({
           </div>
           <div>
             <NDataTable
-               v-slots={{
-                empty:()=><TheEmpty></TheEmpty>
+              v-slots={{
+                empty: () => <TheEmpty></TheEmpty>
               }}
               class={styles.classTable}
               loading={state.loading}
@@ -270,7 +274,7 @@ export default defineComponent({
           v-model:show={state.detailVisiable}
           preset="card"
           class={['modalTitle background', styles.wordDetailModel]}
-          title={'训练详情'}>
+          title={'作业详情'}>
           <StudentTraomomhDetails
             // onNext={() => goToNext()}
             // onPre={() => gotoPre()}

+ 4 - 0
src/views/studentList/index.module.less

@@ -585,4 +585,8 @@
       }
     }
   }
+}
+
+.updateStudent {
+  width: 480px;
 }

+ 51 - 13
src/views/studentList/index.tsx

@@ -9,6 +9,7 @@ import {
   NModal,
   NSelect,
   NSpace,
+  NTooltip,
   useMessage
 } from 'naive-ui';
 import SearchInput from '@/components/searchInput';
@@ -21,8 +22,9 @@ import { classGroupList } from '@/views/classList/api';
 import AddStudentModel from './modals/addStudentModel';
 import Studentguide from '@/custom-plugins/guide-page/student-guide';
 import TheEmpty from '/src/components/TheEmpty';
-import NoticeModal from './modals/noticeModal';
+// import NoticeModal from './modals/noticeModal';
 import { useUserStore } from '/src/store/modules/users';
+import UpdateStudent from './modals/update-student';
 export default defineComponent({
   name: 'student-studentList',
   setup(props, { emit }) {
@@ -49,6 +51,7 @@ export default defineComponent({
       tableList: [] as any,
       classList: [],
       addStudentVisible: false,
+      editStatus: false,
       activeRow: {} as any
     });
     const route = useRoute();
@@ -121,11 +124,18 @@ export default defineComponent({
           key: 'nickname',
           render: (row: any) => {
             return (
-              <div
-                style={{ userSelect: 'all', cursor: 'pointer' }}
-                onClick={() => copyTo(row.nickname)}>
-                {row.nickname}
-              </div>
+              <NTooltip showArrow={false} placement="top-start">
+                {{
+                  trigger: () => (
+                    <div
+                      style={{ userSelect: 'all', cursor: 'pointer' }}
+                      onClick={() => copyTo(row.nickname)}>
+                      {row.nickname}
+                    </div>
+                  ),
+                  default: '点击复制'
+                }}
+              </NTooltip>
             );
           }
         },
@@ -134,11 +144,18 @@ export default defineComponent({
           key: 'phone',
           render: (row: any) => {
             return (
-              <div
-                style={{ userSelect: 'all', cursor: 'pointer' }}
-                onClick={() => copyTo(row.phone)}>
-                {row.phone}
-              </div>
+              <NTooltip showArrow={false} placement="top-start">
+                {{
+                  trigger: () => (
+                    <div
+                      style={{ userSelect: 'all', cursor: 'pointer' }}
+                      onClick={() => copyTo(row.phone)}>
+                      {row.phone}
+                    </div>
+                  ),
+                  default: '点击复制'
+                }}
+              </NTooltip>
             );
           }
         },
@@ -175,7 +192,7 @@ export default defineComponent({
           width: 300,
           render(row: any, index: number) {
             return (
-              <>
+              <NSpace>
                 {index == 0 ? (
                   <NButton
                     {...{ id: 'student-1' }}
@@ -189,7 +206,10 @@ export default defineComponent({
                     详情
                   </NButton>
                 )}
-              </>
+                <NButton text type="primary" onClick={() => onUpdate(row)}>
+                  修改
+                </NButton>
+              </NSpace>
             );
           }
         }
@@ -202,6 +222,12 @@ export default defineComponent({
         query: { ...route.query, studentId: row.id, studentName: row.nickname }
       });
     };
+
+    // 修改
+    const onUpdate = (row: any) => {
+      state.editStatus = true;
+      state.activeRow = row;
+    };
     return () => (
       <div class={styles.listWrap}>
         <div class={styles.searchList}>
@@ -358,6 +384,18 @@ export default defineComponent({
             onClose={() => (state.addStudentVisible = false)}
           />
         </NModal> */}
+
+        <NModal
+          v-model:show={state.editStatus}
+          class={['modalTitle background', styles.updateStudent]}
+          preset="card"
+          title="修改信息">
+          <UpdateStudent
+            onClose={() => (state.editStatus = false)}
+            onConfirm={() => getList()}
+            row={state.activeRow}
+          />
+        </NModal>
         {showGuide.value ? <Studentguide></Studentguide> : null}
       </div>
     );

+ 16 - 0
src/views/studentList/modals/update-student/index.module.less

@@ -0,0 +1,16 @@
+.updateStudentContainer {
+  padding: 24px 30px;
+
+
+  .updateBtnGroup {
+    padding: 0;
+    justify-content: center !important;
+
+    :global {
+      .n-button {
+        height: 48px !important;
+        min-width: 156px;
+      }
+    }
+  }
+}

+ 204 - 0
src/views/studentList/modals/update-student/index.tsx

@@ -0,0 +1,204 @@
+import {
+  NButton,
+  NForm,
+  NFormItem,
+  NInput,
+  NSelect,
+  NSpace,
+  NSpin,
+  useMessage
+} from 'naive-ui';
+import { defineComponent, onMounted, reactive, ref } from 'vue';
+import styles from './index.module.less';
+import { gradeToCN } from '/src/utils/contants';
+import { classGroupList } from '/src/views/home/api';
+import { resetStudentInfo } from '../../api';
+import { classArray, getgradeNumList } from '/src/views/classList/contants';
+
+export default defineComponent({
+  name: 'update-student',
+  props: {
+    row: {
+      type: Object,
+      default: () => ({})
+    }
+  },
+  emits: ['close', 'confirm'],
+  setup(props, { emit }) {
+    const message = useMessage();
+    const state = reactive({
+      uploading: false,
+      gradeList: [] as any,
+      classList: [] as any
+    });
+    const forms = reactive({
+      phone: null,
+      nickname: null,
+      gender: null,
+      currentGradeNum: null,
+      //  expireDate: dayjs().add(7, 'day').format('YYYY-MM-DD') as any, // 默认7天
+      currentClass: null as any
+    });
+
+    const gradeNumList = ref(getgradeNumList());
+    const classArrayRef = ref([...classArray] as any);
+    const formsRef = ref();
+
+    const onSubmit = async () => {
+      formsRef.value?.validate(async (err: any) => {
+        if (err) {
+          return;
+        }
+        state.uploading = true;
+        try {
+          await resetStudentInfo({
+            ...forms,
+            id: props.row.id,
+            schoolId: props.row.schoolId,
+            tenantId: props.row.tenantId
+          });
+          message.success('修改成功');
+          emit('confirm');
+          emit('close');
+        } catch {
+          //
+        }
+        state.uploading = false;
+      });
+    };
+
+    onMounted(async () => {
+      const row = props.row;
+      if (row.id) {
+        forms.nickname = row.nickname;
+        forms.phone = row.phone;
+        forms.gender = row.gender;
+        forms.currentGradeNum = row.currentGradeNum;
+        forms.currentClass = row.currentClass;
+      }
+    });
+
+    const onlyAllowNumber = (value: string) => !value || /^\d+$/.test(value);
+    return () => (
+      <div class={styles.updateStudentContainer}>
+        <NForm
+          ref={formsRef}
+          model={forms}
+          labelAlign="right"
+          labelWidth={'auto'}
+          labelPlacement="left">
+          <NFormItem
+            label="姓名"
+            path="nickname"
+            rule={{
+              required: true,
+              message: '请填写学生姓名',
+              trigger: 'blur'
+            }}>
+            <NInput
+              maxlength={15}
+              placeholder="请填写学生姓名"
+              v-model:value={forms.nickname}></NInput>
+          </NFormItem>
+          <NFormItem
+            label="手机号"
+            path="phone"
+            rule={[
+              {
+                required: true,
+                message: '请填写学生手机号',
+                trigger: 'blur'
+              },
+              {
+                pattern: /^1[3456789]\d{9}$/,
+                message: '手机号格式不正确',
+                trigger: 'blur'
+              }
+            ]}>
+            <NInput
+              maxlength={11}
+              allowInput={onlyAllowNumber}
+              placeholder="请填写学生手机号"
+              v-model:value={forms.phone}></NInput>
+          </NFormItem>
+          <NFormItem
+            label="性别"
+            path="gender"
+            rule={[
+              {
+                required: true,
+                message: '请选择性别',
+                trigger: 'blur',
+                type: 'number'
+              }
+            ]}>
+            <NSelect
+              class={styles.select}
+              clearable
+              filterable
+              placeholder="请选择性别"
+              options={[
+                { label: '男', value: 1 },
+                { label: '女', value: 0 }
+              ]}
+              v-model:value={forms.gender}
+            />
+          </NFormItem>
+          <NFormItem
+            label="年级"
+            path="currentGradeNum"
+            rule={[
+              {
+                required: true,
+                message: '请选择年级',
+                trigger: 'change',
+                type: 'number'
+              }
+            ]}>
+            <NSelect
+              v-model:value={forms.currentGradeNum}
+              placeholder="请选择年级"
+              options={gradeNumList.value as any}
+              clearable
+              filterable
+            />
+          </NFormItem>
+          <NFormItem
+            label="班级"
+            path="currentClass"
+            rule={[
+              {
+                required: true,
+                message: '请选择班级',
+                trigger: 'change',
+                type: 'number'
+              }
+            ]}>
+            <NSelect
+              filterable
+              v-model:value={forms.currentClass}
+              placeholder="请选择班级"
+              clearable
+              options={classArrayRef.value as any}
+            />
+          </NFormItem>
+
+          <NSpace class={styles.updateBtnGroup}>
+            <NButton strong type="default" round onClick={() => emit('close')}>
+              取消
+            </NButton>
+            <NButton
+              strong
+              type="primary"
+              round
+              disabled={state.uploading}
+              loading={state.uploading}
+              onClick={onSubmit}>
+              确认
+            </NButton>
+          </NSpace>
+        </NForm>
+      </div>
+    );
+  }
+});