Browse Source

添加声部选择

lex 1 year ago
parent
commit
ee12b460ff
22 changed files with 914 additions and 120 deletions
  1. 1 1
      dev-dist/sw.js
  2. 1 1
      public/version.json
  3. 10 0
      src/api/user.ts
  4. 15 3
      src/store/modules/catchData.ts
  5. 1 1
      src/views/content-information/content-music/components/list/index.module.less
  6. 58 0
      src/views/natural-resources/components/my-collect/index.module.less
  7. 56 17
      src/views/natural-resources/components/my-collect/search-group-resources.tsx
  8. 60 0
      src/views/natural-resources/components/my-resources/index.module.less
  9. 60 22
      src/views/natural-resources/components/my-resources/search-group-resources.tsx
  10. 59 0
      src/views/natural-resources/components/share-resources/index.module.less
  11. 59 6
      src/views/natural-resources/components/share-resources/search-group-resources.tsx
  12. 3 3
      src/views/notation/index.tsx
  13. 62 1
      src/views/prepare-lessons/model/select-resources/select-item/class-search-group/index.module.less
  14. 55 16
      src/views/prepare-lessons/model/select-resources/select-item/class-search-group/index.tsx
  15. 62 0
      src/views/prepare-lessons/model/select-resources/select-item/resource-search-group/index.module.less
  16. 57 4
      src/views/prepare-lessons/model/select-resources/select-item/resource-search-group/index.tsx
  17. 2 2
      src/views/xiaoku-music/component/play-item/index.module.less
  18. 13 0
      src/views/xiaoku-music/images/icon-arrow.svg
  19. 13 0
      src/views/xiaoku-music/images/icon-arrow2.svg
  20. 61 1
      src/views/xiaoku-music/index.module.less
  21. 204 40
      src/views/xiaoku-music/index.tsx
  22. 2 2
      vite.config.ts

+ 1 - 1
dev-dist/sw.js

