Browse Source

Merge branch 'iteration-20240607-small' into online

lex 10 months ago
parent
commit
202d91c7ba
27 changed files with 2788 additions and 1907 deletions
  1. 1 1
      dev-dist/sw.js
  2. 1 1
      public/version.json
  3. 97 87
      src/api/user.ts
  4. 1 0
      src/components/layout/layoutTop.tsx
  5. 379 377
      src/custom-plugins/guide-page/home-guide.tsx
  6. 42 2
      src/store/modules/catchData.ts
  7. 1 0
      src/views/attend-class/index.module.less
  8. 1 0
      src/views/attend-class/model/class-work/index.module.less
  9. 1 0
      src/views/homework-record/index.module.less
  10. 1 1
      src/views/natural-resources/components/share-resources/index.module.less
  11. 2 1
      src/views/natural-resources/components/share-resources/index.tsx
  12. 210 59
      src/views/natural-resources/components/share-resources/search-group-resources.tsx
  13. 158 155
      src/views/natural-resources/model/add-teaching/index.module.less
  14. 471 467
      src/views/natural-resources/model/add-teaching/index.tsx
  15. 1 0
      src/views/prepare-lessons/components/lesson-main/courseware-presets/index.module.less
  16. 44 15
      src/views/prepare-lessons/components/resource-main/components/resource-item/resource-search-group/index.tsx
  17. 151 101
      src/views/prepare-lessons/components/resource-main/components/select-music/resource-search-group/index.tsx
  18. 82 76
      src/views/prepare-lessons/index.module.less
  19. 1 1
      src/views/prepare-lessons/model/select-music/select-item/index.module.less
  20. 11 2
      src/views/prepare-lessons/model/select-music/select-item/index.tsx
  21. 259 48
      src/views/prepare-lessons/model/select-music/select-item/search-group.tsx
  22. 15 3
      src/views/prepare-lessons/model/select-resources/select-item/index.tsx
  23. 1 1
      src/views/prepare-lessons/model/select-resources/select-item/resource-search-group/index.module.less
  24. 199 54
      src/views/prepare-lessons/model/select-resources/select-item/resource-search-group/index.tsx
  25. 39 23
      src/views/setting/components/schoolInfo/index.tsx
  26. 1 1
      src/views/xiaoku-ai/index.module.less
  27. 618 431
      src/views/xiaoku-ai/index.tsx

+ 1 - 1
dev-dist/sw.js

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

+ 1 - 1
public/version.json

@@ -1 +1 @@
-{"version":1719918227380}
+{"version":1720060648120}

+ 97 - 87
src/api/user.ts

@@ -1,87 +1,97 @@
-import request from '@/utils/request';
-
-/**
- * 用户登录
- * @param prams 登录参数
- */
-export const userLogin = (params: any) => {
-  return request.post('/edu-app/userlogin', {
-    requestType: 'form',
-    data: params
-  });
-};
-
-/**
- * 获取用户信息
- * returns user
- */
-export const getUserInfo = () => {
-  return request.get('/edu-app/user/getUserInfo');
-};
-
-/**
- * 老师端修改用户信息
- */
-export const api_teacherUpdate = (body: any) => {
-  return request.post('/edu-app/teacher/update', { data: body });
-};
-
-/**
- * 获取声部列表
- * returns subjects
- */
-export const getSubjectList = (params: any) => {
-  return request.post('/edu-app/subject/page', {
-    data: params
-  });
-};
-
-/**
- * 获取声部列表
- * returns subjects
- */
-export const getSubjectList2 = (params: any) => {
-  return request.post('/edu-app/subject/list', {
-    data: params
-  });
-};
-
-/**
- * 获取曲谱分类
- * @returns musicSheetCategories
- */
-export const getCategories = (params: any) => {
-  return request.post('/edu-app/musicSheetCategories/page', {
-    data: params
-  });
-};
-
-/**
- * 反馈购买未读条数
- * @returns suggestMessageUnread
- */
-export const suggestMessageUnread = (params?: any) => {
-  return request.get('/edu-app/sysSuggestion/suggestMessageUnread', {
-    params
-  });
-};
-
-/** 曲谱详情 */
-export const api_musicSheetDetail = (data: any) => {
-  return request.get(`/edu-app/musicSheet/detail/${data}`);
-};
-
-/** 获取乐器列表 */
-export const api_musicalInstrumentList = (data: any) => {
-  return request.post('/edu-app/musicalInstrument/list', {
-    data
-  });
-};
-
-/**
- * @description: 上课记录详情
- * @param params
- */
-export const api_cousseScheduleDetail = (id: string) => {
-  return request.post('/edu-app/courseSchedule/detail/' + id);
-};
+import request from '@/utils/request';
+
+/**
+ * 用户登录
+ * @param prams 登录参数
+ */
+export const userLogin = (params: any) => {
+  return request.post('/edu-app/userlogin', {
+    requestType: 'form',
+    data: params
+  });
+};
+
+/**
+ * 获取用户信息
+ * returns user
+ */
+export const getUserInfo = () => {
+  return request.get('/edu-app/user/getUserInfo');
+};
+
+/**
+ * 老师端修改用户信息
+ */
+export const api_teacherUpdate = (body: any) => {
+  return request.post('/edu-app/teacher/update', { data: body });
+};
+
+/**
+ * 获取声部列表
+ * returns subjects
+ */
+export const getSubjectList = (params: any) => {
+  return request.post('/edu-app/subject/page', {
+    data: params
+  });
+};
+
+/**
+ * 获取声部列表
+ * returns subjects
+ */
+export const getSubjectList2 = (params: any) => {
+  return request.post('/edu-app/subject/list', {
+    data: params
+  });
+};
+
+/**
+ * 获取曲谱分类
+ * @returns musicSheetCategories
+ */
+export const getCategories = (params: any) => {
+  return request.post('/edu-app/musicSheetCategories/page', {
+    data: params
+  });
+};
+
+/**
+ * 反馈购买未读条数
+ * @returns suggestMessageUnread
+ */
+export const suggestMessageUnread = (params?: any) => {
+  return request.get('/edu-app/sysSuggestion/suggestMessageUnread', {
+    params
+  });
+};
+
+/** 曲谱详情 */
+export const api_musicSheetDetail = (data: any) => {
+  return request.get(`/edu-app/musicSheet/detail/${data}`);
+};
+
+/** 获取乐器列表 */
+export const api_musicalInstrumentList = (data: any) => {
+  return request.post('/edu-app/musicalInstrument/list', {
+    data
+  });
+};
+
+/**
+ * @description: 上课记录详情
+ * @param params
+ */
+export const api_cousseScheduleDetail = (id: string) => {
+  return request.post('/edu-app/courseSchedule/detail/' + id);
+};
+
+/**
+ * @description: 标签列表
+ * @param params
+ */
+export const api_musicTagTree = (params?: any) => {
+  return request.get('/edu-app/musicTag/tree', {
+    params
+  });
+};

+ 1 - 0
src/components/layout/layoutTop.tsx

