Bladeren bron

资源 上课布置作业

lex 1 jaar geleden
bovenliggende
commit
64febde000
28 gewijzigde bestanden met toevoegingen van 1545 en 17 verwijderingen
  1. 1 1
      src/components/layout/layoutSilder.tsx
  2. 8 0
      src/router/routes/index.ts
  3. 39 0
      src/styles/index.less
  4. BIN
      src/views/attend-class/image/icon-note.png
  5. 8 1
      src/views/attend-class/index.module.less
  6. 28 8
      src/views/attend-class/index.tsx
  7. 31 0
      src/views/attend-class/model/train-settings/index.module.less
  8. 68 6
      src/views/attend-class/model/train-settings/index.tsx
  9. 23 0
      src/views/attend-class/model/train-type/images/e-delete.svg
  10. 23 0
      src/views/attend-class/model/train-type/images/e-edit.svg
  11. 31 0
      src/views/attend-class/model/train-type/images/e-tag.svg
  12. 15 0
      src/views/attend-class/model/train-type/images/icon-pause.svg
  13. 18 0
      src/views/attend-class/model/train-type/images/icon-play.svg
  14. 23 0
      src/views/attend-class/model/train-type/images/p-delete.svg
  15. 23 0
      src/views/attend-class/model/train-type/images/p-edit.svg
  16. 31 0
      src/views/attend-class/model/train-type/images/p-tag.svg
  17. 161 0
      src/views/attend-class/model/train-type/index.module.less
  18. 107 0
      src/views/attend-class/model/train-type/index.tsx
  19. 39 0
      src/views/attend-class/model/train-update/index.module.less
  20. 159 0
      src/views/attend-class/model/train-update/index.tsx
  21. 16 0
      src/views/natural-resources/images/icon-add.svg
  22. 159 0
      src/views/natural-resources/index.module.less
  23. 120 0
      src/views/natural-resources/index.tsx
  24. 123 0
      src/views/natural-resources/search-group-resources.tsx
  25. 1 1
      src/views/prepare-lessons/index.module.less
  26. 122 0
      src/views/prepare-lessons/model/select-music/index.module.less
  27. 75 0
      src/views/prepare-lessons/model/select-music/index.tsx
  28. 93 0
      src/views/prepare-lessons/model/select-music/search-group.tsx

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

@@ -70,7 +70,7 @@ export default defineComponent({
         normalIcon: resourceNormal,
         isActive: false,
         id: 6,
-        path: '/'
+        path: '/natural-resources'
       },
       {
         activeIcon: setIcon,

+ 8 - 0
src/router/routes/index.ts

@@ -64,6 +64,14 @@ export const constantRoutes: RouteRecordRaw[] = [
         meta: {
           title: '曲谱库'
         }
+      },
+      {
+        path: '/natural-resources',
+        name: 'natural-resources',
+        component: () => import('@/views/natural-resources/index'),
+        meta: {
+          title: '资源'
+        }
       }
     ]
   },

+ 39 - 0
src/styles/index.less

@@ -83,6 +83,7 @@ body {
   font-weight: 600 !important;
   font-size: 18px;
 }