@@ -82,7 +82,7 @@ define(['./workbox-5357ef54'], (function (workbox) { 'use strict';
     "revision": "3ca0b8505b4bec776b69afdba2768812"
   }, {
     "url": "index.html",
-    "revision": "0.gkfi3u3c598"
+    "revision": "0.g5tojh8s4j8"
   }], {});
   workbox.cleanupOutdatedCaches();
   workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {

+ 1 - 1
public/version.json

@@ -1 +1 @@
-{"version":1706251752246}
+{"version":1706521488441}

+ 10 - 0
src/api/user.ts

@@ -37,6 +37,16 @@ export const getSubjectList = (params: any) => {
 };
 
 /**
+ * 获取声部列表
+ * returns subjects
+ */
+export const getSubjectList2 = (params: any) => {
+  return request.post('/edu-app/subject/list', {
+    data: params
+  });
+};
+
+/**
  * 获取曲谱分类
  * @returns musicSheetCategories
  */

+ 15 - 3
src/store/modules/catchData.ts

@@ -1,6 +1,6 @@
 import { defineStore } from 'pinia';
 import { store } from '@/store';
-import { getSubjectList, getCategories } from '@/api/user';
+import { getSubjectList, getSubjectList2, getCategories } from '@/api/user';
 
 export const useCatchStore = defineStore('catch-store', {
   state: () => ({
@@ -57,14 +57,26 @@ export const useCatchStore = defineStore('catch-store', {
         if (this.getSubjectList && this.getSubjectList.length > 0) {
           return Promise.resolve();
         }
-        const { data } = await getSubjectList({
+        const { data } = await getSubjectList2({
           enableFlag: true,
           delFlag: 0,
           page: 1,
           rows: 999
         });
 
-        this.setSubjects(data.rows || []);
+        const tempSubjectList = data || [];
+        tempSubjectList.forEach((item: any) => {
+          item.value = item.id;
+          item.label = item.name;
+          if (item.instruments && item.instruments.length > 0) {
+            item.instruments.forEach((child: any) => {
+              child.label = child.name;
+              child.value = child.id;
+            });
+          }
+        });
+
+        this.setSubjects(tempSubjectList || []);
         return Promise.resolve();
       } catch (e) {
         return Promise.reject(e);

+ 1 - 1
src/views/content-information/content-music/components/list/index.module.less

@@ -187,7 +187,7 @@
 
 .popSelect {
   font-size: 16px;
-  width: 160px;
+  width: 200px;
   box-shadow: 0px 2 16px 0px rgba(0, 0, 0, 0.08);
   border-radius: 11px;
   --n-option-height: 34px;

+ 58 - 0
src/views/natural-resources/components/my-collect/index.module.less

@@ -177,4 +177,62 @@
   visibility: hidden;
   height: 0 !important;
   line-height: 0 !important;
+}
+
+.popSelect {
+  font-size: 16px;
+  width: 200px;
+  box-shadow: 0px 2 16px 0px rgba(0, 0, 0, 0.08);
+  border-radius: 11px;
+  --n-option-height: 34px;
+
+  :global {
+    .n-base-select-option__content {
+      width: 80% !important;
+    }
+  }
+
+}
+
+.spaceSection2 {
+  &>div {
+    height: 34Px !important;
+    display: flex;
+    align-items: center;
+  }
+}
+
+.textBtn {
+  background: #fff;
+  border-radius: 8Px;
+  padding: 4Px 20px;
+  font-size: max(17px, 12Px);
+  color: rgba(0, 0, 0, 0.6);
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  font-weight: 500;
+  line-height: 24px;
+
+  .iconArrow {
+    display: inline-block;
+    margin-left: 8px;
+    width: 8px;
+    height: 5px;
+    background: url('../../../content-information/images/icon-arrow2.png') no-repeat center center / contain;
+    transform: rotate(180deg);
+  }
+
+  &:hover,
+  &.textBtnActive {
+    background: #D2ECFF;
+    font-weight: 500;
+    color: #131415;
+  }
+
+  &:hover {
+    .iconArrow {
+      transform: rotate(0deg);
+    }
+  }
 }

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

@@ -1,6 +1,13 @@
 import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue';
 import styles from './index.module.less';
-import { NButton, NForm, NFormItem, NImage, NSpace } from 'naive-ui';
+import {
+  NButton,
+  NForm,
+  NFormItem,
+  NImage,
+  NPopselect,
+  NSpace
+} from 'naive-ui';
 import TheSearch from '/src/components/TheSearch';
 import { resourceTypeArray } from '/src/utils/searchArray';
 import { useCatchStore } from '/src/store/modules/catchData';
@@ -68,6 +75,17 @@ export default defineComponent({
       }
     };
 
+    const selectChildObj = (item: any) => {
+      const obj: any = {};
+      item?.forEach((child: any) => {
+        if (child.id === forms.subjectId) {
+          obj.selected = true;
+          obj.name = child.name;
+        }
+      });
+      return obj;
+    };
+
     onMounted(async () => {
       resourceList.value = [
         // {
@@ -178,22 +196,43 @@ export default defineComponent({
               </NFormItem>
             </div>
           )} */}
-          <NFormItem label="乐器:">
-            <NSpace class={styles.spaceSection}>
-              {catchStore.getSubjectAllList.map((subject: any) => (
-                <NButton
-                  secondary={forms.subjectId === subject.id}
-                  quaternary={forms.subjectId !== subject.id}
-                  strong
-                  focusable={false}
-                  type={forms.subjectId === subject.id ? 'primary' : 'default'}
-                  onClick={() => {
-                    forms.subjectId = subject.id;
-                    onSearch();
-                  }}>
-                  {subject.name}
-                </NButton>
-              ))}
+          <NFormItem label="声部:">
+            <NSpace class={styles.spaceSection2}>
+              {catchStore.getSubjectAllList.map((subject: any) =>
+                subject.instruments && subject.instruments.length > 1 ? (
+                  <NPopselect
+                    options={subject.instruments}
+                    trigger="hover"
+                    v-model:value={forms.subjectId}
+                    onUpdate:value={() => {
+                      onSearch();
+                    }}
+                    key={subject.id}
+                    class={[styles.popSelect]}>
+                    <span
+                      class={[
+                        styles.textBtn,
+                        selectChildObj(subject.instruments).selected &&
+                          styles.textBtnActive
+                      ]}>
+                      {selectChildObj(subject.instruments).name || subject.name}
+                      <i class={styles.iconArrow}></i>
+                    </span>
+                  </NPopselect>
+                ) : (
+                  <span
+                    class={[
+                      styles.textBtn,
+                      forms.subjectId === subject.id && styles.textBtnActive
+                    ]}
+                    onClick={() => {
+                      forms.subjectId = subject.id;
+                      onSearch();
+                    }}>
+                    {subject.name}
+                  </span>
+                )
+              )}
             </NSpace>
           </NFormItem>
 

+ 60 - 0
src/views/natural-resources/components/my-resources/index.module.less

@@ -267,4 +267,64 @@
       }
     }
   }
+}
+
+.popSelect {
+  font-size: 16px;
+  width: 200px;
+  box-shadow: 0px 2 16px 0px rgba(0, 0, 0, 0.08);
+  border-radius: 11px;
+  --n-option-height: 34px;
+
+  :global {
+    .n-base-select-option__content {
+      width: 80% !important;
+    }
+  }
+
+}
+
+.spaceSection2 {
+  &>div {
+    height: 34Px !important;
+    display: flex;
+    align-items: center;
+  }
+}
+
+.textBtn {
+  background: #fff;
+  border-radius: 8Px;
+  padding: 4Px 20px;
+  font-size: max(17px, 12Px);
+  color: rgba(0, 0, 0, 0.6);
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  font-weight: 500;
+  line-height: 24px;
+
+  .iconArrow {
+    display: inline-block;
+    margin-left: 8px;
+    width: 8px;
+    height: 5px;
+    background: url('../../../content-information/images/icon-arrow2.png') no-repeat center center / contain;
+    transform: rotate(180deg);
+
+  }
+
+  &:hover,
+  &.textBtnActive {
+    background: #D2ECFF;
+    font-weight: 500;
+    color: #131415;
+  }
+
+  &:hover {
+    .iconArrow {
+
+      transform: rotate(0deg);
+    }
+  }
 }

+ 60 - 22
src/views/natural-resources/components/my-resources/search-group-resources.tsx

@@ -1,6 +1,6 @@
 import { defineComponent, onMounted, reactive, ref } from 'vue';
 import styles from './index.module.less';
-import { NButton, NForm, NFormItem, NSpace } from 'naive-ui';
+import { NButton, NForm, NFormItem, NPopselect, NSpace } from 'naive-ui';
 import iconUpload from '../../images/icon-upload.png';
 import iconEdit from '../../images/icon-edit.png';
 import iconSelectAll from '../../images/icon-selectall.png';
@@ -24,6 +24,7 @@ export default defineComponent({
       subjectId: null
     });
     const state = reactive({
+      tempSubjectId: null,
       isEdit: false, // 是否编辑
       isSelectAll: false
     });
@@ -47,8 +48,23 @@ export default defineComponent({
 
       // 获取声部列表
       await catchStore.getSubjects();
+
+      if (forms.subjectId) {
+        state.tempSubjectId = forms.subjectId;
+      }
     });
 
+    const selectChildObj = (item: any) => {
+      const obj: any = {};
+      item?.forEach((child: any) => {
+        if (child.id === forms.subjectId) {
+          obj.selected = true;
+          obj.name = child.name;
+        }
+      });
+      return obj;
+    };
+
     const resetStatus = () => {
       state.isSelectAll = false;
     };
@@ -176,27 +192,49 @@ export default defineComponent({
           </NSpace>
         </div>
         <NForm labelAlign="left" labelPlacement="left">
-          <NFormItem label="乐器:">
-            <NSpace class={styles.spaceSection}>
-              {catchStore.getSubjectAllList.map((subject: any) => (
-                <NButton
-                  secondary={forms.subjectId === subject.id}
-                  quaternary={forms.subjectId !== subject.id}
-                  strong
-                  focusable={false}
-                  type={forms.subjectId === subject.id ? 'primary' : 'default'}
-                  onClick={() => {
-                    if (forms.subjectId !== subject.id) {
-                      state.isEdit = false;
-                      state.isSelectAll = false;
-                      emit('edit', state.isEdit);
-                    }
-                    forms.subjectId = subject.id;
-                    onSearch();
-                  }}>
-                  {subject.name}
-                </NButton>
-              ))}
+          <NFormItem label="声部:">
+            <NSpace class={styles.spaceSection2}>
+              {catchStore.getSubjectAllList.map((subject: any) =>
+                subject.instruments && subject.instruments.length > 1 ? (
+                  <NPopselect
+                    options={subject.instruments}
+                    trigger="hover"
+                    v-model:value={state.tempSubjectId}
+                    onUpdate:value={() => {
+                      if (state.tempSubjectId !== subject.id) {
+                        state.isEdit = false;
+                        state.isSelectAll = false;
+                        emit('edit', state.isEdit);
+                      }
+                      forms.subjectId = state.tempSubjectId;
+                      onSearch();
+                    }}
+                    key={subject.id}
+                    class={[styles.popSelect]}>
+                    <span
+                      class={[
+                        styles.textBtn,
+                        selectChildObj(subject.instruments).selected &&
+                          styles.textBtnActive
+                      ]}>
+                      {selectChildObj(subject.instruments).name || subject.name}
+                      <i class={styles.iconArrow}></i>
+                    </span>
+                  </NPopselect>
+                ) : (
+                  <span
+                    class={[
+                      styles.textBtn,
+                      forms.subjectId === subject.id && styles.textBtnActive
+                    ]}
+                    onClick={() => {
+                      forms.subjectId = subject.id;
+                      onSearch();
+                    }}>
+                    {subject.name}
+                  </span>
+                )
+              )}
             </NSpace>
           </NFormItem>
 

+ 59 - 0
src/views/natural-resources/components/share-resources/index.module.less

@@ -182,4 +182,63 @@
   visibility: hidden;
   height: 0 !important;
   line-height: 0 !important;
+}
+
+.popSelect {
+  font-size: 16px;
+  width: 200px;
+  box-shadow: 0px 2 16px 0px rgba(0, 0, 0, 0.08);
+  border-radius: 11px;
+  --n-option-height: 34px;
+
+  :global {
+    .n-base-select-option__content {
+      width: 80% !important;
+    }
+  }
+}
+
+.spaceSection2 {
+  &>div {
+    height: 34Px !important;
+    display: flex;
+    align-items: center;
+  }
+}
+
+.textBtn {
+  background: #fff;
+  border-radius: 8Px;
+  padding: 4Px 20px;
+  font-size: max(17px, 12Px);
+  color: rgba(0, 0, 0, 0.6);
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  font-weight: 500;
+  line-height: 24px;
+
+  .iconArrow {
+    display: inline-block;
+    margin-left: 8px;
+    width: 8px;
+    height: 5px;
+    background: url('../../../content-information/images/icon-arrow2.png') no-repeat center center / contain;
+    transform: rotate(180deg);
+
+  }
+
+  &:hover,
+  &.textBtnActive {
+    background: #D2ECFF;
+    font-weight: 500;
+    color: #131415;
+  }
+
+  &:hover {
+    .iconArrow {
+
+      transform: rotate(0deg);
+    }
+  }
 }

+ 59 - 6
src/views/natural-resources/components/share-resources/search-group-resources.tsx

@@ -1,6 +1,13 @@
 import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue';
 import styles from './index.module.less';
-import { NButton, NForm, NFormItem, NImage, NSpace } from 'naive-ui';
+import {
+  NButton,
+  NForm,
+  NFormItem,
+  NImage,
+  NPopselect,
+  NSpace
+} from 'naive-ui';
 import iconAdd from '../../images/icon-add.png';
 import TheSearch from '/src/components/TheSearch';
 import { resourceTypeArray } from '/src/utils/searchArray';
@@ -66,8 +73,19 @@ export default defineComponent({
         //
       }
     };
+
+    const selectChildObj = (item: any) => {
+      const obj: any = {};
+      item?.forEach((child: any) => {
+        if (child.id === forms.subjectId) {
+          obj.selected = true;
+          obj.name = child.name;
+        }
+      });
+      return obj;
+    };
     onMounted(async () => {
-      console.log('加载');
+      // console.log('加载');
       // 获取教材分类列表
       await catchStore.getMusicSheetCategory();
       // 获取声部列表
@@ -133,7 +151,7 @@ export default defineComponent({
                     isCollapse.value ? '' : styles.isHidden
                   ]}
                   ref={collapseWrapRef}>
-                  <NSpace class={[styles.spaceSection]}>
+                  <NSpace class={[styles.spaceSection2]}>
                     {catchStore.getAllMusicCategories.map((music: any) => (
                       <NButton
                         ref={musicCateRef}
@@ -179,9 +197,9 @@ export default defineComponent({
             </div>
           )}
 
-          <NFormItem label="乐器:">
+          <NFormItem label="声部:">
             <NSpace class={styles.spaceSection}>
-              {catchStore.getSubjectAllList.map((subject: any) => (
+              {/* {catchStore.getSubjectAllList.map((subject: any) => (
                 <NButton
                   secondary={forms.subjectId === subject.id}
                   quaternary={forms.subjectId !== subject.id}
@@ -194,7 +212,42 @@ export default defineComponent({
                   }}>
                   {subject.name}
                 </NButton>
-              ))}
+              ))} */}
+              {catchStore.getSubjectAllList.map((subject: any) =>
+                subject.instruments && subject.instruments.length > 1 ? (
+                  <NPopselect
+                    options={subject.instruments}
+                    trigger="hover"
+                    v-model:value={forms.subjectId}
+                    onUpdate:value={() => {
+                      onSearch();
+                    }}
+                    key={subject.id}
+                    class={[styles.popSelect]}>
+                    <span
+                      class={[
+                        styles.textBtn,
+                        selectChildObj(subject.instruments).selected &&
+                          styles.textBtnActive
+                      ]}>
+                      {selectChildObj(subject.instruments).name || subject.name}
+                      <i class={styles.iconArrow}></i>
+                    </span>
+                  </NPopselect>
+                ) : (
+                  <span
+                    class={[
+                      styles.textBtn,
+                      forms.subjectId === subject.id && styles.textBtnActive
+                    ]}
+                    onClick={() => {
+                      forms.subjectId = subject.id;
+                      onSearch();
+                    }}>
+                    {subject.name}
+                  </span>
+                )
+              )}
             </NSpace>
           </NFormItem>
 

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

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

+ 62 - 1
src/views/prepare-lessons/model/select-resources/select-item/class-search-group/index.module.less

@@ -36,7 +36,8 @@
 
       .n-button {
         height: 32px;
-        font-size: max(17px, 13px);
+        padding: 4Px 20px;
+        font-size: max(17px, 12Px);
         border-radius: 8px;
         color: rgba(0, 0, 0, 0.6);
       }
@@ -146,4 +147,64 @@
   visibility: hidden;
   height: 0 !important;
   line-height: 0 !important;
+}
+
+.popSelect {
+  font-size: 16px;
+  width: 200px;
+  box-shadow: 0px 2 16px 0px rgba(0, 0, 0, 0.08);
+  border-radius: 11px;
+  --n-option-height: 34px;
+
+  :global {
+    .n-base-select-option__content {
+      width: 80% !important;
+    }
+  }
+
+}
+
+.spaceSection2 {
+  &>div {
+    height: 34Px !important;
+    display: flex;
+    align-items: center;
+  }
+}
+
+.textBtn {
+  background: #fff;
+  border-radius: 8Px;
+  padding: 4Px 20px;
+  font-size: max(17px, 12Px);
+  color: rgba(0, 0, 0, 0.6);
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  font-weight: 500;
+  line-height: 24px;
+
+  .iconArrow {
+    display: inline-block;
+    margin-left: 8px;
+    width: 8px;
+    height: 5px;
+    background: url('@/views/content-information/images/icon-arrow2.png') no-repeat center center / contain;
+    transform: rotate(180deg);
+
+  }
+
+  &:hover,
+  &.textBtnActive {
+    background: #D2ECFF;
+    font-weight: 500;
+    color: #131415;
+  }
+
+  &:hover {
+    .iconArrow {
+
+      transform: rotate(0deg);
+    }
+  }
 }

+ 55 - 16
src/views/prepare-lessons/model/select-resources/select-item/class-search-group/index.tsx

@@ -8,7 +8,14 @@ import {
   toRef
 } from 'vue';
 import styles from './index.module.less';
-import { NButton, NForm, NFormItem, NImage, NSpace } from 'naive-ui';
+import {
+  NButton,
+  NForm,
+  NFormItem,
+  NImage,
+  NPopselect,
+  NSpace
+} from 'naive-ui';
 import { resourceTypeArray } from '/src/utils/searchArray';
 import { useCatchStore } from '/src/store/modules/catchData';
 import { useThrottleFn } from '@vueuse/core';
@@ -91,6 +98,17 @@ export default defineComponent({
     //     //
     //   }
     // };
+
+    const selectChildObj = (item: any) => {
+      const obj: any = {};
+      item?.forEach((child: any) => {
+        if (child.id === forms.subjectId) {
+          obj.selected = true;
+          obj.name = child.name;
+        }
+      });
+      return obj;
+    };
     onMounted(async () => {
       // if (props.type === 'myCollect') {
       //   resourceType.value.push({
@@ -216,21 +234,42 @@ export default defineComponent({
           )} */}
 
           <NFormItem label="声部:">
-            <NSpace class={styles.spaceSection}>
-              {catchStore.getSubjectAllList.map((music: any) => (
-                <NButton
-                  secondary={forms.subjectId === music.id}
-                  quaternary={forms.subjectId !== music.id}
-                  strong
-                  focusable={false}
-                  type={forms.subjectId === music.id ? 'primary' : 'default'}
-                  onClick={() => {
-                    forms.subjectId = music.id;
-                    onSearch();
-                  }}>
-                  {music.name}
-                </NButton>
-              ))}
+            <NSpace class={[styles.spaceSection, styles.spaceSection2]}>
+              {catchStore.getSubjectAllList.map((subject: any) =>
+                subject.instruments && subject.instruments.length > 1 ? (
+                  <NPopselect
+                    options={subject.instruments}
+                    trigger="hover"
+                    v-model:value={forms.subjectId}
+                    onUpdate:value={() => {
+                      onSearch();
+                    }}
+                    key={subject.id}
+                    class={[styles.popSelect]}>
+                    <span
+                      class={[
+                        styles.textBtn,
+                        selectChildObj(subject.instruments).selected &&
+                          styles.textBtnActive
+                      ]}>
+                      {selectChildObj(subject.instruments).name || subject.name}
+                      <i class={styles.iconArrow}></i>
+                    </span>
+                  </NPopselect>
+                ) : (
+                  <span
+                    class={[
+                      styles.textBtn,
+                      forms.subjectId === subject.id && styles.textBtnActive
+                    ]}
+                    onClick={() => {
+                      forms.subjectId = subject.id;
+                      onSearch();
+                    }}>
+                    {subject.name}
+                  </span>
+                )
+              )}
             </NSpace>
           </NFormItem>
 

+ 62 - 0
src/views/prepare-lessons/model/select-resources/select-item/resource-search-group/index.module.less

@@ -38,6 +38,8 @@
         height: 32px;
         font-size: 17px;
         border-radius: 8px;
+        padding: 4Px 20px;
+        font-size: max(17px, 12Px);
         color: rgba(0, 0, 0, 0.6);
       }
 
@@ -143,4 +145,64 @@
   visibility: hidden;
   height: 0 !important;
   line-height: 0 !important;
+}
+
+.popSelect {
+  font-size: 16px;
+  width: 200px;
+  box-shadow: 0px 2 16px 0px rgba(0, 0, 0, 0.08);
+  border-radius: 11px;
+  --n-option-height: 34px;
+
+  :global {
+    .n-base-select-option__content {
+      width: 80% !important;
+    }
+  }
+
+}
+
+.spaceSection2 {
+  &>div {
+    height: 34Px !important;
+    display: flex;
+    align-items: center;
+  }
+}
+
+.textBtn {
+  background: #fff;
+  border-radius: 8Px;
+  padding: 4Px 20px;
+  font-size: max(17px, 12Px);
+  color: rgba(0, 0, 0, 0.6);
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  font-weight: 500;
+  line-height: 24px;
+
+  .iconArrow {
+    display: inline-block;
+    margin-left: 8px;
+    width: 8px;
+    height: 5px;
+    background: url('@/views/content-information/images/icon-arrow2.png') no-repeat center center / contain;
+    transform: rotate(180deg);
+
+  }
+
+  &:hover,
+  &.textBtnActive {
+    background: #D2ECFF;
+    font-weight: 500;
+    color: #131415;
+  }
+
+  &:hover {
+    .iconArrow {
+
+      transform: rotate(0deg);
+    }
+  }
 }

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

@@ -8,7 +8,14 @@ import {
   toRef
 } from 'vue';
 import styles from './index.module.less';
-import { NButton, NForm, NFormItem, NImage, NSpace } from 'naive-ui';
+import {
+  NButton,
+  NForm,
+  NFormItem,
+  NImage,
+  NPopselect,
+  NSpace
+} from 'naive-ui';
 import { resourceTypeArray } from '/src/utils/searchArray';
 import { useCatchStore } from '/src/store/modules/catchData';
 import { useThrottleFn } from '@vueuse/core';
@@ -91,6 +98,17 @@ export default defineComponent({
         //
       }
     };
+
+    const selectChildObj = (item: any) => {
+      const obj: any = {};
+      item?.forEach((child: any) => {
+        if (child.id === forms.subjectId) {
+          obj.selected = true;
+          obj.name = child.name;
+        }
+      });
+      return obj;
+    };
     onMounted(async () => {
       // if (props.type === 'myCollect') {
       //   resourceType.value.push({
@@ -224,8 +242,8 @@ export default defineComponent({
           )}
 
           <NFormItem label="声部:">
-            <NSpace class={styles.spaceSection}>
-              {catchStore.getSubjectAllList.map((music: any) => (
+            <NSpace class={styles.spaceSection2}>
+              {/* {catchStore.getSubjectAllList.map((music: any) => (
                 <NButton
                   secondary={forms.subjectId === music.id}
                   quaternary={forms.subjectId !== music.id}
@@ -238,7 +256,42 @@ export default defineComponent({
                   }}>
                   {music.name}
                 </NButton>
-              ))}
+              ))} */}
+              {catchStore.getSubjectAllList.map((subject: any) =>
+                subject.instruments && subject.instruments.length > 1 ? (
+                  <NPopselect
+                    options={subject.instruments}
+                    trigger="hover"
+                    v-model:value={forms.subjectId}
+                    onUpdate:value={() => {
+                      onSearch();
+                    }}
+                    key={subject.id}
+                    class={[styles.popSelect]}>
+                    <span
+                      class={[
+                        styles.textBtn,
+                        selectChildObj(subject.instruments).selected &&
+                          styles.textBtnActive
+                      ]}>
+                      {selectChildObj(subject.instruments).name || subject.name}
+                      <i class={styles.iconArrow}></i>
+                    </span>
+                  </NPopselect>
+                ) : (
+                  <span
+                    class={[
+                      styles.textBtn,
+                      forms.subjectId === subject.id && styles.textBtnActive
+                    ]}
+                    onClick={() => {
+                      forms.subjectId = subject.id;
+                      onSearch();
+                    }}>
+                    {subject.name}
+                  </span>
+                )
+              )}
             </NSpace>
           </NFormItem>
         </NForm>

+ 2 - 2
src/views/xiaoku-music/component/play-item/index.module.less

@@ -87,7 +87,7 @@
     width: 200px;
 
     .titleName {
-      font-size: 16px;
+      font-size: max(16px, 13Px);
       font-weight: 600;
       color: #131415;
       line-height: 28px;
@@ -95,7 +95,7 @@
     }
 
     .titleDes {
-      font-size: 14px;
+      font-size: max(14px, 12Px);
       font-weight: 400;
       color: #777777;
       line-height: 20px;

+ 13 - 0
src/views/xiaoku-music/images/icon-arrow.svg

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="9px" height="5px" viewBox="0 0 9 5" fill="currentColor" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>三角形</title>
+    <g id="所有页面" stroke="none" stroke-width="1" fill="currentColor" fill-rule="evenodd">
+        <g id="68、小酷AI-曲目列表" transform="translate(-338.000000, -195.000000)" fill="currentColor">
+            <g id="编组-20" transform="translate(164.000000, 178.000000)">
+                <g id="资源/第一层级筛选/选中备份" transform="translate(108.000000, 0.000000)">
+                    <path d="M70.8716471,17.4129412 L74.2489659,21.1655176 C74.4336954,21.3707726 74.4170562,21.6869176 74.2118012,21.8716471 C74.1199888,21.9542782 74.0008397,22 73.8773188,22 L67.1226812,22 C66.8465388,22 66.6226812,21.7761424 66.6226812,21.5 C66.6226812,21.3764791 66.668403,21.25733 66.7510341,21.1655176 L70.1283529,17.4129412 C70.3130824,17.2076862 70.6292274,17.191047 70.8344824,17.3757765 C70.8475136,17.3875046 70.859919,17.39991 70.8716471,17.4129412 Z" id="三角形" transform="translate(70.500000, 19.500000) rotate(-360.000000) translate(-70.500000, -19.500000) "></path>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 13 - 0
src/views/xiaoku-music/images/icon-arrow2.svg

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="9px" height="5px" viewBox="0 0 9 5" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>三角形</title>
+    <g id="所有页面" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="68、小酷AI-曲目列表" transform="translate(-338.000000, -195.000000)" fill="#FFFFFF">
+            <g id="编组-20" transform="translate(164.000000, 178.000000)">
+                <g id="资源/第一层级筛选/选中备份" transform="translate(108.000000, 0.000000)">
+                    <path d="M70.8716471,17.4129412 L74.2489659,21.1655176 C74.4336954,21.3707726 74.4170562,21.6869176 74.2118012,21.8716471 C74.1199888,21.9542782 74.0008397,22 73.8773188,22 L67.1226812,22 C66.8465388,22 66.6226812,21.7761424 66.6226812,21.5 C66.6226812,21.3764791 66.668403,21.25733 66.7510341,21.1655176 L70.1283529,17.4129412 C70.3130824,17.2076862 70.6292274,17.191047 70.8344824,17.3757765 C70.8475136,17.3875046 70.859919,17.39991 70.8716471,17.4129412 Z" id="三角形" transform="translate(70.500000, 19.500000) rotate(-360.000000) translate(-70.500000, -19.500000) "></path>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 61 - 1
src/views/xiaoku-music/index.module.less

@@ -351,10 +351,27 @@
     // }
   }
 
-  .favitor {
+  .rightBtns {
     position: absolute;
     top: 20px;
     right: 24px;
+    display: flex;
+    align-items: center;
+
+    .textBtn {
+      margin-right: 24px;
+      padding: 1px 16px !important;
+      line-height: 37px !important;
+      height: 37px !important;
+      background: #F5F6FA;
+      --n-border: #F5F6FA !important;
+
+
+    }
+  }
+
+  .favitor {
+
     width: 48px;
     height: 48px;
     cursor: pointer;
@@ -426,4 +443,47 @@
     background-color: #fff;
     border-radius: 16px;
   }
+}
+
+.popSelect {
+  font-size: 16px;
+  width: 200px;
+  box-shadow: 0px 2 16px 0px rgba(0, 0, 0, 0.08);
+  border-radius: 11px;
+  --n-option-height: 34px;
+
+  :global {
+    .n-base-select-option__content {
+      width: 80% !important;
+    }
+  }
+}
+
+.textBtn {
+  .iconArrow {
+    display: inline-block;
+    margin-left: 8px;
+    margin-top: 2px;
+    width: 8px;
+    height: 5px;
+    background: url('./images/icon-arrow.svg') no-repeat center center / contain;
+    transform: rotate(180deg);
+    color: #131415;
+    fill: #131415;
+  }
+
+  &:hover,
+  &.textBtnActive {
+    background: #198CFE !important;
+    font-weight: 500 !important;
+    color: #fff !important;
+
+    .iconArrow {
+      transform: rotate(0deg);
+      background: url('./images/icon-arrow2.svg') no-repeat center center / contain;
+      color: #fff;
+      fill: #fff;
+      margin-top: 0;
+    }
+  }
 }

+ 204 - 40
src/views/xiaoku-music/index.tsx

@@ -19,6 +19,7 @@ import {
   NEmpty,
   NImage,
   NModal,
+  NPopselect,
   NSpace,
   NSpin
 } from 'naive-ui';
@@ -36,6 +37,7 @@ import { useRoute, useRouter } from 'vue-router';
 import PlayItem from './component/play-item';
 import PlayLoading from './component/play-loading';
 import TheNoticeBar from '/src/components/TheNoticeBar';
+import { useCatchStore } from '/src/store/modules/catchData';
 import {
   api_materialFavorite,
   api_materialFavoriteStatus,
@@ -50,6 +52,7 @@ import { useResizeObserver } from '@vueuse/core';
 export default defineComponent({
   name: 'XiaokuMusic',
   setup() {
+    const catchStore = useCatchStore();
     const user = useUserStore();
     const route = useRoute();
     const router = useRouter();
@@ -68,12 +71,14 @@ export default defineComponent({
       tagIndex: 0,
       list: [] as unknown as IMusicItem[],
       listActive: 0,
+      musicInstrumentIndex: 0,
       playState: 'pause' as 'play' | 'pause',
       showPlayer: false,
       previewModal: false,
       showPreivew: false,
       previewUrl: '',
-      showCloseBtn: true
+      showCloseBtn: true,
+      iframeSrc: ''
     });
     const showGuide = ref(false);
     const userStore = useUserStore();
@@ -81,10 +86,18 @@ export default defineComponent({
     const getSubjects = async () => {
       // const res = await api_subjectList();
       // if (Array.isArray(res?.data)) {
+      const tempSubjectList = catchStore.getSubjectAllList;
       const subjectList = sessionStorage.getItem('musicSubjectList')
         ? JSON.parse(sessionStorage.getItem('musicSubjectList') as any)
         : [];
-      data.tags = [{ name: '全部', id: 0 }, ...subjectList];
+      const resultList: any[] = [];
+      tempSubjectList.forEach((item: any) => {
+        const hasItem = subjectList.find((s: any) => s.id === item.id);
+        if (hasItem) {
+          resultList.push(item);
+        }
+      });
+      data.tags = [{ name: '全部', id: 0 }, ...resultList];
       // }
     };
     const getList = async () => {
@@ -140,13 +153,15 @@ export default defineComponent({
     };
 
     onMounted(async () => {
+      // 获取声部列表
+      await catchStore.getSubjects();
       // musicList-container
       useResizeObserver(
         document.querySelector('.musicList-container') as HTMLElement,
         (entries: any) => {
           const entry = entries[0];
           const { height } = entry.contentRect;
-          console.log(height, 'height - 11');
+          // console.log(height, 'height - 11');
           document.documentElement.style.setProperty(
             '--xiaoku-music-height',
             height + 'px'
@@ -188,6 +203,17 @@ export default defineComponent({
       }
       getFavitor(item);
     };
+
+    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;
+    };
     /** 选中的item */
     const activeItem = computed(() => {
       if (data.list[data.listActive]) {
@@ -232,6 +258,42 @@ export default defineComponent({
       }
     };
 
+    const musicalInstruments = computed(() => {
+      const details: any = data.list[data.listActive];
+      const musics = details?.musicalInstruments || [];
+      const temp: any = [];
+      musics.forEach((item: any, index: number) => {
+        temp.push({
+          label: item.name,
+          value: index
+        });
+      });
+      return temp;
+    });
+    const isEnsemble = computed(() => {
+      const details: any = data.list[data.listActive];
+      const musics: any = details?.musicalInstruments;
+      if (musics && musics.length > 1) {
+        return true;
+      } else {
+        return false;
+      }
+    });
+
+    const musicIframeLoad = () => {
+      const token = userStore.getToken;
+      const details = data.list[data.listActive];
+      const origin = /(localhost|192)/.test(location.host)
+        ? 'https://test.lexiaoya.cn'
+        : location.origin;
+      console.log(
+        origin,
+        'origin',
+        `${origin}/instrument/?id=${details.id}&modelType=practise&modeType=json&Authorization=${token}&isPreView=true&part-index=${data.musicInstrumentIndex}`
+      );
+      data.iframeSrc = `${origin}/instrument/?id=${details.id}&modelType=practise&modeType=json&Authorization=${token}&isPreView=true&part-index=${data.musicInstrumentIndex}`;
+    };
+
     /** 音频控制 */
     const handleChangeAudio = (
       type: 'play' | 'pause' | 'pre' | 'next' | 'favitor'
@@ -285,20 +347,84 @@ export default defineComponent({
                     style={{ width: '100%' }}
                     size={[24, 12]}
                     wrapItem={false}>
-                    {data.tags.map(item => (
-                      <NButton
-                        round
-                        textColor={data.tagIndex === item.id ? '#fff' : '#000'}
-                        color={data.tagIndex === item.id ? '#198CFE' : '#fff'}
-                        type={data.tagIndex === item.id ? 'primary' : 'default'}
-                        onClick={() => {
-                          data.tagIndex = item.id;
-                          data.reshing = true;
-                          handleGetList();
-                        }}>
-                        {item.name}
-                      </NButton>
-                    ))}
+                    {data.tags.map(item =>
+                      item.instruments && item.instruments.length > 1 ? (
+                        <NPopselect
+                          options={item.instruments}
+                          trigger="hover"
+                          v-model:value={data.tagIndex}
+                          onUpdate:value={() => {
+                            // onSearch();
+                            console.log(
+                              data.tagIndex,
+                              'tagIndex',
+                              data.tagIndex
+                            );
+                            data.reshing = true;
+                            handleGetList();
+                          }}
+                          key={item.id}
+                          class={[styles.popSelect]}>
+                          {/* <span
+                            class={[
+                              styles.textBtn,
+                              selectChildObj(item.instruments).selected &&
+                                styles.textBtnActive
+                            ]}>
+                            {selectChildObj(item.instruments).name || item.name}
+                            <i class={styles.iconArrow}></i>
+                          </span> */}
+                          <NButton
+                            round
+                            textColor={
+                              selectChildObj(item.instruments).selected
+                                ? '#fff'
+                                : '#000'
+                            }
+                            color={
+                              selectChildObj(item.instruments).selected
+                                ? '#198CFE'
+                                : '#fff'
+                            }
+                            type={
+                              selectChildObj(item.instruments).selected
+                                ? 'primary'
+                                : 'default'
+                            }
+                            class={[
+                              styles.textBtn,
+                              selectChildObj(item.instruments).selected &&
+                                styles.textBtnActive
+                            ]}
+                            // onClick={() => {
+                            //   data.tagIndex = item.id;
+                            //   data.reshing = true;
+                            //   handleGetList();
+                            // }}
+                          >
+                            {selectChildObj(item.instruments).name || item.name}
+                            <i class={styles.iconArrow}></i>
+                          </NButton>
+                        </NPopselect>
+                      ) : (
+                        <NButton
+                          round
+                          textColor={
+                            data.tagIndex === item.id ? '#fff' : '#000'
+                          }
+                          color={data.tagIndex === item.id ? '#198CFE' : '#fff'}
+                          type={
+                            data.tagIndex === item.id ? 'primary' : 'default'
+                          }
+                          onClick={() => {
+                            data.tagIndex = item.id;
+                            data.reshing = true;
+                            handleGetList();
+                          }}>
+                          {item.name}
+                        </NButton>
+                      )
+                    )}
                   </NSpace>
                 </div>
               </NSpace>
@@ -325,7 +451,10 @@ export default defineComponent({
                             styles.item,
                             data.listActive === index && styles.active
                           ]}
-                          onClick={() => handleChange(item)}>
+                          onClick={() => {
+                            handleChange(item);
+                            musicIframeLoad();
+                          }}>
                           <div class={styles.img}>
                             <NImage
                               lazy
@@ -448,30 +577,65 @@ export default defineComponent({
                   }}
                 />
                 <div
-                  style={{ display: activeItem.value.id ? '' : 'none' }}
-                  class={styles.favitor}
-                  onClick={() => handleFavitor()}>
-                  <Transition name="favitor" mode="out-in">
-                    {activeItem.value.favitor ? (
-                      <img src={icon_favitorActive} key="1" />
-                    ) : (
-                      <img src={icon_favitor} key="2" />
-                    )}
-                  </Transition>
+                  class={styles.rightBtns}
+                  style={{ display: activeItem.value.id ? '' : 'none' }}>
+                  {isEnsemble.value && (
+                    <NPopselect
+                      options={musicalInstruments.value}
+                      trigger="hover"
+                      v-model:value={data.musicInstrumentIndex}
+                      onUpdate:value={(val: any) => {
+                        if (val === data.musicInstrumentIndex) return;
+
+                        musicIframeLoad();
+                      }}
+                      // key={item.id}
+                      class={[styles.popSelect]}>
+                      <NButton round class={[styles.textBtn]}>
+                        切换声轨
+                        <i class={styles.iconArrow}></i>
+                      </NButton>
+                    </NPopselect>
+                  )}
+
+                  <div class={styles.favitor} onClick={() => handleFavitor()}>
+                    <Transition name="favitor" mode="out-in">
+                      {activeItem.value.favitor ? (
+                        <img src={icon_favitorActive} key="1" />
+                      ) : (
+                        <img src={icon_favitor} key="2" />
+                      )}
+                    </Transition>
+                  </div>
                 </div>
+
                 <div class={styles.staffImgs}>
-                  <TransitionGroup name="van-fade">
-                    {activeItem.value?.musicSvg ||
-                    activeItem.value?.musicImg ? (
-                      (activeItem.value?.musicSvg || activeItem.value?.musicImg)
-                        ?.split(',')
-                        .map((item, index) => {
-                          return <img src={item} key={item} />;
-                        })
-                    ) : (
-                      <TheEmpty></TheEmpty>
-                    )}
-                  </TransitionGroup>
+                  {isEnsemble.value ? (
+                    <iframe
+                      id="staffIframeRef"
+                      style={{
+                        width: '100%'
+                        // opacity: loading.value ? 0 : 1
+                      }}
+                      src={data.iframeSrc}
+                      onLoad={musicIframeLoad}></iframe>
+                  ) : (
+                    <TransitionGroup name="van-fade">
+                      {activeItem.value?.musicSvg ||
+                      activeItem.value?.musicImg ? (
+                        (
+                          activeItem.value?.musicSvg ||
+                          activeItem.value?.musicImg
+                        )
+                          ?.split(',')
+                          .map(item => {
+                            return <img src={item} key={item} />;
+                          })
+                      ) : (
+                        <TheEmpty></TheEmpty>
+                      )}
+                    </TransitionGroup>
+                  )}
                 </div>
               </div>
             </div>

+ 2 - 2
vite.config.ts

@@ -23,8 +23,8 @@ function resolve(dir: string) {
 }
 // https://vitejs.dev/config/
 // https://github.com/vitejs/vite/issues/1930 .env
-// const proxyUrl = 'https://dev.kt.colexiu.com/';
-const proxyUrl = 'https://test.lexiaoya.cn';
+const proxyUrl = 'https://dev.kt.colexiu.com/';
+// const proxyUrl = 'https://test.lexiaoya.cn';
 // const proxyUrl = 'http://192.168.3.14:7989';
 const now = new Date().getTime();
 export default defineConfig(() => {