@@ -65,6 +65,7 @@ export default defineComponent({
 
     const oncheckEditStatus = (callBack: any) => {
       showHeadFlag.value = false;
+      userInfoStatus.value = false;
       if (prepareStore.getIsEditResource) {
         eventGlobal.emit('pageBeforeLeave', () => callBack());
       } else {

+ 379 - 377
src/custom-plugins/guide-page/home-guide.tsx

@@ -1,377 +1,379 @@
-import { NButton } from 'naive-ui';
-import {
-  defineComponent,
-  nextTick,
-  onMounted,
-  onUnmounted,
-  reactive,
-  ref,
-  watch
-} from 'vue';
-import styles from './index.module.less';
-import { getImage } from './images';
-import { eventGlobal, px2vw, px2vwH } from '@/utils/index';
-import { getGuidance, setGuidance } from './api';
-export default defineComponent({
-  name: 'coai-guide',
-  emits: ['close'],
-  setup(props, { emit }) {
-    const data = reactive({
-      box: {
-        height: '0px'
-      } as any,
-      show: false,
-      /**
-       *
-            width:  px2vw(840),
-            height:  px2vw(295)
-       */
-      steps: [
-        {
-          ele: '',
-          eleRect: {} as DOMRect,
-          img: getImage('home1.png'),
-          handStyle: {
-            top: '0.91rem'
-          },
-          imgStyle: {
-            top: px2vw(-400 / 2),
-            left: px2vw(-734 / 2),
-            width: px2vw(734),
-            height: px2vw(295)
-          },
-          btnsStyle: {
-            bottom: px2vw(240),
-            left: px2vw(-128)
-          },
-          boxStyle: {
-            border: 'none',
-            width: 0,
-            height: 0,
-            backgroundColor: 'transparent',
-            position: 'fixed',
-            top: `50%`,
-            left: '50%'
-            // visibility: 'hidden'
-          },
-          eleRectPadding: {
-            left: 0,
-            top: 0,
-            width: 0,
-            height: 0
-          }
-        },
-        {
-          ele: '',
-          img: getImage('home2.png'),
-          imgStyle: {
-            top: '100%',
-            left: px2vw(-290),
-            width: px2vw(401),
-            height: px2vw(227)
-          },
-          btnsStyle: {
-            bottom: '30px',
-            left: px2vw(-130)
-          },
-          boxStyle: {},
-          eleRectPadding: {
-            left: 7,
-            top: 7,
-            width: 14,
-            height: 14
-          }
-        },
-        {
-          ele: '',
-          img: getImage('home6.png'),
-          imgStyle: {
-            top: '100%',
-            left: px2vw(-310),
-            width: px2vw(477),
-            height: px2vw(227)
-          },
-          btnsStyle: {
-            bottom: '30px',
-            left: px2vw(-150)
-          },
-          boxStyle: {},
-          eleRectPadding: {
-            left: 7,
-            top: 7,
-            width: 14,
-            height: 14
-          }
-        },
-        {
-          ele: '',
-          img: getImage('home4.png'),
-          imgStyle: {
-            top: '100%',
-            left: px2vw(-310),
-            width: px2vw(477),
-            height: px2vw(227)
-          },
-          btnsStyle: {
-            bottom: '30px',
-            left: px2vw(-150)
-          },
-          boxStyle: {},
-          eleRectPadding: {
-            left: 7,
-            top: 7,
-            width: 14,
-            height: 14
-          }
-        },
-        {
-          ele: '',
-          img: getImage('home3.png'),
-          handStyle: {
-            top: '-1.39rem',
-            left: '0.17rem',
-            transform: 'rotate(180deg)'
-          },
-          imgStyle: {
-            top: px2vw(-4),
-            width: px2vw(454),
-            height: px2vw(227),
-            left: px2vw(-150)
-          },
-          btnsStyle: {
-            bottom: '30px',
-            left: px2vw(8)
-          },
-          boxStyle: {
-            borderRadius: '30px'
-          },
-          eleRectPadding: {
-            left: 7,
-            top: 9,
-            width: 14,
-            height: 14
-          }
-        },
-        {
-          ele: '',
-          img: getImage('home5.png'),
-          handStyle: {
-            top: '-1.39rem',
-            left: '0.17rem',
-            transform: 'rotate(180deg)'
-          },
-          imgStyle: {
-            top: px2vw(-194),
-            width: px2vw(621),
-            height: px2vw(223),
-            left: px2vw(-624)
-          },
-          btnsStyle: {
-            top: px2vw(-42),
-            left: px2vw(-460)
-          },
-          boxStyle: {},
-          eleRectPadding: {
-            left: 7,
-            top: 7,
-            width: 14,
-            height: 14
-          }
-        }
-      ],
-      step: 0
-    });
-    const tipShow = ref(false);
-    // const res =  setGuidance({guideTag:'teacher-guideInfo',guideValue:'{}'})
-    const guideInfo = ref({} as any);
-    const getAllGuidance = async () => {
-      try {
-        const res = await getGuidance({ guideTag: 'teacher-guideInfo' });
-        if (res.data) {
-          guideInfo.value = JSON.parse(res.data?.guideValue) || null;
-        } else {
-          guideInfo.value = {};
-        }
-
-        if (guideInfo.value && guideInfo.value.homeGuide) {
-          tipShow.value = false;
-        } else {
-          tipShow.value = true;
-        }
-      } catch (e) {
-        console.log(e);
-      }
-      // const guideInfo = localStorage.getItem('teacher-guideInfo');
-    };
-    getAllGuidance();
-    const getStepELe = () => {
-      const ele: HTMLElement = document.getElementById(
-        data.step === data.steps.length - 1
-          ? 'moveNPopover'
-          : `home-${data.step}`
-      )!;
-      // console.log(`coai-${data.step}`, data.steps[data.step].eleRectPadding);
-      if (ele) {
-        const eleRect = ele.getBoundingClientRect();
-        const left = data.steps[data.step].eleRectPadding?.left || 0;
-        const top = data.steps[data.step].eleRectPadding?.top || 0;
-        const width = data.steps[data.step].eleRectPadding?.width || 0;
-        const height = data.steps[data.step].eleRectPadding?.height || 0;
-        data.box = {
-          left: eleRect.x - left + 'px',
-          top: eleRect.y - top + 'px',
-          width: eleRect.width + width + 'px',
-          height: eleRect.height + height + 'px'
-        };
-      } else {
-        handleNext();
-      }
-    };
-
-    const onResetGuide = async (name: string) => {
-      try {
-        if (name !== 'Home') return;
-        if (!guideInfo.value) {
-          guideInfo.value = { homeGuide: false };
-        } else {
-          guideInfo.value.homeGuide = false;
-        }
-        try {
-          await setGuidance({
-            guideTag: 'teacher-guideInfo',
-            guideValue: JSON.stringify(guideInfo.value)
-          });
-        } catch (e) {
-          console.log(e);
-        }
-        data.step = 0;
-        getStepELe();
-        tipShow.value = true;
-      } catch {
-        //
-      }
-    };
-    onMounted(() => {
-      getStepELe();
-      window.addEventListener('resize', resetSize);
-      eventGlobal.on('teacher-guideInfo', onResetGuide);
-    });
-    const resetSize = () => {
-      getStepELe();
-    };
-
-    onUnmounted(() => {
-      window.removeEventListener('resize', resetSize);
-      eventGlobal.off('teacher-guideInfo', onResetGuide);
-    });
-
-    const handleNext = () => {
-      if (data.step >= data.steps.length - 1) {
-        endGuide();
-        return;
-      }
-      data.step = data.step + 1;
-      getStepELe();
-    };
-
-    const endGuide = async () => {
-      // let guideInfo =
-      //   JSON.parse(localStorage.getItem('teacher-guideInfo') || '{}') || null;
-      if (!guideInfo.value) {
-        guideInfo.value = { homeGuide: true };
-      } else {
-        guideInfo.value.homeGuide = true;
-      }
-      try {
-        const res = await setGuidance({
-          guideTag: 'teacher-guideInfo',
-          guideValue: JSON.stringify(guideInfo.value)
-        });
-      } catch (e) {
-        console.log(e);
-      }
-      // localStorage.setItem('teacher-guideInfo', JSON.stringify(guideInfo));
-      tipShow.value = false;
-      //  localStorage.setItem('endC')
-    };
-    return () => (
-      <>
-        {tipShow.value ? (
-          <div
-            v-model:show={tipShow.value}
-            class={['n-modal-mask', 'n-modal-mask-guide']}>
-            <div class={styles.content} onClick={() => handleNext()}>
-              <div
-                class={styles.backBtn}
-                onClick={(e: Event) => {
-                  e.stopPropagation();
-                  endGuide();
-                }}>
-                跳过
-              </div>
-              <div
-                class={styles.box}
-                style={{ ...data.box, ...data.steps[data.step].boxStyle }}
-                id={`modeType-${data.step}`}>
-                {data.steps.map((item: any, index) => (
-                  <div
-                    onClick={(e: Event) => e.stopPropagation()}
-                    class={styles.item}
-                    style={
-                      item.type == 'bottom'
-                        ? {
-                            display: index === data.step ? '' : 'none',
-                            left: `${item.eleRect?.left}px`,
-                            top: `-${item.imgStyle?.height}`
-                          }
-                        : {
-                            display: index === data.step ? '' : 'none',
-                            left: `${item.eleRect?.left}px`,
-                            top: `${data.box?.height}`
-                          }
-                    }>
-                    <img
-                      class={styles.img}
-                      style={item.imgStyle}
-                      src={item.img}
-                    />
-                    {/* <img
-                      class={styles.iconHead}
-                      style={item.handStyle}
-                      src={getImage('indexDot.png')}
-                    /> */}
-                    <div class={styles.btns} style={item.btnsStyle}>
-                      {data.step + 1 == data.steps.length ? (
-                        <>
-                          <div
-                            class={[styles.endBtn]}
-                            onClick={() => endGuide()}>
-                            完成
-                          </div>
-                          <div
-                            class={styles.nextBtn}
-                            onClick={() => {
-                              data.step = 0;
-                              getStepELe();
-                            }}>
-                            再看一遍
-                          </div>
-                        </>
-                      ) : (
-                        <div class={styles.btn} onClick={() => handleNext()}>
-                          {data.step !== 0
-                            ? `下一步 ${data.step}/${data.steps.length - 1}`
-                            : '开始体验'}
-                        </div>
-                      )}
-                    </div>
-                  </div>
-                ))}
-              </div>
-            </div>
-          </div>
-        ) : null}
-      </>
-    );
-  }
-});
+import { NButton } from 'naive-ui';
+import {
+  defineComponent,
+  nextTick,
+  onMounted,
+  onUnmounted,
+  reactive,
+  ref,
+  watch
+} from 'vue';
+import styles from './index.module.less';
+import { getImage } from './images';
+import { eventGlobal, px2vw, px2vwH } from '@/utils/index';
+import { getGuidance, setGuidance } from './api';
+export default defineComponent({
+  name: 'coai-guide',
+  emits: ['close'],
+  setup(props, { emit }) {
+    const data = reactive({
+      box: {
+        height: '0px'
+      } as any,
+      show: false,
+      /**
+       *
+            width:  px2vw(840),
+            height:  px2vw(295)
+       */
+      steps: [
+        {
+          ele: '',
+          eleRect: {} as DOMRect,
+          img: getImage('home1.png'),
+          handStyle: {
+            top: '0.91rem'
+          },
+          imgStyle: {
+            top: px2vw(-400 / 2),
+            left: px2vw(-734 / 2),
+            width: px2vw(734),
+            height: px2vw(295)
+          },
+          btnsStyle: {
+            bottom: px2vw(240),
+            left: px2vw(-128)
+          },
+          boxStyle: {
+            border: 'none',
+            width: 0,
+            height: 0,
+            backgroundColor: 'transparent',
+            position: 'fixed',
+            top: `50%`,
+            left: '50%'
+            // visibility: 'hidden'
+          },
+          eleRectPadding: {
+            left: 0,
+            top: 0,
+            width: 0,
+            height: 0
+          }
+        },
+        {
+          ele: '',
+          img: getImage('home2.png'),
+          imgStyle: {
+            top: '100%',
+            left: px2vw(-290),
+            width: px2vw(401),
+            height: px2vw(227)
+          },
+          btnsStyle: {
+            bottom: '30px',
+            left: px2vw(-130)
+          },
+          boxStyle: {},
+          eleRectPadding: {
+            left: 7,
+            top: 7,
+            width: 14,
+            height: 14
+          }
+        },
+        {
+          ele: '',
+          img: getImage('home6.png'),
+          imgStyle: {
+            top: '100%',
+            left: px2vw(-310),
+            width: px2vw(477),
+            height: px2vw(227)
+          },
+          btnsStyle: {
+            bottom: '30px',
+            left: px2vw(-150)
+          },
+          boxStyle: {},
+          eleRectPadding: {
+            left: 7,
+            top: 7,
+            width: 14,
+            height: 14
+          }
+        },
+        {
+          ele: '',
+          img: getImage('home4.png'),
+          imgStyle: {
+            top: '100%',
+            left: px2vw(-310),
+            width: px2vw(477),
+            height: px2vw(227)
+          },
+          btnsStyle: {
+            bottom: '30px',
+            left: px2vw(-150)
+          },
+          boxStyle: {},
+          eleRectPadding: {
+            left: 7,
+            top: 7,
+            width: 14,
+            height: 14
+          }
+        },
+        {
+          ele: '',
+          img: getImage('home3.png'),
+          handStyle: {
+            top: '-1.39rem',
+            left: '0.17rem',
+            transform: 'rotate(180deg)'
+          },
+          imgStyle: {
+            top: px2vw(-4),
+            width: px2vw(454),
+            height: px2vw(227),
+            left: px2vw(-150)
+          },
+          btnsStyle: {
+            bottom: '30px',
+            left: px2vw(8)
+          },
+          boxStyle: {
+            borderRadius: '30px'
+          },
+          eleRectPadding: {
+            left: 7,
+            top: 9,
+            width: 14,
+            height: 14
+          }
+        },
+        {
+          ele: '',
+          img: getImage('home5.png'),
+          handStyle: {
+            top: '-1.39rem',
+            left: '0.17rem',
+            transform: 'rotate(180deg)'
+          },
+          imgStyle: {
+            top: px2vw(-194),
+            width: px2vw(621),
+            height: px2vw(223),
+            left: px2vw(-624)
+          },
+          btnsStyle: {
+            top: px2vw(-42),
+            left: px2vw(-460)
+          },
+          boxStyle: {},
+          eleRectPadding: {
+            left: 7,
+            top: 7,
+            width: 14,
+            height: 14
+          }
+        }
+      ],
+      step: 0
+    });
+    const tipShow = ref(false);
+    // const res =  setGuidance({guideTag:'teacher-guideInfo',guideValue:'{}'})
+    const guideInfo = ref({} as any);
+    const getAllGuidance = async () => {
+      try {
+        const res = await getGuidance({ guideTag: 'teacher-guideInfo' });
+        if (res.data) {
+          guideInfo.value = JSON.parse(res.data?.guideValue) || null;
+        } else {
+          guideInfo.value = {};
+        }
+
+        if (guideInfo.value && guideInfo.value.homeGuide) {
+          tipShow.value = false;
+        } else {
+          tipShow.value = true;
+        }
+      } catch (e) {
+        console.log(e);
+      }
+      // const guideInfo = localStorage.getItem('teacher-guideInfo');
+    };
+    getAllGuidance();
+    const getStepELe = () => {
+      const ele: HTMLElement = document.getElementById(
+        data.step === data.steps.length - 1
+          ? 'moveNPopover'
+          : `home-${data.step}`
+      )!;
+      // console.log(`coai-${data.step}`, data.steps[data.step].eleRectPadding);
+      if (ele) {
+        const eleRect = ele.getBoundingClientRect();
+        const left = data.steps[data.step].eleRectPadding?.left || 0;
+        const top = data.steps[data.step].eleRectPadding?.top || 0;
+        const width = data.steps[data.step].eleRectPadding?.width || 0;
+        const height = data.steps[data.step].eleRectPadding?.height || 0;
+
+        console.log(eleRect, height);
+        data.box = {
+          left: eleRect.x - left + 'px',
+          top: eleRect.y - top + 'px',
+          width: eleRect.width + width + 'px',
+          height: eleRect.height + height + 'px'
+        };
+      } else {
+        handleNext();
+      }
+    };
+
+    const onResetGuide = async (name: string) => {
+      try {
+        if (name !== 'Home') return;
+        if (!guideInfo.value) {
+          guideInfo.value = { homeGuide: false };
+        } else {
+          guideInfo.value.homeGuide = false;
+        }
+        try {
+          await setGuidance({
+            guideTag: 'teacher-guideInfo',
+            guideValue: JSON.stringify(guideInfo.value)
+          });
+        } catch (e) {
+          console.log(e);
+        }
+        data.step = 0;
+        getStepELe();
+        tipShow.value = true;
+      } catch {
+        //
+      }
+    };
+    onMounted(() => {
+      getStepELe();
+      window.addEventListener('resize', resetSize);
+      eventGlobal.on('teacher-guideInfo', onResetGuide);
+    });
+    const resetSize = () => {
+      getStepELe();
+    };
+
+    onUnmounted(() => {
+      window.removeEventListener('resize', resetSize);
+      eventGlobal.off('teacher-guideInfo', onResetGuide);
+    });
+
+    const handleNext = () => {
+      if (data.step >= data.steps.length - 1) {
+        endGuide();
+        return;
+      }
+      data.step = data.step + 1;
+      getStepELe();
+    };
+
+    const endGuide = async () => {
+      // let guideInfo =
+      //   JSON.parse(localStorage.getItem('teacher-guideInfo') || '{}') || null;
+      if (!guideInfo.value) {
+        guideInfo.value = { homeGuide: true };
+      } else {
+        guideInfo.value.homeGuide = true;
+      }
+      try {
+        const res = await setGuidance({
+          guideTag: 'teacher-guideInfo',
+          guideValue: JSON.stringify(guideInfo.value)
+        });
+      } catch (e) {
+        console.log(e);
+      }
+      // localStorage.setItem('teacher-guideInfo', JSON.stringify(guideInfo));
+      tipShow.value = false;
+      //  localStorage.setItem('endC')
+    };
+    return () => (
+      <>
+        {tipShow.value ? (
+          <div
+            v-model:show={tipShow.value}
+            class={['n-modal-mask', 'n-modal-mask-guide']}>
+            <div class={styles.content} onClick={() => handleNext()}>
+              <div
+                class={styles.backBtn}
+                onClick={(e: Event) => {
+                  e.stopPropagation();
+                  endGuide();
+                }}>
+                跳过
+              </div>
+              <div
+                class={styles.box}
+                style={{ ...data.box, ...data.steps[data.step].boxStyle }}
+                id={`modeType-${data.step}`}>
+                {data.steps.map((item: any, index) => (
+                  <div
+                    onClick={(e: Event) => e.stopPropagation()}
+                    class={styles.item}
+                    style={
+                      item.type == 'bottom'
+                        ? {
+                            display: index === data.step ? '' : 'none',
+                            left: `${item.eleRect?.left}px`,
+                            top: `-${item.imgStyle?.height}`
+                          }
+                        : {
+                            display: index === data.step ? '' : 'none',
+                            left: `${item.eleRect?.left}px`,
+                            top: `${data.box?.height}`
+                          }
+                    }>
+                    <img
+                      class={styles.img}
+                      style={item.imgStyle}
+                      src={item.img}
+                    />
+                    {/* <img
+                      class={styles.iconHead}
+                      style={item.handStyle}
+                      src={getImage('indexDot.png')}
+                    /> */}
+                    <div class={styles.btns} style={item.btnsStyle}>
+                      {data.step + 1 == data.steps.length ? (
+                        <>
+                          <div
+                            class={[styles.endBtn]}
+                            onClick={() => endGuide()}>
+                            完成
+                          </div>
+                          <div
+                            class={styles.nextBtn}
+                            onClick={() => {
+                              data.step = 0;
+                              getStepELe();
+                            }}>
+                            再看一遍
+                          </div>
+                        </>
+                      ) : (
+                        <div class={styles.btn} onClick={() => handleNext()}>
+                          {data.step !== 0
+                            ? `下一步 ${data.step}/${data.steps.length - 1}`
+                            : '开始体验'}
+                        </div>
+                      )}
+                    </div>
+                  </div>
+                ))}
+              </div>
+            </div>
+          </div>
+        ) : null}
+      </>
+    );
+  }
+});

+ 42 - 2
src/store/modules/catchData.ts

@@ -4,7 +4,8 @@ import {
   getSubjectList,
   getSubjectList2,
   getCategories,
-  api_musicalInstrumentList
+  api_musicalInstrumentList,
+  api_musicTagTree
 } from '@/api/user';
 import deepClone from '/src/helpers/deep-clone';
 
@@ -14,7 +15,8 @@ export const useCatchStore = defineStore('catch-store', {
     musicTypeList: [] as any[], // 乐谱分类
     subjectList: [] as any[], // 声部列表,
     musicInstrumentList: [] as any[], // 乐器列表,
-    subjectInstruemnts: [] as any[] // 乐器列表,
+    subjectInstruemnts: [] as any[], // 乐器列表,
+    musicTagTree: [] as any[] // 分类列表
   }),
   getters: {
     getBookVersion(): any[] {
@@ -82,6 +84,9 @@ export const useCatchStore = defineStore('catch-store', {
         },
         ...this.subjectInstruemnts
       ];
+    },
+    getMusicTagTree(): any[] {
+      return this.musicTagTree;
     }
   },
   actions: {
@@ -100,6 +105,9 @@ export const useCatchStore = defineStore('catch-store', {
     setMusicInstruments(instruments: any[]) {
       this.musicInstrumentList = instruments;
     },
+    setMusicTagTree(tagTree: any[]) {
+      this.musicTagTree = tagTree;
+    },
     /**
      * 判断是否有声部数据,如不存在则获取声部列表
      * @returns Promise
@@ -250,6 +258,38 @@ export const useCatchStore = defineStore('catch-store', {
       } catch (e) {
         return Promise.reject(e);
       }
+    },
+
+    // ?queryCategory=true
+    /**
+     * 获取层级
+     * @returns Promise
+     */
+    async getMusicTagTreeApi() {
+      try {
+        // // 判断是否存在声部数据
+        if (this.getMusicTagTree && this.getMusicTagTree.length > 0) {
+          return Promise.resolve();
+        }
+        const { data } = await api_musicTagTree();
+
+        const result = data || [];
+        // result.forEach((item: any) => {
+        //   if (item.children && item.children.length > 0) {
+        //     item.children.forEach((child: any) => {
+        //       child.children =
+        //         child.categoriesList && child.categoriesList.length > 0
+        //           ? child.categoriesList
+        //           : '';
+        //     });
+        //   }
+        // });
+        // console.log(result, 'result');
+        this.setMusicTagTree(result || []);
+        return Promise.resolve();
+      } catch (e) {
+        return Promise.reject(e);
+      }
     }
   }
 });

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

@@ -895,6 +895,7 @@
   .resourceMain {
     flex: 0 0 360px;
     height: 55vh;
+    width: 360px;
     box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
   }
 }

+ 1 - 0
src/views/attend-class/model/class-work/index.module.less

@@ -158,6 +158,7 @@
 
   .resourceMain {
     flex: 0 0 360px;
+    width: 360px;
     height: 75vh;
     box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
   }

+ 1 - 0
src/views/homework-record/index.module.less

@@ -108,6 +108,7 @@
 
   .resourceMain {
     flex: 0 0 360px;
+    width: 360px;
     height: 75vh;
     box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
   }

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

@@ -221,7 +221,7 @@
     // display: flex !important;
     // align-items: center;
     &:last-child {
-      margin-left: -12Px;
+      // margin-left: -12Px;
     }
   }
 }

+ 2 - 1
src/views/natural-resources/components/share-resources/index.tsx

@@ -97,7 +97,8 @@ export default defineComponent({
     };
 
     onMounted(() => {
-      getList();
+      // 会在搜索组件里面调用,因为有初始化搜索条件
+      // getList();
     });
     return () => (
       <>

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

@@ -1,4 +1,12 @@
-import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue';
+import {
+  defineComponent,
+  nextTick,
+  onMounted,
+  reactive,
+  ref,
+  watch,
+  toRefs
+} from 'vue';
 import styles from './index.module.less';
 import {
   NButton,
@@ -8,11 +16,98 @@ import {
   NPopselect,
   NSpace
 } from 'naive-ui';
-import iconAdd from '../../images/icon-add.png';
+// import iconAdd from '../../images/icon-add.png';
 import TheSearch from '/src/components/TheSearch';
 import { resourceTypeArray } from '/src/utils/searchArray';
 import { useCatchStore } from '/src/store/modules/catchData';
-import isCollaose from '../../images/isCollaose.png';
+// import isCollaose from '../../images/isCollaose.png';
+
+const ChildNodeSearch = defineComponent({
+  name: 'ChildNodeSearch',
+  props: {
+    activeRow: {
+      type: Object,
+      default: () => ({})
+    },
+    list: {
+      type: Array,
+      default: () => []
+    }
+  },
+  emits: ['selectChildTag'],
+  setup(props, { emit }) {
+    const { activeRow } = toRefs(props);
+    const selectItem = ref({});
+
+    watch(
+      () => props.activeRow,
+      () => {
+        activeRow.value = props.activeRow;
+        selectItem.value = {};
+      }
+    );
+    return () => (
+      <>
+        {activeRow.value?.id && (
+          <>
+            <NFormItem label={activeRow.value.columnName + ':'}>
+              <NSpace class={styles.spaceSection}>
+                {activeRow.value?.children.map((subject: any) => (
+                  <span
+                    class={[
+                      styles.textBtn,
+                      (activeRow.value.activeIndex || '') == subject.id &&
+                        styles.textBtnActive
+                    ]}
+                    onClick={() => {
+                      activeRow.value.activeIndex = subject.id;
+                      let children: any;
+                      let columnName = '';
+                      if (subject.children) {
+                        children = [
+                          {
+                            columnName: subject.children[0].columnName,
+                            name: '全部',
+                            id: ''
+                          },
+                          ...subject.children
+                        ];
+                        columnName = subject.children[0].columnName;
+
+                        selectItem.value = {
+                          ...subject,
+                          columnName,
+                          activeIndex: '',
+                          children
+                        };
+                      } else {
+                        selectItem.value = {};
+                      }
+                      emit('selectChildTag', activeRow.value.activeIndex);
+                    }}>
+                    {subject.name}
+                  </span>
+                ))}
+              </NSpace>
+            </NFormItem>
+
+            <ChildNodeSearch
+              activeRow={selectItem.value}
+              onSelectChildTag={(item: any) => {
+                // console.log(
+                //   activeRow.value.activeIndex,
+                //   'activeRow.value.activeIndex'
+                // );
+                emit('selectChildTag', item || activeRow.value.activeIndex);
+              }}
+            />
+          </>
+        )}
+      </>
+    );
+  }
+});
+
 export default defineComponent({
   name: 'search-group',
   emits: ['search', 'add'],
@@ -22,15 +117,27 @@ export default defineComponent({
     const forms = reactive({
       type: 'MUSIC', //
       name: '',
-      bookVersionId: null,
+      // grade: null as any,
+      bookVersionId: null as any,
+      // musicSheetCategoriesId: null as any,
       subjectId: null
     });
     const state = reactive({
       tempSubjectId: null
     });
+    const data = reactive({
+      selectParents: {}, // 选中的数据
+      tags: [] as any[],
+      tagActiveId: '' as any,
+      tagActive: {} as any,
+      childSelectId: null as any
+    });
 
     const onSearch = () => {
-      emit('search', forms);
+      emit('search', {
+        ...forms,
+        bookVersionId: data.childSelectId || data.tagActiveId
+      });
     };
     const collapseWrapRef = ref();
     const divDomList = ref([] as any);
@@ -38,15 +145,15 @@ export default defineComponent({
     const line = ref(0);
     const isCollapse = ref(false);
     const loadingCollapse = ref(false); // 是否加载完成
-    const musicCateRef = (el: any) => {
-      if (el?.selfElRef) {
-        divDomList.value.push(el.selfElRef.parentNode);
-      }
-    };
-    const setCollapse = (flag: boolean) => {
-      isCollapse.value = flag;
-      getLive();
-    };
+    // const musicCateRef = (el: any) => {
+    //   if (el?.selfElRef) {
+    //     divDomList.value.push(el.selfElRef.parentNode);
+    //   }
+    // };
+    // const setCollapse = (flag: boolean) => {
+    //   isCollapse.value = flag;
+    //   getLive();
+    // };
     const getLive = () => {
       try {
         divDomList.value = [...new Set(divDomList.value)];
@@ -87,10 +194,55 @@ export default defineComponent({
       });
       return obj;
     };
+
+    const _initTags = () => {
+      const tags = catchStore.getMusicTagTree;
+      data.tags = [
+        {
+          columnName: tags[0].columnName,
+          name: '全部',
+          id: ''
+        },
+        ...tags
+      ];
+      data.tagActiveId = data.tags[0].id;
+    };
+
+    const changeTag = (item: any) => {
+      data.tagActiveId = item.id;
+      data.childSelectId = null;
+      let children: any;
+      let columnName = '';
+      if (item.children) {
+        children = [
+          {
+            columnName: item.children[0].columnName,
+            name: '全部',
+            id: ''
+          },
+          ...item.children
+        ];
+        columnName = item.children[0].columnName;
+        data.selectParents = {
+          ...item,
+          columnName,
+          activeIndex: '',
+          children
+        };
+      } else {
+        data.selectParents = {};
+      }
+
+      onSearch();
+    };
+
     onMounted(async () => {
       // console.log('加载');
       // 获取教材分类列表
-      await catchStore.getMusicSheetCategory();
+      // await catchStore.getMusicSheetCategory();
+      await catchStore.getMusicTagTreeApi();
+      _initTags();
+      // console.log(data, 'data');
       // 获取声部列表
       await catchStore.getSubjects();
 
@@ -99,7 +251,22 @@ export default defineComponent({
         // hiddenHeight.value = collapseWrapRef.value.offsetHeight / line.value;
         // 默认隐藏
         getLive();
+
+        // const musicTagTreeList = catchStore.getMusicTagTree;
+        // if (musicTagTreeList.length > 0) {
+        //   forms.bookVersionId = musicTagTreeList[0].id;
+        //   state.gradeList = musicTagTreeList[0].children || [];
+        //   if (state.gradeList.length > 0) {
+        //     forms.grade = state.gradeList[0].id;
+        //     state.musicCategory = state.gradeList[0].children || [];
+        //     if (state.musicCategory.length > 0) {
+        //       forms.musicSheetCategoriesId = state.musicCategory[0].id;
+        //     }
+        //   }
+        // }
       }
+
+      onSearch();
     });
     return () => (
       <div class={styles.searchGroup}>
@@ -116,6 +283,9 @@ export default defineComponent({
                   forms.type = item.value;
                   forms.subjectId = null;
                   state.tempSubjectId = null;
+                  data.tagActiveId = '';
+                  data.childSelectId = null;
+                  data.selectParents = {};
 
                   onSearch();
 
@@ -148,54 +318,35 @@ export default defineComponent({
         </div>
         <NForm labelAlign="left" labelPlacement="left">
           {forms.type === 'MUSIC' && (
-            <div class={[styles.collapsSection]}>
-              <NFormItem label="教材:">
-                <div
-                  class={[
-                    styles.collapseWrap,
-                    loadingCollapse.value ? '' : styles.hideButton,
-                    isCollapse.value ? '' : styles.isHidden
-                  ]}
-                  ref={collapseWrapRef}>
-                  <NSpace class={[styles.spaceSection2]}>
-                    {catchStore.getAllMusicCategories.map((music: any) => (
-                      <NButton
-                        ref={musicCateRef}
-                        secondary={forms.bookVersionId === music.id}
-                        quaternary={forms.bookVersionId !== music.id}
-                        strong
-                        focusable={false}
-                        type={
-                          forms.bookVersionId === music.id
-                            ? 'primary'
-                            : 'default'
-                        }
+            <>
+              {data.tags.length > 0 && (
+                <NFormItem label={data.tags[0]?.columnName + ':'}>
+                  <NSpace class={styles.spaceSection}>
+                    {data.tags.map((subject: any) => (
+                      <span
+                        class={[
+                          styles.textBtn,
+                          data.tagActiveId === subject.id &&
+                            styles.textBtnActive
+                        ]}
                         onClick={() => {
-                          forms.bookVersionId = music.id;
-                          onSearch();
+                          changeTag(subject);
                         }}>
-                        {music.name}
-                      </NButton>
+                        {subject.name}
+                      </span>
                     ))}
-                    {line.value > 1 && (
-                      <div
-                        class={styles.collaoseGroup}
-                        onClick={() => {
-                          setCollapse(!isCollapse.value);
-                        }}>
-                        <NImage
-                          previewDisabled
-                          src={isCollaose}
-                          class={[
-                            styles.collaoseBtn,
-                            isCollapse.value ? styles.isStart : ''
-                          ]}></NImage>
-                      </div>
-                    )}
                   </NSpace>
-                </div>
-              </NFormItem>
-            </div>
+                </NFormItem>
+              )}
+
+              <ChildNodeSearch
+                activeRow={data.selectParents}
+                onSelectChildTag={(val: any) => {
+                  data.childSelectId = val;
+                  onSearch();
+                }}
+              />
+            </>
           )}
 
           <NFormItem label="乐器:">

+ 158 - 155
src/views/natural-resources/model/add-teaching/index.module.less

@@ -1,155 +1,158 @@
-.container {
-  min-height: 100%;
-  display: flex;
-  flex-direction: column;
-
-  :global {
-
-    .n-base-selection--error-status,
-    .n-input--error-status {
-      animation: errorRotate 0.3s ease 3;
-    }
-  }
-}
-
-.closeBtn {
-  position: absolute;
-  top: -15px;
-  right: -10px;
-
-  img {
-    width: 44px;
-    height: 44px;
-  }
-}
-
-.topForms {
-  padding: 40px 40px 0;
-  display: flex;
-  align-items: center;
-
-  :global {
-    .n-upload {
-      width: 210px !important;
-    }
-
-    .n-upload-trigger.n-upload-trigger--image-card {
-      width: 210px !important;
-      height: 297px !important;
-    }
-
-    .n-upload-file.n-upload-file--image-card-type {
-      width: 210px !important;
-      height: 297px !important;
-      border-radius: 12px;
-    }
-
-    .n-upload-dragger {
-      border-radius: 12px;
-      background: #F9FAFD;
-      border: 2px solid #DCE2F1;
-
-      &:hover {
-        border: 2px solid #198CFE;
-      }
-    }
-  }
-
-  .uploadContent {
-    .iconUpload {
-      width: 60px;
-      height: 60px;
-    }
-
-    p {
-      padding-top: 32px;
-      font-size: 18px;
-      color: #9EADD9;
-      line-height: 25px;
-    }
-  }
-
-  .topFormInput {
-    margin-left: 60px;
-  }
-}
-
-.menuTitle {
-  display: flex;
-  align-items: center;
-  padding: 20px 40px;
-  font-size: 18px;
-  font-weight: 600;
-  color: #131415;
-  // border-bottom: 1px solid #EDEEF3;
-
-  .iconMenu {
-    margin-right: 8px;
-    width: 24px;
-    height: 24px;
-  }
-}
-
-.lessonItem {
-  border-radius: 20px;
-  background: #F7F9FF;
-  position: relative;
-  margin: 0 40px 24px;
-  padding: 24px 26px 0;
-  --n-border: 1px solid #289bff !important;
-
-  :global {
-    .n-input {
-      width: 320px;
-    }
-  }
-
-  .btnGroupAll {
-    gap: 8px 24px !important;
-  }
-
-  .btnImg {
-    width: 50px;
-    height: 50px;
-  }
-}
-
-.line {
-  background-color: #EDEEF3;
-  width: calc(100% - 80px);
-  margin: 0 auto;
-  height: 1px;
-}
-
-//
-.addUnitBtn {
-
-  height: 52px;
-  border-radius: 12px;
-  margin: 24px 40px 0;
-
-  width: calc(100% - 80px) !important;
-  background: #E8F4FF;
-
-  &:not(.n-button--disabled):hover,
-  &:not(.n-button--disabled):active,
-  &:not(.n-input--disabled).n-input--focus {
-    background: #E8F4FF;
-  }
-
-  img {
-    width: 16px;
-    height: 16px;
-  }
-}
-
-.btnGroup {
-  padding: 40px 0;
-
-  :global {
-    .n-button {
-      height: 47px;
-      min-width: 156px;
-    }
-  }
-}
+.container {
+  min-height: 100%;
+  display: flex;
+  flex-direction: column;
+
+  :global {
+
+    .n-base-selection--error-status,
+    .n-input--error-status {
+      animation: errorRotate 0.3s ease 3;
+    }
+  }
+}
+
+.closeBtn {
+  position: absolute;
+  top: -15px;
+  right: -10px;
+  background: transparent;
+  width: 44px;
+  height: 44px;
+
+  img {
+    width: 44px;
+    height: 44px;
+  }
+}
+
+.topForms {
+  padding: 40px 40px 0;
+  display: flex;
+  align-items: center;
+
+  :global {
+    .n-upload {
+      width: 210px !important;
+    }
+
+    .n-upload-trigger.n-upload-trigger--image-card {
+      width: 210px !important;
+      height: 297px !important;
+    }
+
+    .n-upload-file.n-upload-file--image-card-type {
+      width: 210px !important;
+      height: 297px !important;
+      border-radius: 12px;
+    }
+
+    .n-upload-dragger {
+      border-radius: 12px;
+      background: #F9FAFD;
+      border: 2px solid #DCE2F1;
+
+      &:hover {
+        border: 2px solid #198CFE;
+      }
+    }
+  }
+
+  .uploadContent {
+    .iconUpload {
+      width: 60px;
+      height: 60px;
+    }
+
+    p {
+      padding-top: 32px;
+      font-size: 18px;
+      color: #9EADD9;
+      line-height: 25px;
+    }
+  }
+
+  .topFormInput {
+    margin-left: 60px;
+  }
+}
+
+.menuTitle {
+  display: flex;
+  align-items: center;
+  padding: 20px 40px;
+  font-size: 18px;
+  font-weight: 600;
+  color: #131415;
+  // border-bottom: 1px solid #EDEEF3;
+
+  .iconMenu {
+    margin-right: 8px;
+    width: 24px;
+    height: 24px;
+  }
+}
+
+.lessonItem {
+  border-radius: 20px;
+  background: #F7F9FF;
+  position: relative;
+  margin: 0 40px 24px;
+  padding: 24px 26px 0;
+  --n-border: 1px solid #289bff !important;
+
+  :global {
+    .n-input {
+      width: 320px;
+    }
+  }
+
+  .btnGroupAll {
+    gap: 8px 24px !important;
+  }
+
+  .btnImg {
+    width: 50px;
+    height: 50px;
+  }
+}
+
+.line {
+  background-color: #EDEEF3;
+  width: calc(100% - 80px);
+  margin: 0 auto;
+  height: 1px;
+}
+
+//
+.addUnitBtn {
+
+  height: 52px;
+  border-radius: 12px;
+  margin: 24px 40px 0;
+
+  width: calc(100% - 80px) !important;
+  background: #E8F4FF;
+
+  &:not(.n-button--disabled):hover,
+  &:not(.n-button--disabled):active,
+  &:not(.n-input--disabled).n-input--focus {
+    background: #E8F4FF;
+  }
+
+  img {
+    width: 16px;
+    height: 16px;
+  }
+}
+
+.btnGroup {
+  padding: 40px 0;
+
+  :global {
+    .n-button {
+      height: 47px;
+      min-width: 156px;
+    }
+  }
+}

+ 471 - 467
src/views/natural-resources/model/add-teaching/index.tsx

@@ -1,467 +1,471 @@
-import {
-  NButton,
-  NCascader,
-  NForm,
-  NFormItem,
-  NInput,
-  NScrollbar,
-  NSelect,
-  NSpace,
-  useMessage
-} from 'naive-ui';
-import {
-  TransitionGroup,
-  defineComponent,
-  onMounted,
-  reactive,
-  ref
-} from 'vue';
-import styles from './index.module.less';
-import UploadFile from '@/components/upload-file';
-import { nextTick } from 'vue';
-import { scrollToErrorForm } from '@/utils';
-import { api_lessonCoursewareSave } from '../../api';
-import iconUpload from '../../images/icon-upload.png';
-import iconUpload2 from '../../images/icon-upload2.png';
-import iconAdd from '../../images/icon-add.png';
-import iconMenu from '../../images/icon-menu.png';
-import btnAdd from '../../images/btn-add.png';
-import btnDelete from '../../images/btn-delete.png';
-import btnUp from '../../images/btn-up.png';
-import btnDown from '../../images/btn-down.png';
-import btnRemove from '../../images/btn-remove.png';
-import { lessonCoursewareDetail } from '/src/views/prepare-lessons/api';
-import { useCatchStore } from '/src/store/modules/catchData';
-export const BOOK_DATA = {
-  grades: [
-    { label: '一年级', value: 1 },
-    { label: '二年级', value: 2 },
-    { label: '三年级', value: 3 },
-    { label: '四年级', value: 4 },
-    { label: '五年级', value: 5 },
-    { label: '六年级', value: 6 },
-    { label: '七年级', value: 7 },
-    { label: '八年级', value: 8 },
-    { label: '九年级', value: 9 }
-  ],
-  bookTypes: [
-    { label: '上册', value: 'LAST' },
-    { label: '下册', value: 'NEXT' }
-  ]
-};
-
-/** 添加单元 */
-const createLesson = () => {
-  return {
-    key: 'item' + Date.now(),
-    name: '', // 单元名称
-    lessonTargetDesc: '', // 课时目标描述
-    knowledgeList: [
-      {
-        key: Date.now() + '' + 0,
-        name: '' // 章节名称
-      }
-    ] // 章节信息
-  };
-};
-const initState = () => ({
-  id: null, // 教材id
-  name: '',
-  currentGradeNum: null as any,
-  instrumentIds: null as any,
-  // bookType: null, // 上下册
-  coverImg: '', // 封面
-  instruemntIds: [] as any,
-  enableFlag: true, // 状态
-  type: 'COURSEWARE', // 教材类型:COURSEWARE,THEORY,可用值:COURSEWARE,THEORY
-  lessonList: [createLesson()] // 单元列表
-});
-
-export default defineComponent({
-  name: 'addNatural',
-  props: {
-    item: {
-      type: Object,
-      default: () => ({})
-    }
-  },
-  emits: ['close', 'confirm'],
-  setup(props, { emit }) {
-    const catchStore = useCatchStore();
-    const message = useMessage();
-    const data = reactive({
-      uploading: false,
-      subjectList: [] as any
-    });
-    const formRef = ref();
-    const form = reactive(initState());
-    const handleSave = () => {
-      formRef.value?.validate((err: any) => {
-        if (err) {
-          nextTick(scrollToErrorForm);
-          return;
-        }
-        handleSubmit();
-      });
-    };
-    const handleSubmit = async () => {
-      data.uploading = true;
-      try {
-        const { currentGradeNum, instrumentIds, ...more } = form;
-        await api_lessonCoursewareSave({
-          currentGradeNum: currentGradeNum.join(','),
-          instrumentIds: instrumentIds.join(','),
-          ...more
-        });
-        Object.assign(form, initState());
-        message.success(props.item.id ? '保存成功' : '添加成功');
-        emit('close', true);
-        emit('confirm');
-      } catch {
-        //
-      }
-      data.uploading = false;
-    };
-
-    onMounted(async () => {
-      await catchStore.getSubjects();
-      if (props.item.id) {
-        const { data } = await lessonCoursewareDetail({ id: props.item.id });
-        form.id = data.id;
-        form.name = data.name;
-        form.currentGradeNum = data.currentGradeNum
-          ? data.currentGradeNum.split(',').map((item: any) => Number(item))
-          : null;
-        form.instrumentIds = data.instrumentIds
-          ? data.instrumentIds.split(',').map((item: any) => item)
-          : null;
-        // form.bookType = data.bookType;
-        form.coverImg = data.coverImg;
-        form.lessonList = [];
-        const lessonList = data.lessonList || [];
-        const tempLesson: any[] = [];
-        lessonList.forEach((item: any) => {
-          const tmpItem: any = {
-            id: item.id,
-            key: 'item' + Date.now() + '-' + Math.random() * 100,
-            name: item.name,
-            lessonTargetDesc: item.lessonTargetDesc,
-            knowledgeList: [] as any
-          };
-
-          if (item.knowledgeList && item.knowledgeList.length) {
-            item.knowledgeList.forEach((knowledge: any) => {
-              tmpItem.knowledgeList.push({
-                id: knowledge.id,
-                key: Date.now() + '-' + Math.random() * 100,
-                name: knowledge.name
-              });
-            });
-          }
-          tempLesson.push(tmpItem);
-        });
-
-        form.lessonList = tempLesson;
-      }
-
-      data.subjectList = catchStore.getEnableSingleAllSubjects(
-        form.instrumentIds
-      );
-    });
-    return () => (
-      <div class={styles.container}>
-        <NScrollbar style={{ 'max-height': '65vh' }}>
-          <NForm
-            ref={formRef}
-            labelPlacement="left"
-            labelWidth={120}
-            model={form}>
-            <div class={styles.topForms}>
-              <NFormItem
-                path="coverImg"
-                rule={[
-                  {
-                    required: true,
-                    message: '请上传教材封面',
-                    trigger: ['change']
-                  }
-                ]}>
-                <UploadFile
-                  cropper
-                  // tips="建议尺寸:210*297, 文件大小: 5MB以内;"
-                  v-model:fileList={form.coverImg}
-                  showType="custom"
-                  size={2}
-                  accept=".jpg,jpeg,.png"
-                  options={{
-                    autoCropWidth: 210,
-                    autoCropHeight: 297,
-                    fixedBox: true
-                  }}>
-                  {{
-                    custom: () => (
-                      <div class={styles.uploadContent}>
-                        <img src={iconUpload2} class={styles.iconUpload} />
-                        <p>请上传教材封面</p>
-                      </div>
-                    )
-                  }}
-                </UploadFile>
-              </NFormItem>
-              <div class={styles.topFormInput}>
-                <NFormItem
-                  style={{ minWidth: '360px' }}
-                  path="name"
-                  rule={[
-                    {
-                      required: true,
-                      message: '请输入教材名称',
-                      trigger: ['blur', 'change']
-                    }
-                  ]}>
-                  <NInput
-                    placeholder="请输入教材名称"
-                    maxlength={25}
-                    v-model:value={form.name}
-                    clearable></NInput>
-                </NFormItem>
-                <NFormItem
-                  path="currentGradeNum"
-                  rule={{
-                    required: true,
-                    message: '请选择年级',
-                    trigger: 'change',
-                    type: 'array'
-                  }}>
-                  <NSelect
-                    style={{ minWidth: '360px' }}
-                    placeholder="请选择年级"
-                    options={BOOK_DATA.grades}
-                    v-model:value={form.currentGradeNum}
-                    clearable
-                    multiple
-                    filterable
-                    maxTagCount={3}
-                  />
-                </NFormItem>
-                <NFormItem
-                  path="instrumentIds"
-                  style={{ width: '360px' }}
-                  rule={{
-                    required: true,
-                    message: '请选择乐器',
-                    trigger: 'change',
-                    type: 'array'
-                  }}>
-                  <NCascader
-                    placeholder="请选择乐器"
-                    options={data.subjectList}
-                    v-model:value={form.instrumentIds}
-                    checkStrategy="child"
-                    showPath={false}
-                    childrenField="instruments"
-                    expandTrigger="hover"
-                    labelField="name"
-                    valueField="id"
-                    clearable
-                    filterable
-                    multiple
-                    maxTagCount="responsive"
-                    style={{ width: '400px' }}
-                  />
-                </NFormItem>
-                {/* <NFormItem
-                  path="bookType"
-                  style={{ width: '360px' }}
-                  rule={{
-                    required: true,
-                    message: '请选择册别',
-                    trigger: 'change'
-                  }}>
-                  <NSelect
-                    placeholder="请选择册别"
-                    options={BOOK_DATA.bookTypes}
-                    v-model:value={form.bookType}
-                    clearable
-                  />
-                </NFormItem> */}
-              </div>
-            </div>
-
-            <div class={styles.menuTitle}>
-              <img src={iconMenu} class={styles.iconMenu} />
-              目录
-            </div>
-            <TransitionGroup name="list" tag="div">
-              {form.lessonList.map((item, index) => {
-                return (
-                  <NSpace
-                    class={styles.lessonItem}
-                    wrap={false}
-                    wrapItem={false}
-                    align="start"
-                    key={item.key}>
-                    <NFormItem
-                      label="单元名称"
-                      labelPlacement="top"
-                      path={`lessonList[${index}].name`}
-                      rule={{
-                        required: true,
-                        message: '填写单元名称',
-                        trigger: ['blur', 'change']
-                      }}>
-                      <NInput
-                        placeholder="填写单元名称"
-                        maxlength={25}
-                        v-model:value={item.name}
-                        clearable></NInput>
-                    </NFormItem>
-                    <TransitionGroup name="list" tag="div">
-                      {item.knowledgeList.map((know, knowIndex) => {
-                        return (
-                          <NFormItem
-                            style={{
-                              '--n-label-height': knowIndex === 0 ? '26px' : '0'
-                            }}
-                            labelPlacement="top"
-                            label={knowIndex === 0 ? '章节名称' : ''}
-                            key={know.key}
-                            path={`lessonList[${index}].knowledgeList[${knowIndex}].name`}
-                            rule={{
-                              required: true,
-                              message: '填写章节名称',
-                              trigger: ['blur', 'change']
-                            }}>
-                            <NSpace
-                              wrap={false}
-                              align="center"
-                              class={styles.btnGroupAll}
-                              wrapItem={false}>
-                              <NInput
-                                maxlength={25}
-                                placeholder="填写章节名称"
-                                v-model:value={know.name}
-                                clearable></NInput>
-                              <NButton
-                                quaternary
-                                circle
-                                onClick={() => {
-                                  item.knowledgeList.splice(knowIndex + 1, 0, {
-                                    name: '',
-                                    key: Date.now() + '' + knowIndex
-                                  });
-                                }}>
-                                {{
-                                  icon: () => (
-                                    <img src={btnAdd} class={styles.btnImg} />
-                                  )
-                                }}
-                              </NButton>
-                              <NButton
-                                quaternary
-                                circle
-                                disabled={item.knowledgeList.length < 2}
-                                onClick={() => {
-                                  item.knowledgeList.splice(knowIndex, 1);
-                                }}>
-                                {{
-                                  icon: () => (
-                                    <img
-                                      src={btnDelete}
-                                      class={styles.btnImg}
-                                    />
-                                  )
-                                }}
-                              </NButton>
-                              <NButton
-                                quaternary
-                                circle
-                                disabled={knowIndex === 0}
-                                onClick={() => {
-                                  if (knowIndex === 0) return;
-                                  const tmp = item.knowledgeList[knowIndex - 1];
-                                  item.knowledgeList[knowIndex - 1] =
-                                    item.knowledgeList[knowIndex];
-                                  item.knowledgeList[knowIndex] = tmp;
-                                }}>
-                                {{
-                                  icon: () => (
-                                    <img src={btnUp} class={styles.btnImg} />
-                                  )
-                                }}
-                              </NButton>
-                              <NButton
-                                quaternary
-                                circle
-                                disabled={
-                                  knowIndex === item.knowledgeList.length - 1
-                                }
-                                onClick={() => {
-                                  if (
-                                    knowIndex ===
-                                    item.knowledgeList.length - 1
-                                  )
-                                    return;
-                                  const tmp = item.knowledgeList[knowIndex + 1];
-                                  item.knowledgeList[knowIndex + 1] =
-                                    item.knowledgeList[knowIndex];
-                                  item.knowledgeList[knowIndex] = tmp;
-                                }}>
-                                {{
-                                  icon: () => (
-                                    <img src={btnDown} class={styles.btnImg} />
-                                  )
-                                }}
-                              </NButton>
-                            </NSpace>
-                          </NFormItem>
-                        );
-                      })}
-                    </TransitionGroup>
-                    <NButton
-                      class={styles.closeBtn}
-                      secondary
-                      circle
-                      size="small"
-                      disabled={form.lessonList.length < 2}
-                      onClick={() => {
-                        form.lessonList.splice(index, 1);
-                      }}>
-                      <img src={btnRemove} />
-                    </NButton>
-                  </NSpace>
-                );
-              })}
-            </TransitionGroup>
-            <div class={styles.line}></div>
-            <NButton
-              block
-              class={styles.addUnitBtn}
-              ghost
-              color="#198CFE"
-              onClick={() => {
-                form.lessonList.push(createLesson());
-              }}>
-              {{
-                icon: () => <img src={iconAdd} />,
-                default: () => '新增单元'
-              }}
-            </NButton>
-          </NForm>
-        </NScrollbar>
-        <NSpace class={styles.btnGroup} justify="center">
-          <NButton round onClick={() => emit('close')}>
-            取消
-          </NButton>
-          <NButton
-            round
-            loading={data.uploading}
-            type="primary"
-            onClick={() => handleSave()}>
-            保存
-          </NButton>
-        </NSpace>
-      </div>
-    );
-  }
-});
+import {
+  NButton,
+  NCascader,
+  NForm,
+  NFormItem,
+  NInput,
+  NScrollbar,
+  NSelect,
+  NSpace,
+  useMessage
+} from 'naive-ui';
+import {
+  TransitionGroup,
+  defineComponent,
+  onMounted,
+  reactive,
+  ref
+} from 'vue';
+import styles from './index.module.less';
+import UploadFile from '@/components/upload-file';
+import { nextTick } from 'vue';
+import { scrollToErrorForm } from '@/utils';
+import { api_lessonCoursewareSave } from '../../api';
+import iconUpload from '../../images/icon-upload.png';
+import iconUpload2 from '../../images/icon-upload2.png';
+import iconAdd from '../../images/icon-add.png';
+import iconMenu from '../../images/icon-menu.png';
+import btnAdd from '../../images/btn-add.png';
+import btnDelete from '../../images/btn-delete.png';
+import btnUp from '../../images/btn-up.png';
+import btnDown from '../../images/btn-down.png';
+import btnRemove from '../../images/btn-remove.png';
+import { lessonCoursewareDetail } from '/src/views/prepare-lessons/api';
+import { useCatchStore } from '/src/store/modules/catchData';
+export const BOOK_DATA = {
+  grades: [
+    { label: '一年级', value: 1 },
+    { label: '二年级', value: 2 },
+    { label: '三年级', value: 3 },
+    { label: '四年级', value: 4 },
+    { label: '五年级', value: 5 },
+    { label: '六年级', value: 6 },
+    { label: '七年级', value: 7 },
+    { label: '八年级', value: 8 },
+    { label: '九年级', value: 9 }
+  ],
+  bookTypes: [
+    { label: '上册', value: 'LAST' },
+    { label: '下册', value: 'NEXT' }
+  ]
+};
+
+/** 添加单元 */
+const createLesson = () => {
+  return {
+    key: 'item' + Date.now(),
+    name: '', // 单元名称
+    lessonTargetDesc: '', // 课时目标描述
+    knowledgeList: [
+      {
+        key: Date.now() + '' + 0,
+        name: '' // 章节名称
+      }
+    ] // 章节信息
+  };
+};
+const initState = () => ({
+  id: null, // 教材id
+  name: '',
+  currentGradeNum: null as any,
+  instrumentIds: null as any,
+  // bookType: null, // 上下册
+  coverImg: '', // 封面
+  instruemntIds: [] as any,
+  enableFlag: true, // 状态
+  type: 'COURSEWARE', // 教材类型:COURSEWARE,THEORY,可用值:COURSEWARE,THEORY
+  lessonList: [] as any // 单元列表
+});
+
+export default defineComponent({
+  name: 'addNatural',
+  props: {
+    item: {
+      type: Object,
+      default: () => ({})
+    }
+  },
+  emits: ['close', 'confirm'],
+  setup(props, { emit }) {
+    const catchStore = useCatchStore();
+    const message = useMessage();
+    const data = reactive({
+      uploading: false,
+      subjectList: [] as any
+    });
+    const formRef = ref();
+    const form = reactive(initState());
+    const handleSave = () => {
+      formRef.value?.validate((err: any) => {
+        if (err) {
+          nextTick(scrollToErrorForm);
+          return;
+        }
+        handleSubmit();
+      });
+    };
+    const handleSubmit = async () => {
+      data.uploading = true;
+      try {
+        const { currentGradeNum, instrumentIds, ...more } = form;
+        await api_lessonCoursewareSave({
+          currentGradeNum: currentGradeNum.join(','),
+          instrumentIds: instrumentIds.join(','),
+          ...more
+        });
+        Object.assign(form, initState());
+        message.success(props.item.id ? '保存成功' : '添加成功');
+        emit('close', true);
+        emit('confirm');
+      } catch {
+        //
+      }
+      data.uploading = false;
+    };
+
+    onMounted(async () => {
+      if (!props.item.id) {
+        form.lessonList = [createLesson()];
+      }
+      await catchStore.getSubjects();
+      if (props.item.id) {
+        // form.lessonList = [];
+        const { data } = await lessonCoursewareDetail({ id: props.item.id });
+        form.id = data.id;
+        form.name = data.name;
+        form.currentGradeNum = data.currentGradeNum
+          ? data.currentGradeNum.split(',').map((item: any) => Number(item))
+          : null;
+        form.instrumentIds = data.instrumentIds
+          ? data.instrumentIds.split(',').map((item: any) => item)
+          : null;
+        // form.bookType = data.bookType;
+        form.coverImg = data.coverImg;
+        form.lessonList = [];
+        const lessonList = data.lessonList || [];
+        const tempLesson: any[] = [];
+        lessonList.forEach((item: any) => {
+          const tmpItem: any = {
+            id: item.id,
+            key: 'item' + Date.now() + '-' + Math.random() * 100,
+            name: item.name,
+            lessonTargetDesc: item.lessonTargetDesc,
+            knowledgeList: [] as any
+          };
+
+          if (item.knowledgeList && item.knowledgeList.length) {
+            item.knowledgeList.forEach((knowledge: any) => {
+              tmpItem.knowledgeList.push({
+                id: knowledge.id,
+                key: Date.now() + '-' + Math.random() * 100,
+                name: knowledge.name
+              });
+            });
+          }
+          tempLesson.push(tmpItem);
+        });
+
+        form.lessonList = tempLesson;
+      }
+
+      data.subjectList = catchStore.getEnableSingleAllSubjects(
+        form.instrumentIds
+      );
+    });
+    return () => (
+      <div class={styles.container}>
+        <NScrollbar style={{ 'max-height': '65vh' }}>
+          <NForm
+            ref={formRef}
+            labelPlacement="left"
+            labelWidth={120}
+            model={form}>
+            <div class={styles.topForms}>
+              <NFormItem
+                path="coverImg"
+                rule={[
+                  {
+                    required: true,
+                    message: '请上传教材封面',
+                    trigger: ['change']
+                  }
+                ]}>
+                <UploadFile
+                  cropper
+                  // tips="建议尺寸:210*297, 文件大小: 5MB以内;"
+                  v-model:fileList={form.coverImg}
+                  showType="custom"
+                  size={2}
+                  accept=".jpg,jpeg,.png"
+                  options={{
+                    autoCropWidth: 210,
+                    autoCropHeight: 297,
+                    fixedBox: true
+                  }}>
+                  {{
+                    custom: () => (
+                      <div class={styles.uploadContent}>
+                        <img src={iconUpload2} class={styles.iconUpload} />
+                        <p>请上传教材封面</p>
+                      </div>
+                    )
+                  }}
+                </UploadFile>
+              </NFormItem>
+              <div class={styles.topFormInput}>
+                <NFormItem
+                  style={{ minWidth: '360px' }}
+                  path="name"
+                  rule={[
+                    {
+                      required: true,
+                      message: '请输入教材名称',
+                      trigger: ['blur', 'change']
+                    }
+                  ]}>
+                  <NInput
+                    placeholder="请输入教材名称"
+                    maxlength={25}
+                    v-model:value={form.name}
+                    clearable></NInput>
+                </NFormItem>
+                <NFormItem
+                  path="currentGradeNum"
+                  rule={{
+                    required: true,
+                    message: '请选择年级',
+                    trigger: 'change',
+                    type: 'array'
+                  }}>
+                  <NSelect
+                    style={{ minWidth: '360px' }}
+                    placeholder="请选择年级"
+                    options={BOOK_DATA.grades}
+                    v-model:value={form.currentGradeNum}
+                    clearable
+                    multiple
+                    filterable
+                    maxTagCount={3}
+                  />
+                </NFormItem>
+                <NFormItem
+                  path="instrumentIds"
+                  style={{ width: '360px' }}
+                  rule={{
+                    required: true,
+                    message: '请选择乐器',
+                    trigger: 'change',
+                    type: 'array'
+                  }}>
+                  <NCascader
+                    placeholder="请选择乐器"
+                    options={data.subjectList}
+                    v-model:value={form.instrumentIds}
+                    checkStrategy="child"
+                    showPath={false}
+                    childrenField="instruments"
+                    expandTrigger="hover"
+                    labelField="name"
+                    valueField="id"
+                    clearable
+                    filterable
+                    multiple
+                    maxTagCount="responsive"
+                    style={{ width: '400px' }}
+                  />
+                </NFormItem>
+                {/* <NFormItem
+                  path="bookType"
+                  style={{ width: '360px' }}
+                  rule={{
+                    required: true,
+                    message: '请选择册别',
+                    trigger: 'change'
+                  }}>
+                  <NSelect
+                    placeholder="请选择册别"
+                    options={BOOK_DATA.bookTypes}
+                    v-model:value={form.bookType}
+                    clearable
+                  />
+                </NFormItem> */}
+              </div>
+            </div>
+
+            <div class={styles.menuTitle}>
+              <img src={iconMenu} class={styles.iconMenu} />
+              目录
+            </div>
+            <TransitionGroup name="list" tag="div">
+              {form.lessonList.map((item, index) => {
+                return (
+                  <NSpace
+                    class={styles.lessonItem}
+                    wrap={false}
+                    wrapItem={false}
+                    align="start"
+                    key={item.key}>
+                    <NFormItem
+                      label="单元名称"
+                      labelPlacement="top"
+                      path={`lessonList[${index}].name`}
+                      rule={{
+                        required: true,
+                        message: '填写单元名称',
+                        trigger: ['blur', 'change']
+                      }}>
+                      <NInput
+                        placeholder="填写单元名称"
+                        maxlength={25}
+                        v-model:value={item.name}
+                        clearable></NInput>
+                    </NFormItem>
+                    <TransitionGroup name="list" tag="div">
+                      {item.knowledgeList.map((know, knowIndex) => {
+                        return (
+                          <NFormItem
+                            style={{
+                              '--n-label-height': knowIndex === 0 ? '26px' : '0'
+                            }}
+                            labelPlacement="top"
+                            label={knowIndex === 0 ? '章节名称' : ''}
+                            key={know.key}
+                            path={`lessonList[${index}].knowledgeList[${knowIndex}].name`}
+                            rule={{
+                              required: true,
+                              message: '填写章节名称',
+                              trigger: ['blur', 'change']
+                            }}>
+                            <NSpace
+                              wrap={false}
+                              align="center"
+                              class={styles.btnGroupAll}
+                              wrapItem={false}>
+                              <NInput
+                                maxlength={25}
+                                placeholder="填写章节名称"
+                                v-model:value={know.name}
+                                clearable></NInput>
+                              <NButton
+                                quaternary
+                                circle
+                                onClick={() => {
+                                  item.knowledgeList.splice(knowIndex + 1, 0, {
+                                    name: '',
+                                    key: Date.now() + '' + knowIndex
+                                  });
+                                }}>
+                                {{
+                                  icon: () => (
+                                    <img src={btnAdd} class={styles.btnImg} />
+                                  )
+                                }}
+                              </NButton>
+                              <NButton
+                                quaternary
+                                circle
+                                disabled={item.knowledgeList.length < 2}
+                                onClick={() => {
+                                  item.knowledgeList.splice(knowIndex, 1);
+                                }}>
+                                {{
+                                  icon: () => (
+                                    <img
+                                      src={btnDelete}
+                                      class={styles.btnImg}
+                                    />
+                                  )
+                                }}
+                              </NButton>
+                              <NButton
+                                quaternary
+                                circle
+                                disabled={knowIndex === 0}
+                                onClick={() => {
+                                  if (knowIndex === 0) return;
+                                  const tmp = item.knowledgeList[knowIndex - 1];
+                                  item.knowledgeList[knowIndex - 1] =
+                                    item.knowledgeList[knowIndex];
+                                  item.knowledgeList[knowIndex] = tmp;
+                                }}>
+                                {{
+                                  icon: () => (
+                                    <img src={btnUp} class={styles.btnImg} />
+                                  )
+                                }}
+                              </NButton>
+                              <NButton
+                                quaternary
+                                circle
+                                disabled={
+                                  knowIndex === item.knowledgeList.length - 1
+                                }
+                                onClick={() => {
+                                  if (
+                                    knowIndex ===
+                                    item.knowledgeList.length - 1
+                                  )
+                                    return;
+                                  const tmp = item.knowledgeList[knowIndex + 1];
+                                  item.knowledgeList[knowIndex + 1] =
+                                    item.knowledgeList[knowIndex];
+                                  item.knowledgeList[knowIndex] = tmp;
+                                }}>
+                                {{
+                                  icon: () => (
+                                    <img src={btnDown} class={styles.btnImg} />
+                                  )
+                                }}
+                              </NButton>
+                            </NSpace>
+                          </NFormItem>
+                        );
+                      })}
+                    </TransitionGroup>
+                    <NButton
+                      class={styles.closeBtn}
+                      secondary
+                      circle
+                      size="small"
+                      disabled={form.lessonList.length < 2}
+                      onClick={() => {
+                        form.lessonList.splice(index, 1);
+                      }}>
+                      <img src={btnRemove} />
+                    </NButton>
+                  </NSpace>
+                );
+              })}
+            </TransitionGroup>
+            <div class={styles.line}></div>
+            <NButton
+              block
+              class={styles.addUnitBtn}
+              ghost
+              color="#198CFE"
+              onClick={() => {
+                form.lessonList.push(createLesson());
+              }}>
+              {{
+                icon: () => <img src={iconAdd} />,
+                default: () => '新增单元'
+              }}
+            </NButton>
+          </NForm>
+        </NScrollbar>
+        <NSpace class={styles.btnGroup} justify="center">
+          <NButton round onClick={() => emit('close')}>
+            取消
+          </NButton>
+          <NButton
+            round
+            loading={data.uploading}
+            type="primary"
+            onClick={() => handleSave()}>
+            保存
+          </NButton>
+        </NSpace>
+      </div>
+    );
+  }
+});

+ 1 - 0
src/views/prepare-lessons/components/lesson-main/courseware-presets/index.module.less

@@ -379,6 +379,7 @@
 
   .resourceMain {
     flex: 0 0 360px;
+    width: 360px;
     height: 75vh;
     box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
   }

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

@@ -18,10 +18,13 @@ export default defineComponent({
   },
   setup(props, { emit }) {
     const catchStore = useCatchStore();
+    const musics = ref([] as any);
     const forms = reactive({
       type: 'MUSIC', //
       name: '',
-      bookVersionId: null,
+      // grade: null as any,
+      bookVersionId: null as any,
+      // musicSheetCategoriesId: null,
       musicalInstrumentId: ''
     });
     const resourceType = ref([] as any);
@@ -32,17 +35,29 @@ export default defineComponent({
 
     const debouncedRequest = useThrottleFn(() => onSearch(), 500);
 
+    // const formatParentId = (id: any, list: any, ids = [] as any) => {
+    //   for (const item of list) {
+    //     if (item.children && item.children.length > 0) {
+    //       const cIds: any = formatParentId(id, item.children, [
+    //         ...ids,
+    //         item.id
+    //       ]);
+    //       if (cIds.includes(id)) {
+    //         return cIds;
+    //       }
+    //     }
+    //     if (item.id === id) {
+    //       return [...ids, id];
+    //     }
+    //   }
+    //   return ids;
+    // };
     onMounted(async () => {
-      await catchStore.getMusicSheetCategory();
+      // await catchStore.getMusicSheetCategory();
+      await catchStore.getMusicTagTreeApi();
       // 获取教材分类列表
       await catchStore.getSubjects();
-      // if (props.type === 'myCollect') {
-      //   resourceType.value.push({
-      //     label: '全部',
-      //     value: ''
-      //   });
-      //   forms.type = ''; // 默认全部
-      // }
+
       resourceTypeArray.forEach((item: any) => {
         // if (props.type === 'myResources') {
         //   item.value !== 'MUSIC' && resourceType.value.push(item);
@@ -94,17 +109,31 @@ export default defineComponent({
           </div>
           {forms.type === 'MUSIC' && props.type === 'shareResources' && (
             <div class={styles.searchSelect}>
-              <NSelect
+              <NCascader
                 placeholder="全部教材"
                 options={[
-                  { name: '全部教材', id: null },
-                  ...catchStore.getMusicCategories
+                  { id: '', name: '全部教材' },
+                  ...catchStore.getMusicTagTree
                 ]}
                 clearable
-                labelField="name"
+                style={{ width: '100%' }}
+                childrenField="children"
                 valueField="id"
-                v-model:value={forms.bookVersionId}
-                onUpdate:value={() => {
+                labelField="name"
+                checkStrategy="child"
+                expandTrigger="hover"
+                showPath
+                v-model:value={musics.value}
+                onUpdate:value={(value: any) => {
+                  // onSearch();
+                  // const selectValue = formatParentId(value, [
+                  //   { id: '', name: '全部教材' },
+                  //   ...catchStore.getMusicTagTree
+                  // ]);
+
+                  forms.bookVersionId = value || '';
+                  // forms.grade = selectValue[1] || '';
+                  // forms.musicSheetCategoriesId = selectValue[2] || null;
                   onSearch();
                 }}
               />

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

@@ -1,101 +1,151 @@
-import { PropType, defineComponent, onMounted, reactive } from 'vue';
-import styles from './index.module.less';
-import { NButton, NCascader, NInput, NSelect, NSpace } from 'naive-ui';
-import { useCatchStore } from '/src/store/modules/catchData';
-import { useThrottleFn } from '@vueuse/core';
-
-export default defineComponent({
-  name: 'resource-search-group',
-  props: {
-    type: {
-      type: String as PropType<'myMusic' | 'sahreMusic' | 'collectMusic'>,
-      default: 'myMusic'
-    }
-  },
-  emits: ['search'],
-  setup(props, { emit }) {
-    const catchStore = useCatchStore();
-    const forms = reactive({
-      name: '',
-      musicSheetCategoriesId: null,
-      musicalInstrumentId: null
-    });
-
-    const onSearch = () => {
-      emit('search', forms);
-    };
-
-    const throttledFn = useThrottleFn(() => onSearch(), 500);
-
-    onMounted(async () => {
-      // 获取教材分类列表
-      await catchStore.getMusicSheetCategory();
-      // 获取声部列表
-      await catchStore.getSubjects();
-    });
-    return () => (
-      <>
-        <div class={styles.searchGroup}>
-          {props.type !== 'myMusic' && (
-            <div class={styles.searchSelect}>
-              <NSelect
-                placeholder="全部教材"
-                options={[
-                  { name: '全部教材', id: null },
-                  ...catchStore.getMusicCategories
-                ]}
-                clearable
-                labelField="name"
-                valueField="id"
-                v-model:value={forms.musicSheetCategoriesId}
-                onUpdate:value={() => {
-                  onSearch();
-                }}
-              />
-            </div>
-          )}
-
-          <div class={styles.searchSelect}>
-            <NCascader
-              placeholder="全部乐器"
-              v-model:value={forms.musicalInstrumentId}
-              options={[...catchStore.getSubjectList]}
-              checkStrategy="child"
-              showPath={false}
-              childrenField="instruments"
-              expandTrigger="hover"
-              clearable
-              filterable
-              onUpdate:value={() => {
-                onSearch();
-              }}
-            />
-          </div>
-          <NInput
-            type="text"
-            placeholder="请输入搜索关键词"
-            clearable
-            v-model:value={forms.name}
-            class={styles.inputSearch}
-            onKeyup={(e: KeyboardEvent) => {
-              if (e.code === 'Enter') {
-                throttledFn();
-              }
-            }}
-            onClear={() => {
-              forms.name = '';
-              throttledFn();
-            }}>
-            {{
-              prefix: () => (
-                <span
-                  class={'icon-search-input'}
-                  onClick={() => throttledFn()}></span>
-              )
-            }}
-          </NInput>
-        </div>
-      </>
-    );
-  }
-});
+import { PropType, defineComponent, onMounted, reactive, ref } from 'vue';
+import styles from './index.module.less';
+import { NButton, NCascader, NInput, NSelect, NSpace } from 'naive-ui';
+import { useCatchStore } from '/src/store/modules/catchData';
+import { useThrottleFn } from '@vueuse/core';
+
+export default defineComponent({
+  name: 'resource-search-group',
+  props: {
+    type: {
+      type: String as PropType<'myMusic' | 'sahreMusic' | 'collectMusic'>,
+      default: 'myMusic'
+    }
+  },
+  emits: ['search'],
+  setup(props, { emit }) {
+    const catchStore = useCatchStore();
+    const musics = ref([] as any);
+    const forms = reactive({
+      name: '',
+      // grade: null as any,
+      bookVersionId: null as any,
+      // musicSheetCategoriesId: null,
+      musicalInstrumentId: null
+    });
+
+    const onSearch = () => {
+      emit('search', forms);
+    };
+
+    const throttledFn = useThrottleFn(() => onSearch(), 500);
+
+    // const formatParentId = (id: any, list: any, ids = [] as any) => {
+    //   for (const item of list) {
+    //     if (item.children && item.children.length > 0) {
+    //       const cIds: any = formatParentId(id, item.children, [
+    //         ...ids,
+    //         item.id
+    //       ]);
+    //       if (cIds.includes(id)) {
+    //         return cIds;
+    //       }
+    //     }
+    //     if (item.id === id) {
+    //       return [...ids, id];
+    //     }
+    //   }
+    //   return ids;
+    // };
+
+    onMounted(async () => {
+      // 获取教材分类列表
+      // await catchStore.getMusicSheetCategory();
+      await catchStore.getMusicTagTreeApi();
+      // 获取声部列表
+      await catchStore.getSubjects();
+    });
+    return () => (
+      <>
+        <div class={styles.searchGroup}>
+          {props.type !== 'myMusic' && (
+            <div class={styles.searchSelect}>
+              {/* <NSelect
+                placeholder="全部教材"
+                options={[
+                  { name: '全部教材', id: null },
+                  ...catchStore.getMusicCategories
+                ]}
+                clearable
+                labelField="name"
+                valueField="id"
+                v-model:value={forms.musicSheetCategoriesId}
+                onUpdate:value={() => {
+                  onSearch();
+                }}
+              /> */}
+              <NCascader
+                placeholder="全部教材"
+                options={[
+                  { id: '', name: '全部教材' },
+                  ...catchStore.getMusicTagTree
+                ]}
+                clearable
+                style={{ width: '100%' }}
+                childrenField="children"
+                valueField="id"
+                labelField="name"
+                checkStrategy="child"
+                expandTrigger="hover"
+                showPath
+                v-model:value={musics.value}
+                onUpdate:value={(value: any) => {
+                  // onSearch();
+                  // const selectValue = formatParentId(value, [
+                  //   { id: '', name: '全部教材' },
+                  //   ...catchStore.getMusicTagTree
+                  // ]);
+
+                  forms.bookVersionId = value || '';
+                  // forms.grade = selectValue[1] || '';
+                  // forms.musicSheetCategoriesId = selectValue[2] || null;
+                  onSearch();
+                }}
+              />
+            </div>
+          )}
+
+          <div class={styles.searchSelect}>
+            <NCascader
+              placeholder="全部乐器"
+              v-model:value={forms.musicalInstrumentId}
+              options={[...catchStore.getSubjectList]}
+              checkStrategy="child"
+              showPath={false}
+              childrenField="instruments"
+              expandTrigger="hover"
+              clearable
+              filterable
+              onUpdate:value={() => {
+                onSearch();
+              }}
+            />
+          </div>
+          <NInput
+            type="text"
+            placeholder="请输入搜索关键词"
+            clearable
+            v-model:value={forms.name}
+            class={styles.inputSearch}
+            onKeyup={(e: KeyboardEvent) => {
+              if (e.code === 'Enter') {
+                throttledFn();
+              }
+            }}
+            onClear={() => {
+              forms.name = '';
+              throttledFn();
+            }}>
+            {{
+              prefix: () => (
+                <span
+                  class={'icon-search-input'}
+                  onClick={() => throttledFn()}></span>
+              )
+            }}
+          </NInput>
+        </div>
+      </>
+    );
+  }
+});

+ 82 - 76
src/views/prepare-lessons/index.module.less

@@ -1,77 +1,83 @@
-.prepareLessons {
-  display: flex;
-  // padding: 32px;
-  // padding-bottom: 32px;
-  height: calc(100vh - 118px);
-  overflow: hidden;
-  border-radius: 20px;
-
-  .directoryMain,
-  .resourceMain {
-    flex: 0 0 360px;
-    background-color: #fff;
-    border-radius: 20px;
-  }
-
-
-  .directoryMain {
-    margin-right: 20px;
-  }
-
-
-  .lessonMain {
-    margin: 0 20px 0 0;
-    flex: 1;
-    // background-color: #fff;
-    border-radius: 20px;
-    transition: all .2s ease;
-  }
-
-  .resourceMain {
-
-    transition: all .2s ease;
-
-    &.resourceClose {
-      transition: all .2s ease;
-      width: 0;
-      transform: translateX(100%);
-      opacity: 0;
-    }
-  }
-
-  &.showSideBar {
-    .directoryMain {
-      width: 360px;
-      transition: all .2s ease;
-      opacity: 0;
-      position: absolute;
-      right: 0;
-      transform: translateX(100%);
-    }
-
-    .lessonMain {
-      transition: all .2s ease;
-      margin-left: 0;
-    }
-  }
-
-  &.hideSideBar {
-    position: relative;
-    overflow: hidden;
-
-    .resourceMain {
-      width: 360px;
-      transition: all .2s ease;
-      opacity: 0;
-      position: absolute;
-      right: 0;
-      transform: translateX(100%);
-    }
-
-
-    .lessonMain {
-      transition: all .2s ease;
-      margin-right: 0;
-    }
-  }
+.prepareLessons {
+  display: flex;
+  // padding: 32px;
+  // padding-bottom: 32px;
+  height: calc(100vh - 118px);
+  overflow: hidden;
+  border-radius: 20px;
+
+  .directoryMain,
+  .resourceMain {
+    flex: 0 0 360px;
+    width: 360px;
+    background-color: #fff;
+    border-radius: 20px;
+  }
+
+  .resourceMain {
+    flex: 0 0 400px;
+    width: 400px;
+  }
+
+
+  .directoryMain {
+    margin-right: 20px;
+  }
+
+
+  .lessonMain {
+    margin: 0 20px 0 0;
+    flex: 1;
+    // background-color: #fff;
+    border-radius: 20px;
+    transition: all .2s ease;
+  }
+
+  .resourceMain {
+
+    transition: all .2s ease;
+
+    &.resourceClose {
+      transition: all .2s ease;
+      width: 0;
+      transform: translateX(100%);
+      opacity: 0;
+    }
+  }
+
+  &.showSideBar {
+    .directoryMain {
+      width: 360px;
+      transition: all .2s ease;
+      opacity: 0;
+      position: absolute;
+      right: 0;
+      transform: translateX(100%);
+    }
+
+    .lessonMain {
+      transition: all .2s ease;
+      margin-left: 0;
+    }
+  }
+
+  &.hideSideBar {
+    position: relative;
+    overflow: hidden;
+
+    .resourceMain {
+      width: 360px;
+      transition: all .2s ease;
+      opacity: 0;
+      position: absolute;
+      right: 0;
+      transform: translateX(100%);
+    }
+
+
+    .lessonMain {
+      transition: all .2s ease;
+      margin-right: 0;
+    }
+  }
 }

+ 1 - 1
src/views/prepare-lessons/model/select-music/select-item/index.module.less

@@ -208,7 +208,7 @@
     line-height: var(--n-blank-height);
 
     &:last-child {
-      margin-left: -12Px;
+      // margin-left: -12Px;
     }
   }
 }

+ 11 - 2
src/views/prepare-lessons/model/select-music/select-item/index.tsx

@@ -114,11 +114,14 @@ export default defineComponent({
     //   }
     // );
 
-    const throttledFnSearch = useDebounceFn(item => {
+    const onSearch = (item: any) => {
       state.pagination.page = 1;
       state.tableList = [];
       state.searchGroup = Object.assign(state.searchGroup, item);
       getList();
+    };
+    const throttledFnSearch = useDebounceFn(item => {
+      onSearch(item);
     }, 500);
 
     const throttledFn = useThrottleFn(() => {
@@ -159,7 +162,13 @@ export default defineComponent({
         <div class={className}>
           <SearchGroup
             type={props.type}
-            onSearch={(item: any) => throttledFnSearch(item)}
+            onSearch={(item: any, type: any) => {
+              if (type) {
+                onSearch(item);
+                return;
+              }
+              throttledFnSearch(item);
+            }}
           />
         </div>
 

+ 259 - 48
src/views/prepare-lessons/model/select-music/select-item/search-group.tsx

@@ -1,4 +1,4 @@
-import { defineComponent, reactive, onMounted, ref } from 'vue';
+import { defineComponent, reactive, onMounted, ref, toRefs, watch } from 'vue';
 import styles from './index.module.less';
 import {
   NButton,
@@ -13,6 +13,88 @@ import { useCatchStore } from '/src/store/modules/catchData';
 import { useThrottleFn } from '@vueuse/core';
 import isCollaose from '/src/views/natural-resources/images/isCollaose.png';
 
+const ChildNodeSearch = defineComponent({
+  name: 'ChildNodeSearch',
+  props: {
+    activeRow: {
+      type: Object,
+      default: () => ({})
+    },
+    list: {
+      type: Array,
+      default: () => []
+    }
+  },
+  emits: ['selectChildTag'],
+  setup(props, { emit }) {
+    const { activeRow } = toRefs(props);
+    const selectItem = ref({});
+
+    watch(
+      () => props.activeRow,
+      () => {
+        activeRow.value = props.activeRow;
+        selectItem.value = {};
+      }
+    );
+    return () => (
+      <>
+        {activeRow.value?.id && (
+          <>
+            <NFormItem label={activeRow.value.columnName + ':'}>
+              <NSpace class={styles.spaceSection2}>
+                {activeRow.value?.children.map((subject: any) => (
+                  <span
+                    class={[
+                      styles.textBtn,
+                      (activeRow.value.activeIndex || '') == subject.id &&
+                        styles.textBtnActive
+                    ]}
+                    onClick={() => {
+                      activeRow.value.activeIndex = subject.id;
+                      let children: any;
+                      let columnName = '';
+                      if (subject.children) {
+                        children = [
+                          {
+                            columnName: subject.children[0].columnName,
+                            name: '全部',
+                            id: ''
+                          },
+                          ...subject.children
+                        ];
+                        columnName = subject.children[0].columnName;
+
+                        selectItem.value = {
+                          ...subject,
+                          columnName,
+                          activeIndex: '',
+                          children
+                        };
+                      } else {
+                        selectItem.value = {};
+                      }
+                      emit('selectChildTag', activeRow.value.activeIndex);
+                    }}>
+                    {subject.name}
+                  </span>
+                ))}
+              </NSpace>
+            </NFormItem>
+
+            <ChildNodeSearch
+              activeRow={selectItem.value}
+              onSelectChildTag={(item: any) => {
+                emit('selectChildTag', item || activeRow.value.activeIndex);
+              }}
+            />
+          </>
+        )}
+      </>
+    );
+  }
+});
+
 export default defineComponent({
   name: 'search-group',
   props: {
@@ -26,16 +108,34 @@ export default defineComponent({
     const catchStore = useCatchStore();
     const forms = reactive({
       name: '',
-      musicSheetCategoriesId: null,
+      // grade: null as any,
+      bookVersionId: null as any,
+      // musicSheetCategoriesId: null as any,
       musicalInstrumentId: null
     });
 
     const state = reactive({
-      tempSubjectId: null
+      tempSubjectId: null,
+      gradeList: [] as any[],
+      musicCategory: [] as any
+    });
+    const data = reactive({
+      selectParents: {}, // 选中的数据
+      tags: [] as any[],
+      tagActiveId: '' as any,
+      tagActive: {} as any,
+      childSelectId: null as any
     });
 
-    const onSearch = () => {
-      emit('search', forms);
+    const onSearch = (type?: string) => {
+      emit(
+        'search',
+        {
+          ...forms,
+          bookVersionId: data.childSelectId || data.tagActiveId
+        },
+        type
+      );
     };
 
     const throttledFn = useThrottleFn(() => {
@@ -100,9 +200,52 @@ export default defineComponent({
       return obj;
     };
 
+    const _initTags = () => {
+      const tags = catchStore.getMusicTagTree;
+      data.tags = [
+        {
+          columnName: tags[0].columnName,
+          name: '全部',
+          id: ''
+        },
+        ...tags
+      ];
+      data.tagActiveId = data.tags[0].id;
+    };
+
+    const changeTag = (item: any) => {
+      data.tagActiveId = item.id;
+      data.childSelectId = null;
+      let children: any;
+      let columnName = '';
+      if (item.children) {
+        children = [
+          {
+            columnName: item.children[0].columnName,
+            name: '全部',
+            id: ''
+          },
+          ...item.children
+        ];
+        columnName = item.children[0].columnName;
+        data.selectParents = {
+          ...item,
+          columnName,
+          activeIndex: '',
+          children
+        };
+      } else {
+        data.selectParents = {};
+      }
+
+      onSearch();
+    };
+
     onMounted(async () => {
       // 获取教材分类列表
-      await catchStore.getMusicSheetCategory();
+      // await catchStore.getMusicSheetCategory();
+      await catchStore.getMusicTagTreeApi();
+      _initTags();
       // 获取声部列表
       await catchStore.getSubjects();
 
@@ -110,6 +253,22 @@ export default defineComponent({
       hiddenHeight.value = collapseWrapRef.value?.offsetHeight / line.value;
       // 默认隐藏
       getLive();
+
+      // const musicTagTreeList = catchStore.getMusicTagTree;
+      // if (musicTagTreeList.length > 0) {
+      //   forms.bookVersionId = musicTagTreeList[0].id;
+      //   state.gradeList = musicTagTreeList[0].children || [];
+      //   if (state.gradeList.length > 0) {
+      //     forms.grade = state.gradeList[0].id;
+      //     state.musicCategory = state.gradeList[0].children || [];
+      //     if (state.musicCategory.length > 0) {
+      //       forms.musicSheetCategoriesId = state.musicCategory[0].id;
+      //     }
+      //   }
+      // }
+      // console.log(state.musicCategory, 'state.musicCategory');
+
+      onSearch('timer');
     });
     return () => (
       <div class={styles.searchGroup}>
@@ -119,53 +278,105 @@ export default defineComponent({
               styles.collapsSection,
               props.type === 'myResources' && styles.collapsSectionEmpty
             ]}>
-            <NFormItem label="教材:">
-              <div
-                class={[
-                  styles.collapseWrap,
-                  loadingCollapse.value ? '' : styles.hideButton,
-                  isCollapse.value ? '' : styles.isHidden
-                ]}
-                ref={collapseWrapRef}>
-                <NSpace class={[styles.spaceSection]}>
-                  {catchStore.getAllMusicCategories.map((music: any) => (
-                    <NButton
-                      ref={musicCateRef}
-                      secondary={forms.musicSheetCategoriesId === music.id}
-                      quaternary={forms.musicSheetCategoriesId !== music.id}
-                      strong
-                      focusable={false}
-                      type={
-                        forms.musicSheetCategoriesId === music.id
-                          ? 'primary'
-                          : 'default'
-                      }
+            <NFormItem label={data.tags[0]?.columnName + ':'}>
+              <NSpace class={styles.spaceSection2}>
+                {data.tags.map((subject: any) => (
+                  <span
+                    class={[
+                      styles.textBtn,
+                      data.tagActiveId === subject.id && styles.textBtnActive
+                    ]}
+                    onClick={() => {
+                      changeTag(subject);
+                    }}>
+                    {subject.name}
+                  </span>
+                ))}
+              </NSpace>
+            </NFormItem>
+
+            <ChildNodeSearch
+              activeRow={data.selectParents}
+              onSelectChildTag={(val: any) => {
+                data.childSelectId = val;
+                onSearch();
+              }}
+            />
+            {/* {state.gradeList.length > 0 && (
+              <NFormItem label="年级:">
+                <NSpace class={styles.spaceSection2}>
+                  {state.gradeList.map((subject: any) => (
+                    <span
+                      class={[
+                        styles.textBtn,
+                        forms.grade === subject.id && styles.textBtnActive
+                      ]}
                       onClick={() => {
-                        forms.musicSheetCategoriesId = music.id;
-                        throttledFn();
+                        forms.grade = subject.id;
+                        onChangeSearch('grade', subject.children || []);
+                        onSearch();
                       }}>
-                      {music.name}
-                    </NButton>
+                      {subject.name}
+                    </span>
                   ))}
-                  {line.value > 1 && (
-                    <div
-                      class={styles.collaoseGroup}
-                      onClick={() => {
-                        setCollapse(!isCollapse.value);
-                      }}>
-                      <NImage
-                        previewDisabled
-                        src={isCollaose}
-                        class={[
-                          styles.collaoseBtn,
-                          isCollapse.value ? styles.isStart : ''
-                        ]}></NImage>
-                    </div>
-                  )}
                 </NSpace>
-              </div>
-            </NFormItem>
+              </NFormItem>
+            )} */}
           </div>
+          {/* {state.musicCategory.length > 0 && (
+            <div
+              class={[
+                styles.collapsSection,
+                props.type === 'myResources' && styles.collapsSectionEmpty
+              ]}>
+              <NFormItem label="教材:">
+                <div
+                  class={[
+                    styles.collapseWrap,
+                    loadingCollapse.value ? '' : styles.hideButton,
+                    isCollapse.value ? '' : styles.isHidden
+                  ]}
+                  ref={collapseWrapRef}>
+                  <NSpace class={[styles.spaceSection]}>
+                    {state.musicCategory.map((music: any) => (
+                      <NButton
+                        ref={musicCateRef}
+                        secondary={forms.musicSheetCategoriesId === music.id}
+                        quaternary={forms.musicSheetCategoriesId !== music.id}
+                        strong
+                        focusable={false}
+                        type={
+                          forms.musicSheetCategoriesId === music.id
+                            ? 'primary'
+                            : 'default'
+                        }
+                        onClick={() => {
+                          forms.musicSheetCategoriesId = music.id;
+                          throttledFn();
+                        }}>
+                        {music.name}
+                      </NButton>
+                    ))}
+                    {line.value > 1 && (
+                      <div
+                        class={styles.collaoseGroup}
+                        onClick={() => {
+                          setCollapse(!isCollapse.value);
+                        }}>
+                        <NImage
+                          previewDisabled
+                          src={isCollaose}
+                          class={[
+                            styles.collaoseBtn,
+                            isCollapse.value ? styles.isStart : ''
+                          ]}></NImage>
+                      </div>
+                    )}
+                  </NSpace>
+                </div>
+              </NFormItem>
+            </div>
+          )} */}
 
           <NFormItem label="乐器:">
             <NSpace class={styles.spaceSection2}>

+ 15 - 3
src/views/prepare-lessons/model/select-resources/select-item/index.tsx

@@ -114,7 +114,7 @@ export default defineComponent({
       }
     };
 
-    const throttledFnSearch = useDebounceFn(item => {
+    const onSearch = (item: any) => {
       state.pagination.page = 1;
       state.tableList = [];
       const { subjectId, ...res } = item;
@@ -124,6 +124,9 @@ export default defineComponent({
         subjectId: null
       });
       getList();
+    };
+    const throttledFnSearch = useDebounceFn(item => {
+      onSearch(item);
     }, 500);
 
     // 添加资源
@@ -192,7 +195,10 @@ export default defineComponent({
           state.searchHeight = height + 'px';
         }
       );
-      getList();
+
+      if (props.type !== 'shareResources') {
+        getList();
+      }
 
       if (props.type === 'relateResources') {
         eventGlobal.on('onCoursewareUpdate', onUpdate);
@@ -241,7 +247,13 @@ export default defineComponent({
             <ResourceSearchGroup
               type={props.type}
               // subjectId={prepareStore.getSubjectId as any}
-              onSearch={(item: any) => throttledFnSearch(item)}
+              onSearch={(item: any, type: any) => {
+                if (type) {
+                  onSearch(item);
+                  return;
+                }
+                throttledFnSearch(item);
+              }}
             />
           )}
         </div>

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

@@ -112,7 +112,7 @@
     line-height: var(--n-blank-height);
 
     &:last-child {
-      margin-left: -12Px;
+      // margin-left: -12Px;
     }
   }
 }

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

@@ -5,7 +5,9 @@ import {
   onMounted,
   reactive,
   ref,
-  toRef
+  toRef,
+  toRefs,
+  watch
 } from 'vue';
 import styles from './index.module.less';
 import {
@@ -22,6 +24,88 @@ import { useThrottleFn } from '@vueuse/core';
 import TheSearch from '/src/components/TheSearch';
 import isCollaose from '/src/views/natural-resources/images/isCollaose.png';
 
+const ChildNodeSearch = defineComponent({
+  name: 'ChildNodeSearch',
+  props: {
+    activeRow: {
+      type: Object,
+      default: () => ({})
+    },
+    list: {
+      type: Array,
+      default: () => []
+    }
+  },
+  emits: ['selectChildTag'],
+  setup(props, { emit }) {
+    const { activeRow } = toRefs(props);
+    const selectItem = ref({});
+
+    watch(
+      () => props.activeRow,
+      () => {
+        activeRow.value = props.activeRow;
+        selectItem.value = {};
+      }
+    );
+    return () => (
+      <>
+        {activeRow.value?.id && (
+          <>
+            <NFormItem label={activeRow.value.columnName + ':'}>
+              <NSpace class={styles.spaceSection}>
+                {activeRow.value?.children.map((subject: any) => (
+                  <span
+                    class={[
+                      styles.textBtn,
+                      (activeRow.value.activeIndex || '') == subject.id &&
+                        styles.textBtnActive
+                    ]}
+                    onClick={() => {
+                      activeRow.value.activeIndex = subject.id;
+                      let children: any;
+                      let columnName = '';
+                      if (subject.children) {
+                        children = [
+                          {
+                            columnName: subject.children[0].columnName,
+                            name: '全部',
+                            id: ''
+                          },
+                          ...subject.children
+                        ];
+                        columnName = subject.children[0].columnName;
+
+                        selectItem.value = {
+                          ...subject,
+                          columnName,
+                          activeIndex: '',
+                          children
+                        };
+                      } else {
+                        selectItem.value = {};
+                      }
+                      emit('selectChildTag', activeRow.value.activeIndex);
+                    }}>
+                    {subject.name}
+                  </span>
+                ))}
+              </NSpace>
+            </NFormItem>
+
+            <ChildNodeSearch
+              activeRow={selectItem.value}
+              onSelectChildTag={(item: any) => {
+                emit('selectChildTag', item || activeRow.value.activeIndex);
+              }}
+            />
+          </>
+        )}
+      </>
+    );
+  }
+});
+
 export default defineComponent({
   name: 'resource-search-group',
   props: {
@@ -44,15 +128,34 @@ export default defineComponent({
       type: 'MUSIC', //
       name: '',
       subjectId: subjectId.value as any,
-      bookVersionId: null
+      // grade: null as any,
+      bookVersionId: null as any
+      // musicSheetCategoriesId: null as any
     });
     const state = reactive({
-      tempSubjectId: null
+      tempSubjectId: null,
+      gradeList: [] as any[],
+      musicCategory: [] as any
     });
+    const data = reactive({
+      selectParents: {}, // 选中的数据
+      tags: [] as any[],
+      tagActiveId: '' as any,
+      tagActive: {} as any,
+      childSelectId: null as any
+    });
+
     const resourceType = ref([] as any);
 
-    const onSearch = () => {
-      emit('search', forms);
+    const onSearch = (type?: string) => {
+      emit(
+        'search',
+        {
+          ...forms,
+          bookVersionId: data.childSelectId || data.tagActiveId
+        },
+        type
+      );
     };
 
     const throttleFn = useThrottleFn(() => onSearch(), 500);
@@ -114,6 +217,48 @@ export default defineComponent({
       });
       return obj;
     };
+
+    const _initTags = () => {
+      const tags = catchStore.getMusicTagTree;
+      data.tags = [
+        {
+          columnName: tags[0].columnName,
+          name: '全部',
+          id: ''
+        },
+        ...tags
+      ];
+      data.tagActiveId = data.tags[0].id;
+    };
+
+    const changeTag = (item: any) => {
+      data.tagActiveId = item.id;
+      data.childSelectId = null;
+      let children: any;
+      let columnName = '';
+      if (item.children) {
+        children = [
+          {
+            columnName: item.children[0].columnName,
+            name: '全部',
+            id: ''
+          },
+          ...item.children
+        ];
+        columnName = item.children[0].columnName;
+        data.selectParents = {
+          ...item,
+          columnName,
+          activeIndex: '',
+          children
+        };
+      } else {
+        data.selectParents = {};
+      }
+
+      onSearch();
+    };
+
     onMounted(async () => {
       // if (props.type === 'myCollect') {
       //   resourceType.value.push({
@@ -130,8 +275,10 @@ export default defineComponent({
         // }
       });
 
-      // 获取教材分类列表
-      await catchStore.getMusicSheetCategory();
+      // // 获取教材分类列表
+      // await catchStore.getMusicSheetCategory();
+      await catchStore.getMusicTagTreeApi();
+      _initTags();
       // 获取声部
       await catchStore.getSubjects();
 
@@ -157,6 +304,23 @@ export default defineComponent({
         hiddenHeight.value = collapseWrapRef.value?.offsetHeight / line.value;
         // 默认隐藏
         getLive();
+
+        // const musicTagTreeList = catchStore.getMusicTagTree;
+        // if (musicTagTreeList.length > 0) {
+        //   forms.bookVersionId = musicTagTreeList[0].id;
+        //   state.gradeList = musicTagTreeList[0].children || [];
+        //   if (state.gradeList.length > 0) {
+        //     forms.grade = state.gradeList[0].id;
+        //     state.musicCategory = state.gradeList[0].children || [];
+        //     if (state.musicCategory.length > 0) {
+        //       forms.musicSheetCategoriesId = state.musicCategory[0].id;
+        //     }
+        //   }
+        // }
+      }
+
+      if (props.type === 'shareResources') {
+        onSearch('timer');
       }
     });
     return () => (
@@ -173,6 +337,9 @@ export default defineComponent({
                 onClick={() => {
                   forms.type = item.value;
                   forms.subjectId = null;
+                  data.tagActiveId = '';
+                  data.childSelectId = null;
+                  data.selectParents = {};
                   onSearch();
 
                   try {
@@ -207,54 +374,32 @@ export default defineComponent({
         </div>
         <NForm labelAlign="left" labelPlacement="left">
           {forms.type === 'MUSIC' && props.type === 'shareResources' && (
-            <div class={styles.collapsSection}>
-              <NFormItem label="教材:">
-                <div
-                  class={[
-                    styles.collapseWrap,
-                    loadingCollapse.value ? '' : styles.hideButton,
-                    isCollapse.value ? '' : styles.isHidden
-                  ]}
-                  ref={collapseWrapRef}>
-                  <NSpace class={[styles.spaceSection]}>
-                    {catchStore.getAllMusicCategories.map((music: any) => (
-                      <NButton
-                        ref={musicCateRef}
-                        secondary={forms.bookVersionId === music.id}
-                        quaternary={forms.bookVersionId !== music.id}
-                        strong
-                        focusable={false}
-                        type={
-                          forms.bookVersionId === music.id
-                            ? 'primary'
-                            : 'default'
-                        }
-                        onClick={() => {
-                          forms.bookVersionId = music.id;
-                          onSearch();
-                        }}>
-                        {music.name}
-                      </NButton>
-                    ))}
-                    {line.value > 1 && (
-                      <div
-                        class={styles.collaoseGroup}
-                        onClick={() => {
-                          setCollapse(!isCollapse.value);
-                        }}>
-                        <NImage
-                          previewDisabled
-                          src={isCollaose}
-                          class={[
-                            styles.collaoseBtn,
-                            isCollapse.value ? styles.isStart : ''
-                          ]}></NImage>
-                      </div>
-                    )}
-                  </NSpace>
-                </div>
+            <>
+              <NFormItem label={data.tags[0]?.columnName + ':'}>
+                <NSpace class={styles.spaceSection}>
+                  {data.tags.map((subject: any) => (
+                    <span
+                      class={[
+                        styles.textBtn,
+                        data.tagActiveId === subject.id && styles.textBtnActive
+                      ]}
+                      onClick={() => {
+                        changeTag(subject);
+                      }}>
+                      {subject.name}
+                    </span>
+                  ))}
+                </NSpace>
               </NFormItem>
-            </div>
+
+              <ChildNodeSearch
+                activeRow={data.selectParents}
+                onSelectChildTag={(val: any) => {
+                  data.childSelectId = val;
+                  onSearch();
+                }}
+              />
+            </>
           )}
 
           <NFormItem label="乐器:">

+ 39 - 23
src/views/setting/components/schoolInfo/index.tsx

@@ -10,7 +10,6 @@ import {
   NInput,
   NModal,
   NSpace,
-  useDialog,
   useMessage
 } from 'naive-ui';
 import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue';
@@ -62,6 +61,7 @@ export default defineComponent({
       resetVisiable: false,
       resetLoading: false,
       resetMessage: '',
+      resetMessageType: 'reset',
       activeRow: {} as any,
 
       modal: false,
@@ -138,6 +138,7 @@ export default defineComponent({
                 onClick={() => {
                   data.resetMessage = `重置"${row.nickname}"的密码,是否继续?`;
                   data.resetVisiable = true;
+                  data.resetMessageType = 'reset';
                   data.activeRow = row;
                 }}>
                 重置密码
@@ -224,35 +225,50 @@ export default defineComponent({
       getList();
     });
 
-    const dialog = useDialog();
+    // const dialog = useDialog();
     const message = useMessage();
     const handleChange = (row: any) => {
       const statuStr = row.status === 'LOCKED' ? '解冻' : '冻结';
-      dialog.warning({
-        title: '温馨提示',
-        content: `是否${statuStr}"${row.nickname}"?`,
-        positiveText: '确定',
-        negativeText: '取消',
-        maskClosable: false,
-        onPositiveClick: async () => {
-          await api_tenantInfoUpdateStatus({
-            ids: [row.id],
-            status: row.status === 'LOCKED' ? 'ACTIVATION' : 'LOCKED'
-          });
-          getList();
-          message.success(statuStr + '成功');
-        }
-      });
+      // dialog.warning({
+      //   title: '温馨提示',
+      //   content: `是否${statuStr}"${row.nickname}"?`,
+      //   positiveText: '确定',
+      //   negativeText: '取消',
+      //   maskClosable: false,
+      //   onPositiveClick: async () => {
+      //     await api_tenantInfoUpdateStatus({
+      //       ids: [row.id],
+      //       status: row.status === 'LOCKED' ? 'ACTIVATION' : 'LOCKED'
+      //     });
+      //     getList();
+      //     message.success(statuStr + '成功');
+      //   }
+      // });
+      data.resetMessageType = 'locked';
+      data.resetVisiable = true;
+      data.resetMessage = `是否${statuStr}"${row.nickname}"?`;
+      data.activeRow = row;
     };
     // 重置密码
     const onResetPassword = async () => {
       data.resetLoading = true;
       try {
-        await api_userResetPassword({
-          userId: data.activeRow.id,
-          clientType: 'TEACHER'
-        });
-        message.success('重置成功');
+        if (data.resetMessageType === 'locked') {
+          const statuStr = data.activeRow.status === 'LOCKED' ? '解冻' : '冻结';
+          await api_tenantInfoUpdateStatus({
+            ids: [data.activeRow.id],
+            status: data.activeRow.status === 'LOCKED' ? 'ACTIVATION' : 'LOCKED'
+          });
+          getList();
+          message.success(statuStr + '成功');
+        } else {
+          await api_userResetPassword({
+            userId: data.activeRow.id,
+            clientType: 'TEACHER'
+          });
+          message.success('重置成功');
+        }
+
         data.resetVisiable = false;
       } catch {
         //
@@ -472,7 +488,7 @@ export default defineComponent({
           v-model:show={data.resetVisiable}
           preset="card"
           class={['modalTitle', styles.removeVisiable1]}
-          title={'重置密码'}>
+          title={data.resetMessageType === 'reset' ? '重置密码' : '温馨提示'}>
           <TheMessageDialog
             content={data.resetMessage}
             cancelButtonText="取消"

+ 1 - 1
src/views/xiaoku-ai/index.module.less

@@ -31,7 +31,7 @@
 
   .tagWrap {
     flex: 1;
-    margin-right: 20px;
+    margin-right: 28px;
   }
 
   .tags {

+ 618 - 431
src/views/xiaoku-ai/index.tsx

@@ -1,431 +1,618 @@
-import { defineComponent, onMounted, reactive } from 'vue';
-import styles from './index.module.less';
-import TheSearch from '@/components/TheSearch';
-import { NButton, NImage, NPopselect, NSpace, NSpin } from 'naive-ui';
-import { useRouter } from 'vue-router';
-import { api_musicSheetCategoriesPage, api_musicTagTree } from './api';
-import TheEmpty from '/src/components/TheEmpty';
-import { useCatchStore } from '/src/store/modules/catchData';
-
-export default defineComponent({
-  name: 'XiaokuAi',
-  setup() {
-    const catchStore = useCatchStore();
-    const router = useRouter();
-
-    const xiaokuAiSearch = localStorage.getItem('xiaoku-ai-search');
-    const xiaokuAi = xiaokuAiSearch ? JSON.parse(xiaokuAiSearch) : {};
-    const forms = reactive({
-      musicTagIds: xiaokuAi.musicTagIds ? xiaokuAi.musicTagIds : ([] as any[]),
-      enable: true,
-      instrumentId: xiaokuAi.instrumentId || null,
-      keyword: '',
-      page: 1,
-      rows: 9999
-    });
-    const data = reactive({
-      tags: [] as any[],
-      tagChildren: [] as any[],
-      tagActiveId: xiaokuAi.tagActiveId || '',
-      tagActive: {} as any,
-      tagIndex: xiaokuAi.instrumentId || 0,
-      list: [] as any,
-      loading: false
-    });
-    const getTags = async () => {
-      const res = await api_musicTagTree();
-      if (Array.isArray(res?.data) && res.data.length) {
-        data.tags = res.data || [];
-        const index = data.tags.findIndex(
-          (item: any) => item.id == data.tagActiveId
-        );
-        if (index > -1) {
-          data.tagActiveId = res.data[index].id;
-          const list: any[] = [];
-          renderTag(res.data[index].children, list);
-          data.tagChildren = list;
-        } else {
-          data.tagActiveId = res.data[0].id;
-          const list: any[] = [];
-          renderTag(res.data[0].children, list);
-          data.tagChildren = list;
-        }
-      }
-    };
-
-    const getList = async () => {
-      data.loading = true;
-      try {
-        const res = await api_musicSheetCategoriesPage({
-          ...forms,
-          musicTagIds: [data.tagActiveId, ...forms.musicTagIds].filter(Boolean)
-        });
-        if (Array.isArray(res?.data?.rows)) {
-          data.list = res.data.rows;
-        }
-      } catch {
-        //
-      }
-      data.loading = false;
-    };
-
-    // 递归渲染标签
-    const renderTag = (_data: any[], _list: any[]): any => {
-      if (!_data?.length) return;
-      const item = {
-        columnName: _data[0].columnName,
-        list: [] as any[]
-      };
-      const childrens = [];
-      for (let i = 0; i < _data.length; i++) {
-        item.list.push({
-          name: _data[i].name,
-          id: _data[i].id,
-          activeIndex: -1
-        });
-        if (_data[i].children) {
-          childrens.push(..._data[i].children);
-        }
-      }
-      _list.push(item);
-      if (childrens.length) {
-        renderTag(childrens, _list);
-      }
-    };
-    onMounted(async () => {
-      data.loading = true;
-      try {
-        await getTags();
-        await getList();
-        // 获取教材分类列表
-        await catchStore.getSubjects();
-
-        localStorage.setItem(
-          'xiaoku-ai-search',
-          JSON.stringify({
-            tagActiveId: data.tagActiveId,
-            instrumentId: forms.instrumentId,
-            musicTagIds: forms.musicTagIds
-          })
-        );
-        console.log(forms.instrumentId, 'forms.instrumentId');
-        if (forms.instrumentId) {
-          let childInstruments: any[] = [];
-          catchStore.getSubjectInstruments.forEach((item: any) => {
-            if (Array.isArray(item.instruments)) {
-              item.instruments.forEach((child: any) => {
-                if (forms.instrumentId === child.value) {
-                  childInstruments = item.instruments || [];
-                }
-              });
-            }
-          });
-
-          console.log(childInstruments, 'childInstruments');
-          if (childInstruments.length > 0) {
-            selectChildObj(childInstruments);
-          }
-          //  else {
-          //   forms.instrumentId = '';
-          // }
-        }
-      } catch {
-        //
-      }
-      data.loading = false;
-    });
-
-    /** 改变顶级分类 */
-    const changeTag = (item: any, index: number) => {
-      data.tagActiveId = item.id;
-      forms.musicTagIds = [];
-
-      localStorage.setItem(
-        'xiaoku-ai-search',
-        JSON.stringify({
-          tagActiveId: item.id,
-          instrumentId: forms.instrumentId,
-          musicTagIds: forms.musicTagIds
-        })
-      );
-
-      const list: any[] = [];
-      renderTag(data.tags[index].children, list);
-      data.tagChildren = list;
-      getList();
-    };
-
-    /** 选中子选项 */
-    const selectChildTag = (columnIndex: number, index: number) => {
-      const oldActiveItem =
-        data.tagChildren[columnIndex].list[
-          data.tagChildren[columnIndex].activeIndex
-        ];
-      const activeItem = data.tagChildren[columnIndex].list[index];
-      if (oldActiveItem && oldActiveItem.id !== activeItem.id) {
-        forms.musicTagIds = forms.musicTagIds.filter(
-          (item: any) => item !== oldActiveItem.id
-        );
-      }
-      if (forms.musicTagIds.includes(activeItem.id)) {
-        forms.musicTagIds = forms.musicTagIds.filter(
-          (item: any) => item !== activeItem.id
-        );
-        data.tagChildren[columnIndex].activeIndex = -1;
-      } else {
-        forms.musicTagIds.push(activeItem.id);
-        data.tagChildren[columnIndex].activeIndex = index;
-      }
-
-      localStorage.setItem(
-        'xiaoku-ai-search',
-        JSON.stringify({
-          tagActiveId: data.tagActiveId,
-          instrumentId: forms.instrumentId,
-          musicTagIds: forms.musicTagIds
-        })
-      );
-      getList();
-    };
-    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;
-    };
-    return () => (
-      <div class={styles.container}>
-        <div class={styles.tools}>
-          <div class={styles.tagWrap}>
-            <div class={styles.tags}>
-              <NSpace size={[20, 12]}>
-                <span class={styles.firstButton}>
-                  {data.tags?.[0]?.columnName}
-                </span>
-
-                {data.tags.map((item: any, index: number) => {
-                  return (
-                    <>
-                      <NButton
-                        round
-                        secondary={data.tagActiveId === item.id ? false : true}
-                        type={
-                          data.tagActiveId === item.id ? 'primary' : 'default'
-                        }
-                        onClick={() => changeTag(item, index)}>
-                        {item.name}
-                      </NButton>
-                    </>
-                  );
-                })}
-              </NSpace>
-            </div>
-
-            {data.tagChildren.map((column: any, columnIndex: number) => {
-              return (
-                <div class={styles.tags}>
-                  <NSpace size={[20, 12]}>
-                    <span class={styles.firstButton}>{column.columnName}</span>
-
-                    {column.list.map((item: any, index: number) => {
-                      return (
-                        <>
-                          <NButton
-                            round
-                            secondary={
-                              column.activeIndex === index ? false : true
-                            }
-                            type={
-                              column.activeIndex === index
-                                ? 'primary'
-                                : 'default'
-                            }
-                            onClick={() => selectChildTag(columnIndex, index)}>
-                            {item.name}
-                          </NButton>
-                        </>
-                      );
-                    })}
-                  </NSpace>
-                </div>
-              );
-            })}
-            <div class={styles.tags}>
-              <NSpace size={[20, 12]}>
-                <span class={styles.firstButton}>乐器</span>
-
-                {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={() => {
-                        forms.instrumentId = data.tagIndex;
-                        localStorage.setItem(
-                          'xiaoku-ai-search',
-                          JSON.stringify({
-                            tagActiveId: data.tagActiveId,
-                            instrumentId: data.tagIndex,
-                            musicTagIds: forms.musicTagIds
-                          })
-                        );
-                        getList();
-                      }}
-                      key={item.value}
-                      class={[styles.popSelect1]}>
-                      <NButton
-                        round
-                        textColor={
-                          selectChildObj(item.instruments).selected
-                            ? '#fff'
-                            : '#000'
-                        }
-                        color={
-                          selectChildObj(item.instruments).selected
-                            ? '#198CFE'
-                            : 'rgba(46, 51, 56, .05)'
-                        }
-                        type={
-                          selectChildObj(item.instruments).selected
-                            ? 'primary'
-                            : 'default'
-                        }
-                        class={[
-                          styles.textBtn,
-                          selectChildObj(item.instruments).selected &&
-                            styles.textBtnActive
-                        ]}>
-                        {selectChildObj(item.instruments).name || item.name}
-                        <i class={styles.iconArrow}></i>
-                      </NButton>
-                    </NPopselect>
-                  ) : (
-                    <NButton
-                      round
-                      textColor={
-                        data.tagIndex === (item.value || 0) ? '#fff' : '#000'
-                      }
-                      color={
-                        data.tagIndex === (item.value || 0)
-                          ? '#198CFE'
-                          : 'rgba(46, 51, 56, .05)'
-                      }
-                      type={
-                        data.tagIndex === (item.value || 0)
-                          ? 'primary'
-                          : 'default'
-                      }
-                      onClick={() => {
-                        data.tagIndex = item.value || 0;
-                        forms.instrumentId = item.value;
-                        localStorage.setItem(
-                          'xiaoku-ai-search',
-                          JSON.stringify({
-                            tagActiveId: data.tagActiveId,
-                            instrumentId: item.value,
-                            musicTagIds: forms.musicTagIds
-                          })
-                        );
-                        getList();
-                      }}>
-                      {item.name}
-                    </NButton>
-                  )
-                )}
-                {/* // {
-                //   return (
-                //     <>
-                //       <NButton
-                //         round
-                //         secondary={item.id === forms.instrumentId ? false : true}
-                //         type={
-                //           item.id === forms.instrumentId ? 'primary' : 'default'
-                //         }
-                //         onClick={() => {
-                //           forms.instrumentId = item.id;
-
-                //           localStorage.setItem(
-                //             'xiaoku-ai-search',
-                //             JSON.stringify({
-                //               tagActiveId: data.tagActiveId,
-                //               instrumentId: item.id,
-                //               musicTagIds: forms.musicTagIds
-                //             })
-                //           );
-                //           getList();
-                //         }}>
-                //         {item.name}
-                //       </NButton>
-                //     </>
-                //   );
-                // })} */}
-              </NSpace>
-            </div>
-          </div>
-          <TheSearch
-            round
-            onSearch={val => {
-              forms.keyword = val;
-              getList();
-            }}
-          />
-        </div>
-        <NSpin show={data.loading}>
-          <div
-            class={[styles.content, data.loading ? styles.loadingContent : '']}>
-            {data.list.length > 0
-              ? data.list.map((item: any, index: number) => {
-                  return (
-                    <div class={styles.itemWrap}>
-                      <div class={styles.itemWrapBox}>
-                        <div
-                          class={styles.item}
-                          key={`item-${index}`}
-                          onClick={() => {
-                            sessionStorage.setItem(
-                              'musicSubjectList',
-                              JSON.stringify(item.subjects)
-                            );
-                            router.push({
-                              path: '/xiaoku-music',
-                              query: {
-                                id: item.id,
-                                name: item.name
-                              }
-                            });
-                          }}>
-                          <div class={styles.cover}>
-                            <div class={styles.itemImg}>
-                              <div class={styles.itemBg}></div>
-                              <NImage
-                                objectFit="cover"
-                                src={item.coverImg}
-                                lazy
-                                previewDisabled={true}
-                                onLoad={e => {
-                                  (e.target as any).dataset.loaded = 'true';
-                                }}
-                              />
-                            </div>
-                          </div>
-                          <div class={styles.itemName}>{item.name}</div>
-                        </div>
-                      </div>
-                    </div>
-                  );
-                })
-              : ''}
-            {!data.loading && data.list.length <= 0 && <TheEmpty></TheEmpty>}
-          </div>
-        </NSpin>
-      </div>
-    );
-  }
-});
+import { defineComponent, onMounted, reactive, ref, toRefs, watch } from 'vue';
+import styles from './index.module.less';
+import TheSearch from '@/components/TheSearch';
+import { NButton, NImage, NPopselect, NSpace, NSpin } from 'naive-ui';
+import { useRouter } from 'vue-router';
+import { api_musicSheetCategoriesPage, api_musicTagTree } from './api';
+import TheEmpty from '/src/components/TheEmpty';
+import { useCatchStore } from '/src/store/modules/catchData';
+
+const ChildNodeSearch = defineComponent({
+  name: 'ChildNodeSearch',
+  props: {
+    activeRow: {
+      type: Object,
+      default: () => ({})
+    },
+    list: {
+      type: Array,
+      default: () => []
+    },
+    loading: {
+      type: Boolean,
+      default: false
+    }
+  },
+  emits: ['selectChildTag'],
+  setup(props, { emit }) {
+    const { activeRow } = toRefs(props);
+    const selectItem = ref({});
+
+    watch(
+      () => props.activeRow,
+      () => {
+        activeRow.value = props.activeRow;
+        initActiveRow();
+      }
+    );
+
+    const initActiveRow = () => {
+      if (activeRow.value.activeIndex) {
+        const childList = activeRow.value.children || [];
+        childList.forEach((subject: any) => {
+          if (subject.id === activeRow.value.activeIndex) {
+            let children: any;
+            let columnName = '';
+            if (subject.children) {
+              children = [
+                {
+                  columnName: subject.children[0].columnName,
+                  name: '全部',
+                  id: ''
+                },
+                ...subject.children
+              ];
+              columnName = subject.children[0].columnName;
+
+              selectItem.value = {
+                ...subject,
+                columnName,
+                activeIndex: subject.activeIndex,
+                children
+              };
+            }
+          }
+        });
+      } else {
+        selectItem.value = {};
+      }
+    };
+
+    onMounted(() => {
+      initActiveRow();
+    });
+    return () => (
+      <>
+        {activeRow.value?.id && (
+          <>
+            <div class={styles.tags}>
+              <NSpace size={[12, 8]}>
+                <span class={styles.firstButton}>
+                  {activeRow.value.columnName}
+                </span>
+
+                {activeRow.value?.children.map((subject: any) => {
+                  return (
+                    <>
+                      <NButton
+                        round
+                        secondary={
+                          (activeRow.value.activeIndex || '') == subject.id
+                            ? false
+                            : true
+                        }
+                        type={
+                          (activeRow.value.activeIndex || '') == subject.id
+                            ? 'primary'
+                            : 'default'
+                        }
+                        onClick={() => {
+                          if (props.loading) return;
+                          activeRow.value.activeIndex = subject.id;
+                          let children: any;
+                          let columnName = '';
+                          if (subject.children) {
+                            children = [
+                              {
+                                columnName: subject.children[0].columnName,
+                                name: '全部',
+                                id: ''
+                              },
+                              ...subject.children
+                            ];
+                            columnName = subject.children[0].columnName;
+
+                            selectItem.value = {
+                              ...subject,
+                              columnName,
+                              activeIndex: '',
+                              children
+                            };
+                          } else {
+                            selectItem.value = {};
+                          }
+                          emit('selectChildTag', activeRow.value.activeIndex);
+                        }}>
+                        {subject.name}
+                      </NButton>
+                    </>
+                  );
+                })}
+              </NSpace>
+            </div>
+
+            <ChildNodeSearch
+              activeRow={selectItem.value}
+              onSelectChildTag={(item: any) => {
+                emit('selectChildTag', item || activeRow.value.activeIndex);
+              }}
+            />
+          </>
+        )}
+      </>
+    );
+  }
+});
+
+export default defineComponent({
+  name: 'XiaokuAi',
+  setup() {
+    const catchStore = useCatchStore();
+    const router = useRouter();
+
+    const xiaokuAiSearch = localStorage.getItem('xiaoku-ai-search');
+    const xiaokuAi = xiaokuAiSearch ? JSON.parse(xiaokuAiSearch) : {};
+    const id = xiaokuAi.childSelectId || xiaokuAi.tagActiveId;
+    const forms = reactive({
+      musicTagIds: id ? [id] : ([] as any[]),
+      enable: true,
+      instrumentId: xiaokuAi.instrumentId || null,
+      keyword: '',
+      page: 1,
+      rows: 9999
+    });
+    const data = reactive({
+      tags: [] as any[],
+      tagChildren: [] as any[],
+      tagActiveId: xiaokuAi.tagActiveId || '',
+      tagActive: {} as any,
+      tagIndex: xiaokuAi.instrumentId || 0,
+      list: [] as any,
+      loading: false,
+      selectParents: {}, // 选中的数据
+      // tags: [] as any[],
+      // tagActiveId: '' as any,
+      // tagActive: {} as any,
+      childSelectId: xiaokuAi.childSelectId || (null as any)
+    });
+
+    // const mapList: any = new Map();
+    const formatParentId = (id: any, list: any, ids = [] as any) => {
+      for (const item of list) {
+        if (item.children && item.children.length > 0) {
+          const cIds: any = formatParentId(id, item.children, [
+            ...ids,
+            item.id
+          ]);
+          if (cIds.includes(id)) {
+            return cIds;
+          }
+        }
+        if (item.id === id) {
+          return [...ids, id];
+        }
+        // mapList[item.id] = item.parentTagId;
+        // mapList.push()
+      }
+      return ids;
+    };
+
+    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 formatParentresetValue = (list: any) => {
+      for (const item of list) {
+        if (item.children && item.children.length > 0) {
+          // item.children.forEach(() => {
+          //   item.activeIndex = '';
+          // });
+        }
+        item.activeIndex = '';
+
+        if (item.children && item.children.length > 0) {
+          formatParentresetValue(item.children);
+        }
+      }
+    };
+
+    const changeTag = (item: any) => {
+      if (data.loading) return;
+      data.tagActiveId = item.id;
+      data.childSelectId = null;
+      formatParentresetValue(data.tags);
+      let children: any;
+      let columnName = '';
+      if (item.children) {
+        children = [
+          {
+            columnName: item.children[0].columnName,
+            name: '全部',
+            id: ''
+          },
+          ...item.children
+        ];
+        columnName = item.children[0].columnName;
+        data.selectParents = {
+          ...item,
+          columnName,
+          activeIndex: '',
+          children
+        };
+      } else {
+        data.selectParents = {};
+      }
+
+      localStorage.setItem(
+        'xiaoku-ai-search',
+        JSON.stringify({
+          tagActiveId: data.tagActiveId,
+          instrumentId: forms.instrumentId,
+          childSelectId: data.childSelectId
+        })
+      );
+      getList();
+    };
+    const getTags = async () => {
+      const res = await api_musicTagTree();
+      if (Array.isArray(res?.data) && res.data.length) {
+        // data.tags = res.data || [];
+        const tags = res.data || [];
+        data.tags = [
+          {
+            columnName: tags[0].columnName,
+            name: '全部',
+            id: ''
+          },
+          ...tags
+        ];
+        if (!data.tagActiveId) {
+          data.tagActiveId = data.tags[0].id;
+        } else {
+          let ids = formatParentId(xiaokuAi.childSelectId, data.tags);
+          // console.log(ids, 'ids', xiaokuAi.childSelectId);
+          const index = ids.findIndex(
+            (id: any) => id === xiaokuAi.childSelectId
+          );
+          // console.log(index, 'id');
+          ids = ids.slice(0, index + 1);
+          formatParentCurrentValue(ids, data.tags);
+          data.tags.forEach((item: any) => {
+            if (item.id === data.tagActiveId) {
+              let children: any;
+              let columnName = '';
+              if (item.children) {
+                children = [
+                  {
+                    columnName: item.children[0].columnName,
+                    name: '全部',
+                    id: ''
+                  },
+                  ...item.children
+                ];
+                columnName = item.children[0].columnName;
+
+                let id: any;
+                item.children.forEach((item: any) => {
+                  if (ids.includes(item.id)) {
+                    id = item.id;
+                  }
+                });
+
+                data.selectParents = {
+                  ...item,
+                  columnName,
+                  activeIndex: id || '',
+                  children
+                };
+              } else {
+                data.selectParents = {};
+              }
+            }
+          });
+        }
+      }
+    };
+
+    const getList = async () => {
+      data.loading = true;
+      try {
+        const id = data.childSelectId || data.tagActiveId;
+        const res = await api_musicSheetCategoriesPage({
+          ...forms,
+          musicTagIds: [id]
+        });
+        if (Array.isArray(res?.data?.rows)) {
+          data.list = res.data.rows;
+        }
+      } catch {
+        //
+      }
+      data.loading = false;
+    };
+
+    onMounted(async () => {
+      data.loading = true;
+      try {
+        await getTags();
+        await getList();
+        // 获取教材分类列表
+        await catchStore.getSubjects();
+
+        localStorage.setItem(
+          'xiaoku-ai-search',
+          JSON.stringify({
+            tagActiveId: data.tagActiveId,
+            instrumentId: forms.instrumentId,
+            childSelectId: data.childSelectId,
+            musicTagIds: forms.musicTagIds
+          })
+        );
+        // console.log(forms.instrumentId, 'forms.instrumentId');
+        if (forms.instrumentId) {
+          let childInstruments: any[] = [];
+          catchStore.getSubjectInstruments.forEach((item: any) => {
+            if (Array.isArray(item.instruments)) {
+              item.instruments.forEach((child: any) => {
+                if (forms.instrumentId === child.value) {
+                  childInstruments = item.instruments || [];
+                }
+              });
+            }
+          });
+
+          if (childInstruments.length > 0) {
+            selectChildObj(childInstruments);
+          }
+        }
+      } catch {
+        //
+      }
+      data.loading = 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;
+    };
+    return () => (
+      <div class={styles.container}>
+        <div class={styles.tools}>
+          <div class={styles.tagWrap}>
+            <div class={styles.tags}>
+              <NSpace size={[12, 8]}>
+                <span class={styles.firstButton}>
+                  {data.tags?.[0]?.columnName}
+                </span>
+
+                {data.tags.map((item: any) => {
+                  return (
+                    <>
+                      <NButton
+                        round
+                        secondary={data.tagActiveId === item.id ? false : true}
+                        type={
+                          data.tagActiveId === item.id ? 'primary' : 'default'
+                        }
+                        onClick={() => changeTag(item)}>
+                        {item.name}
+                      </NButton>
+                    </>
+                  );
+                })}
+              </NSpace>
+            </div>
+
+            <ChildNodeSearch
+              activeRow={data.selectParents}
+              loading={data.loading}
+              onSelectChildTag={(val: any) => {
+                data.childSelectId = val;
+                localStorage.setItem(
+                  'xiaoku-ai-search',
+                  JSON.stringify({
+                    tagActiveId: data.tagActiveId,
+                    instrumentId: forms.instrumentId,
+                    childSelectId: data.childSelectId,
+                    musicTagIds: forms.musicTagIds
+                  })
+                );
+                getList();
+              }}
+            />
+            <div class={styles.tags}>
+              <NSpace size={[12, 8]}>
+                <span class={styles.firstButton}>乐器</span>
+
+                {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={() => {
+                        forms.instrumentId = data.tagIndex;
+                        localStorage.setItem(
+                          'xiaoku-ai-search',
+                          JSON.stringify({
+                            tagActiveId: data.tagActiveId,
+                            instrumentId: data.tagIndex,
+                            musicTagIds: forms.musicTagIds
+                          })
+                        );
+                        getList();
+                      }}
+                      key={item.value}
+                      class={[styles.popSelect1]}>
+                      <NButton
+                        round
+                        textColor={
+                          selectChildObj(item.instruments).selected
+                            ? '#fff'
+                            : '#000'
+                        }
+                        color={
+                          selectChildObj(item.instruments).selected
+                            ? '#198CFE'
+                            : 'rgba(46, 51, 56, .05)'
+                        }
+                        type={
+                          selectChildObj(item.instruments).selected
+                            ? 'primary'
+                            : 'default'
+                        }
+                        class={[
+                          styles.textBtn,
+                          selectChildObj(item.instruments).selected &&
+                            styles.textBtnActive
+                        ]}>
+                        {selectChildObj(item.instruments).name || item.name}
+                        <i class={styles.iconArrow}></i>
+                      </NButton>
+                    </NPopselect>
+                  ) : (
+                    <NButton
+                      round
+                      textColor={
+                        data.tagIndex === (item.value || 0) ? '#fff' : '#000'
+                      }
+                      color={
+                        data.tagIndex === (item.value || 0)
+                          ? '#198CFE'
+                          : 'rgba(46, 51, 56, .05)'
+                      }
+                      type={
+                        data.tagIndex === (item.value || 0)
+                          ? 'primary'
+                          : 'default'
+                      }
+                      onClick={() => {
+                        data.tagIndex = item.value || 0;
+                        forms.instrumentId = item.value;
+                        localStorage.setItem(
+                          'xiaoku-ai-search',
+                          JSON.stringify({
+                            tagActiveId: data.tagActiveId,
+                            instrumentId: item.value,
+                            musicTagIds: forms.musicTagIds
+                          })
+                        );
+                        getList();
+                      }}>
+                      {item.name}
+                    </NButton>
+                  )
+                )}
+                {/* // {
+                //   return (
+                //     <>
+                //       <NButton
+                //         round
+                //         secondary={item.id === forms.instrumentId ? false : true}
+                //         type={
+                //           item.id === forms.instrumentId ? 'primary' : 'default'
+                //         }
+                //         onClick={() => {
+                //           forms.instrumentId = item.id;
+
+                //           localStorage.setItem(
+                //             'xiaoku-ai-search',
+                //             JSON.stringify({
+                //               tagActiveId: data.tagActiveId,
+                //               instrumentId: item.id,
+                //               musicTagIds: forms.musicTagIds
+                //             })
+                //           );
+                //           getList();
+                //         }}>
+                //         {item.name}
+                //       </NButton>
+                //     </>
+                //   );
+                // })} */}
+              </NSpace>
+            </div>
+          </div>
+          <TheSearch
+            round
+            onSearch={val => {
+              forms.keyword = val;
+              getList();
+            }}
+          />
+        </div>
+        <NSpin show={data.loading}>
+          <div
+            class={[styles.content, data.loading ? styles.loadingContent : '']}>
+            {data.list.length > 0
+              ? data.list.map((item: any, index: number) => {
+                  return (
+                    <div class={styles.itemWrap}>
+                      <div class={styles.itemWrapBox}>
+                        <div
+                          class={styles.item}
+                          key={`item-${index}`}
+                          onClick={() => {
+                            sessionStorage.setItem(
+                              'musicSubjectList',
+                              JSON.stringify(item.subjects)
+                            );
+                            router.push({
+                              path: '/xiaoku-music',
+                              query: {
+                                id: item.id,
+                                name: item.name
+                              }
+                            });
+                          }}>
+                          <div class={styles.cover}>
+                            <div class={styles.itemImg}>
+                              <div class={styles.itemBg}></div>
+                              <NImage
+                                objectFit="cover"
+                                src={item.coverImg}
+                                lazy
+                                previewDisabled={true}
+                                onLoad={e => {
+                                  (e.target as any).dataset.loaded = 'true';
+                                }}
+                              />
+                            </div>
+                          </div>
+                          <div class={styles.itemName}>{item.name}</div>
+                        </div>
+                      </div>
+                    </div>
+                  );
+                })
+              : ''}
+            {!data.loading && data.list.length <= 0 && <TheEmpty></TheEmpty>}
+          </div>
+        </NSpin>
+      </div>
+    );
+  }
+});