+
 .resetBtn {
   width: 90px;
   height: 43px;
@@ -96,26 +97,31 @@ body {
   border-radius: 10px 10px 0 0;
   overflow: hidden;
 }
+
 .n-data-table-thead {
   height: 54px;
   line-height: 54px;
 }
+
 .n-data-table-th {
   padding: 0 20px !important;
   background-color: #f7f7f8 !important;
   color: rgba(0, 0, 0, 0.88) !important;
 }
+
 .n-data-table-th__title-wrapper {
   &::after {
     content: '';
     width: 1px;
     height: 22px;
     background: #ebebeb;
+
     &:nth-last-child(1) {
       display: none;
     }
   }
 }
+
 .n-data-table-th--last {
   .n-data-table-th__title-wrapper {
     &::after {
@@ -126,3 +132,36 @@ body {
     }
   }
 }
+
+// 给弹窗设置标题的基础样式
+.modalTitle {
+  border-radius: 16px;
+  overflow: hidden;
+
+  &.background {
+    .n-card-header {
+      background: #F5F6FA;
+    }
+  }
+
+  .n-card-header {
+    position: relative;
+    padding: 20px 18px;
+    text-align: center;
+    background: #fff;
+    font-size: 22px;
+    font-weight: 600;
+    color: #131415;
+    line-height: 30px;
+  }
+
+  .n-card-header__close {
+    position: absolute;
+    right: 18px;
+    z-index: 99;
+  }
+
+  .n-card__content {
+    padding: 0;
+  }
+}

BIN
src/views/attend-class/image/icon-note.png


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

@@ -15,6 +15,7 @@
   width: 187px;
   height: 60px;
   cursor: pointer;
+  transition: all .5s;
 
   img {
     width: 100%;
@@ -22,6 +23,13 @@
   }
 }
 
+.sectionAnimateUp {
+  opacity: 0;
+  pointer-events: none;
+  transform: translateY(-100%);
+  transition: all .5s;
+}
+
 .coursewarePlay {
   position: relative;
   height: 100vh;
@@ -359,7 +367,6 @@
   transition: all .5s;
 }
 
-
 .attendClassModal {
   width: 442px;
   border-radius: 16px;

+ 28 - 8
src/views/attend-class/index.tsx

@@ -20,7 +20,8 @@ import iconUp from './image/icon-up.svg';
 import iconUpDisabled from './image/icon-up-disabled.svg';
 import iconDown from './image/icon-down.svg';
 import iconDownDisabled from './image/icon-down-disabled.svg';
-import iconWhiteboard from './image/icon-whiteboard.svg';
+// import iconWhiteboard from './image/icon-whiteboard.svg';
+import iconNote from './image/icon-note.png';
 // import Points from './component/points';
 import iconAssignHomework from './image/icon-assignHomework.svg';
 import { Vue3Lottie } from 'vue3-lottie';
@@ -185,6 +186,14 @@ export default defineComponent({
       });
     };
 
+    // ifram事件处理
+    const iframeHandle = (ev: MessageEvent) => {
+      if (ev.data?.api === 'headerTogge') {
+        activeData.model =
+          ev.data.show || (ev.data.playState == 'play' ? false : true);
+      }
+    };
+
     onMounted(() => {
       getDetail();
     });
@@ -427,13 +436,17 @@ export default defineComponent({
 
     // 监听页面键盘事件 - 上下切换
     document.body.addEventListener('keyup', (e: KeyboardEvent) => {
-      if (e.key === 'ArrowUp') {
+      console.log(e, 'e');
+      if (e.code === 'ArrowUp') {
         if (popupData.activeIndex === 0) return;
         handlePreAndNext('up');
-      } else if (e.key === 'ArrowDown') {
+      } else if (e.code === 'ArrowDown') {
         if (popupData.activeIndex === data.itemList.length - 1) return;
         handlePreAndNext('down');
       }
+      //  else if (e.code === 'Space') {
+      //   handleStop();
+      // }
     });
 
     /** 教学数据 */
@@ -472,6 +485,10 @@ export default defineComponent({
       toggleModel();
     };
 
+    onMounted(() => {
+      window.addEventListener('message', iframeHandle);
+    });
+
     return () => (
       <div id="playContent" class={styles.playContent}>
         <div
@@ -621,7 +638,10 @@ export default defineComponent({
         </div> */}
         {/* 布置作业按钮 */}
         <div
-          class={styles.assignHomework}
+          class={[
+            styles.assignHomework,
+            activeData.model ? '' : styles.sectionAnimateUp
+          ]}
           onClick={() => (data.modelAttendStatus = true)}>
           <img src={iconAssignHomework} />
         </div>
@@ -668,11 +688,11 @@ export default defineComponent({
             onClick={() =>
               openStudyTool({
                 type: 'pen',
-                icon: iconWhiteboard,
-                name: '白板'
+                icon: iconNote,
+                name: '批注'
               })
             }>
-            <img src={iconWhiteboard} />
+            <img src={iconNote} />
           </div>
         </div>
 
@@ -719,7 +739,7 @@ export default defineComponent({
                 // window.close();
                 data.modelAttendStatus = false;
               }}>
-              暂布置
+              暂布置
             </NButton>
             <NButton
               type="primary"

+ 31 - 0
src/views/attend-class/model/train-settings/index.module.less

@@ -57,5 +57,36 @@
   .trainList {
     margin-top: 28px;
     max-height: 50vh;
+    padding: 0 40px;
+
+    :global {
+      .n-scrollbar-content {
+        display: flex;
+        gap: 24px;
+        flex-wrap: wrap;
+      }
+    }
+  }
+}
+
+.trainEditModal {
+  width: 494px;
+}
+
+.selectMusicModal {
+  position: relative;
+  width: 1352px;
+
+  :global {
+    .n-card-header {
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+
+      .n-card-header__main {
+        color: #fff;
+      }
+    }
   }
 }

+ 68 - 6
src/views/attend-class/model/train-settings/index.tsx

@@ -1,15 +1,47 @@
-import { defineComponent } from 'vue';
+import { defineComponent, reactive } from 'vue';
 import styles from './index.module.less';
-import { NButton, NDatePicker, NEmpty, NScrollbar, NSpace } from 'naive-ui';
+import {
+  NButton,
+  NDatePicker,
+  NEmpty,
+  NModal,
+  NScrollbar,
+  NSpace
+} from 'naive-ui';
+import TrainType from '@/views/attend-class/model/train-type';
+import TrainUpdate from '../train-update';
+import SelectMusic from '@/views/prepare-lessons/model/select-music';
 
 export default defineComponent({
   name: 'train-settings',
   emits: ['close'],
   setup(props, { emit }) {
+    const trainForms = reactive({
+      editStatus: false,
+      selectMusicStatus: false
+    });
+    const list = [
+      {
+        id: 1,
+        src: 'https://lanhu-dds-backend.oss-cn-beijing.aliyuncs.com/merge_image/imgs/4eb9b81ad9ff4b8c9f026e22d37d7c14_mergeImage.png',
+        type: 'practice',
+        name: '小星星',
+        typeList: ['1-12小节', '速度90', '20分钟']
+      },
+      {
+        id: 2,
+        src: 'https://lanhu-dds-backend.oss-cn-beijing.aliyuncs.com/merge_image/imgs/4eb9b81ad9ff4b8c9f026e22d37d7c14_mergeImage.png',
+        type: 'evaluation',
+        name: '夏日狂欢曲',
+        typeList: ['入门级', '全部小节', '速度90', '20分钟']
+      }
+    ];
     return () => (
       <div class={styles.trainSettings}>
         <div class={styles.searchGroup}>
-          <NButton>添加训练</NButton>
+          <NButton onClick={() => (trainForms.selectMusicStatus = true)}>
+            添加训练
+          </NButton>
 
           <div class={styles.datetime}>
             <label>截止时间:</label>
@@ -23,16 +55,46 @@ export default defineComponent({
           </div>
         </div>
         <NScrollbar class={styles.trainList}>
-          <NEmpty description="暂无训练" />
+          {/* <NEmpty description="暂无训练" /> */}
+          {list.map((item: any) => (
+            <TrainType
+              item={item}
+              onEdit={() => {
+                console.log('edit');
+                trainForms.editStatus = true;
+              }}
+            />
+          ))}
         </NScrollbar>
         <NSpace class={styles.trainBtnGroup}>
-          <NButton type="default" round onClick={() => emit('close')}>
+          <NButton strong type="default" round onClick={() => emit('close')}>
             取消布置
           </NButton>
-          <NButton type="primary" round>
+          <NButton strong type="primary" round>
             立即布置
           </NButton>
         </NSpace>
+
+        <NModal
+          v-model:show={trainForms.editStatus}
+          class={['modalTitle background', styles.trainEditModal]}
+          preset="card"
+          title="训练设置">
+          <TrainUpdate onClose={() => (trainForms.editStatus = false)} />
+        </NModal>
+
+        <NModal
+          v-model:show={trainForms.selectMusicStatus}
+          class={['modalTitle', styles.selectMusicModal]}
+          preset="card"
+          title={'选择曲目'}>
+          <SelectMusic
+            onSelect={(item: any) => {
+              trainForms.selectMusicStatus = false;
+              trainForms.editStatus = true;
+            }}
+          />
+        </NModal>
       </div>
     );
   }

+ 23 - 0
src/views/attend-class/model/train-type/images/e-delete.svg

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="26px" height="26px" viewBox="0 0 26 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>切片</title>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
+        <g id="64、布置作业-训练设置" transform="translate(-1388.000000, -701.000000)" stroke="#F92D53" stroke-width="1.86666667">
+            <g id="编组-4" transform="translate(446.000000, 206.000000)">
+                <g id="位图备份" transform="translate(526.000000, 169.000000)">
+                    <g id="删除" transform="translate(416.000000, 326.000000)">
+                        <g transform="translate(4.000000, 4.000000)" id="编组">
+                            <line x1="11.5634909" y1="7.66953939" x2="11.5634909" y2="14.4243273" id="Stroke-1"></line>
+                            <line x1="7.02112727" y1="7.66953939" x2="7.02112727" y2="14.4243273" id="Stroke-2"></line>
+                            <g>
+                                <path d="M16.1212121,6.78787879 L16.1212121,17.1818182 C16.1212121,18.002303 15.3609697,18.6666667 14.4242424,18.6666667 L4.24242424,18.6666667 C3.30569697,18.6666667 2.54545455,18.002303 2.54545455,17.1818182 L2.54545455,6.78787879" id="Stroke-3"></path>
+                                <line x1="0" y1="4.24242424" x2="18.6666667" y2="4.24242424" id="Stroke-5"></line>
+                                <path d="M12.7272727,0 L5.93939394,0 C5.00266667,0 4.24242424,0.760242424 4.24242424,1.6969697 L4.24242424,4.24242424 L14.4242424,4.24242424 L14.4242424,1.6969697 C14.4242424,0.760242424 13.664,0 12.7272727,0 Z" id="Stroke-7"></path>
+                            </g>
+                        </g>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 23 - 0
src/views/attend-class/model/train-type/images/e-edit.svg

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="26px" height="26px" viewBox="0 0 26 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>切片</title>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
+        <g id="64、布置作业-训练设置" transform="translate(-1388.000000, -696.000000)" stroke="#F92D53" stroke-width="1.89584019">
+            <g id="编组-4" transform="translate(446.000000, 219.000000)">
+                <g id="位图备份" transform="translate(526.000000, 168.000000)">
+                    <g id="图标/通用/返回备份" transform="translate(416.000000, 309.000000)">
+                        <g id="编组" transform="translate(4.875000, 3.791667)">
+                            <path d="M16.2496553,13.0856648 L16.2498599,16.2494713 C16.249793,17.446032 15.279894,18.4161211 14.0833334,18.4164223 L12.221101,18.4166667 L12.221101,18.4166667" id="Stroke-1" stroke-linejoin="round"></path>
+                            <path d="M16.2496553,5.52567849 L16.2496553,2.16666667 C16.2496553,0.970049709 15.2796056,-2.19814969e-16 14.0829886,0 L2.16666667,0 C0.970049709,2.19814969e-16 2.97545897e-16,0.970049709 0,2.16666667 L0,16.2494713 C5.90632523e-16,17.4460883 0.970049709,18.416138 2.16666667,18.416138 L4.87491383,18.416138 L4.87491383,18.416138" id="Stroke-3" stroke-linejoin="round"></path>
+                            <g id="编组-2" transform="translate(4.333333, 3.323284)">
+                                <line x1="0" y1="1.523912" x2="7.58359185" y2="1.55171575" id="Stroke-5"></line>
+                                <line x1="0" y1="6.48380889" x2="3.79158049" y2="6.48380889" id="Stroke-9"></line>
+                            </g>
+                            <line x1="8.19289145" y1="18.4164904" x2="16.25" y2="8.23912327" id="Stroke-7"></line>
+                        </g>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 31 - 0
src/views/attend-class/model/train-type/images/e-tag.svg

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="28px" height="28px" viewBox="0 0 28 28" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>专辑标签(2)</title>
+    <defs>
+        <linearGradient x1="100%" y1="50%" x2="0%" y2="50%" id="linearGradient-1">
+            <stop stop-color="#FF7B57" offset="0%"></stop>
+            <stop stop-color="#FF3460" offset="100%"></stop>
+        </linearGradient>
+        <linearGradient x1="60.2548008%" y1="8.41286024%" x2="50%" y2="100%" id="linearGradient-2">
+            <stop stop-color="#FFFFFF" offset="0%"></stop>
+            <stop stop-color="#FFFFFF" offset="100%"></stop>
+        </linearGradient>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="46.9481485%" id="linearGradient-3">
+            <stop stop-color="#FFFFFF" stop-opacity="0" offset="0%"></stop>
+            <stop stop-color="#FFFFFF" offset="100%"></stop>
+        </linearGradient>
+    </defs>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" opacity="0.900000036">
+        <g id="64、布置作业-训练设置" transform="translate(-992.000000, -407.000000)">
+            <g id="编组-4" transform="translate(446.000000, 219.000000)">
+                <g id="位图备份" transform="translate(526.000000, 168.000000)">
+                    <g id="专辑标签(2)" transform="translate(20.000000, 20.000000)">
+                        <rect id="矩形" fill="url(#linearGradient-1)" x="0" y="0" width="28" height="28" rx="14"></rect>
+                        <path d="M14,5.6 C14.3155402,5.6 14.6270168,5.61739826 14.9335228,5.65128781 L14.9330114,9.42661825 C14.631542,9.36544538 14.3195211,9.33333333 14,9.33333333 C11.4226712,9.33333333 9.33333333,11.4226712 9.33333333,14 C9.33333333,16.5773288 11.4226712,18.6666667 14,18.6666667 C16.5494313,18.6666667 18.6213787,16.6223149 18.6666667,14.0838855 L18.6666667,14.0838855 L18.6671259,7.01481986 C20.9180416,8.5217493 22.4,11.0878097 22.4,14 C22.4,18.6391919 18.6391919,22.4 14,22.4 C9.3608081,22.4 5.6,18.6391919 5.6,14 C5.6,9.3608081 9.3608081,5.6 14,5.6 Z" id="形状结合" fill="url(#linearGradient-2)"></path>
+                        <rect id="矩形" fill="url(#linearGradient-3)" x="18.6658869" y="0.691618793" width="3.73333333" height="13.0666667"></rect>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 15 - 0
src/views/attend-class/model/train-type/images/icon-pause.svg

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="8px" height="10px" viewBox="0 0 8 10" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>三角形</title>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="64、布置作业-训练设置" transform="translate(-908.000000, -414.000000)" fill="#FFFFFF">
+            <g id="编组-4" transform="translate(446.000000, 219.000000)">
+                <g id="位图" transform="translate(40.000000, 168.000000)">
+                    <g id="编组-14" transform="translate(338.000000, 16.000000)">
+                        <path d="M88.8240419,13.1986064 L92.4230114,18.4334712 C92.7358967,18.888577 92.6206041,19.5111567 92.1654983,19.8240419 C91.9988,19.9386471 91.8012631,20 91.5989695,20 L84.4010305,20 C83.8487457,20 83.4010305,19.5522847 83.4010305,19 C83.4010305,18.7977064 83.4623834,18.6001695 83.5769886,18.4334712 L87.1759581,13.1986064 C87.4888433,12.7435006 88.111423,12.6282081 88.5665288,12.9410933 C88.6674048,13.0104456 88.7546897,13.0977304 88.8240419,13.1986064 Z" id="三角形" transform="translate(88.000000, 16.000000) rotate(-270.000000) translate(-88.000000, -16.000000) "></path>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 18 - 0
src/views/attend-class/model/train-type/images/icon-play.svg

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="8px" height="10px" viewBox="0 0 8 10" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>编组 2</title>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="64、布置作业-训练设置" transform="translate(-1394.000000, -416.000000)" fill="#FFFFFF">
+            <g id="编组-4" transform="translate(446.000000, 219.000000)">
+                <g id="位图备份" transform="translate(526.000000, 168.000000)">
+                    <g id="编组-43备份-5" transform="translate(338.000000, 18.000000)">
+                        <g id="编组-2" transform="translate(84.000000, 11.000000)">
+                            <rect id="矩形" x="0" y="0" width="2" height="10" rx="1"></rect>
+                            <rect id="矩形备份-2" x="6" y="0" width="2" height="10" rx="1"></rect>
+                        </g>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 23 - 0
src/views/attend-class/model/train-type/images/p-delete.svg

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="26px" height="26px" viewBox="0 0 26 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>切片</title>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
+        <g id="64、布置作业-训练设置" transform="translate(-902.000000, -701.000000)" stroke="#198CFE" stroke-width="1.86666667">
+            <g id="编组-4" transform="translate(446.000000, 206.000000)">
+                <g id="位图" transform="translate(40.000000, 169.000000)">
+                    <g id="删除" transform="translate(416.000000, 326.000000)">
+                        <g transform="translate(4.000000, 4.000000)" id="编组">
+                            <line x1="11.5634909" y1="7.66953939" x2="11.5634909" y2="14.4243273" id="Stroke-1"></line>
+                            <line x1="7.02112727" y1="7.66953939" x2="7.02112727" y2="14.4243273" id="Stroke-2"></line>
+                            <g>
+                                <path d="M16.1212121,6.78787879 L16.1212121,17.1818182 C16.1212121,18.002303 15.3609697,18.6666667 14.4242424,18.6666667 L4.24242424,18.6666667 C3.30569697,18.6666667 2.54545455,18.002303 2.54545455,17.1818182 L2.54545455,6.78787879" id="Stroke-3"></path>
+                                <line x1="0" y1="4.24242424" x2="18.6666667" y2="4.24242424" id="Stroke-5"></line>
+                                <path d="M12.7272727,0 L5.93939394,0 C5.00266667,0 4.24242424,0.760242424 4.24242424,1.6969697 L4.24242424,4.24242424 L14.4242424,4.24242424 L14.4242424,1.6969697 C14.4242424,0.760242424 13.664,0 12.7272727,0 Z" id="Stroke-7"></path>
+                            </g>
+                        </g>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 23 - 0
src/views/attend-class/model/train-type/images/p-edit.svg

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="26px" height="26px" viewBox="0 0 26 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>切片</title>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
+        <g id="64、布置作业-训练设置" transform="translate(-902.000000, -696.000000)" stroke="#198CFE" stroke-width="1.89584019">
+            <g id="编组-4" transform="translate(446.000000, 219.000000)">
+                <g id="位图" transform="translate(40.000000, 168.000000)">
+                    <g id="图标/通用/返回备份" transform="translate(416.000000, 309.000000)">
+                        <g id="编组" transform="translate(4.875000, 3.791667)">
+                            <path d="M16.2496553,13.0856648 L16.2498599,16.2494713 C16.249793,17.446032 15.279894,18.4161211 14.0833334,18.4164223 L12.221101,18.4166667 L12.221101,18.4166667" id="Stroke-1" stroke-linejoin="round"></path>
+                            <path d="M16.2496553,5.52567849 L16.2496553,2.16666667 C16.2496553,0.970049709 15.2796056,-2.19814969e-16 14.0829886,0 L2.16666667,0 C0.970049709,2.19814969e-16 2.97545897e-16,0.970049709 0,2.16666667 L0,16.2494713 C5.90632523e-16,17.4460883 0.970049709,18.416138 2.16666667,18.416138 L4.87491383,18.416138 L4.87491383,18.416138" id="Stroke-3" stroke-linejoin="round"></path>
+                            <g id="编组-2" transform="translate(4.333333, 3.323284)">
+                                <line x1="0" y1="1.523912" x2="7.58359185" y2="1.55171575" id="Stroke-5"></line>
+                                <line x1="0" y1="6.48380889" x2="3.79158049" y2="6.48380889" id="Stroke-9"></line>
+                            </g>
+                            <line x1="8.19289145" y1="18.4164904" x2="16.25" y2="8.23912327" id="Stroke-7"></line>
+                        </g>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 31 - 0
src/views/attend-class/model/train-type/images/p-tag.svg

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="28px" height="28px" viewBox="0 0 28 28" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>专辑标签(2)</title>
+    <defs>
+        <linearGradient x1="-2.71033196e-12%" y1="4.30211422e-14%" x2="100%" y2="100%" id="linearGradient-1">
+            <stop stop-color="#23C3FF" offset="0%"></stop>
+            <stop stop-color="#007AFE" offset="100%"></stop>
+        </linearGradient>
+        <linearGradient x1="60.2548008%" y1="8.41286024%" x2="50%" y2="100%" id="linearGradient-2">
+            <stop stop-color="#FFFFFF" offset="0%"></stop>
+            <stop stop-color="#FFFFFF" offset="100%"></stop>
+        </linearGradient>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="46.9481485%" id="linearGradient-3">
+            <stop stop-color="#FFFFFF" stop-opacity="0" offset="0%"></stop>
+            <stop stop-color="#FFFFFF" offset="100%"></stop>
+        </linearGradient>
+    </defs>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" opacity="0.900000036">
+        <g id="64、布置作业-训练设置" transform="translate(-506.000000, -407.000000)">
+            <g id="编组-4" transform="translate(446.000000, 219.000000)">
+                <g id="位图" transform="translate(40.000000, 168.000000)">
+                    <g id="专辑标签(2)" transform="translate(20.000000, 20.000000)">
+                        <rect id="矩形" fill="url(#linearGradient-1)" x="0" y="0" width="28" height="28" rx="14"></rect>
+                        <path d="M14,5.6 C14.3155402,5.6 14.6270168,5.61739826 14.9335228,5.65128781 L14.9330114,9.42661825 C14.631542,9.36544538 14.3195211,9.33333333 14,9.33333333 C11.4226712,9.33333333 9.33333333,11.4226712 9.33333333,14 C9.33333333,16.5773288 11.4226712,18.6666667 14,18.6666667 C16.5494313,18.6666667 18.6213787,16.6223149 18.6666667,14.0838855 L18.6666667,14.0838855 L18.6671259,7.01481986 C20.9180416,8.5217493 22.4,11.0878097 22.4,14 C22.4,18.6391919 18.6391919,22.4 14,22.4 C9.3608081,22.4 5.6,18.6391919 5.6,14 C5.6,9.3608081 9.3608081,5.6 14,5.6 Z" id="形状结合" fill="url(#linearGradient-2)"></path>
+                        <rect id="矩形" fill="url(#linearGradient-3)" x="18.6658869" y="0.691618793" width="3.73333333" height="13.0666667"></rect>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 161 - 0
src/views/attend-class/model/train-type/index.module.less

@@ -0,0 +1,161 @@
+.trainType {
+  display: inline-block;
+  width: 462px;
+  background: #ECF6FF;
+  border-radius: 16px;
+  padding: 20px;
+}
+
+.train-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+
+  .title {
+    display: flex;
+    align-items: center;
+    font-size: 18px;
+    font-weight: 600;
+    color: #131415;
+
+    .title-tag {
+      width: 28px;
+      height: 28px;
+      margin-right: 8px;
+    }
+
+    .title-text {
+      max-width: 200px;
+    }
+  }
+
+  .btn {
+    padding: 0 12px;
+    height: 32px;
+    background: linear-gradient(270deg, #23C3FF 0%, #007AFE 100%);
+    font-size: 16px;
+    font-weight: 600;
+    color: #FFFFFF;
+    line-height: 22px;
+    --n-border: 0 !important;
+    --n-border-hover: 0 !important;
+    --n-border-pressed: 0 !important;
+    --n-border-focus: 0 !important;
+
+    &:hover,
+    &:active,
+    &:visited,
+    &:focus {
+      border: 0;
+      color: #fff;
+    }
+
+    img {
+      margin-left: 10px;
+      width: 8px;
+      height: 10px;
+    }
+  }
+}
+
+.train-content {
+  margin: 20px 0;
+  height: 238px;
+  background: #FFFFFF;
+  border-radius: 11px;
+  border: 1px solid #74BAFF;
+  position: relative;
+  overflow: hidden;
+
+  :global {
+    .n-image {
+      width: inherit;
+      height: inherit;
+
+      img {
+        width: 100%;
+      }
+    }
+  }
+
+  .preview {
+    position: absolute;
+    opacity: 0;
+    visibility: hidden;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, .7);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    transition: all .2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+
+    .previewBtn {
+      background: #fff;
+      height: 44px;
+      padding: 0 44px;
+      border-radius: 12px;
+    }
+  }
+
+  &:hover {
+    .preview {
+      opacity: 1;
+      visibility: visible;
+      transition: all .3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+    }
+  }
+}
+
+.train-footer {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+
+  :global {
+    .n-tag {
+      font-size: 14px;
+      font-weight: 500;
+      color: #0378EC;
+      line-height: 20px;
+      border: 1px solid #198CFE;
+      border-radius: 6px;
+      background-color: transparent;
+      height: 28px;
+    }
+  }
+
+  .operation {
+    display: flex;
+    height: 26px;
+    padding: 0;
+
+    img {
+      height: 26px;
+      width: 26px;
+    }
+  }
+}
+
+.evaluationType {
+  background: #FFF0EB;
+
+  .btn {
+    background: linear-gradient(270deg, #FF7B57 0%, #FF3460 100%);
+  }
+
+  .train-content {
+    border: 1px solid rgba(249, 45, 83, 0.5);
+  }
+
+  .train-footer {
+    :global {
+      .n-tag {
+        color: #F92D53;
+        border: 1px solid #F92D53;
+      }
+    }
+  }
+}

+ 107 - 0
src/views/attend-class/model/train-type/index.tsx

@@ -0,0 +1,107 @@
+import { PropType, defineComponent } from 'vue';
+import styles from './index.module.less';
+import { NButton, NEllipsis, NSpace, NImage, NTag, useDialog } from 'naive-ui';
+import pTag from './images/p-tag.svg';
+import eTag from './images/e-tag.svg';
+import pEdit from './images/p-edit.svg';
+import eEdit from './images/e-edit.svg';
+// import iconPlay from './images/icon-play.svg';
+import iconPause from './images/icon-pause.svg';
+import pDelete from './images/p-delete.svg';
+import eDelete from './images/e-delete.svg';
+
+type ItemType = {
+  id: string | number;
+  type: 'practice' | 'evaluation';
+  src: string;
+  name: string;
+  typeList: string[];
+};
+
+export default defineComponent({
+  name: 'train-type',
+  props: {
+    item: {
+      type: Object as PropType<ItemType>,
+      default: () => ({})
+    }
+  },
+  emits: ['click', 'delete', 'edit'],
+  setup(props, { emit }) {
+    const dialog = useDialog();
+
+    const onDelete = () => {
+      const dialogT = dialog.warning({
+        title: '提示',
+        content: '您确定是否删除?',
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: () => {
+          dialogT.loading = true;
+          emit('delete', props.item);
+        }
+      });
+    };
+    return () => (
+      <div
+        class={[
+          styles.trainType,
+          props.item.type === 'evaluation' ? styles.evaluationType : ''
+        ]}
+        onClick={() => emit('click', props.item)}>
+        <div class={styles['train-header']}>
+          <div class={styles.title}>
+            <img
+              src={props.item.type === 'evaluation' ? eTag : pTag}
+              class={styles['title-tag']}
+            />
+            <NEllipsis class={styles['title-text']}>
+              {props.item.name}
+            </NEllipsis>
+          </div>
+
+          <NButton class={styles.btn} round>
+            {props.item.type === 'evaluation' ? '评测模式' : '练习模式'}
+            <img src={iconPause} />
+          </NButton>
+        </div>
+        <div class={styles['train-content']}>
+          <NImage src={props.item.src} previewDisabled />
+          <div class={styles.preview}>
+            <NButton strong secondary class={styles.previewBtn}>
+              预览
+            </NButton>
+          </div>
+        </div>
+        <div class={styles['train-footer']}>
+          <NSpace class={styles.type}>
+            {props.item.typeList.map((type: string) => (
+              <NTag>{type}</NTag>
+            ))}
+          </NSpace>
+
+          <NSpace size={6}>
+            <n-button
+              quaternary
+              class={styles.operation}
+              onClick={(e: MouseEvent) => {
+                e.stopPropagation();
+                emit('edit', props.item);
+              }}>
+              <img src={props.item.type === 'evaluation' ? eEdit : pEdit} />
+            </n-button>
+            <n-button
+              quaternary
+              class={styles.operation}
+              onClick={(e: MouseEvent) => {
+                e.stopPropagation();
+                onDelete();
+              }}>
+              <img src={props.item.type === 'evaluation' ? eDelete : pDelete} />
+            </n-button>
+          </NSpace>
+        </div>
+      </div>
+    );
+  }
+});

+ 39 - 0
src/views/attend-class/model/train-update/index.module.less

@@ -0,0 +1,39 @@
+.trainUpdate {
+  padding: 24px 30px;
+
+  .updateBtnGroup {
+    padding: 0;
+    justify-content: center !important;
+
+    :global {
+      .n-button {
+        height: 48px !important;
+        min-width: 156px;
+      }
+    }
+  }
+
+  .switch {
+    height: 37px !important;
+    border-radius: 8px;
+
+    &.active {
+      background: #198CFE;
+      color: #fff;
+    }
+  }
+
+  :global {
+    .n-input-group-label {
+      width: 76px;
+      padding: 0;
+      text-align: center;
+      background-color: #fff;
+      border-radius: 8px;
+    }
+
+    .n-input {
+      border-radius: 8px;
+    }
+  }
+}

+ 159 - 0
src/views/attend-class/model/train-update/index.tsx

@@ -0,0 +1,159 @@
+import { defineComponent, reactive } from 'vue';
+import styles from './index.module.less';
+import {
+  NButton,
+  NForm,
+  NFormItem,
+  NInput,
+  NInputGroup,
+  NInputGroupLabel,
+  NInputNumber,
+  NSpace
+} from 'naive-ui';
+
+export default defineComponent({
+  name: 'train-update',
+  emits: ['close'],
+  setup(props, { emit }) {
+    // 'practice' | 'evaluation'
+    const forms = reactive({
+      type: 'practice',
+      minScore: null,
+      maxScore: null,
+      difficulty: '1'
+    });
+    return () => (
+      <div class={styles.trainUpdate}>
+        <NForm labelAlign="left" labelPlacement="left">
+          <NFormItem label="训练方式" path="type">
+            <NSpace>
+              <NButton
+                secondary
+                class={[
+                  styles.switch,
+                  forms.type === 'practice' ? styles.active : ''
+                ]}
+                onClick={() => (forms.type = 'practice')}>
+                练习
+              </NButton>
+              <NButton
+                secondary
+                class={[
+                  styles.switch,
+                  forms.type === 'evaluation' ? styles.active : ''
+                ]}
+                onClick={() => (forms.type = 'evaluation')}>
+                评测
+              </NButton>
+            </NSpace>
+          </NFormItem>
+          {forms.type === 'practice' && (
+            <>
+              <NFormItem label="练习小节" path="minScore">
+                <NInputNumber
+                  v-model:value={forms.minScore}
+                  showButton={false}
+                  min={0}
+                  max={99}
+                  placeholder="最小练习小节"
+                  onUpdate:value={() => {
+                    forms.maxScore = null;
+                  }}
+                  style={{ width: '46%' }}
+                />
+                <div
+                  style={{
+                    display: 'flex',
+                    alignItems: 'center',
+                    lineHeight: '1',
+                    marginTop: '-2px',
+                    margin: '-2px 4% 0 4%'
+                  }}>
+                  -
+                </div>
+                <NInputNumber
+                  v-model:value={forms.maxScore}
+                  showButton={false}
+                  min={forms.minScore || 0}
+                  max={99}
+                  placeholder="最大练习小节"
+                  style={{ width: '46%' }}
+                />
+              </NFormItem>
+              <NFormItem label="练习速度">
+                <NInputNumber
+                  min={0}
+                  showButton={false}
+                  style={{ width: '100%' }}
+                />
+              </NFormItem>
+              <NFormItem label="练习时长">
+                <NInputGroup>
+                  <NInput />
+                  <NInputGroupLabel>分钟</NInputGroupLabel>
+                </NInputGroup>
+              </NFormItem>
+            </>
+          )}
+
+          {forms.type === 'evaluation' && (
+            <>
+              <NFormItem label="评测难度" path="type">
+                <NSpace>
+                  <NButton
+                    secondary
+                    class={[
+                      styles.switch,
+                      forms.difficulty === '1' ? styles.active : ''
+                    ]}
+                    onClick={() => (forms.difficulty = '1')}>
+                    入门级
+                  </NButton>
+                  <NButton
+                    secondary
+                    class={[
+                      styles.switch,
+                      forms.difficulty === '2' ? styles.active : ''
+                    ]}
+                    onClick={() => (forms.difficulty = '2')}>
+                    进阶级
+                  </NButton>
+                  <NButton
+                    secondary
+                    class={[
+                      styles.switch,
+                      forms.difficulty === '3' ? styles.active : ''
+                    ]}
+                    onClick={() => (forms.difficulty = '3')}>
+                    大师级
+                  </NButton>
+                </NSpace>
+              </NFormItem>
+              <NFormItem label="评测速度">
+                <NInputGroup>
+                  <NInput />
+                  <NInputGroupLabel>分钟</NInputGroupLabel>
+                </NInputGroup>
+              </NFormItem>
+              <NFormItem label="合格分数">
+                <NInputGroup>
+                  <NInput />
+                  <NInputGroupLabel>分</NInputGroupLabel>
+                </NInputGroup>
+              </NFormItem>
+            </>
+          )}
+
+          <NSpace class={styles.updateBtnGroup}>
+            <NButton strong type="default" round onClick={() => emit('close')}>
+              取消
+            </NButton>
+            <NButton strong type="primary" round onClick={() => emit('close')}>
+              确认
+            </NButton>
+          </NSpace>
+        </NForm>
+      </div>
+    );
+  }
+});

+ 16 - 0
src/views/natural-resources/images/icon-add.svg

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>编组 8</title>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="32、资源-乐谱" transform="translate(-1693.000000, -200.000000)" fill="#198CFE">
+            <g id="编组-20" transform="translate(164.000000, 190.000000)">
+                <g id="编组-43备份-3" transform="translate(1513.000000, 0.000000)">
+                    <g id="编组-8" transform="translate(16.000000, 10.000000)">
+                        <rect id="矩形" transform="translate(8.000000, 8.000000) rotate(-270.000000) translate(-8.000000, -8.000000) " x="-4.54747351e-13" y="7" width="16" height="2" rx="1"></rect>
+                        <rect id="矩形" transform="translate(8.000000, 8.000000) rotate(-180.000000) translate(-8.000000, -8.000000) " x="0" y="7" width="16" height="2" rx="1"></rect>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 159 - 0
src/views/natural-resources/index.module.less

@@ -0,0 +1,159 @@
+.listWrap {
+  padding: 32px;
+  background-color: #fff;
+  border-radius: 20px;
+
+  :global {
+    .n-tabs-tab-pad {
+      width: 80px !important;
+    }
+
+    .n-tabs-nav {
+      padding: 0px 20px 24px;
+    }
+
+    .n-tabs-tab {
+      color: #8B8D98;
+      font-size: 22px;
+      padding-top: 0;
+      padding-bottom: 6px;
+      line-height: 22px;
+
+      &.n-tabs-tab--active {
+        font-weight: 600 !important;
+        color: #131415 !important;
+      }
+    }
+
+    .n-tabs-tab__label {
+      z-index: 10;
+    }
+
+    .n-tabs-bar {
+      height: 10px;
+      background: linear-gradient(90deg, #77BBFF 0%, rgba(163, 231, 255, 0.22) 100%);
+      z-index: 0;
+      bottom: 2px;
+    }
+
+    .n-tab-pane {
+      padding-top: 0 !important;
+    }
+
+    .n-pagination {
+      margin-top: 36px !important;
+    }
+  }
+}
+
+.list {
+  margin-top: 12px;
+
+  display: flex;
+  flex-flow: row wrap;
+  justify-content: flex-start;
+  gap: 22px;
+}
+
+.searchGroup {
+  position: relative;
+  padding: 0;
+
+
+  .btnType {
+    gap: 0px 24px !important;
+
+    :global {
+      .n-button {
+        height: 37px;
+        padding: 0 24px;
+        font-size: 18px;
+        color: rgba(0, 0, 0, .6);
+
+        &.n-button--primary-type {
+          font-weight: bold;
+          color: #fff;
+        }
+      }
+    }
+  }
+
+  :global {
+    .n-form {
+      position: relative;
+    }
+
+    .n-form-item {
+      .n-form-item-label {
+        font-size: 17px;
+        font-weight: 600;
+        color: #131415;
+        line-height: 24px;
+      }
+
+      .n-button {
+        height: 32px;
+        font-size: 17px;
+        border-radius: 8px;
+        color: rgba(0, 0, 0, 0.6);
+      }
+
+      .n-button--primary-type {
+        color: #131415;
+      }
+    }
+
+    .n-form-item-feedback-wrapper {
+      min-height: 14px;
+    }
+  }
+
+  .inputSearch {
+    position: absolute;
+    top: 4px;
+    right: 0px;
+    width: 360px;
+    height: 42px;
+    font-size: 16px;
+
+    :global {
+      .n-input-wrapper {
+        padding-left: 12px;
+        padding-right: 4px;
+      }
+    }
+
+    .searchBtn {
+      height: 34px;
+      font-size: 15px;
+      font-weight: 500;
+    }
+
+    .iconSearch {
+      width: 16px;
+      height: 17px;
+    }
+  }
+
+  .searchCatatory {
+    display: flex;
+    justify-content: space-between;
+    padding-bottom: 24px;
+    border-bottom: 1px solid #F2F2F2;
+    margin-bottom: 20px;
+
+    .addTrain {
+      height: 37px;
+      border-radius: 8px;
+      font-size: 18px;
+      background-color: #E8F4FF;
+      color: #0378EC;
+
+      img {
+        width: 16px;
+        height: 16px;
+        margin-right: 8px;
+      }
+    }
+  }
+}

+ 120 - 0
src/views/natural-resources/index.tsx

@@ -0,0 +1,120 @@
+import { defineComponent, reactive } from 'vue';
+import styles from './index.module.less';
+import Pagination from '@/components/pagination';
+import { NScrollbar, NTabPane, NTabs } from 'naive-ui';
+import CardType from '/src/components/card-type';
+import SearchGroupResources from './search-group-resources';
+export default defineComponent({
+  name: 'student-studentList',
+  setup() {
+    const state = reactive({
+      searchWord: '',
+      loading: false,
+      pagination: {
+        page: 1,
+        rows: 10,
+        pageTotal: 0
+      },
+      tableList: [] as any
+    });
+    const forms = reactive({
+      list: [
+        {
+          id: 1,
+          type: 'IMG',
+          url: 'https://lanhu-dds-backend.oss-cn-beijing.aliyuncs.com/merge_image/imgs/24a8551d69b245e0aec1c8613bf50d46_mergeImage.png',
+          title: '夏日曲演奏',
+          isCollect: false, // 是否收藏
+          isSelected: false // 是否精选
+        },
+        {
+          id: 2,
+          type: 'IMG',
+          url: 'https://lanhu-dds-backend.oss-cn-beijing.aliyuncs.com/merge_image/imgs/24a8551d69b245e0aec1c8613bf50d46_mergeImage.png',
+          title: '欢乐颂',
+          isCollect: true, // 是否收藏
+          isSelected: true // 是否精选
+        },
+        {
+          id: 3,
+          type: 'IMG',
+          url: 'https://lanhu-dds-backend.oss-cn-beijing.aliyuncs.com/merge_image/imgs/24a8551d69b245e0aec1c8613bf50d46_mergeImage.png',
+          title: '夏日曲演奏',
+          isCollect: false, // 是否收藏
+          isSelected: true // 是否精选
+        },
+        {
+          id: 4,
+          type: 'IMG',
+          url: 'https://lanhu-dds-backend.oss-cn-beijing.aliyuncs.com/merge_image/imgs/24a8551d69b245e0aec1c8613bf50d46_mergeImage.png',
+          title: '欢乐颂',
+          isCollect: true, // 是否收藏
+          isSelected: false // 是否精选
+        }
+      ],
+      height: '100%' as any
+    });
+    const getList = () => {
+      console.log('getList');
+    };
+    return () => (
+      <div class={styles.listWrap}>
+        <NTabs
+          animated
+          defaultValue="shareResources"
+          paneClass={styles.paneTitle}
+          justifyContent="center"
+          paneWrapperClass={styles.paneWrapperContainer}>
+          <NTabPane name="shareResources" tab="选择曲目">
+            <SearchGroupResources />
+
+            <div class={styles.list}>
+              {forms.list.map((item: any) => (
+                <CardType item={item} />
+              ))}
+            </div>
+
+            <Pagination
+              v-model:page={state.pagination.page}
+              v-model:pageSize={state.pagination.rows}
+              v-model:pageTotal={state.pagination.pageTotal}
+              onList={getList}
+            />
+          </NTabPane>
+          <NTabPane name="myResources" tab="我的资源">
+            <SearchGroupResources />
+
+            <div class={styles.list}>
+              {forms.list.map((item: any) => (
+                <CardType item={item} />
+              ))}
+            </div>
+
+            <Pagination
+              v-model:page={state.pagination.page}
+              v-model:pageSize={state.pagination.rows}
+              v-model:pageTotal={state.pagination.pageTotal}
+              onList={getList}
+            />
+          </NTabPane>
+          <NTabPane name="myCollect" tab="我的收藏">
+            <SearchGroupResources />
+
+            <div class={styles.list}>
+              {forms.list.map((item: any) => (
+                <CardType item={item} />
+              ))}
+            </div>
+
+            <Pagination
+              v-model:page={state.pagination.page}
+              v-model:pageSize={state.pagination.rows}
+              v-model:pageTotal={state.pagination.pageTotal}
+              onList={getList}
+            />
+          </NTabPane>
+        </NTabs>
+      </div>
+    );
+  }
+});

+ 123 - 0
src/views/natural-resources/search-group-resources.tsx

@@ -0,0 +1,123 @@
+import { defineComponent, reactive, ref } from 'vue';
+import styles from './index.module.less';
+import { NButton, NForm, NFormItem, NInput, NSpace } from 'naive-ui';
+import disSearch from '@/components/searchInput/images/disSearch.png';
+import searchIcon from '@/components/searchInput/images/searchIcon.png';
+import iconAdd from './images/icon-add.svg';
+
+export default defineComponent({
+  name: 'search-group',
+  setup() {
+    const isFocus = ref(false);
+    const forms = reactive({
+      search: ''
+    });
+    return () => (
+      <div class={styles.searchGroup}>
+        <div class={styles.searchCatatory}>
+          <NSpace size="small" class={styles.btnType}>
+            <NButton type="primary" round size="small">
+              全部
+            </NButton>
+            <NButton secondary round size="small">
+              乐谱
+            </NButton>
+            <NButton secondary round size="small">
+              图片
+            </NButton>
+            <NButton secondary round size="small">
+              音频
+            </NButton>
+            <NButton secondary round size="small">
+              视频
+            </NButton>
+          </NSpace>
+
+          <NButton
+            type="primary"
+            class={styles.addTrain}
+            focusable={false}
+            strong>
+            <img src={iconAdd} />
+            添加自定义教材
+          </NButton>
+        </div>
+        <NForm labelAlign="left" labelPlacement="left">
+          <NFormItem label="教材:">
+            <NSpace>
+              <NButton secondary strong type="primary" focusable={false}>
+                全部
+              </NButton>
+              <NButton quaternary focusable={false}>
+                人教版
+              </NButton>
+              <NButton quaternary focusable={false}>
+                声部训练
+              </NButton>
+              <NButton quaternary focusable={false}>
+                小曲目
+              </NButton>
+              <NButton quaternary focusable={false}>
+                考级曲目
+              </NButton>
+            </NSpace>
+          </NFormItem>
+          <NFormItem label="乐器:">
+            <NSpace>
+              <NButton secondary strong type="primary">
+                全部
+              </NButton>
+              <NButton quaternary focusable={false} type="default">
+                竖笛
+              </NButton>
+              <NButton quaternary focusable={false} type="default">
+                排萧
+              </NButton>
+              <NButton quaternary focusable={false} type="default">
+                口风琴
+              </NButton>
+              <NButton quaternary focusable={false} type="default">
+                陶笛
+              </NButton>
+              <NButton quaternary focusable={false} type="default">
+                葫芦丝
+              </NButton>
+            </NSpace>
+          </NFormItem>
+
+          <NInput
+            type="text"
+            placeholder="请输入搜索关键词"
+            clearable
+            round
+            v-model:value={forms.search}
+            class={styles.inputSearch}
+            onFocus={() => {
+              isFocus.value = true;
+            }}
+            onBlur={() => {
+              isFocus.value = false;
+            }}>
+            {{
+              prefix: () => (
+                <img
+                  src={isFocus.value ? searchIcon : disSearch}
+                  class={styles.iconSearch}
+                />
+              ),
+              suffix: () => (
+                <NButton
+                  round
+                  type="primary"
+                  class={styles.searchBtn}
+                  disabled={forms.search ? false : true}>
+                  搜索
+                </NButton>
+              )
+            }}
+          </NInput>
+        </NForm>
+      </div>
+    );
+  }
+});

+ 1 - 1
src/views/prepare-lessons/index.module.less

@@ -18,4 +18,4 @@
     background-color: #fff;
     border-radius: 20px;
   }
-}
+}

+ 122 - 0
src/views/prepare-lessons/model/select-music/index.module.less

@@ -0,0 +1,122 @@
+.selectMusic {
+  :global {
+    .n-tabs-tab-pad {
+      width: 24px !important;
+    }
+
+    .n-tabs-nav {
+      padding: 12px 20px 24px;
+    }
+
+    .n-tabs-tab {
+      color: #8B8D98;
+      font-size: 22px;
+      padding-top: 12px;
+      padding-bottom: 6px;
+      line-height: 22px;
+
+      &.n-tabs-tab--active {
+        font-weight: 600 !important;
+        color: #131415 !important;
+      }
+    }
+
+    .n-tabs-tab__label {
+      z-index: 10;
+    }
+
+    .n-tabs-bar {
+      height: 10px;
+      background: linear-gradient(90deg, #77BBFF 0%, rgba(163, 231, 255, 0.22) 100%);
+      z-index: 0;
+      bottom: 2px;
+    }
+
+    .n-tab-pane {
+      padding-top: 0 !important;
+    }
+  }
+
+  .close {
+    padding: 0;
+
+    :global {
+      .n-icon {
+        font-size: var(--n-close-size);
+        color: var(--n-close-icon-color);
+      }
+    }
+  }
+}
+
+.listContainer {
+  margin-top: 10px;
+  margin-bottom: 32px;
+  padding: 0 40px 0;
+  max-height: 50vh;
+}
+
+.list {
+  display: flex;
+  flex-flow: row wrap;
+  justify-content: flex-start;
+  gap: 22px;
+}
+
+.searchGroup {
+  position: relative;
+  padding: 0 40px;
+
+  :global {
+    .n-form {
+      .n-form-item .n-form-item-label {
+        font-size: 17px;
+        font-weight: 600;
+        color: #131415;
+        line-height: 24px;
+      }
+
+      .n-button {
+        height: 32px;
+        font-size: 17px;
+        border-radius: 8px;
+        color: rgba(0, 0, 0, 0.6);
+      }
+
+      .n-button--primary-type {
+        color: #131415;
+      }
+
+      .n-form-item-feedback-wrapper {
+        min-height: 14px;
+      }
+    }
+  }
+
+  .inputSearch {
+    position: absolute;
+    top: 0;
+    right: 40px;
+    width: 360px;
+    height: 42px;
+    font-size: 16px;
+
+    :global {
+      .n-input-wrapper {
+        padding-left: 12px;
+        padding-right: 4px;
+      }
+    }
+
+    .searchBtn {
+      height: 34px;
+      font-size: 15px;
+      font-weight: 500;
+    }
+
+    .iconSearch {
+      width: 16px;
+      height: 17px;
+    }
+  }
+}

+ 75 - 0
src/views/prepare-lessons/model/select-music/index.tsx

@@ -0,0 +1,75 @@
+import { NButton, NIcon, NScrollbar, NTabPane, NTabs } from 'naive-ui';
+import { defineComponent, reactive } from 'vue';
+import styles from './index.module.less';
+import CardType from '@/components/card-type';
+import { NBaseIcon } from 'naive-ui/es/_internal';
+import SearchGroup from './search-group';
+
+export default defineComponent({
+  name: 'select-music',
+  emits: ['select'],
+  setup(props, { emit }) {
+    const forms = reactive({
+      list: [
+        {
+          id: 1,
+          type: 'IMG',
+          url: 'https://lanhu-dds-backend.oss-cn-beijing.aliyuncs.com/merge_image/imgs/24a8551d69b245e0aec1c8613bf50d46_mergeImage.png',
+          title: '夏日曲演奏',
+          isCollect: false, // 是否收藏
+          isSelected: false // 是否精选
+        },
+        {
+          id: 2,
+          type: 'IMG',
+          url: 'https://lanhu-dds-backend.oss-cn-beijing.aliyuncs.com/merge_image/imgs/24a8551d69b245e0aec1c8613bf50d46_mergeImage.png',
+          title: '欢乐颂',
+          isCollect: true, // 是否收藏
+          isSelected: true // 是否精选
+        },
+        {
+          id: 3,
+          type: 'IMG',
+          url: 'https://lanhu-dds-backend.oss-cn-beijing.aliyuncs.com/merge_image/imgs/24a8551d69b245e0aec1c8613bf50d46_mergeImage.png',
+          title: '夏日曲演奏',
+          isCollect: false, // 是否收藏
+          isSelected: true // 是否精选
+        },
+        {
+          id: 4,
+          type: 'IMG',
+          url: 'https://lanhu-dds-backend.oss-cn-beijing.aliyuncs.com/merge_image/imgs/24a8551d69b245e0aec1c8613bf50d46_mergeImage.png',
+          title: '欢乐颂',
+          isCollect: true, // 是否收藏
+          isSelected: false // 是否精选
+        }
+      ],
+      height: '100%' as any
+    });
+    return () => (
+      <div class={styles.selectMusic}>
+        <NTabs
+          animated
+          defaultValue="shareResources"
+          paneClass={styles.paneTitle}
+          justifyContent="center"
+          paneWrapperClass={styles.paneWrapperContainer}>
+          <NTabPane name="shareResources" tab="选择曲目">
+            <SearchGroup />
+            <NScrollbar class={styles.listContainer}>
+              <div class={styles.list}>
+                {forms.list.map((item: any) => (
+                  <CardType
+                    isShowAdd
+                    item={item}
+                    onAdd={(i: any) => emit('select', i)}
+                  />
+                ))}
+              </div>
+            </NScrollbar>
+          </NTabPane>
+        </NTabs>
+      </div>
+    );
+  }
+});

+ 93 - 0
src/views/prepare-lessons/model/select-music/search-group.tsx

@@ -0,0 +1,93 @@
+import { defineComponent, reactive, ref } from 'vue';
+import styles from './index.module.less';
+import { NButton, NForm, NFormItem, NInput, NSpace } from 'naive-ui';
+import disSearch from '@/components/searchInput/images/disSearch.png';
+import searchIcon from '@/components/searchInput/images/searchIcon.png';
+
+export default defineComponent({
+  name: 'search-group',
+  setup() {
+    const isFocus = ref(false);
+    const forms = reactive({
+      search: ''
+    });
+    return () => (
+      <div class={styles.searchGroup}>
+        <NForm labelAlign="left" labelPlacement="left">
+          <NFormItem label="教材:">
+            <NSpace>
+              <NButton secondary strong type="primary" focusable={false}>
+                全部
+              </NButton>
+              <NButton quaternary focusable={false}>
+                人教版
+              </NButton>
+              <NButton quaternary focusable={false}>
+                声部训练
+              </NButton>
+              <NButton quaternary focusable={false}>
+                小曲目
+              </NButton>
+              <NButton quaternary focusable={false}>
+                考级曲目
+              </NButton>
+            </NSpace>
+          </NFormItem>
+          <NFormItem label="乐器:">
+            <NSpace>
+              <NButton secondary strong type="primary">
+                全部
+              </NButton>
+              <NButton quaternary focusable={false} type="default">
+                竖笛
+              </NButton>
+              <NButton quaternary focusable={false} type="default">
+                排萧
+              </NButton>
+              <NButton quaternary focusable={false} type="default">
+                口风琴
+              </NButton>
+              <NButton quaternary focusable={false} type="default">
+                陶笛
+              </NButton>
+              <NButton quaternary focusable={false} type="default">
+                葫芦丝
+              </NButton>
+            </NSpace>
+          </NFormItem>
+        </NForm>
+        <NInput
+          type="text"
+          placeholder="请输入搜索关键词"
+          clearable
+          round
+          v-model:value={forms.search}
+          class={styles.inputSearch}
+          onFocus={() => {
+            isFocus.value = true;
+          }}
+          onBlur={() => {
+            isFocus.value = false;
+          }}>
+          {{
+            prefix: () => (
+              <img
+                src={isFocus.value ? searchIcon : disSearch}
+                class={styles.iconSearch}
+              />
+            ),
+            suffix: () => (
+              <NButton
+                round
+                type="primary"
+                class={styles.searchBtn}
+                disabled={forms.search ? false : true}>
+                搜索
+              </NButton>
+            )
+          }}
+        </NInput>
+      </div>
+    );
+  }
+});