Browse Source

Merge branch 'iteration-20250321-bug' into online

lex-xin 1 day ago
parent
commit
ac884caa96
1 changed files with 587 additions and 587 deletions
  1. 587 587
      src/views/xiaoku-list/index.tsx

+ 587 - 587
src/views/xiaoku-list/index.tsx

@@ -1,587 +1,587 @@
-import {
-  defineComponent,
-  nextTick,
-  onMounted,
-  onUnmounted,
-  reactive,
-  ref
-} from 'vue';
-import styles from './index.module.less';
-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 {
-  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';
-import { api_musicSheetPage } from '../xiaoku-ai/api';
-import TheEmpty from '/src/components/TheEmpty';
-import titleBg from './images/title-bg.png';
-import { vaildMusicScoreUrl } from '/src/utils/urlUtils';
-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) {
-    return num;
-  } else {
-    const n = num / 10000;
-    return Number(n.toFixed(1)) + '万';
-  }
-};
-
-export default defineComponent({
-  name: 'xiaoku-list',
-  setup() {
-    const catchStore = useCatchStore();
-    const router = useRouter();
-    const userStore = useUserStore();
-    const state = reactive({
-      HOT: [] as any,
-      NEW: [] as any,
-      RECOMMEND: [] as any,
-      isSearch: false, // 是否点击搜索
-      keyword: null as any,
-      detailLoading: false,
-      list: [] as any,
-      loading: false as any,
-      finshed: false,
-      instrumentId: null as any,
-      page: 1,
-      rows: 36,
-      previewModal: false,
-      previewParams: {
-        type: '',
-        src: ''
-      } 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: 20,
-          musicalInstrumentId: state.instrumentId
-        });
-        state.RECOMMEND = data.RECOMMEND || [];
-        state.HOT = data.HOT || [];
-        state.NEW = data.NEW || [];
-      } catch {
-        //
-      }
-      state.detailLoading = false;
-    };
-
-    const selectChildObj = (item: any) => {
-      const obj: any = {};
-      item?.forEach((child: any) => {
-        if (child.id === data.tagIndex) {
-          obj.selected = true;
-          obj.name = child.name;
-        }
-      });
-
-      return obj;
-    };
-
-    /** 获取更多 */
-    const getList = async () => {
-      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
-        });
-        const result = data.rows || [];
-        result.forEach((item: any) => {
-          if (item.musicSheetName) {
-            const regex = new RegExp(state.keyword, 'gi');
-            const highlightedText = item.musicSheetName.replace(
-              regex,
-              `<span>$&</span>`
-            );
-            item.musicNameReg = highlightedText;
-          }
-        });
-        state.list = [...state.list, ...data.rows];
-        state.finshed = state.page >= data.pages;
-      } catch (e) {
-        //
-        console.log(e, 'e');
-      }
-      state.loading = false;
-    };
-
-    const spinRef = ref();
-    const handleResh = () => {
-      if (state.loading || state.finshed) return;
-      state.page = state.page + 1;
-      getList();
-    };
-
-    const __initSpin = () => {
-      // const obv = new IntersectionObserver(entries => {
-      //   if (entries[0].intersectionRatio > 0) {
-      //     handleResh();
-      //   }
-      // });
-      // obv.observe(spinRef.value);
-    };
-
-    // 查看更多
-    const onMore = (type?: '' | 'RECOMMEND' | 'NEW' | 'HOT') => {
-      router.push({
-        path: '/xiaoku-detail',
-        query: {
-          type: type
-        }
-      });
-    };
-
-    // 查看详情
-    const onDetail = (item: any) => {
-      // 默认进页面显示对应的曲谱
-      const lineType = item.scoreType === 'FIRST'
-        ? 'firstTone'
-        : item.scoreType === 'JIAN'
-        ? 'fixedTone'
-        : item.scoreType === 'STAVE'
-        ? 'staff'
-        : 'firstTone';
-      let src = `${vaildMusicScoreUrl()}/instrument?v=${+new Date()}&platform=pc&id=${
-        item.id
-      }&Authorization=${
-        userStore.getToken
-      }&musicRenderType=${lineType}&showGuide=true&part-index=${0}`;
-
-      if (state.instrumentId) {
-        src += '&instrumentId=' + state.instrumentId;
-      }
-
-      if (window.matchMedia('(display-mode: standalone)').matches) {
-        baseState.application = window.matchMedia(
-          '(display-mode: standalone)'
-        ).matches;
-        state.previewModal = true;
-        fscreen();
-        state.previewParams = {
-          type: 'music',
-          src
-        };
-      } else {
-        window.open(src, +new Date() + '');
-      }
-    };
-
-    const iframeHandle = (ev: MessageEvent) => {
-      console.log(ev.data)
-      if (ev.data?.api === 'back') {
-        exitFullscreen();
-        state.previewModal = !state.previewModal;
-      }
-    };
-
-    const onSearch = () => {
-      state.isSearch = true;
-      state.loading = true;
-      state.finshed = false;
-      state.list = [];
-      getList();
-      nextTick(() => {
-        __initSpin();
-      });
-    };
-
-    /** 默认选中第一个声部 */
-    const formatFirstSubject = () => {
-      const tempSubjects = catchStore.getSubjectInstrumentOnly;
-      if (tempSubjects.length > 0) {
-        const firstSubject = tempSubjects[0];
-        if (firstSubject.instruments && firstSubject.instruments.length > 1) {
-          data.tagIndex = firstSubject.instruments[0]?.value;
-          state.instrumentId = firstSubject.instruments[0]?.value;
-        } else {
-          data.tagIndex = firstSubject.instruments[0]?.value;
-          state.instrumentId = firstSubject.value;
-        }
-      }
-    };
-
-    onMounted(async () => {
-      // 获取教材分类列表
-      await catchStore.getSubjects();
-      formatFirstSubject();
-
-      getDetail();
-
-      window.addEventListener('message', iframeHandle);
-    });
-
-    onUnmounted(() => {
-      window.removeEventListener('message', iframeHandle);
-    });
-    return () => (
-      <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.getSubjectInstrumentOnly.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;
-                      state.isSearch = state.keyword ? true : false
-                      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,
-                      state.instrumentId === (item.value || 0) &&
-                        styles.textBtnActive
-                    ]}
-                    onClick={() => {
-                      data.tagIndex = item.value || 0;
-                      state.instrumentId = item.value;
-                      state.isSearch = state.keyword ? true : false
-                      if (state.isSearch) {
-                        onSearch();
-                      } else {
-                        getDetail();
-                      }
-                    }}>
-                    {item.name}
-                  </NButton>
-                )
-              )}
-            </NSpace>
-          </NFormItem>
-          <TheSearch
-            round
-            class={styles.searchInput}
-            placeholder="请输入曲目名称"
-            value={state.keyword}
-            onUpdate:value={(val: string) => {
-              state.keyword = val
-            }}
-            onSearch={val => {
-              if (val && val.trim()) {
-                state.keyword = val.trim();
-                onSearch();
-              } else {
-                state.isSearch = false;
-                getDetail();
-              }
-            }}
-          />
-        </div>
-
-        {state.isSearch ? (
-          <div class={styles.searchContainer}>
-            <NScrollbar
-              class={
-                !state.loading && state.list.length === 0
-                  ? styles.emptyScrollBar
-                  : ''
-              }
-              onScroll={async (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;
-                  await getList();
-                }
-              }}>
-              <NSpin show={state.loading}>
-                <div class={styles.sectionContainer}>
-                  <div>
-                    {state.list.map((item: any) => (
-                      <div
-                        class={styles.sectionItem}
-                        onClick={() => onDetail(item)}>
-                        <div class={styles.img} style={{ marginLeft: 0 }}>
-                          <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>
-                        </div>
-                      </div>
-                    ))}
-                  </div>
-                </div>
-              </NSpin>
-              {/* <div
-                // ref={spinRef}
-                class={[
-                  styles.loadingWrap,
-                  state.finshed && !state.loading && styles.showLoading
-                ]}>
-                <NSpin show={true}></NSpin>
-              </div> */}
-            </NScrollbar>
-
-            {!state.loading && state.list.length === 0 && (
-              <div class={styles.empty}>
-                <TheEmpty description="暂无曲目"></TheEmpty>
-              </div>
-            )}
-          </div>
-        ) : (
-          <div class={styles.container}>
-            <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>
-                </div>
-
-                <NScrollbar>
-                  {state.RECOMMEND.map((item: any, index: number) => (
-                    <div
-                      class={styles.item}
-                      onClick={() => {
-                        onDetail(item);
-                      }}>
-                      <div
-                        class={[
-                          styles.num,
-                          index === 0 ? styles.num1 : '',
-                          index === 1 ? styles.num2 : '',
-                          index === 2 ? styles.num3 : ''
-                        ]}>
-                        {(index + 1).toString().padStart(2, '0')}
-                      </div>
-                      <div class={styles.img}>
-                        <img referrerpolicy="no-referrer" src={item.titleImg} />
-                      </div>
-                      <div class={styles.infos}>
-                        <div class={styles.topName}>
-                          <TheNoticeBar text={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>
-                          )}
-
-                          <div class={styles.author}>{item.composer}</div>
-                        </div>
-                      </div>
-                    </div>
-                  ))}
-
-                  {!state.detailLoading && state.RECOMMEND.length === 0 && (
-                    <div class={styles.empty}>
-                      <TheEmpty description="暂无曲目"></TheEmpty>
-                    </div>
-                  )}
-                </NScrollbar>
-              </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>
-                <NScrollbar>
-                  {state.HOT.map((item: any, index: number) => (
-                    <div
-                      class={styles.item}
-                      onClick={() => {
-                        onDetail(item);
-                      }}>
-                      <div
-                        class={[
-                          styles.num,
-                          index === 0 ? styles.num1 : '',
-                          index === 1 ? styles.num2 : '',
-                          index === 2 ? styles.num3 : ''
-                        ]}>
-                        {(index + 1).toString().padStart(2, '0')}
-                      </div>
-                      <div class={styles.img}>
-                        <img referrerpolicy="no-referrer" src={item.titleImg} />
-                      </div>
-                      <div class={styles.infos}>
-                        <div class={styles.topName}>
-                          <TheNoticeBar text={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>
-                          )}
-
-                          <div class={styles.author}>{item.composer}</div>
-                        </div>
-                      </div>
-                    </div>
-                  ))}
-                  {!state.detailLoading && state.HOT.length === 0 && (
-                    <div class={styles.empty}>
-                      <TheEmpty description="暂无曲目"></TheEmpty>
-                    </div>
-                  )}
-                </NScrollbar>
-              </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>
-                </div>
-                <NScrollbar>
-                  {state.NEW.map((item: any, index: number) => (
-                    <div
-                      class={styles.item}
-                      onClick={() => {
-                        onDetail(item);
-                      }}>
-                      <div
-                        class={[
-                          styles.num,
-                          index === 0 ? styles.num1 : '',
-                          index === 1 ? styles.num2 : '',
-                          index === 2 ? styles.num3 : ''
-                        ]}>
-                        {(index + 1).toString().padStart(2, '0')}
-                      </div>
-                      <div class={styles.img}>
-                        <img referrerpolicy="no-referrer" src={item.titleImg} />
-                      </div>
-                      <div class={styles.infos}>
-                        <div class={styles.topName}>
-                          <TheNoticeBar text={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>
-                          )}
-
-                          <div class={styles.author}>{item.composer}</div>
-                        </div>
-                      </div>
-                    </div>
-                  ))}
-                  {!state.detailLoading && state.NEW.length === 0 && (
-                    <div class={styles.empty}>
-                      <TheEmpty description="暂无曲目"></TheEmpty>
-                    </div>
-                  )}
-                </NScrollbar>
-              </div>
-            </NSpin>
-          </div>
-        )}
-
-        {/* 应用内预览*/}
-        <PreviewWindow
-          v-model:show={state.previewModal}
-          type="music"
-          params={state.previewParams}
-        />
-      </div>
-    );
-  }
-});
+import {
+  defineComponent,
+  nextTick,
+  onMounted,
+  onUnmounted,
+  reactive,
+  ref
+} from 'vue';
+import styles from './index.module.less';
+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 {
+  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';
+import { api_musicSheetPage } from '../xiaoku-ai/api';
+import TheEmpty from '/src/components/TheEmpty';
+import titleBg from './images/title-bg.png';
+import { vaildMusicScoreUrl } from '/src/utils/urlUtils';
+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) {
+    return num;
+  } else {
+    const n = num / 10000;
+    return Number(n.toFixed(1)) + '万';
+  }
+};
+
+export default defineComponent({
+  name: 'xiaoku-list',
+  setup() {
+    const catchStore = useCatchStore();
+    const router = useRouter();
+    const userStore = useUserStore();
+    const state = reactive({
+      HOT: [] as any,
+      NEW: [] as any,
+      RECOMMEND: [] as any,
+      isSearch: false, // 是否点击搜索
+      keyword: null as any,
+      detailLoading: false,
+      list: [] as any,
+      loading: false as any,
+      finshed: false,
+      instrumentId: null as any,
+      page: 1,
+      rows: 36,
+      previewModal: false,
+      previewParams: {
+        type: '',
+        src: ''
+      } 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: 20,
+          musicalInstrumentId: state.instrumentId
+        });
+        state.RECOMMEND = data.RECOMMEND || [];
+        state.HOT = data.HOT || [];
+        state.NEW = data.NEW || [];
+      } catch {
+        //
+      }
+      state.detailLoading = false;
+    };
+
+    const selectChildObj = (item: any) => {
+      const obj: any = {};
+      item?.forEach((child: any) => {
+        if (child.id === data.tagIndex) {
+          obj.selected = true;
+          obj.name = child.name;
+        }
+      });
+
+      return obj;
+    };
+
+    /** 获取更多 */
+    const getList = async () => {
+      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
+        });
+        const result = data.rows || [];
+        result.forEach((item: any) => {
+          if (item.musicSheetName) {
+            const regex = new RegExp(state.keyword, 'gi');
+            const highlightedText = item.musicSheetName.replace(
+              regex,
+              `<span>$&</span>`
+            );
+            item.musicNameReg = highlightedText;
+          }
+        });
+        state.list = [...state.list, ...data.rows];
+        state.finshed = state.page >= data.pages;
+      } catch (e) {
+        //
+        console.log(e, 'e');
+      }
+      state.loading = false;
+    };
+
+    const spinRef = ref();
+    const handleResh = () => {
+      if (state.loading || state.finshed) return;
+      state.page = state.page + 1;
+      getList();
+    };
+
+    const __initSpin = () => {
+      // const obv = new IntersectionObserver(entries => {
+      //   if (entries[0].intersectionRatio > 0) {
+      //     handleResh();
+      //   }
+      // });
+      // obv.observe(spinRef.value);
+    };
+
+    // 查看更多
+    const onMore = (type?: '' | 'RECOMMEND' | 'NEW' | 'HOT') => {
+      router.push({
+        path: '/xiaoku-detail',
+        query: {
+          type: type
+        }
+      });
+    };
+
+    // 查看详情
+    const onDetail = (item: any) => {
+      // 默认进页面显示对应的曲谱
+      const lineType = item.scoreType === 'FIRST'
+        ? 'firstTone'
+        : item.scoreType === 'JIAN'
+        ? 'fixedTone'
+        : item.scoreType === 'STAVE'
+        ? 'staff'
+        : 'firstTone';
+      let src = `${vaildMusicScoreUrl()}/instrument?v=${+new Date()}&platform=pc&id=${
+        item.id
+      }&Authorization=${
+        userStore.getToken
+      }&musicRenderType=${lineType}&showGuide=true`;
+
+      if (state.instrumentId) {
+        src += '&instrumentId=' + state.instrumentId;
+      }
+
+      if (window.matchMedia('(display-mode: standalone)').matches) {
+        baseState.application = window.matchMedia(
+          '(display-mode: standalone)'
+        ).matches;
+        state.previewModal = true;
+        fscreen();
+        state.previewParams = {
+          type: 'music',
+          src
+        };
+      } else {
+        window.open(src, +new Date() + '');
+      }
+    };
+
+    const iframeHandle = (ev: MessageEvent) => {
+      console.log(ev.data)
+      if (ev.data?.api === 'back') {
+        exitFullscreen();
+        state.previewModal = !state.previewModal;
+      }
+    };
+
+    const onSearch = () => {
+      state.isSearch = true;
+      state.loading = true;
+      state.finshed = false;
+      state.list = [];
+      getList();
+      nextTick(() => {
+        __initSpin();
+      });
+    };
+
+    /** 默认选中第一个声部 */
+    const formatFirstSubject = () => {
+      const tempSubjects = catchStore.getSubjectInstrumentOnly;
+      if (tempSubjects.length > 0) {
+        const firstSubject = tempSubjects[0];
+        if (firstSubject.instruments && firstSubject.instruments.length > 1) {
+          data.tagIndex = firstSubject.instruments[0]?.value;
+          state.instrumentId = firstSubject.instruments[0]?.value;
+        } else {
+          data.tagIndex = firstSubject.instruments[0]?.value;
+          state.instrumentId = firstSubject.value;
+        }
+      }
+    };
+
+    onMounted(async () => {
+      // 获取教材分类列表
+      await catchStore.getSubjects();
+      formatFirstSubject();
+
+      getDetail();
+
+      window.addEventListener('message', iframeHandle);
+    });
+
+    onUnmounted(() => {
+      window.removeEventListener('message', iframeHandle);
+    });
+    return () => (
+      <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.getSubjectInstrumentOnly.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;
+                      state.isSearch = state.keyword ? true : false
+                      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,
+                      state.instrumentId === (item.value || 0) &&
+                        styles.textBtnActive
+                    ]}
+                    onClick={() => {
+                      data.tagIndex = item.value || 0;
+                      state.instrumentId = item.value;
+                      state.isSearch = state.keyword ? true : false
+                      if (state.isSearch) {
+                        onSearch();
+                      } else {
+                        getDetail();
+                      }
+                    }}>
+                    {item.name}
+                  </NButton>
+                )
+              )}
+            </NSpace>
+          </NFormItem>
+          <TheSearch
+            round
+            class={styles.searchInput}
+            placeholder="请输入曲目名称"
+            value={state.keyword}
+            onUpdate:value={(val: string) => {
+              state.keyword = val
+            }}
+            onSearch={val => {
+              if (val && val.trim()) {
+                state.keyword = val.trim();
+                onSearch();
+              } else {
+                state.isSearch = false;
+                getDetail();
+              }
+            }}
+          />
+        </div>
+
+        {state.isSearch ? (
+          <div class={styles.searchContainer}>
+            <NScrollbar
+              class={
+                !state.loading && state.list.length === 0
+                  ? styles.emptyScrollBar
+                  : ''
+              }
+              onScroll={async (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;
+                  await getList();
+                }
+              }}>
+              <NSpin show={state.loading}>
+                <div class={styles.sectionContainer}>
+                  <div>
+                    {state.list.map((item: any) => (
+                      <div
+                        class={styles.sectionItem}
+                        onClick={() => onDetail(item)}>
+                        <div class={styles.img} style={{ marginLeft: 0 }}>
+                          <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>
+                        </div>
+                      </div>
+                    ))}
+                  </div>
+                </div>
+              </NSpin>
+              {/* <div
+                // ref={spinRef}
+                class={[
+                  styles.loadingWrap,
+                  state.finshed && !state.loading && styles.showLoading
+                ]}>
+                <NSpin show={true}></NSpin>
+              </div> */}
+            </NScrollbar>
+
+            {!state.loading && state.list.length === 0 && (
+              <div class={styles.empty}>
+                <TheEmpty description="暂无曲目"></TheEmpty>
+              </div>
+            )}
+          </div>
+        ) : (
+          <div class={styles.container}>
+            <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>
+                </div>
+
+                <NScrollbar>
+                  {state.RECOMMEND.map((item: any, index: number) => (
+                    <div
+                      class={styles.item}
+                      onClick={() => {
+                        onDetail(item);
+                      }}>
+                      <div
+                        class={[
+                          styles.num,
+                          index === 0 ? styles.num1 : '',
+                          index === 1 ? styles.num2 : '',
+                          index === 2 ? styles.num3 : ''
+                        ]}>
+                        {(index + 1).toString().padStart(2, '0')}
+                      </div>
+                      <div class={styles.img}>
+                        <img referrerpolicy="no-referrer" src={item.titleImg} />
+                      </div>
+                      <div class={styles.infos}>
+                        <div class={styles.topName}>
+                          <TheNoticeBar text={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>
+                          )}
+
+                          <div class={styles.author}>{item.composer}</div>
+                        </div>
+                      </div>
+                    </div>
+                  ))}
+
+                  {!state.detailLoading && state.RECOMMEND.length === 0 && (
+                    <div class={styles.empty}>
+                      <TheEmpty description="暂无曲目"></TheEmpty>
+                    </div>
+                  )}
+                </NScrollbar>
+              </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>
+                <NScrollbar>
+                  {state.HOT.map((item: any, index: number) => (
+                    <div
+                      class={styles.item}
+                      onClick={() => {
+                        onDetail(item);
+                      }}>
+                      <div
+                        class={[
+                          styles.num,
+                          index === 0 ? styles.num1 : '',
+                          index === 1 ? styles.num2 : '',
+                          index === 2 ? styles.num3 : ''
+                        ]}>
+                        {(index + 1).toString().padStart(2, '0')}
+                      </div>
+                      <div class={styles.img}>
+                        <img referrerpolicy="no-referrer" src={item.titleImg} />
+                      </div>
+                      <div class={styles.infos}>
+                        <div class={styles.topName}>
+                          <TheNoticeBar text={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>
+                          )}
+
+                          <div class={styles.author}>{item.composer}</div>
+                        </div>
+                      </div>
+                    </div>
+                  ))}
+                  {!state.detailLoading && state.HOT.length === 0 && (
+                    <div class={styles.empty}>
+                      <TheEmpty description="暂无曲目"></TheEmpty>
+                    </div>
+                  )}
+                </NScrollbar>
+              </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>
+                </div>
+                <NScrollbar>
+                  {state.NEW.map((item: any, index: number) => (
+                    <div
+                      class={styles.item}
+                      onClick={() => {
+                        onDetail(item);
+                      }}>
+                      <div
+                        class={[
+                          styles.num,
+                          index === 0 ? styles.num1 : '',
+                          index === 1 ? styles.num2 : '',
+                          index === 2 ? styles.num3 : ''
+                        ]}>
+                        {(index + 1).toString().padStart(2, '0')}
+                      </div>
+                      <div class={styles.img}>
+                        <img referrerpolicy="no-referrer" src={item.titleImg} />
+                      </div>
+                      <div class={styles.infos}>
+                        <div class={styles.topName}>
+                          <TheNoticeBar text={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>
+                          )}
+
+                          <div class={styles.author}>{item.composer}</div>
+                        </div>
+                      </div>
+                    </div>
+                  ))}
+                  {!state.detailLoading && state.NEW.length === 0 && (
+                    <div class={styles.empty}>
+                      <TheEmpty description="暂无曲目"></TheEmpty>
+                    </div>
+                  )}
+                </NScrollbar>
+              </div>
+            </NSpin>
+          </div>
+        )}
+
+        {/* 应用内预览*/}
+        <PreviewWindow
+          v-model:show={state.previewModal}
+          type="music"
+          params={state.previewParams}
+        />
+      </div>
+    );
+  }
+});