lex 1 年之前
父節點
當前提交
ce33335056
共有 22 個文件被更改,包括 984 次插入209 次删除
  1. 1 1
      public/version.json
  2. 2 2
      src/components/card-preview/rhythm-modal/index.tsx
  3. 15 0
      src/views/attend-class/component/rhythm-modal/index.module.less
  4. 42 0
      src/views/attend-class/component/rhythm-modal/index.tsx
  5. 6 0
      src/views/attend-class/index.module.less
  6. 55 6
      src/views/attend-class/index.tsx
  7. 16 13
      src/views/prepare-lessons/components/lesson-main/courseware-presets/index.tsx
  8. 14 2
      src/views/prepare-lessons/components/lesson-main/courseware/addCourseware.tsx
  9. 14 15
      src/views/prepare-lessons/model/add-other-source/index.tsx
  10. 0 87
      src/views/prepare-lessons/model/content-instrument/components/list/search-group-resources.tsx
  11. 38 0
      src/views/prepare-lessons/model/source-instrument/components/list/index.module.less
  12. 1 0
      src/views/prepare-lessons/model/source-instrument/components/list/index.tsx
  13. 147 0
      src/views/prepare-lessons/model/source-instrument/components/list/search-group-resources.tsx
  14. 8 31
      src/views/prepare-lessons/model/source-instrument/detail.module.less
  15. 47 42
      src/views/prepare-lessons/model/source-instrument/detail.tsx
  16. 1 6
      src/views/prepare-lessons/model/source-instrument/index.module.less
  17. 11 1
      src/views/prepare-lessons/model/source-instrument/index.tsx
  18. 313 0
      src/views/prepare-lessons/model/source-knowledge/index.module.less
  19. 236 0
      src/views/prepare-lessons/model/source-knowledge/index.tsx
  20. 2 2
      src/views/prepare-lessons/model/source-rhythm/index.tsx
  21. 5 0
      src/views/xiaoku-music/component/play-item/index.module.less
  22. 10 1
      src/views/xiaoku-music/component/play-item/index.tsx

+ 1 - 1
public/version.json

@@ -1 +1 @@
-{"version":1709908537642}
+{"version":1710145447945}

+ 2 - 2
src/components/card-preview/rhythm-modal/index.tsx

@@ -18,10 +18,10 @@ export default defineComponent({
     const origin = /(localhost|192)/.test(location.host)
       ? 'http://localhost:9002'
       : location.origin;
-    // const src = `${origin}/classroom-app/#/tempo-practice?v=${+new Date()}&win=modal&dataJson=${
+    // const src = `${origin}/classroom-app/#/tempo-practice?v=${+new Date()}&platform=modal&dataJson=${
     //   props.item.dataJson
     // }&Authorization=${userStore.getToken}`;
-    const src = `${origin}/#/tempo-practice?v=${+new Date()}&win=modal&dataJson=${
+    const src = `${origin}/#/tempo-practice?v=${+new Date()}&platform=modal&dataJson=${
       props.item.dataJson
     }&Authorization=${userStore.getToken}`;
     return () => (

+ 15 - 0
src/views/attend-class/component/rhythm-modal/index.module.less

@@ -0,0 +1,15 @@
+.musicScore {
+  width: 100%;
+  height: 100%;
+
+  iframe {
+    width: inherit;
+    height: inherit;
+
+    :global {
+      .headTopBackBtn {
+        display: none;
+      }
+    }
+  }
+}

+ 42 - 0
src/views/attend-class/component/rhythm-modal/index.tsx

@@ -0,0 +1,42 @@
+import { defineComponent, ref } from 'vue';
+import styles from './index.module.less';
+import { useUserStore } from '/src/store/modules/users';
+import { vaildMusicScoreUrl } from '/src/utils/urlUtils';
+
+export default defineComponent({
+  name: 'song-modal',
+  props: {
+    item: {
+      type: Object,
+      default: () => ({})
+    }
+  },
+  emits: ['setIframe'],
+  setup(props, { emit }) {
+    const userStore = useUserStore();
+    const iframeRef = ref();
+    const isLoaded = ref(false);
+    const origin = /(localhost|192)/.test(location.host)
+      ? 'http://localhost:9002'
+      : location.origin;
+    // const src = `${origin}/classroom-app/#/tempo-practice?v=${+new Date()}&platform=modal&dataJson=${
+    //   props.item.dataJson
+    // }&Authorization=${userStore.getToken}&win=pc`;
+    const src = `${origin}/#/tempo-practice?v=${+new Date()}&platform=modal&dataJson=${
+      props.item.dataJson
+    }&Authorization=${userStore.getToken}&win=pc`;
+    return () => (
+      <div class={styles.musicScore}>
+        <iframe
+          ref={iframeRef}
+          onLoad={() => {
+            emit('setIframe', iframeRef.value);
+            isLoaded.value = true;
+          }}
+          class={[styles.container, 'musicIframe']}
+          frameborder="0"
+          src={src}></iframe>
+      </div>
+    );
+  }
+});

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

@@ -778,6 +778,12 @@
   }
 }
 
