lex-xin преди 8 месеца
родител
ревизия
da766ecc24

+ 52 - 46
src/components/CCascader/index.tsx

@@ -69,24 +69,24 @@ export default defineComponent({
     });
     const audioPlayTypeList = ref([] as any);
 
-    // const formatParentCurrentValue = (ids: any, list: any) => {
-    //   for (const item of list) {
-    //     if (ids.includes(item.id)) {
-    //       if (item.children && item.children.length > 0) {
-    //         let lastId: any;
-    //         item.children.forEach((child: any) => {
-    //           if (ids.includes(child.id)) {
-    //             lastId = child.id;
-    //           }
-    //         });
-    //         item.activeIndex = lastId;
-    //       }
-    //     }
-    //     if (item.children && item.children.length > 0) {
-    //       formatParentCurrentValue(ids, item.children);
-    //     }
-    //   }
-    // };
+    const formatParentCurrentValue = (ids: any, list: any) => {
+      for (const item of list) {
+        if (ids.includes(item.id)) {
+          if (item.children && item.children.length > 0) {
+            let lastId: any;
+            item.children.forEach((child: any) => {
+              if (ids.includes(child.id)) {
+                lastId = child.id;
+              }
+            });
+            item.activeIndex = lastId;
+          }
+        }
+        if (item.children && item.children.length > 0) {
+          formatParentCurrentValue(ids, item.children);
+        }
+      }
+    };
 
     const initParentSelect = (subject: any) => {
       let children: any;
@@ -116,32 +116,33 @@ export default defineComponent({
       }
     };
 
-    // watch(
-    //   () => state.popoverShow,
-    //   () => {
-    //     if (!state.popoverShow || !props.value) return;
-    //     let ids = formatParentId(props.value, props.options);
-    //     state.tagActiveId = ids[0].id;
-    //     props.options.forEach((item: any) => {
-    //       if (item.id === state.tagActiveId) {
-    //         initParentSelect(item);
-    //       }
-    //     });
+    watch(
+      () => state.popoverShow,
+      () => {
+        if (!state.popoverShow || !props.value) return;
+        let ids = formatParentId(props.value, props.options);
+        console.log(ids, 'ids')
+        state.tagActiveId = ids[0].id;
+        props.options.forEach((item: any) => {
+          if (item.id === state.tagActiveId) {
+            initParentSelect(item);
+          }
+        });
 
-    //     //
-    //     const index = ids.findIndex((child: any) => child.id === props.value);
-    //     ids = ids.slice(0, index + 1);
-    //     const values = ids.map((item: any) => {
-    //       return item.id;
-    //     });
-    //     console.log(values, 'values');
-    //     formatParentCurrentValue(values, props.options);
-    //   }
-    // );
+        //
+        const index = ids.findIndex((child: any) => child.id === props.value);
+        ids = ids.slice(0, index + 1);
+        const values = ids.map((item: any) => {
+          return item.id;
+        });
+        formatParentCurrentValue(values, props.options);
+      }
+    );
 
     const valueText = computed(() => {
       const id = props.value;
       const values = getValues(id);
+      console.log(values, 'values')
       const names: any = [];
       audioPlayTypeList.value.forEach((item: any) => {
         if (item.id === state.tempAudioPlayTypes && props.showAudioPlayType) {
@@ -201,15 +202,20 @@ export default defineComponent({
 
     // 重置
     const onReset = () => {
-      state.childSelectId = null;
-      state.tagActiveId = '';
+      // 重置默认选中第一个
+      const firstChild = props.options[0]
+      const children = firstChild.children ? firstChild.children[0] : null
+      console.log(firstChild, '1111111')
+      state.childSelectId = children?.value;
+      state.tagActiveId = children?.value || firstChild.value || '';
       state.audioPlayTypes = '';
       state.tempAudioPlayTypes = '';
       state.selectParents = {};
-      emit('update:value', '');
+      emit('update:value', children?.value || firstChild.value || '');
+      
       emit('moreId', {
-        childId: '',
-        parentId: '',
+        childId: children?.value,
+        parentId: firstChild.value,
         audioPlayTypes: ''
       });
       state.popoverShow = false;
@@ -231,8 +237,8 @@ export default defineComponent({
           parentId: '',
           audioPlayTypes: state.audioPlayTypes
         });
-        state.tagActiveId = '';
-        state.childSelectId = null;
+        // state.tagActiveId = '';
+        // state.childSelectId = null;
       }
 
       state.tempAudioPlayTypes = state.audioPlayTypes;

+ 12 - 8
src/views/prepare-lessons/components/resource-main/components/resource-item/index.tsx

@@ -127,11 +127,11 @@ export default defineComponent({
     };
 
     const throttledFnSearch = useDebounceFn(item => {
-      state.pagination.page = state.pagination.page + 1;
-      state.pagination.page = 1;
-      state.tableList = [];
-      state.searchGroup = Object.assign(state.searchGroup, item);
-      getList();
+      // state.pagination.page = 1;
+      // state.tableList = [];
+      // state.searchGroup = Object.assign(state.searchGroup, item);
+      // getList();
+      onSearch(item)
     }, 300);
 
     // 声部变化时
@@ -204,7 +204,7 @@ export default defineComponent({
 
     onMounted(() => {
       // 加载的时候判断是否有资源数据
-      onUpdate();
+      // onUpdate();
 
       if (props.type === 'relateResources') {
         eventGlobal.on('onCoursewareUpdate', onUpdate);
@@ -226,9 +226,13 @@ export default defineComponent({
       <div>
         <ResourceSearchGroup
           type={props.type}
-          onSearch={(item: any) => {
+          onSearch={(item: any, type?: string) => {
             state.searchGroup = Object.assign(state.searchGroup, item);
-            throttledFnSearch(item);
+            if(type) {
+              onSearch(item)
+            } else {
+              throttledFnSearch(item);
+            }
           }}
         />
         <NScrollbar

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

@@ -40,7 +40,7 @@ export default defineComponent({
     });
     const resourceType = ref([] as any);
 
-    const onSearch = () => {
+    const onSearch = (type?: string) => {
       emit('search', {
         ...forms,
         audioPlayTypes:
@@ -51,7 +51,7 @@ export default defineComponent({
                 : [forms.audioPlayTypes]
               : []
             : []
-      });
+      }, type);
     };
 
     const debouncedRequest = useThrottleFn(() => onSearch(), 500);
@@ -83,14 +83,16 @@ export default defineComponent({
     const _initSubjectTags = () => {
       const tags = catchStore.getSubjectList;
       formatParentCurrentValue(tags);
-      tagSubjectList.value = [
-        {
-          columnName: '声部',
-          name: '全部声部',
-          id: ''
-        },
-        ...tags
-      ];
+      if(tags.length > 0) {
+        tags[0].columnName = '声部'
+
+        console.log(tags[0])
+        const firstChild = tags[0]
+        forms.subjectId = firstChild.value
+        forms.musicalInstrumentId = firstChild.children[0]?.value
+        subjects.value = firstChild.children[0]?.value
+      }
+      tagSubjectList.value = tags
 
     };
     onMounted(async () => {
@@ -108,6 +110,8 @@ export default defineComponent({
         resourceType.value.push(item);
         // }
       });
+
+      onSearch()
     });
     return () => (
       <>

+ 4 - 2
src/views/prepare-lessons/components/resource-main/components/select-music/index.tsx

@@ -237,7 +237,7 @@ export default defineComponent({
     };
 
     onMounted(() => {
-      getList();
+      // getList();
 
       eventGlobal.on('onTrainDragItem', (item: any, point?: any) => {
         onAdd(item);
@@ -264,7 +264,9 @@ export default defineComponent({
       <div>
         <ResourceSearchGroup
           type={props.type}
-          onSearch={(item: any) => onSearch(item)}
+          onSearch={(item: any) => {
+            onSearch(item)
+          }}
         />
         <NScrollbar
           class={[

+ 14 - 10
src/views/prepare-lessons/components/resource-main/components/select-music/resource-search-group/index.tsx

@@ -35,8 +35,8 @@ export default defineComponent({
       musicalInstrumentId: ''
     });
 
-    const onSearch = () => {
-      emit('search', forms);
+    const onSearch = (type?: string) => {
+      emit('search', forms, type);
     };
 
     const throttledFn = useThrottleFn(() => onSearch(), 500);
@@ -86,14 +86,16 @@ export default defineComponent({
     const _initSubjectTags = () => {
       const tags = catchStore.getSubjectList;
       formatParentCurrentValue(tags);
-      tagSubjectList.value = [
-        {
-          columnName: '声部',
-          name: '全部声部',
-          id: ''
-        },
-        ...tags
-      ];
+
+      if(tags.length > 0) {
+        tags[0].columnName = '声部'
+
+        const firstChild = tags[0]
+        forms.subjectId = firstChild.value
+        forms.musicalInstrumentId = firstChild.children[0]?.value
+        subjects.value = firstChild.children[0]?.value
+      }
+      tagSubjectList.value = tags
     };
     onMounted(async () => {
       // 获取教材分类列表
@@ -105,6 +107,8 @@ export default defineComponent({
       _initSubjectTags();
       // 获取声部列表
       await catchStore.getSubjects();
+
+      onSearch('time')
     });
     return () => (
       <>

+ 55 - 11
src/views/xiaoku-list/detail.module.less

@@ -2,6 +2,20 @@
   min-height: 100%;
   display: flex;
   flex-direction: column;
+  img {
+    -moz-user-select: none;
+    /* 火狐浏览器 */
+    -webkit-user-drag: none;
+    /* 谷歌、Safari和Opera浏览器 */
+    -webkit-user-select: none;
+    /* 谷歌、Safari和Opera浏览器 */
+    -ms-user-select: none;
+    /* IE10+浏览器 */
+    user-select: none;
+    /* 通用 */
+    -webkit-touch-callout: none;
+    /* iOS Safari */
+  }
 }
 .detailContainer {
   flex: 1 auto;
@@ -91,9 +105,13 @@
 .searchGroup {
   background: #f7f8f9;
   border-radius: 12px;
-  padding: 24px 24px 34px;
+  padding: 20px 24px 30px;
   position: relative;
 
+  &.searchGroupOnly {
+    padding-bottom: 6px;
+  }
+
   .hideItem {
     visibility: hidden;
     opacity: 0;
@@ -125,16 +143,23 @@
     }
 
     .n-form-item {
-      .n-form-item-label {
-        font-size: max(17px, 13px);
-        // font-weight: 600;
+      // .n-form-item-label {
+       
+      // }
+      .n-form-item-label__text {
+        font-size: max(17px, 13Px);
+        // cursor: pointer;
+        display: flex;
+        align-items: center;
+        padding: 4px 0;
+        font-weight: 600;
         color: #131415;
         line-height: 24px;
       }
 
       .n-button {
         height: 32px;
-        font-size: max(17px, 12px);
+        font-size: max(17px, 13Px);
         border-radius: 8px;
         color: rgba(0, 0, 0, 0.6);
       }
@@ -156,7 +181,7 @@
     left: 50%;
     transform: translateX(-50%);
     font-size: 17px;
-    color: #000000;
+    color: rgba(0,0,0,0.6);
     cursor: pointer;
     background: url('./images/search-bg.png') no-repeat center;
     background-size: contain;
@@ -171,14 +196,22 @@
       display: inline-block;
       width: 12px;
       height: 12px;
-      background: url('./images/icon-arrow-down.png') no-repeat center;
+      background: url('./images/icon-arrow-down.svg') no-repeat center;
       background-size: contain;
       margin-left: 6px;
-      margin-top: 1px;
+      margin-top: -1px;
+    }
+
+    &:hover {
+      color: #1677FF;
+      &::after {
+        background-image: url('./images/icon-arrow-up.svg');
+      }
     }
 
     &.activeSearch::after {
       transform: rotate(180deg);
+      // background-image: url('./images/icon-arrow-up.svg');
     }
   }
 }
@@ -271,7 +304,7 @@
   background: transparent;
   border-radius: 8px;
   padding: 4px 20px;
-  font-size: max(17px, 13px);
+  font-size: max(17px, 13Px);
   color: rgba(0, 0, 0, 0.6);
   cursor: pointer;
   display: flex;
@@ -332,6 +365,9 @@
       flex: 1 auto;
     }
   }
+  .loadingSection {
+    min-height: calc(100vh - 64px - 64px - 56px - 80px);
+  }
 }
 
 .empty {
@@ -346,6 +382,7 @@
   display: flex;
   justify-content: center;
   min-height: 80px;
+  position: relative;
 
   &.showLoading {
     height: 0;
@@ -364,6 +401,14 @@
   width: 402px;
   background: #f7f8f9;
   cursor: pointer;
+  transition: all .2s ease;
+  border: 2px solid #F4F4F4;
+  box-sizing: border-box;
+  &:hover {
+    transform: scale(1.01);
+    border: 2px solid rgba(0, 122, 254, 1);
+    transition: all .2s ease;
+  }
 
   .img {
     width: 60px;
@@ -423,8 +468,7 @@
           vertical-align: middle;
         }
         span {
-          line-height: 1;
-          vertical-align: text-bottom;
+          vertical-align: text-top;
         }
       }
       .sing,

+ 187 - 110
src/views/xiaoku-list/detail.tsx

@@ -1,4 +1,12 @@
-import { computed, defineComponent, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue';
+import {
+  computed,
+  defineComponent,
+  nextTick,
+  onMounted,
+  onUnmounted,
+  reactive,
+  ref
+} from 'vue';
 import styles from './detail.module.less';
 import CBreadcrumb from '/src/components/CBreadcrumb';
 import { useRoute } from 'vue-router';
@@ -10,7 +18,7 @@ import { api_musicSheetPage } from '../xiaoku-ai/api';
 import { formatUsedNum } from '.';
 import { vaildMusicScoreUrl } from '/src/utils/urlUtils';
 import { exitFullscreen, fscreen } from '/src/utils';
-import {state as baseState} from '/src/state';
+import { state as baseState } from '/src/state';
 import { useUserStore } from '/src/store/modules/users';
 import PreviewWindow from '../preview-window';
 
@@ -21,19 +29,19 @@ export default defineComponent({
     const userStore = useUserStore();
     const routerList = ref([
       { name: 'AI学练', path: '/xiaoku-list' },
-      { name: '全部曲目', path: '' }
+      { name: '曲目列表', path: '' }
     ]);
     const forms = reactive({
       page: 1,
       rows: 32,
       status: true,
-      searchType: '',
+      searchType: ''
     });
     const state = reactive({
       loading: true,
       finshed: false,
       reshing: false,
-      tabName: '' as any,
+      tabName: '' as '' | 'RECOMMEND' | 'HOT' | 'NEW',
       list: [] as any,
       allSearch: {
         name: '',
@@ -45,31 +53,45 @@ export default defineComponent({
       },
       hotSearch: {
         name: '',
+        musicalInstrumentId: null as any
       },
       newSearch: {
         name: '',
+        musicalInstrumentId: null as any
       },
       recommendSearch: {
         name: '',
+        musicalInstrumentId: null as any
       },
       previewModal: false,
       previewParams: {
         type: '',
         src: ''
-      } as any,
+      } as any
     });
 
     const searchValue = computed(() => {
-      if(state.tabName === 'RECOMMEND') {
-        return state.recommendSearch.name
-      } else if(state.tabName === 'HOT') {
-        return state.hotSearch.name
-      } else if(state.tabName === 'NEW') {
-        return state.newSearch.name
+      if (state.tabName === 'RECOMMEND') {
+        return state.recommendSearch.name;
+      } else if (state.tabName === 'HOT') {
+        return state.hotSearch.name;
+      } else if (state.tabName === 'NEW') {
+        return state.newSearch.name;
       } else {
-        return state.allSearch.name
+        return state.allSearch.name;
       }
-    })
+    });
+    const musicalInstrumentId = computed(() => {
+      let id = state.allSearch.musicalInstrumentId;
+      if (state.tabName === 'RECOMMEND') {
+        id = state.recommendSearch.musicalInstrumentId;
+      } else if (state.tabName === 'HOT') {
+        id = state.hotSearch.musicalInstrumentId;
+      } else if (state.tabName === 'NEW') {
+        id = state.newSearch.musicalInstrumentId;
+      }
+      return id;
+    });
 
     const onSearch = async (item: any) => {
       forms.page = 1;
@@ -77,20 +99,32 @@ export default defineComponent({
       state.finshed = false;
 
       const { subjectId, ...res } = item;
-      
-      state.allSearch = Object.assign(state.allSearch, {
-        ...res,
-        musicalInstrumentId: subjectId,
-        subjectId: null
-      });
+      if (state.tabName === 'HOT') {
+        state.hotSearch = Object.assign(state.hotSearch, {
+          musicalInstrumentId: subjectId
+        });
+      } else if (state.tabName == 'NEW') {
+        state.newSearch = Object.assign(state.newSearch, {
+          musicalInstrumentId: subjectId
+        });
+      } else if (state.tabName === 'RECOMMEND') {
+        state.recommendSearch = Object.assign(state.recommendSearch, {
+          musicalInstrumentId: subjectId
+        });
+      } else {
+        state.allSearch = Object.assign(state.allSearch, {
+          ...res,
+          musicalInstrumentId: subjectId,
+          subjectId: null
+        });
+      }
 
       getList();
       nextTick(() => {
-        __initSpin()
-      })
+        __initSpin();
+      });
     };
 
-
     const spinRef = ref();
     const handleResh = () => {
       if (state.loading || state.finshed) return;
@@ -99,26 +133,27 @@ export default defineComponent({
     };
 
     const getList = async () => {
-      state.loading = true;
+      if(forms.page == 1) {
+        state.loading = true;
+      }
       let res = {} as any;
+      const { ...result } = forms;
+      let params = {
+        ...result,
+        searchType: state.tabName
+      } as any;
+      if (state.tabName === 'RECOMMEND') {
+        params = Object.assign(params, state.recommendSearch);
+      } else if (state.tabName === 'HOT') {
+        params = Object.assign(params, state.hotSearch);
+      } else if (state.tabName === 'NEW') {
+        params = Object.assign(params, state.newSearch);
+      } else {
+        params.name = state.allSearch.name;
+        const { ...more } = state.allSearch;
+        params = Object.assign(params, { ...more });
+      }
       try {
-        const { ...result } = forms;
-        let params = {
-          ...result,
-          searchType: state.tabName
-        } as any
-        if(state.tabName === 'RECOMMEND') {
-          params = Object.assign(params, state.recommendSearch);
-        } else if(state.tabName === 'HOT') {
-          params = Object.assign(params, state.hotSearch);
-        } else if(state.tabName === 'NEW') {
-          params = Object.assign(params, state.newSearch);
-        } else {
-          params.name = state.allSearch.name
-          const { ...more } = state.allSearch
-          params = Object.assign(params, { ...more });
-          // params.audioPlayTypes =  audioPlayTypes
-        }
         res = await api_musicSheetPage(params);
       } catch (error) {
         console.log(error);
@@ -134,9 +169,18 @@ export default defineComponent({
           item.audioPlayTypeArray = item.audioPlayTypes
             ? item.audioPlayTypes.split(',')
             : [];
+
+          if (item.musicSheetName) {
+            const regex = new RegExp(params.name, 'gi');
+            const highlightedText = item.musicSheetName.replace(
+              regex,
+              `<span>$&</span>`
+            );
+            item.musicNameReg = highlightedText;
+          }
         });
         state.list = [...state.list, ...res.data.rows];
-        state.finshed = forms.page >= res.data.pages; 
+        state.finshed = forms.page >= res.data.pages;
       } else {
         state.finshed = true;
       }
@@ -144,13 +188,13 @@ export default defineComponent({
     };
 
     const __initSpin = () => {
-      const obv = new IntersectionObserver(entries => {
-        if (entries[0].intersectionRatio > 0) {
-          handleResh();
-        }
-      });
-      obv.observe(spinRef.value);
-    }
+      // const obv = new IntersectionObserver(entries => {
+      //   if (entries[0].intersectionRatio > 0) {
+      //     handleResh();
+      //   }
+      // });
+      // obv.observe(spinRef.value);
+    };
 
     // 查看详情
     const onDetail = (item: any) => {
@@ -160,9 +204,7 @@ export default defineComponent({
         item.id
       }&Authorization=${
         userStore.getToken
-      }&musicRenderType=${lineType}&showGuide=true&part-index=${
-        0
-      }`;
+      }&musicRenderType=${lineType}&showGuide=true&part-index=${0}`;
 
       if (state.allSearch.musicalInstrumentId && !state.tabName) {
         src += '&instrumentId=' + state.allSearch.musicalInstrumentId;
@@ -181,28 +223,28 @@ export default defineComponent({
       } else {
         window.open(src, +new Date() + '');
       }
-    }
+    };
 
     const iframeHandle = (ev: MessageEvent) => {
       if (ev.data?.api === 'onAttendToggleMenu') {
-        exitFullscreen()
+        exitFullscreen();
         state.previewModal = !state.previewModal;
       }
-    }
+    };
 
     onMounted(async () => {
-      if(route.query.type) {
-        state.tabName = route.query.type
+      if (route.query.type) {
+        state.tabName = route.query.type as any;
       }
 
       // getList();
-      __initSpin()
+      __initSpin();
       window.addEventListener('message', iframeHandle);
     });
 
     onUnmounted(() => {
-      window.removeEventListener('message', iframeHandle)
-    })
+      window.removeEventListener('message', iframeHandle);
+    });
     return () => (
       <div class={styles.xiaokuDetail}>
         <CBreadcrumb list={routerList.value}></CBreadcrumb>
@@ -217,31 +259,31 @@ export default defineComponent({
               forms.page = 1;
               state.finshed = false;
               state.reshing = true;
-              state.list = []
+              state.list = [];
               getList();
 
-              __initSpin()
+              __initSpin();
             }}
             v-slots={{
               suffix: () => (
                 <TheSearch
-                  placeholder='请输入曲目名称'
+                  placeholder="请输入曲目名称"
                   round
                   value={searchValue.value}
                   class={styles.inputSearch}
                   onSearch={val => {
-                    if(state.tabName === 'RECOMMEND') {
-                      state.recommendSearch.name = val
-                    } else if(state.tabName === 'HOT') {
-                      state.hotSearch.name = val
-                    } else if(state.tabName === 'NEW') {
-                      state.newSearch.name = val
+                    if (state.tabName === 'RECOMMEND') {
+                      state.recommendSearch.name = val;
+                    } else if (state.tabName === 'HOT') {
+                      state.hotSearch.name = val;
+                    } else if (state.tabName === 'NEW') {
+                      state.newSearch.name = val;
                     } else {
-                      state.allSearch.name = val
+                      state.allSearch.name = val;
                     }
                     forms.page = 1;
                     state.finshed = false;
-                    state.list = []
+                    state.list = [];
                     getList();
                   }}
                 />
@@ -253,60 +295,95 @@ export default defineComponent({
             <NTabPane name={`NEW`} tab={'最新曲目'}></NTabPane>
           </NTabs>
 
-          <NScrollbar class={[[styles.wrapList, !state.loading && state.list.length === 0 && styles.wrapListEmpty]]}>
-              <div class={[styles.searchSection, state.tabName ? styles.searchSectionHide : '']}>
-                <SearchGroupResources onSearch={(val: any) => {
-                  onSearch(val)
-                }} />
-              </div>
-            
-            {state.list.length > 0 && <div
-              class={[
-                styles.sectionContainer,
-                state.tabName && styles.noSearchContainer
-              ]}>
-              {state.list.map((item: any) => (
-                <div class={styles.sectionItem} onClick={() => onDetail(item)}>
-                  <div class={styles.img}>
-                    <img referrerpolicy="no-referrer" src={item.titleImg} />
-                  </div>
-                  <div class={styles.infos}>
-                    <div class={styles.topName}>{item.musicSheetName}</div>
-                    <div class={styles.types}>
-                      <div class={styles.hot}>
-                        <span>{formatUsedNum(item.usedNum)}</span>
-                      </div>
-                      {item.audioPlayTypes?.includes('SING') && (
-                        <div class={styles.sing}>演唱</div>
-                      )}
-                      {item.audioPlayTypes?.includes('PLAY') && (
-                        <div class={styles.song}>演奏</div>
-                      )}
+          <NScrollbar
+            class={[
+              [
+                styles.wrapList,
+                !state.loading &&
+                  state.list.length === 0 &&
+                  styles.wrapListEmpty
+              ]
+            ]}
+            onScroll={(e: any) => {
+              const clientHeight = e.target?.clientHeight;
+              const scrollTop = e.target?.scrollTop;
+              const scrollHeight = e.target?.scrollHeight;
+              // 是否到底,是否加载完
+              if (
+                clientHeight + scrollTop + 20 >= scrollHeight &&
+                !state.finshed &&
+                !state.loading
+              ) {
+                forms.page = forms.page + 1;
+                getList();
+              }
+            }}
+            >
+            {/* , state.tabName ? styles.searchSectionHide : '' */}
+            <NSpin show={state.loading}>
+            <div class={styles.loadingSection}>
+            <div class={[styles.searchSection]}>
+              <SearchGroupResources
+                type={state.tabName}
+                musicalInstrumentId={musicalInstrumentId.value}
+                onSearch={(val: any) => {
+                  onSearch(val);
+                }}
+              />
+            </div>
+
+            {state.list.length > 0 && (
+              <div
+                class={[
+                  styles.sectionContainer
+                  // state.tabName && styles.noSearchContainer
+                ]}>
+                {state.list.map((item: any) => (
+                  <div
+                    class={styles.sectionItem}
+                    onClick={() => onDetail(item)}>
+                    <div class={styles.img}>
+                      <img referrerpolicy="no-referrer" src={item.titleImg} />
+                    </div>
+                    <div class={styles.infos}>
+                      <div class={styles.topName} v-html={item.musicNameReg}></div>
+                      <div class={styles.types}>
+                        <div class={styles.hot}>
+                          <span>{formatUsedNum(item.usedNum)}</span>
+                        </div>
+                        {item.audioPlayTypes?.includes('SING') && (
+                          <div class={styles.sing}>演唱</div>
+                        )}
+                        {item.audioPlayTypes?.includes('PLAY') && (
+                          <div class={styles.song}>演奏</div>
+                        )}
 
-                      <div class={styles.author}>{item.composer}</div>
+                        <div class={styles.author}>{item.composer}</div>
+                      </div>
                     </div>
                   </div>
-                </div>
-              ))}
-            </div>}
-            
+                ))}
+              </div>
+            )}
 
-            <div
-              ref={spinRef}
-              class={[styles.loadingWrap, state.finshed && styles.showLoading]}>
+            {/* <div
+              // ref={spinRef}
+              class={[styles.loadingWrap, (state.finshed || !state.loading) && styles.showLoading]}>
               <NSpin show={true}></NSpin>
-            </div>
+            </div> */}
 
             {!state.loading && state.list.length === 0 && (
               <div class={styles.empty}>
                 <TheEmpty></TheEmpty>
               </div>
             )}
+            </div>
+            </NSpin>
           </NScrollbar>
         </div>
 
         {/* 应用内预览或上课 */}
-      <PreviewWindow
+        <PreviewWindow
           v-model:show={state.previewModal}
           type="music"
           params={state.previewParams}

+ 19 - 0
src/views/xiaoku-list/images/icon-arrow-down.svg

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="12px" height="13px" viewBox="0 0 12 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>小箭头/展开</title>
+    <g id="AI学练" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="5、全部曲目备份" transform="translate(-1073, -408)" fill="#616162" fill-rule="nonzero">
+            <g id="编组-17-+-编组-18-+-编组-13蒙版" transform="translate(132, 140)">
+                <g id="编组-13" transform="translate(32, 93)">
+                    <g id="编组-10" transform="translate(767, 164)">
+                        <g id="编组-7" transform="translate(68, 5.2213)">
+                            <g id="小箭头/展开" transform="translate(74.8206, 8.9994)">
+                                <path d="M3.56433292,-1.95456088 L3.58024499,-1.93904332 L7.93910126,2.41974719 C8.25425238,2.73496407 8.25944681,3.24283539 7.95455306,3.56429874 L7.93910126,3.58027657 L3.58024499,7.93900133 C3.25983368,8.25954414 2.74025843,8.25954414 2.41971562,7.93900133 C2.1045645,7.62385021 2.09937006,7.11597888 2.40426381,6.79451553 L2.41978137,6.77853771 L6.19837295,3.00001188 L2.41978137,-0.7785797 C2.1045645,-1.09379657 2.09937006,-1.60160214 2.40426381,-1.92313124 L2.41978137,-1.93904332 C2.73499824,-2.25426019 3.24280382,-2.25945463 3.56433292,-1.95456088 Z" id="路径备份" transform="translate(5.1794, 3) rotate(-270) translate(-5.1794, -3)"></path>
+                            </g>
+                        </g>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 19 - 0
src/views/xiaoku-list/images/icon-arrow-up.svg

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="12px" height="13px" viewBox="0 0 12 13" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>小箭头/展开</title>
+    <g id="AI学练" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="5、全部曲目备份" transform="translate(-1357, -408)" fill="#1677FF" fill-rule="nonzero">
+            <g id="编组-17-+-编组-18-+-编组-13蒙版" transform="translate(132, 140)">
+                <g id="编组-13" transform="translate(32, 93)">
+                    <g id="编组-10备份" transform="translate(1051, 164)">
+                        <g id="编组-7" transform="translate(68, 5.2213)">
+                            <g id="小箭头/展开" transform="translate(74.8206, 8.9994)">
+                                <path d="M3.56433292,-1.95456088 L3.58024499,-1.93904332 L7.93910126,2.41974719 C8.25425238,2.73496407 8.25944681,3.24283539 7.95455306,3.56429874 L7.93910126,3.58027657 L3.58024499,7.93900133 C3.25983368,8.25954414 2.74025843,8.25954414 2.41971562,7.93900133 C2.1045645,7.62385021 2.09937006,7.11597888 2.40426381,6.79451553 L2.41978137,6.77853771 L6.19837295,3.00001188 L2.41978137,-0.7785797 C2.1045645,-1.09379657 2.09937006,-1.60160214 2.40426381,-1.92313124 L2.41978137,-1.93904332 C2.73499824,-2.25426019 3.24280382,-2.25945463 3.56433292,-1.95456088 Z" id="路径备份" transform="translate(5.1794, 3) rotate(-270) translate(-5.1794, -3)"></path>
+                            </g>
+                        </g>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 134 - 50
src/views/xiaoku-list/index.module.less

@@ -23,19 +23,39 @@
 }
 
 .topTitle {
-  padding-top: 30px;
-  padding-bottom: 24px;
+  padding: 30px 60px 24px;
   font-size: 0;
-  // color: #131415;
-  // height: 60px;
-  // letter-spacing: 1px;
-  // text-align: center;
-  // font-style: normal;
-  // color: #004aff;
-  text-align: center;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
   img {
     height: 50px;
-    margin: 0 auto;
+  }
+
+  .moreMusic {
+    // position: absolute;
+    // right: 60px;
+    padding: 9px 25px;
+    background: rgba(255, 255, 255, 0.7);
+    border-radius: 22px;
+    font-weight: 600;
+    font-size: 18px;
+    color: #131415;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+    line-height: 1.6;
+
+    &::after {
+      content: '';
+      display: inline-block;
+      width: 6px;
+      height: 10px;
+      background: url('./images/icon-arrow.png') no-repeat center;
+      background-size: contain;
+      margin-left: 6px;
+    }
   }
 }
 
@@ -43,51 +63,78 @@
   position: relative;
   display: flex;
   align-items: center;
-  justify-content: center;
+  justify-content: space-between;
+  padding: 0 60px;
   .searchInput {
-    width: 700px;
-    --n-height: 50px !important;
+    width: 480px;
+    --n-border: #fff !important;
     :global {
       .n-button {
         padding: 0 24px;
-        font-size: 18px !important;
+        font-size: max(16px, 13px) !important;
         color: #ffffff;
         --n-border: none !important;
-        background: linear-gradient( 312deg, #1B7AF8 0%, #3CBBFF 100%);
+        background: linear-gradient(312deg, #1b7af8 0%, #3cbbff 100%);
       }
       .n-input__input-el {
-        font-size: 18px !important;
+        font-size: max(16px, 13px) !important;
         color: #000000;
       }
 
       .n-input__placeholder {
-        font-size: 18px !important;
+        font-size: max(16px, 13px) !important;
       }
     }
   }
-  .moreMusic {
-    position: absolute;
-    right: 60px;
-    padding: 9px 25px;
-    background: rgba(255, 255, 255, 0.7);
-    border-radius: 22px;
-    font-weight: 600;
-    font-size: 18px;
-    color: #131415;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    cursor: pointer;
-    line-height: 1.5;
 
-    &::after {
-      content: '';
+  .textBtn {
+    background-color: rgba(255, 255, 255, 0.7);
+    --n-border: none !important;
+    .iconArrow {
       display: inline-block;
-      width: 6px;
-      height: 10px;
-      background: url('./images/icon-arrow.png') no-repeat center;
-      background-size: contain;
-      margin-left: 6px;
+      margin-left: 8px;
+      width: 8px;
+      height: 5px;
+      background: url('../xiaoku-music/images/icon-arrow.svg') no-repeat center
+        center / contain;
+      transform: rotate(180deg);
+      color: #8B8D98;
+      fill: #8B8D98;
+    }
+
+    &:hover,
+    &.textBtnActive {
+      transition-duration: 0s !important;
+      background: linear-gradient( 312deg, #1B7AF8 0%, #3CBBFF 100%) !important;
+      font-weight: 500 !important;
+      color: #fff !important;
+
+      .iconArrow {
+        transform: rotate(0deg);
+        background: url('../xiaoku-music/images/icon-arrow2.svg') no-repeat
+          center center / contain;
+        color: #fff;
+        fill: #fff;
+        margin-top: 0;
+      }
+    }
+  }
+  .tags {
+    :global {
+      .n-form-item-feedback-wrapper {
+        min-height: 0;
+      }
+
+      .n-button {
+        min-width: 102px;
+        height: 37px;
+        padding: 0 24px;
+        font-size: max(18px, 13px);
+      }
+
+      .n-button--primary-type {
+        font-weight: 500 !important;
+      }
     }
   }
 }
@@ -97,6 +144,17 @@
   display: flex;
   gap: 0 30px;
   flex: 1 auto;
+  :global {
+    .n-spin-container {
+     width: 100%;
+    }
+    .n-spin-content {
+      display: flex;
+      gap: 0 30px;
+      width: 100%;
+    height: 100%;
+    }
+  }
   .section {
     flex: 1;
     border-radius: 16px;
@@ -117,7 +175,7 @@
         font-weight: 600;
         font-size: 18px;
         color: #131415;
-        padding: 7px 20px;
+        padding: 8px 20px;
         display: flex;
         align-items: center;
         justify-content: center;
@@ -167,6 +225,9 @@
       height: calc(100vh - 64px - 154px - 48px - 91px);
     }
   }
+  .empty {
+    height: calc(100vh - 64px - 154px - 48px - 91px);
+  }
 }
 
 .item {
@@ -185,7 +246,7 @@
   .num {
     font-family: DINAlternate, DINAlternate;
     font-weight: bold;
-    font-size: 18px;
+    font-size: max(18px, 13Px);
     color: #7e8287;
     line-height: 22px;
     text-align: center;
@@ -240,7 +301,7 @@
         background: #fff3f3;
         border-radius: 3px;
         border: 1px solid rgba(254, 67, 67, 0.5);
-        font-size: max(12px, 11px);
+        font-size: max(12px, 11Px);
         color: #fe4343;
         padding: 0 5px;
         &::before {
@@ -254,17 +315,16 @@
           vertical-align: middle;
         }
         span {
-          line-height: 1;
-          vertical-align: text-bottom;
+          // line-height: 1;
+          vertical-align: text-top;
         }
       }
       .sing,
       .song {
         background: #ffffff;
-        font-size: max(12px, 11px);
+        font-size: max(12px, 11Px);
         border-radius: 3px;
         padding: 0 4px;
-        line-height: 1;
         display: flex;
         align-items: center;
       }
@@ -294,13 +354,13 @@
     height: 100%;
     // height: 100%;
   }
-  
+
   .loadingWrap {
     display: flex;
     justify-content: center;
     // min-height: 80px;
     padding-bottom: 10px;
-  
+
     &.showLoading {
       height: 0;
       opacity: 0;
@@ -324,19 +384,28 @@
   padding: 0 48px;
   display: flex;
   flex-wrap: wrap;
+  min-height: calc(100vh - 64px - 160px - 40px);
 }
 
 .sectionItem {
   display: flex;
   align-items: center;
-  margin: 0 12px 10px;
+  margin: 0 12px 24px;
   cursor: pointer;
   padding: 15px 12px;
   border-radius: 12px;
   width: 405px;
-  background: #FFFFFF;
+  background: #ffffff;
   cursor: pointer;
   box-sizing: border-box;
+  transition: all .2s ease;
+  border: 2px solid #F4F4F4;
+  box-sizing: border-box;
+  &:hover {
+    transform: scale(1.01);
+    border: 2px solid rgba(0, 122, 254, 1);
+    transition: all .2s ease;
+  }
 
   .img {
     width: 60px;
@@ -366,7 +435,7 @@
       max-width: 270px;
 
       span {
-        color: #198CFE;
+        color: #198cfe;
         font-weight: bold;
       }
     }
@@ -425,3 +494,18 @@
     }
   }
 }
+
+
+.popSelect1 {
+  font-size: 16px;
+  width: 200px;
+  box-shadow: 0px 2px 16px 0px rgba(0, 0, 0, 0.08);
+  border-radius: 11px;
+  --n-option-height: 34px;
+
+  :global {
+    .n-base-select-option__content {
+      width: 80% !important;
+    }
+  }
+}

+ 186 - 56
src/views/xiaoku-list/index.tsx

@@ -11,7 +11,14 @@ import TheSearch from '/src/components/TheSearch';
 import recommendTitle from './images/reommon_title.png';
 import newTitle from './images/new_title.png';
 import hotTitle from './images/hot_title.png';
-import { NScrollbar, NSpin } from 'naive-ui';
+import {
+  NButton,
+  NFormItem,
+  NPopselect,
+  NScrollbar,
+  NSpace,
+  NSpin
+} from 'naive-ui';
 import TheNoticeBar from '/src/components/TheNoticeBar';
 import { useRouter } from 'vue-router';
 import { api_musicSheetQueryByTag } from './api';
@@ -23,6 +30,7 @@ import PreviewWindow from '../preview-window';
 import { useUserStore } from '/src/store/modules/users';
 import { state as baseState } from '/src/state';
 import { exitFullscreen, fscreen } from '/src/utils';
+import { useCatchStore } from '/src/store/modules/catchData';
 
 export const formatUsedNum = (num: number) => {
   if (num < 10000) {
@@ -36,6 +44,7 @@ export const formatUsedNum = (num: number) => {
 export default defineComponent({
   name: 'xiaoku-list',
   setup() {
+    const catchStore = useCatchStore();
     const router = useRouter();
     const userStore = useUserStore();
     const state = reactive({
@@ -48,6 +57,7 @@ export default defineComponent({
       list: [] as any,
       loading: false as any,
       finshed: false,
+      instrumentId: null as any,
       page: 1,
       rows: 36,
       previewModal: false,
@@ -57,11 +67,21 @@ export default defineComponent({
       } as any
     });
 
+    const data = reactive({
+      tags: [] as any[],
+      tagIndex: 0,
+      list: [] as any,
+      loading: false
+    });
+
     /** 获取三个模块 */
     const getDetail = async () => {
       state.detailLoading = true;
       try {
-        const { data } = await api_musicSheetQueryByTag({ rows: 48 });
+        const { data } = await api_musicSheetQueryByTag({
+          rows: 48,
+          musicalInstrumentId: state.instrumentId
+        });
         state.RECOMMEND = data.RECOMMEND || [];
         state.HOT = data.HOT || [];
         state.NEW = data.NEW || [];
@@ -71,12 +91,28 @@ export default defineComponent({
       state.detailLoading = false;
     };
 
+    const selectChildObj = (item: any) => {
+      const obj: any = {};
+      item?.forEach((child: any) => {
+        if (child.id === data.tagIndex) {
+          console.log(child, '1212');
+          obj.selected = true;
+          obj.name = child.name;
+        }
+      });
+
+      return obj;
+    };
+
     /** 获取更多 */
     const getList = async () => {
-      state.loading = true;
+      if (state.page === 1) {
+        state.loading = true;
+      }
       try {
         const { data } = await api_musicSheetPage({
           name: state.keyword,
+          musicalInstrumentId: state.instrumentId,
           page: state.page,
           rows: state.rows
         });
@@ -93,7 +129,6 @@ export default defineComponent({
         });
         state.list = [...state.list, ...data.rows];
         state.finshed = state.page >= data.pages;
-        console.log(data, state.list, 'list');
       } catch (e) {
         //
         console.log(e, 'e');
@@ -109,12 +144,12 @@ export default defineComponent({
     };
 
     const __initSpin = () => {
-      const obv = new IntersectionObserver(entries => {
-        if (entries[0].intersectionRatio > 0) {
-          handleResh();
-        }
-      });
-      obv.observe(spinRef.value);
+      // const obv = new IntersectionObserver(entries => {
+      //   if (entries[0].intersectionRatio > 0) {
+      //     handleResh();
+      //   }
+      // });
+      // obv.observe(spinRef.value);
     };
 
     // 查看更多
@@ -159,7 +194,20 @@ export default defineComponent({
       }
     };
 
-    onMounted(() => {
+    const onSearch = () => {
+      state.isSearch = true;
+      state.loading = true;
+      state.finshed = false;
+      state.list = [];
+      getList();
+      nextTick(() => {
+        __initSpin();
+      });
+    };
+
+    onMounted(async () => {
+      // 获取教材分类列表
+      await catchStore.getSubjects();
       getDetail();
 
       window.addEventListener('message', iframeHandle);
@@ -172,38 +220,105 @@ export default defineComponent({
       <div class={styles.list}>
         <h2 class={styles.topTitle}>
           <img src={titleBg} />
+
+          <div class={styles.moreMusic} onClick={() => onMore()}>
+            全部曲目
+          </div>
         </h2>
 
         <div class={styles.searchSection}>
+          <NFormItem class={styles.tags} showLabel={false}>
+            <NSpace size={[12, 20]}>
+              {catchStore.getSubjectInstruments.map((item: any) =>
+                item.instruments && item.instruments.length > 1 ? (
+                  <NPopselect
+                    options={item.instruments}
+                    trigger="hover"
+                    v-model:value={data.tagIndex}
+                    scrollable
+                    onUpdate:value={() => {
+                      state.instrumentId = data.tagIndex;
+                      if (state.isSearch) {
+                        onSearch();
+                      } else {
+                        getDetail();
+                      }
+                    }}
+                    key={item.value}
+                    class={[styles.popSelect1]}>
+                    <NButton
+                      round
+                      class={[
+                        styles.textBtn,
+                        selectChildObj(item.instruments).selected &&
+                          styles.textBtnActive
+                      ]}>
+                      {selectChildObj(item.instruments).name || item.name}
+                      <i class={styles.iconArrow}></i>
+                    </NButton>
+                  </NPopselect>
+                ) : (
+                  <NButton
+                    round
+                    class={[
+                      styles.textBtn,
+                      data.tagIndex === (item.value || 0) &&
+                        styles.textBtnActive
+                    ]}
+                    onClick={() => {
+                      data.tagIndex = item.value || 0;
+                      state.instrumentId = item.value;
+                      if (state.isSearch) {
+                        onSearch();
+                      } else {
+                        getDetail();
+                      }
+                    }}>
+                    {item.name}
+                  </NButton>
+                )
+              )}
+            </NSpace>
+          </NFormItem>
           <TheSearch
             round
             class={styles.searchInput}
-            placeholder='请输入曲目名称'
+            placeholder="请输入曲目名称"
             onSearch={val => {
               if (val && val.trim()) {
-                state.isSearch = true;
                 state.keyword = val.trim();
-                state.loading = true;
-                state.finshed = false;
-                state.list = [];
-                getList();
-                nextTick(() => {
-                  __initSpin();
-                });
+                onSearch();
               } else {
                 state.isSearch = false;
+                getDetail();
               }
             }}
           />
-
-          <div class={styles.moreMusic} onClick={() => onMore()}>
-            全部曲目
-          </div>
         </div>
 
         {state.isSearch ? (
           <div class={styles.searchContainer}>
-            <NScrollbar class={!state.loading && state.list.length === 0 ? styles.emptyScrollBar : ''}>
+            <NScrollbar
+              class={
+                !state.loading && state.list.length === 0
+                  ? styles.emptyScrollBar
+                  : ''
+              } 
+              onScroll={(e: any) => {
+                const clientHeight = e.target?.clientHeight;
+                const scrollTop = e.target?.scrollTop;
+                const scrollHeight = e.target?.scrollHeight;
+                // 是否到底,是否加载完
+                if (
+                  clientHeight + scrollTop + 20 >= scrollHeight &&
+                  !state.finshed &&
+                  !state.loading
+                ) {
+                  state.page = state.page + 1;
+                  getList();
+                }
+              }}>
+              <NSpin show={state.loading}>
               <div class={styles.sectionContainer}>
                 {state.list.map((item: any) => (
                   <div
@@ -233,14 +348,15 @@ export default defineComponent({
                   </div>
                 ))}
               </div>
-              <div
-                ref={spinRef}
+              </NSpin>
+              {/* <div
+                // ref={spinRef}
                 class={[
                   styles.loadingWrap,
-                  state.finshed && styles.showLoading
+                  state.finshed && !state.loading && styles.showLoading
                 ]}>
                 <NSpin show={true}></NSpin>
-              </div>
+              </div> */}
             </NScrollbar>
 
             {!state.loading && state.list.length === 0 && (
@@ -251,16 +367,18 @@ export default defineComponent({
           </div>
         ) : (
           <div class={styles.container}>
-            <div class={[styles.section, styles.recommendSection]}>
-              <div class={styles.sectionTitle}>
-                <img src={recommendTitle} class={styles.imgTitle} />
+            <NSpin show={state.detailLoading}>
+              <div class={[styles.section, styles.recommendSection]}>
+                <div class={styles.sectionTitle}>
+                  <img src={recommendTitle} class={styles.imgTitle} />
 
-                <div class={styles.moreBtn} onClick={() => onMore('RECOMMEND')}>
-                  更多
+                  <div
+                    class={styles.moreBtn}
+                    onClick={() => onMore('RECOMMEND')}>
+                    更多
+                  </div>
                 </div>
-              </div>
 
-              <NSpin show={state.detailLoading}>
                 <NScrollbar>
                   {state.RECOMMEND.map((item: any, index: number) => (
                     <div
@@ -300,17 +418,21 @@ export default defineComponent({
                       </div>
                     </div>
                   ))}
+
+                  {!state.detailLoading && state.RECOMMEND.length === 0 && (
+                    <div class={styles.empty}>
+                      <TheEmpty description="暂无曲目"></TheEmpty>
+                    </div>
+                  )}
                 </NScrollbar>
-              </NSpin>
-            </div>
-            <div class={[styles.section, styles.hotSection]}>
-              <div class={styles.sectionTitle}>
-                <img src={hotTitle} class={styles.imgTitle} />
-                <div class={styles.moreBtn} onClick={() => onMore('HOT')}>
-                  更多
-                </div>
               </div>
-              <NSpin show={state.detailLoading}>
+              <div class={[styles.section, styles.hotSection]}>
+                <div class={styles.sectionTitle}>
+                  <img src={hotTitle} class={styles.imgTitle} />
+                  <div class={styles.moreBtn} onClick={() => onMore('HOT')}>
+                    更多
+                  </div>
+                </div>
                 <NScrollbar>
                   {state.HOT.map((item: any, index: number) => (
                     <div
@@ -350,18 +472,21 @@ export default defineComponent({
                       </div>
                     </div>
                   ))}
+                  {!state.detailLoading && state.HOT.length === 0 && (
+                    <div class={styles.empty}>
+                      <TheEmpty description="暂无曲目"></TheEmpty>
+                    </div>
+                  )}
                 </NScrollbar>
-              </NSpin>
-            </div>
-            <div class={[styles.section, styles.newSection]}>
-              <div class={styles.sectionTitle}>
-                <img src={newTitle} class={styles.imgTitle} />
+              </div>
+              <div class={[styles.section, styles.newSection]}>
+                <div class={styles.sectionTitle}>
+                  <img src={newTitle} class={styles.imgTitle} />
 
-                <div class={styles.moreBtn} onClick={() => onMore('NEW')}>
-                  更多
+                  <div class={styles.moreBtn} onClick={() => onMore('NEW')}>
+                    更多
+                  </div>
                 </div>
-              </div>
-              <NSpin show={state.detailLoading}>
                 <NScrollbar>
                   {state.NEW.map((item: any, index: number) => (
                     <div
@@ -401,9 +526,14 @@ export default defineComponent({
                       </div>
                     </div>
                   ))}
+                  {!state.detailLoading && state.NEW.length === 0 && (
+                    <div class={styles.empty}>
+                      <TheEmpty description="暂无曲目"></TheEmpty>
+                    </div>
+                  )}
                 </NScrollbar>
-              </NSpin>
-            </div>
+              </div>
+            </NSpin>
           </div>
         )}
 

+ 130 - 38
src/views/xiaoku-list/search-group-resources.tsx

@@ -5,7 +5,9 @@ import {
   reactive,
   ref,
   watch,
-  toRefs
+  toRefs,
+  PropType,
+  computed
 } from 'vue';
 import styles from './detail.module.less';
 import {
@@ -22,7 +24,6 @@ import {
 import { useCatchStore } from '/src/store/modules/catchData';
 import { audioPlayType } from '/src/utils/contants';
 import { api_musicSheetTagQueryList } from './api';
-import item from '../prepare-lessons/components/lesson-main/courseware-presets/select-related/item';
 // import isCollaose from '../../images/isCollaose.png';
 
 const ChildNodeSearch = defineComponent({
@@ -35,6 +36,10 @@ const ChildNodeSearch = defineComponent({
     list: {
       type: Array,
       default: () => []
+    },
+    isHide: {
+      type: Boolean,
+      default: false,
     }
   },
   emits: ['selectChildTag'],
@@ -53,7 +58,7 @@ const ChildNodeSearch = defineComponent({
       <>
         {activeRow.value?.id && (
           <>
-            <NFormItem label={activeRow.value.columnName + ':'}>
+            <NFormItem label={activeRow.value.columnName + ':'} class={props.isHide && styles.hideItem}>
               <NSpace class={styles.spaceSection}>
                 {activeRow.value?.children.map((subject: any) => (
                   <span
@@ -95,6 +100,7 @@ const ChildNodeSearch = defineComponent({
             </NFormItem>
 
             <ChildNodeSearch
+              isHide={props.isHide}
               activeRow={selectItem.value}
               onSelectChildTag={(item: any) => {
                 emit('selectChildTag', item || activeRow.value.activeIndex);
@@ -109,6 +115,16 @@ const ChildNodeSearch = defineComponent({
 
 export default defineComponent({
   name: 'search-group',
+  props: {
+    type: {
+      type: String as PropType<'' | 'RECOMMEND' | 'HOT' | 'NEW'>,
+      default: ''
+    },
+    musicalInstrumentId: {
+      type: String,
+      default: ''
+    }
+  },
   emits: ['search', 'add'],
   expose: ['init'],
   setup(props, { emit }) {
@@ -117,11 +133,11 @@ export default defineComponent({
       musicTagIds: '',
       audioPlayTypes: '',
       bookVersionId: null as any,
-      subjectId: null
+      subjectId: null as any
     });
     const state = reactive({
       showMore: false,
-      tempSubjectId: null
+      tempSubjectId: null as any
     });
     const data = reactive({
       audioPlayTypeList: [] as any, // 场景
@@ -133,6 +149,26 @@ export default defineComponent({
       childSelectId: null as any
     });
 
+    watch(
+      () => props.musicalInstrumentId,
+      () => {
+        if (props.musicalInstrumentId) {
+          backInstruments();
+        } else {
+          formatFirstSubject();
+        }
+      }
+    );
+
+    // 是否显示声部
+    const isShowInstrument = computed(() => {
+      if (props.type) {
+        return true;
+      } else {
+        return false;
+      }
+    });
+
     const onSearch = () => {
       emit('search', {
         ...forms,
@@ -147,9 +183,8 @@ export default defineComponent({
     };
 
     const onShowMore = () => {
-      // 
-      state.showMore = !state.showMore
-    }
+      state.showMore = !state.showMore;
+    };
 
     const selectChildObj = (item: any) => {
       const obj: any = {};
@@ -166,15 +201,13 @@ export default defineComponent({
       const tags = catchStore.getMusicTagTree;
       // 去掉上下册
       tags.forEach((item: any) => {
-        if(item.children && item.children.length > 0) {
-          const child = item.children
+        if (item.children && item.children.length > 0) {
+          const child = item.children;
           child?.forEach((c: any) => {
-            c.children = null
-          })
+            c.children = null;
+          });
         }
-      })
-
-      console.log(tags, 'tags')
+      });
       data.tags = [
         {
           columnName: tags[0].columnName,
@@ -228,23 +261,53 @@ export default defineComponent({
       }
     };
 
+    const backInstruments = () => {
+      let childInstruments: any[] = [];
+      catchStore.getSubjectInstrumentOnly.forEach((item: any) => {
+        if(props.musicalInstrumentId === item.value) {
+          childInstruments = item.instruments || [];
+              
+          forms.subjectId = props.musicalInstrumentId;
+          state.tempSubjectId = props.musicalInstrumentId;
+        } else {
+          if (Array.isArray(item.instruments)) {
+            item.instruments.forEach((child: any) => {
+              if (props.musicalInstrumentId === child.value) {
+                childInstruments = item.instruments || [];
+                
+                forms.subjectId = props.musicalInstrumentId;
+                state.tempSubjectId = props.musicalInstrumentId;
+              }
+            });
+          }
+        }
+        
+      });
+      if (childInstruments.length > 0) {
+        selectChildObj(childInstruments);
+      }
+    };
+
     const getTags = async () => {
       try {
-        const res = await api_musicSheetTagQueryList()
-        const result = res.data || []
-        data.newTags = [{
+        const res = await api_musicSheetTagQueryList();
+        const result = res.data || [];
+        data.newTags = [
+          {
             name: '全部',
             id: ''
-        }, ...result.map((item: any) => {
-          return {
-            name: item.name,
-            id: item.id
-          }
-        })]
+          },
+          ...result.map((item: any) => {
+            return {
+              name: item.name,
+              id: item.id
+            };
+          })
+        ];
       } catch {
-        // 
+        //
       }
-    }
+    };
 
     onMounted(async () => {
       // 场景
@@ -256,7 +319,7 @@ export default defineComponent({
       });
       data.audioPlayTypeList = [{ name: '全部', value: '' }, ...tempAudio];
 
-      await getTags()
+      await getTags();
       // 获取教材分类列表
       await catchStore.getMusicTagTreeApi();
       _initTags();
@@ -264,14 +327,24 @@ export default defineComponent({
       // 获取声部列表
       await catchStore.getSubjects();
 
-      formatFirstSubject();
+      if (props.musicalInstrumentId) {
+        backInstruments();
+      } else {
+        formatFirstSubject();
+      }
       onSearch();
     });
     return () => (
-      <div class={styles.searchGroup}>
+      <div
+        class={[
+          styles.searchGroup,
+          isShowInstrument.value && styles.searchGroupOnly
+        ]}>
         <NForm labelAlign="left" labelPlacement="left">
-        {data.newTags.length > 0 && (
-            <NFormItem label={'标签:'}>
+          {data.newTags.length > 0 && (
+            <NFormItem
+              label={'标签:'}
+              class={isShowInstrument.value && styles.hideItem}>
               <NSpace class={styles.spaceSection}>
                 {data.newTags.map((subject: any) => (
                   <span
@@ -291,7 +364,9 @@ export default defineComponent({
           )}
 
           {data.tags.length > 0 && (
-            <NFormItem label={data.tags[0]?.columnName + ':'}>
+            <NFormItem
+              label={data.tags[0]?.columnName + ':'}
+              class={isShowInstrument.value && styles.hideItem}>
               <NSpace class={styles.spaceSection}>
                 {data.tags.map((subject: any) => (
                   <span
@@ -310,6 +385,7 @@ export default defineComponent({
           )}
 
           <ChildNodeSearch
+            isHide={isShowInstrument.value}
             activeRow={data.selectParents}
             onSelectChildTag={(val: any) => {
               data.childSelectId = val;
@@ -317,7 +393,12 @@ export default defineComponent({
             }}
           />
 
-          <NFormItem label="场景:" class={!state.showMore && styles.hideItem}>
+          <NFormItem
+            label="场景:"
+            class={[
+              !state.showMore && styles.hideItem,
+              isShowInstrument.value && styles.hideItem
+            ]}>
             <NSpace class={styles.spaceSection}>
               {data.audioPlayTypeList.map((subject: any) => (
                 <span
@@ -337,8 +418,12 @@ export default defineComponent({
             </NSpace>
           </NFormItem>
 
-          {forms.audioPlayTypes !== 'SING' && (
-            <NFormItem label="乐器:" class={!state.showMore && styles.hideItem}>
+          {(forms.audioPlayTypes !== 'SING' || isShowInstrument.value) && (
+            <NFormItem
+              label="乐器:"
+              class={
+                !state.showMore && !isShowInstrument.value && styles.hideItem
+              }>
               <NSpace class={styles.spaceSection}>
                 {catchStore.getSubjectInstrumentOnly.map((subject: any) =>
                   subject.instruments && subject.instruments.length > 1 ? (
@@ -368,7 +453,6 @@ export default defineComponent({
                     <span
                       class={[
                         styles.textBtn,
-
                         forms.subjectId === subject.value &&
                           styles.textBtnActive
                       ]}
@@ -386,8 +470,16 @@ export default defineComponent({
             </NFormItem>
           )}
         </NForm>
-
-        <div class={[styles.moreSearch, state.showMore ? styles.activeSearch:'']} onClick={onShowMore}>{state.showMore ? '收起选项' : '展开更多'}</div>
+        {!isShowInstrument.value && (
+          <div
+            class={[
+              styles.moreSearch,
+              state.showMore ? styles.activeSearch : ''
+            ]}
+            onClick={onShowMore}>
+            {state.showMore ? '收起选项' : '展开更多'}
+          </div>
+        )}
       </div>
     );
   }