+.instrumentContainer {
+  background: #FFFFFF;
+  padding: 68px;
+  height: 100%;
+}
+
 .bottomColumn {
   position: fixed;
   right: 40px;

+ 55 - 6
src/views/attend-class/index.tsx

@@ -33,7 +33,8 @@ import {
   NSpace,
   NButton,
   NCollapse,
-  NCollapseItem
+  NCollapseItem,
+  NTooltip
 } from 'naive-ui';
 import CardType from '@/components/card-type';
 import Pen from './component/tools/pen';
@@ -79,6 +80,8 @@ import TheNoticeBar from '/src/components/TheNoticeBar';
 import ClassWork from './model/class-work';
 import SelectClass from './model/select-class';
 import SourceList from './model/source-list';
+import RhythmModal from './component/rhythm-modal';
+import InstruemntDetail from '/src/views/prepare-lessons/model/source-instrument/detail';
 
 export type ToolType = 'init' | 'pen' | 'whiteboard' | 'call';
 export type ToolItem = {
@@ -221,12 +224,14 @@ export default defineComponent({
           const childList: any[] = [];
           row.chapterKnowledgeMaterialList.forEach((child: any) => {
             if (!child.removeFlag) {
+              const dataJson = child.dataJson ? JSON.parse(child.dataJson) : {};
               childList.push({
                 id: child.id,
                 materialId: child.bizId,
                 coverImg: child.bizInfo.coverImg,
                 type: child.type,
                 title: child.bizInfo.name,
+                dataJson: dataJson.setting ? dataJson.setting : {},
                 isCollect: !!child.favoriteFlag,
                 isSelected: child.source === 'PLATFORM' ? true : false,
                 content: child.bizInfo.content,
@@ -241,6 +246,7 @@ export default defineComponent({
           allItem.push(...childList);
         });
 
+        console.log(allItem, 'temp');
         data.knowledgePointList = temp;
         data.itemList = allItem?.map((m: any) => {
           return {
@@ -449,6 +455,17 @@ export default defineComponent({
             '*'
           );
         }
+
+        if (activeItem.type === 'INSTRUMENT') {
+          activeItem.iframeRef?.handleChangeAudio('pause');
+        }
+
+        if (activeItem.type === 'RHYTHM') {
+          activeItem.iframeRef?.contentWindow?.postMessage(
+            { api: 'setPlayState', data: false },
+            '*'
+          );
+        }
       }
     };
     // 切换素材
@@ -1534,6 +1551,20 @@ export default defineComponent({
                           width="100%"
                           height="100%"
                           frameborder="1"></iframe>
+                      ) : m.type === 'RHYTHM' ? (
+                        <RhythmModal
+                          item={m}
+                          onSetIframe={(el: any) => {
+                            m.iframeRef = el;
+                          }}
+                        />
+                      ) : m.type === 'INSTRUMENT' ? (
+                        <InstruemntDetail
+                          type="preview"
+                          id={m.content}
+                          activeStatus={popupData.activeIndex === mIndex}
+                          ref={(el: any) => (m.iframeRef = el)}
+                        />
                       ) : (
                         <MusicScore
                           activeModel={activeData.model}
@@ -1576,12 +1607,24 @@ export default defineComponent({
                 item.id === 10 && !data.classId ? styles.itemHide : ''
               ]}
               onClick={() => operateRightBtn(item.id)}>
-              <img src={item.icon} />
-              <div class={styles.rightTips}>
+              <NTooltip showArrow={false} placement="left">
+                {{
+                  trigger: () => <img src={item.icon} />,
+                  default: (
+                    <>
+                      {index === 0 && data.type === 'preview'
+                        ? item.name2
+                        : item.name}
+                    </>
+                  )
+                }}
+              </NTooltip>
+
+              {/* <div class={styles.rightTips}>
                 {index === 0 && data.type === 'preview'
                   ? item.name2
                   : item.name}
-              </div>
+              </div> */}
             </div>
           ))}
         </div>
@@ -1607,8 +1650,14 @@ export default defineComponent({
                   : ''
               ]}
               onClick={() => operateBottomBtn(item.id)}>
-              <img src={item.icon} />
-              <div class={styles.bottomTips}>{item.name}</div>
+              <NTooltip showArrow={false} placement="top">
+                {{
+                  trigger: () => <img src={item.icon} />,
+                  default: <>{item.name}</>
+                }}
+              </NTooltip>
+              {/* <img src={item.icon} />
+              <div class={styles.bottomTips}>{item.name}</div> */}
             </div>
           ))}
         </div>

+ 16 - 13
src/views/prepare-lessons/components/lesson-main/courseware-presets/index.tsx

@@ -145,7 +145,7 @@ export default defineComponent({
             name: item.name,
             coverImg: firstItem?.bizInfo.coverImg,
             type: firstItem?.bizInfo.type,
-            isAdd: index !== -1 ? true : false
+            isAdd: item.addFlag
           });
         });
 
@@ -174,18 +174,18 @@ export default defineComponent({
     );
 
     // 检测数据是否存在
-    watch(
-      () => forms.tableList,
-      () => {
-        // fromChapterLessonCoursewareId;
-        forms.openTableList.forEach((item: any) => {
-          const index = forms.tableList.findIndex(
-            (i: any) => i.fromChapterLessonCoursewareId === item.id
-          );
-          item.isAdd = index !== -1 ? true : false;
-        });
-      }
-    );
+    // watch(
+    //   () => forms.tableList,
+    //   () => {
+    //     // fromChapterLessonCoursewareId;
+    //     forms.openTableList.forEach((item: any) => {
+    //       const index = forms.tableList.findIndex(
+    //         (i: any) => i.fromChapterLessonCoursewareId === item.id
+    //       );
+    //       item.isAdd = index !== -1 ? true : false;
+    //     });
+    //   }
+    // );
 
     watch(
       () => prepareStore.getSubjectList,
@@ -277,6 +277,7 @@ export default defineComponent({
         });
         message.success('修改成功');
         getCoursewareList();
+        // getOpenCoursewareList()
         forms.editTitleVisiable = false;
       } catch {
         //
@@ -292,6 +293,7 @@ export default defineComponent({
         });
         message.success('删除成功');
         getCoursewareList();
+        getOpenCoursewareList();
         forms.preRemoveVisiable = false;
       } catch {
         //
@@ -309,6 +311,7 @@ export default defineComponent({
         await api_addByOpenCourseware({ id: item.id });
         message.success('添加成功');
         getCoursewareList();
+        getOpenCoursewareList();
       } catch {
         //
       }

+ 14 - 2
src/views/prepare-lessons/components/lesson-main/courseware/addCourseware.tsx

@@ -134,12 +134,14 @@ export default defineComponent({
           const childList: any[] = [];
           if (Array.isArray(child) && child.length > 0) {
             child.forEach((sub: any) => {
+              const dataJson = sub.dataJson ? JSON.parse(sub.dataJson) : {};
               childList.push({
                 id: sub.id,
                 materialId: sub.bizId,
                 coverImg: sub.bizInfo.coverImg,
                 type: sub.type,
                 title: sub.bizInfo.name,
+                dataJson: dataJson.setting || {},
                 // isCollect: !!sub.favoriteFlag,
                 isSelected: sub.source === 'PLATFORM' ? true : false,
                 content: sub.bizInfo.content,
@@ -361,6 +363,10 @@ export default defineComponent({
           let tempItem: any = [];
           if (Array.isArray(item.list) && item.list.length > 0) {
             tempItem = item.list.map((child: any) => {
+              console.log(
+                !['IMG', 'VIDEO', 'SONG', 'MUSIC', 'PPT'].includes(child.type),
+                child
+              );
               return {
                 bizId: child.materialId,
                 type: child.type,
@@ -383,6 +389,7 @@ export default defineComponent({
             chapterKnowledgeMaterialList: tempItem
           });
         });
+        console.log(params.chapterKnowledgeList);
         if (props.groupItem?.id) {
           await api_teacherChapterLessonCoursewareUpdate({
             id: props.groupItem.id,
@@ -842,8 +849,13 @@ export default defineComponent({
           <AddOtherSource
             onClose={() => (forms.addOtherSource = false)}
             onComfirm={item => {
-              console.log({ ...item, index: forms.addOtherIndex });
-              addItem({ ...item, index: forms.addOtherIndex });
+              if (Array.isArray(item)) {
+                item.forEach((child: any) => {
+                  addItem({ ...child, index: forms.addOtherIndex });
+                });
+              } else {
+                addItem({ ...item, index: forms.addOtherIndex });
+              }
             }}
           />
         </NModal>

+ 14 - 15
src/views/prepare-lessons/model/add-other-source/index.tsx

@@ -10,7 +10,7 @@ import icon6 from '../../images/addSource/icon6.png';
 import icon7 from '../../images/addSource/icon7.png';
 import { useRouter } from 'vue-router';
 import SourceRhythm from '../source-rhythm';
-import SourceInstrument from '../content-instrument';
+import SourceInstrument from '../source-instrument';
 
 export default defineComponent({
   name: 'add-other-source',
@@ -134,36 +134,35 @@ export default defineComponent({
           class={['modalTitle', styles.instrumentModal]}
           title={'乐器百科'}>
           <SourceInstrument
+            onClose={() => (state.instrumentStatus = false)}
             onConfirm={(val: any) => {
               state.instrumentStatus = false;
               const value = val || [];
               const temp: any[] = [];
               value.forEach((item: any) => {
                 temp.push({
-                  materialId: '',
+                  materialId: item.materialId,
                   coverImg: item.coverImg,
                   dataJson: null,
-                  title: '节奏练习',
+                  title: item.title,
                   isCollect: false,
                   isSelected: false,
-                  content: '',
+                  content: item.content,
                   type: 'INSTRUMENT'
                 });
               });
-              // emit('comfirm', {
-              //   materialId: '',
-              //   coverImg: item.coverImg,
-              //   dataJson: item.dataJson,
-              //   title: '节奏练习',
-              //   isCollect: false,
-              //   isSelected: false,
-              //   content: '',
-              //   type: 'RHYTHM'
-              // });
-              // emit('close');
+              emit('comfirm', temp);
+              emit('close');
             }}
           />
         </NModal>
+
+        {/* 乐理知识 */}
+        {/* <NModal
+          v-model:show={state.instrumentStatus}
+          preset="card"
+          class={['modalTitle', styles.instrumentModal]}
+          title={'乐器百科'}></NModal> */}
       </>
     );
   }

+ 0 - 87
src/views/prepare-lessons/model/content-instrument/components/list/search-group-resources.tsx

@@ -1,87 +0,0 @@
-import { PropType, defineComponent, onMounted, reactive } from 'vue';
-import styles from './index.module.less';
-import { NButton, NSpace } from 'naive-ui';
-import TheSearch from '/src/components/TheSearch';
-export default defineComponent({
-  name: 'search-group',
-  props: {
-    categoryChildList: {
-      type: Array as PropType<any>,
-      default: () => []
-    },
-    wikiCategoryId: {
-      type: String,
-      default: ''
-    }
-  },
-  emits: ['search', 'add'],
-  expose: ['init'],
-  setup(props, { emit }) {
-    // const catchStore = useCatchStore();
-    const forms = reactive({
-      keyword: '',
-      wikiCategoryId: props.wikiCategoryId || ''
-    });
-
-    const onSearch = () => {
-      emit('search', forms);
-    };
-    onMounted(async () => {
-      // 获取教材分类列表
-      // await catchStore.getMusicSheetCategory()
-    });
-    return () => (
-      <div class={styles.searchGroup}>
-        <div class={[styles.searchCatatory]}>
-          <NSpace size="small" class={styles.btnType}>
-            {props.categoryChildList.length > 0 ? (
-              <NButton
-                type={
-                  forms.wikiCategoryId === props.wikiCategoryId
-                    ? 'primary'
-                    : 'default'
-                }
-                secondary={
-                  forms.wikiCategoryId === props.wikiCategoryId ? false : true
-                }
-                round
-                size="small"
-                focusable={false}
-                onClick={() => {
-                  forms.wikiCategoryId = props.wikiCategoryId;
-                  onSearch();
-                }}>
-                全部
-              </NButton>
-            ) : (
-              <span></span>
-            )}
-            {props.categoryChildList.map((item: any) => (
-              <NButton
-                type={forms.wikiCategoryId === item.id ? 'primary' : 'default'}
-                secondary={forms.wikiCategoryId === item.id ? false : true}
-                round
-                size="small"
-                focusable={false}
-                onClick={() => {
-                  forms.wikiCategoryId = item.id;
-                  onSearch();
-                }}>
-                {item.name}
-              </NButton>
-            ))}
-          </NSpace>
-          <TheSearch
-            class={styles.inputSearch}
-            placeholder="请输入乐器关键词"
-            round
-            onSearch={(val: string) => {
-              forms.keyword = val;
-              onSearch();
-            }}
-          />
-        </div>
-      </div>
-    );
-  }
-});

+ 38 - 0
src/views/prepare-lessons/model/content-instrument/components/list/index.module.less → src/views/prepare-lessons/model/source-instrument/components/list/index.module.less

@@ -5,6 +5,32 @@
 
   .btnType {
     gap: 0px 24px !important;
+    flex-wrap: nowrap !important;
+
+    &>div {
+      display: flex;
+      align-items: center;
+    }
+
+
+    .swipeControll {
+      height: 25Px;
+
+      .leftIcon {
+        transform: rotate(180deg);
+      }
+
+      img {
+        cursor: pointer;
+        width: 25Px;
+        height: 25Px;
+      }
+
+      .disabled {
+        opacity: 0.4;
+        cursor: not-allowed;
+      }
+    }
 
     :global {
       .n-button {
@@ -19,6 +45,18 @@
         }
       }
     }
+
+    .carouselContainer {
+      max-width: 550px;
+
+      :global {
+        .n-carousel__slide {
+          width: auto !important;
+          display: flex;
+          align-items: center;
+        }
+      }
+    }
   }
 
 

+ 1 - 0
src/views/prepare-lessons/model/content-instrument/components/list/index.tsx → src/views/prepare-lessons/model/source-instrument/components/list/index.tsx

@@ -78,6 +78,7 @@ export default defineComponent({
     const onSearch = async (item: any) => {
       state.pagination.page = 1;
       state.searchGroup = Object.assign(state.searchGroup, item);
+      state.tableList = [];
       getList();
     };
 

+ 147 - 0
src/views/prepare-lessons/model/source-instrument/components/list/search-group-resources.tsx

@@ -0,0 +1,147 @@
+import { PropType, defineComponent, onMounted, reactive, ref } from 'vue';
+import styles from './index.module.less';
+import { NButton, NCarousel, NCarouselItem, NImage, NSpace } from 'naive-ui';
+import TheSearch from '/src/components/TheSearch';
+import iconSlideRight from '/src/views/prepare-lessons/images/icon-slide-right.png';
+import { nextTick } from 'process';
+export default defineComponent({
+  name: 'search-group',
+  props: {
+    categoryChildList: {
+      type: Array as PropType<any>,
+      default: () => []
+    },
+    wikiCategoryId: {
+      type: String,
+      default: ''
+    }
+  },
+  emits: ['search', 'add'],
+  expose: ['init'],
+  setup(props, { emit }) {
+    // const catchStore = useCatchStore();
+    const forms = reactive({
+      currentIndex: 0,
+      keyword: '',
+      wikiCategoryId: props.wikiCategoryId || '',
+      maxIndex: 0
+    });
+
+    const onSearch = () => {
+      emit('search', forms);
+    };
+
+    const carouselRef = ref();
+    const onChangeSlide = (type: string) => {
+      if (type === 'left') {
+        carouselRef.value?.prev();
+      } else if (type === 'right') {
+        carouselRef.value?.next();
+      }
+    };
+    onMounted(async () => {
+      // 获取教材分类列表
+      // await catchStore.getMusicSheetCategory()
+      // nextTick(() => {
+      //   carouselRef.value?.to(100);
+      // });
+    });
+    return () => (
+      <div class={styles.searchGroup}>
+        <div class={[styles.searchCatatory]}>
+          <NSpace size="small" class={styles.btnType}>
+            {props.categoryChildList.length > 0 ? (
+              <NButton
+                type={
+                  forms.wikiCategoryId === props.wikiCategoryId
+                    ? 'primary'
+                    : 'default'
+                }
+                secondary={
+                  forms.wikiCategoryId === props.wikiCategoryId ? false : true
+                }
+                round
+                size="small"
+                focusable={false}
+                onClick={() => {
+                  forms.wikiCategoryId = props.wikiCategoryId;
+                  onSearch();
+                }}>
+                全部
+              </NButton>
+            ) : (
+              ''
+            )}
+            <NCarousel
+              ref={carouselRef}
+              slidesPerView={'auto'}
+              loop={false}
+              class={styles.carouselContainer}
+              showDots={false}
+              spaceBetween={20}
+              currentIndex={forms.currentIndex}
+              onUpdate:currentIndex={(val: any) => {
+                //
+                // if (val > forms.maxIndex) {
+                //   forms.maxIndex = val;
+                //   carouselRef.value?.to(0);
+                // }
+                forms.currentIndex = val;
+              }}>
+              {props.categoryChildList.map((item: any) => (
+                <NCarouselItem>
+                  <NButton
+                    type={
+                      forms.wikiCategoryId === item.id ? 'primary' : 'default'
+                    }
+                    secondary={forms.wikiCategoryId === item.id ? false : true}
+                    round
+                    size="small"
+                    focusable={false}
+                    onClick={() => {
+                      forms.wikiCategoryId = item.id;
+                      onSearch();
+                    }}>
+                    {item.name}
+                  </NButton>
+                </NCarouselItem>
+              ))}
+            </NCarousel>
+
+            <NSpace class={styles.swipeControll}>
+              <div onClick={() => onChangeSlide('left')}>
+                <NImage
+                  previewDisabled
+                  class={[
+                    styles.leftIcon
+                    // forms.currentIndex === 0 && styles.disabled
+                  ]}
+                  src={iconSlideRight}
+                />
+              </div>
+              <div onClick={() => onChangeSlide('right')}>
+                <NImage
+                  // class={
+                  //   // forms.currentIndex == forms.openTableList.length - 4 &&
+                  //   styles.disabled
+                  // }
+                  previewDisabled
+                  src={iconSlideRight}
+                />
+              </div>
+            </NSpace>
+          </NSpace>
+          <TheSearch
+            class={styles.inputSearch}
+            placeholder="请输入乐器关键词"
+            round
+            onSearch={(val: string) => {
+              forms.keyword = val;
+              onSearch();
+            }}
+          />
+        </div>
+      </div>
+    );
+  }
+});

+ 8 - 31
src/views/prepare-lessons/model/content-instrument/detail.module.less → src/views/prepare-lessons/model/source-instrument/detail.module.less

@@ -3,41 +3,17 @@
   flex-direction: column;
   height: 100%;
 
-  .iconBack {
-    width: 36px;
-    height: 36px;
-  }
-
-  :global {
-    .n-breadcrumb>ul {
-      display: flex;
-      align-items: center;
-
-      .n-breadcrumb-item {
-        display: flex;
-        align-items: center;
-      }
+  &.containerPreview {
+    padding: 68px 78px 68px 68px;
+    // height: calc(100% - 136px);
+    background-color: #fff;
 
-      .n-breadcrumb-item__separator {
-        display: none;
-      }
-
-      .n-breadcrumb-item__link {
-        padding: 5px 18px;
-        background: #FFFFFF;
-        border-radius: 16px;
-        color: #21225D;
-        line-height: 20px;
-      }
-    }
-
-    .n-breadcrumb .n-breadcrumb-item:last-child .n-breadcrumb-item__link {
-      color: #fff;
-      background: var(--product-color);
+    .wrapBottom {
+      padding-bottom: 60px !important;
     }
-
   }
 
+
   &> :global(.n-space) {
     height: 36px;
     flex-shrink: 0;
@@ -60,6 +36,7 @@
     padding-bottom: 108px;
 
   }
+
 }
 
 .content {

+ 47 - 42
src/views/prepare-lessons/model/content-instrument/detail.tsx → src/views/prepare-lessons/model/source-instrument/detail.tsx

@@ -7,17 +7,17 @@ import {
   NSpace,
   NSpin
 } from 'naive-ui';
-import { computed, defineComponent, onMounted, reactive } from 'vue';
+import { computed, defineComponent, onMounted, reactive, watch } from 'vue';
 import styles from './detail.module.less';
-import icon_back from '../../xiaoku-music/images/icon_back.png';
-import icon_arrow from '../../xiaoku-music/images/icon_arrow.png';
-import icon_play from '../../xiaoku-music/images/icon_play.png';
-import icon_pause from '../../xiaoku-music/images/icon_pause.png';
-import icon_default from '../../xiaoku-music/images/icon_default.png';
-import icon_separator from '../../xiaoku-music/images/icon_separator.png';
-import iconT from '../images/icon-t.png';
-import iconAddT from '../images/icon-add-t.png';
-import iconPlusT from '../images/icon-plus-t.png';
+// import icon_back from '../../xiaoku-music/images/icon_back.png';
+import icon_arrow from '../../../xiaoku-music/images/icon_arrow.png';
+import icon_play from '../../../xiaoku-music/images/icon_play.png';
+import icon_pause from '../../../xiaoku-music/images/icon_pause.png';
+import icon_default from '../../../xiaoku-music/images/icon_default.png';
+// import icon_separator from '../../xiaoku-music/images/icon_separator.png';
+import iconT from '/src/views/content-information/images/icon-t.png';
+import iconAddT from '/src/views/content-information/images/icon-add-t.png';
+import iconPlusT from '/src/views/content-information/images/icon-plus-t.png';
 import { useRoute, useRouter } from 'vue-router';
 import PlayLoading from '../../../xiaoku-music/component/play-loading';
 import TheNoticeBar from '/src/components/TheNoticeBar';
@@ -27,7 +27,21 @@ import { api_knowledgeWiki_detail } from '/src/views/content-information/api';
 
 export default defineComponent({
   name: 'instrument-detail',
-  setup() {
+  props: {
+    id: {
+      type: String,
+      default: ''
+    },
+    type: {
+      type: String,
+      default: ''
+    },
+    activeStatus: {
+      type: Boolean,
+      default: false
+    }
+  },
+  setup(props, { expose }) {
     const route = useRoute();
     const router = useRouter();
     const forms = reactive({
@@ -94,7 +108,9 @@ export default defineComponent({
       data.loading = true;
       let res = {} as any;
       try {
-        res = await api_knowledgeWiki_detail({ id: route.query.id });
+        res = await api_knowledgeWiki_detail({
+          id: props.id || route.query.id
+        });
       } catch (error) {
         console.log(error);
       }
@@ -125,37 +141,25 @@ export default defineComponent({
     onMounted(() => {
       getDetail();
     });
-    return () => (
-      <div class={styles.container}>
-        <NSpace align="center" wrapItem={false} size={16}>
-          <img
-            style={{ cursor: 'pointer' }}
-            src={icon_back}
-            class={styles.iconBack}
-            onClick={() => {
-              const path =
-                forms.type === 'MUSICIAN'
-                  ? '/content-musician'
-                  : '/content-instruments';
-              router.push({ path });
-            }}
-          />
-          <NBreadcrumb separator="">
-            <NBreadcrumbItem
-              onClick={() => {
-                const path =
-                  forms.type === 'MUSICIAN'
-                    ? '/content-musician'
-                    : '/content-instruments';
-                router.push({ path });
-              }}>
-              {forms.type === 'MUSICIAN' ? '音乐家' : '乐器百科'}
-            </NBreadcrumbItem>
-            <img class={styles.separator} src={icon_separator} />
-            <NBreadcrumbItem>{route.query.name}</NBreadcrumbItem>
-          </NBreadcrumb>
-        </NSpace>
 
+    watch(
+      () => props.activeStatus,
+      () => {
+        if (!props.activeStatus) {
+          handleChangeAudio('pause');
+        }
+      }
+    );
+
+    expose({
+      handleChangeAudio
+    });
+    return () => (
+      <div
+        class={[
+          styles.container,
+          props.type === 'preview' && styles.containerPreview
+        ]}>
         <div class={[styles.wrap, data.showPlayer ? styles.wrapBottom : '']}>
           <div class={styles.content}>
             <div class={styles.contentWrap}>
@@ -305,6 +309,7 @@ export default defineComponent({
 
         {data.list.length !== 0 && (
           <PlayItem
+            type={props.type}
             show={data.showPlayer}
             playState={data.playState}
             item={activeItem.value}

+ 1 - 6
src/views/prepare-lessons/model/content-instrument/index.module.less → src/views/prepare-lessons/model/source-instrument/index.module.less

@@ -1,5 +1,4 @@
 .container {
-
   .iconBack {
     width: 36px;
     height: 36px;
@@ -50,7 +49,7 @@
   }
 
   &> :global(.n-space) {
-    height: 36px;
+    // height: 36px;
     flex-shrink: 0;
   }
 
@@ -62,18 +61,14 @@
 }
 
 .wrap {
-  // padding-top: 12px;
   flex: 1;
   transition: padding 0.3s;
-  // overflow: hidden;
 }
 
 .listWrap {
   padding: 0;
   background-color: #fff;
   border-radius: 20px;
-  // min-height: 100%;
-  min-height: calc(100vh - 192px);
 
   &.listWrapEmpty {
     display: flex;

+ 11 - 1
src/views/prepare-lessons/model/content-instrument/index.tsx → src/views/prepare-lessons/model/source-instrument/index.tsx

@@ -5,6 +5,7 @@ import { useRoute, useRouter } from 'vue-router';
 import List from './components/list';
 import { api_knowledgeWikiCategoryType_page } from '/src/views/content-information/api';
 import TheEmpty from '/src/components/TheEmpty';
+import { PageEnum } from '/src/enums/pageEnum';
 
 export default defineComponent({
   name: 'content-instrument',
@@ -44,7 +45,16 @@ export default defineComponent({
 
     // 添加
     const onSubmit = async () => {
-      emit('confirm', state.selectItems);
+      const tempList: any = [];
+      state.selectItems.forEach((item: any) => {
+        tempList.push({
+          coverImg: PageEnum.INSTRUMENT_DEFAULT_COVER,
+          title: item.name,
+          materialId: item.id,
+          content: item.id
+        });
+      });
+      emit('confirm', tempList);
     };
     return () => (
       <div class={styles.container}>

+ 313 - 0
src/views/prepare-lessons/model/source-knowledge/index.module.less

@@ -0,0 +1,313 @@
+.container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+
+  .iconBack {
+    width: 36px;
+    height: 36px;
+  }
+
+  :global {
+    .n-breadcrumb>ul {
+      display: flex;
+      align-items: center;
+
+      .n-breadcrumb-item {
+        display: flex;
+        align-items: center;
+      }
+
+      .n-breadcrumb-item__separator {
+        display: none;
+      }
+
+      .n-breadcrumb-item__link {
+        padding: 5px 18px;
+        background: #FFFFFF;
+        border-radius: 16px;
+        color: #21225D;
+        line-height: 20px;
+      }
+    }
+
+    .n-breadcrumb .n-breadcrumb-item:last-child .n-breadcrumb-item__link {
+      color: #fff;
+      background: var(--product-color);
+    }
+
+  }
+
+  &> :global(.n-space) {
+    height: 36px;
+    flex-shrink: 0;
+  }
+
+  .separator {
+    width: 9px;
+    height: 15px;
+    margin: 0 16px;
+  }
+}
+
+.wrap {
+  padding-top: 15px;
+  flex: 1;
+  transition: padding .3s;
+  overflow: hidden;
+
+  &.wrapBottom {
+    padding-bottom: 108px;
+
+  }
+}
+
+.contentWrap {
+  position: relative;
+  flex: 1;
+  display: flex;
+  padding: 0 55px 0 0;
+  overflow: hidden;
+  gap: 0 32px;
+}
+
+.content {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+  border-radius: 20px;
+  // max-height: 90vh;
+}
+
+.contentWrap {
+  :global {
+    .n-scrollbar-container {
+      max-height: 100%;
+    }
+  }
+
+  .scrollBar {
+    margin-top: 12px;
+    padding: 0 20px;
+    // max-height: calc(100% - 64px - 52px - 36px);
+
+    &.empty {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+  }
+
+
+  .directoryList {
+    width: 300px;
+    background: #FFFFFF;
+    border-radius: 17px;
+    flex-shrink: 0;
+    height: 100%;
+    overflow-x: hidden;
+    overflow-y: auto;
+
+    &::-webkit-scrollbar {
+      width: 0;
+      display: none;
+    }
+  }
+
+  .treeParent {
+    transition: height 1s ease-in-out;
+  }
+
+  .treeChild {
+    line-height: 54px;
+  }
+
+  .treeItem {
+    display: flex;
+    align-items: center;
+    line-height: 54px;
+    border-radius: 10px;
+    padding: 0 5px;
+    cursor: pointer;
+    border-radius: 10px;
+    font-size: max(17px, 13Px);
+
+    &:hover {
+      background: #F5F6FA;
+    }
+
+    .title {
+      padding-left: 8px;
+      overflow: hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      max-width: 280px !important;
+      color: rgba(0, 0, 0, .5);
+      display: flex;
+      align-items: center;
+
+      .dir {
+        flex-shrink: 1;
+        display: inline-block;
+        width: 16px;
+        height: 18px;
+        background: url('../../prepare-lessons/components/directory-main/images/icon-d.png') no-repeat center;
+        background-size: contain;
+        margin-right: 6px;
+      }
+
+      &.titleSelect {
+        color: var(--n-color);
+        font-weight: bold;
+
+        .dir {
+          background: url('../../prepare-lessons/components/directory-main/images/icon-d-active.png') no-repeat center;
+          background-size: contain;
+        }
+      }
+    }
+
+    .arrow {
+      display: inline-block;
+      width: 14px;
+      height: 15px;
+      background: url('../../prepare-lessons/components/directory-main/images/arrow-default.png') no-repeat center;
+      background-size: contain;
+
+      &.arrowSelect {
+        background: url('../../prepare-lessons/components/directory-main/images/arrow-active.png') no-repeat center;
+        background-size: contain;
+      }
+    }
+
+    .childArrow {
+      width: 12px;
+    }
+
+    &.childItem {
+      padding-left: 30px;
+      font-size: max(15px, 12Px);
+
+      .title {
+        color: #131415;
+      }
+    }
+
+    &.childSelect {
+      background: #F5F6FA;
+
+      .title {
+        color: var(--n-color);
+        font-weight: bold;
+      }
+    }
+  }
+}
+
+.musicStaff {
+  // display: flex;
+  // flex-direction: column;
+  // position: relative;
+  // left: -8px;
+  flex: 1;
+  background-color: #fff;
+  border-radius: 16px;
+  // height: 100%;
+  z-index: 1;
+  overflow: hidden;
+  padding: 27px 0 27px 27px;
+
+  &::-webkit-scrollbar {
+    width: 0;
+    display: none;
+  }
+
+  .empty {
+    :global {
+      .n-spin-content {
+        min-height: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+  }
+
+  :global {
+    .n-spin-container {
+      overflow-y: auto;
+      height: 100%;
+    }
+
+  }
+
+  .musicTitle {
+    padding: 27px 27px 13px;
+    font-size: 20px;
+    font-weight: 600;
+    color: #000000;
+    line-height: 30px;
+    text-align: center;
+  }
+
+  .musicContent {
+    flex: 1;
+    // overflow-y: auto;
+    // height: 100%;
+    // padding: 27px;
+    padding-right: 27px;
+
+    &>img {
+      width: 100%;
+    }
+
+    section,
+    &>div {
+      font-size: inherit !important;
+    }
+  }
+}
+
+.changeSizeSection {
+  position: absolute;
+  right: 10px;
+  bottom: 50%;
+  width: 35px;
+  transform: translate(0, 50%);
+  background: #fff;
+  border-radius: 7px;
+  display: flex;
+  align-items: center;
+  flex-direction: column;
+  padding: 13px 0;
+
+  .iconT {
+    width: 15px;
+    height: 15px;
+  }
+
+  .iconAddT,
+  .iconPlusT {
+    width: 23px;
+    height: 23px;
+    cursor: pointer;
+  }
+
+  .iconAddT {
+    margin-top: 13px;
+    margin-bottom: 8px;
+  }
+
+  .iconPlusT {
+    margin-top: 8px;
+  }
+
+  :global {
+    .n-slider {
+      height: 125px;
+      --n-handle-size: 15px !important;
+      --n-rail-height: 0 !important;
+    }
+
+  }
+}

+ 236 - 0
src/views/prepare-lessons/model/source-knowledge/index.tsx

@@ -0,0 +1,236 @@
+import { defineComponent, onMounted, reactive, ref } from 'vue';
+import styles from './index.module.less';
+import {
+  NBreadcrumb,
+  NBreadcrumbItem,
+  // NScrollbar,
+  NSlider,
+  NSpace,
+  NSpin
+} from 'naive-ui';
+import icon_back from '../../xiaoku-music/images/icon_back.png';
+// import icon_default from '../../xiaoku-music/images/icon_default.png';
+// import icon_separator from '../../xiaoku-music/images/icon_separator.png';
+import iconT from '../images/icon-t.png';
+import iconAddT from '../images/icon-add-t.png';
+import iconPlusT from '../images/icon-plus-t.png';
+import {
+  api_lessonCoursewareDetail_listKnowledge,
+  api_lessonCoursewareKnowledgeDetail
+} from '../api';
+import TheEmpty from '/src/components/TheEmpty';
+import { useRouter } from 'vue-router';
+
+export default defineComponent({
+  name: 'cotnent-knowledge',
+  setup() {
+    const router = useRouter();
+    const show = ref(false);
+    const content = ref(false);
+    const musicContentRef = ref();
+    const state = reactive({
+      fontSize: 18,
+      tableList: [] as any,
+      selectKey: null,
+      details: {} as any
+    });
+
+    const getDetails = async () => {
+      show.value = true;
+      content.value = true;
+      try {
+        const { data } = await api_lessonCoursewareDetail_listKnowledge({
+          type: 'COURSEWARE'
+        });
+
+        state.tableList = data || [];
+        if (state.tableList.length) {
+          const item =
+            state.tableList[0].lessonCoursewareDetailKnowledgeDetailList;
+          state.tableList[0].selected = true;
+          if (item && item.length) {
+            const child = item[0];
+            state.selectKey = child.id;
+            await getDetail();
+          }
+        }
+      } catch {
+        //
+      }
+      content.value = false;
+      show.value = false;
+    };
+
+    const getDetail = async () => {
+      content.value = true;
+      try {
+        const { data } = await api_lessonCoursewareKnowledgeDetail({
+          id: state.selectKey
+        });
+
+        state.details = data;
+      } catch {
+        //
+      }
+      content.value = false;
+    };
+
+    onMounted(() => {
+      getDetails();
+    });
+    return () => (
+      <div class={styles.container}>
+        <NSpace align="center" wrapItem={false} size={16}>
+          <img
+            style={{ cursor: 'pointer' }}
+            src={icon_back}
+            class={styles.iconBack}
+            onClick={() => {
+              //
+              router.push('/');
+            }}
+          />
+          <NBreadcrumb separator="">
+            <NBreadcrumbItem
+              onClick={() => {
+                //
+              }}>
+              乐理知识
+            </NBreadcrumbItem>
+          </NBreadcrumb>
+        </NSpace>
+        <div class={[styles.wrap]}>
+          <div class={styles.content}>
+            <div class={styles.contentWrap}>
+              <div class={styles.directoryList}>
+                <div
+                  class={[
+                    styles.scrollBar,
+                    !show.value && state.tableList.length <= 0
+                      ? styles.empty
+                      : ''
+                  ]}
+                  style={{ minHeight: '100%' }}>
+                  <NSpin show={show.value}>
+                    <div class={[styles.listSection]}>
+                      {state.tableList.map((item: any, index: number) => (
+                        <div class={styles.treeParent} key={'parent' + index}>
+                          <div
+                            class={[styles.treeItem, styles.parentItem]}
+                            onClick={() => {
+                              state.tableList.forEach((child: any) => {
+                                if (item.id !== child.id) {
+                                  child.selected = false;
+                                }
+                              });
+                              item.selected = item.selected ? false : true;
+                            }}>
+                            {item.lessonCoursewareDetailKnowledgeDetailList &&
+                              item.lessonCoursewareDetailKnowledgeDetailList
+                                .length > 0 && (
+                                <span
+                                  class={[
+                                    styles.arrow,
+                                    item.selected ? styles.arrowSelect : ''
+                                  ]}></span>
+                              )}
+                            <p
+                              class={[
+                                styles.title,
+                                item.selected ? styles.titleSelect : ''
+                              ]}>
+                              <span
+                                class={[
+                                  styles.dir,
+                                  item.selected ? styles.dirSelect : ''
+                                ]}></span>
+                              {item.name}
+                            </p>
+                          </div>
+
+                          {item.selected &&
+                            item.lessonCoursewareDetailKnowledgeDetailList &&
+                            item.lessonCoursewareDetailKnowledgeDetailList.map(
+                              (child: any, j: number) => (
+                                <div
+                                  key={'child' + j}
+                                  class={[
+                                    styles.treeItem,
+                                    styles.childItem,
+                                    styles.animation,
+                                    state.selectKey === child.id
+                                      ? styles.childSelect
+                                      : ''
+                                  ]}
+                                  onClick={() => {
+                                    if (state.selectKey === child.id) return;
+                                    state.selectKey = child.id;
+                                    getDetail();
+                                    musicContentRef.value.$el.scrollTo(0, 0);
+                                  }}>
+                                  <span class={styles.childArrow}></span>
+                                  <p class={styles.title}>{child.name}</p>
+                                </div>
+                              )
+                            )}
+                        </div>
+                      ))}
+                    </div>
+                  </NSpin>
+                  {!show.value && state.tableList.length <= 0 && (
+                    <TheEmpty style={{ height: '100%' }} />
+                  )}
+                </div>
+              </div>
+
+              <div class={styles.musicStaff}>
+                <NSpin
+                  show={content.value}
+                  ref={musicContentRef}
+                  class={
+                    !content.value && !state.details?.desc ? styles.empty : ''
+                  }>
+                  {state.details?.desc ? (
+                    <div
+                      class={styles.musicContent}
+                      v-html={state.details?.desc}
+                      style={{ fontSize: state.fontSize + 'px' }}></div>
+                  ) : (
+                    ''
+                  )}
+                  {!content.value && !state.details?.desc && <TheEmpty />}
+                </NSpin>
+              </div>
+
+              <div class={styles.changeSizeSection}>
+                <img src={iconT} class={styles.iconT} />
+                <img
+                  src={iconAddT}
+                  class={styles.iconAddT}
+                  onClick={() => {
+                    if (state.fontSize >= 32) return;
+                    state.fontSize += 1;
+                  }}
+                />
+                <NSlider
+                  v-model:value={state.fontSize}
+                  vertical
+                  min={12}
+                  max={32}
+                />
+                <img
+                  src={iconPlusT}
+                  class={styles.iconPlusT}
+                  onClick={() => {
+                    if (state.fontSize <= 12) return;
+                    state.fontSize -= 1;
+                  }}
+                />
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    );
+  }
+});

+ 2 - 2
src/views/prepare-lessons/model/source-rhythm/index.tsx

@@ -12,10 +12,10 @@ export default defineComponent({
     const loading = ref(true);
     // const src = `${origin}/classroom-app/#/tempo-practice?v=${Date.now()}&Authorization=${
     //   userStore.getToken
-    // }&win=modal`;
+    // }&platform=modal`;
     const src = `http://localhost:9002/#/tempo-practice?v=${Date.now()}&Authorization=${
       userStore.getToken
-    }&win=modal`;
+    }&platform=modal`;
 
     // emit('confirm');
     const onSubmit = () => {

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

@@ -11,6 +11,11 @@
   box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.1);
   z-index: 10;
   transition: all .3s;
+
+  &.previewcontainer {
+    left: 0;
+    padding-right: 380px;
+  }
 }
 
 .hidden {

+ 10 - 1
src/views/xiaoku-music/component/play-item/index.tsx

@@ -31,6 +31,10 @@ export default defineComponent({
     playState: {
       type: String as PropType<'play' | 'pause'>,
       default: 'pause'
+    },
+    type: {
+      type: String,
+      default: ''
     }
   },
   emits: ['change'],
@@ -84,7 +88,12 @@ export default defineComponent({
     );
 
     return () => (
-      <div class={[styles.container, props.show ? styles.show : styles.hidden]}>
+      <div
+        class={[
+          styles.container,
+          props.type === 'preview' && styles.previewcontainer,
+          props.show ? styles.show : styles.hidden
+        ]}>
         <div class={[styles.item]}>
           <div
             class={[