Bladeren bron

添加页面

lex 1 jaar geleden
bovenliggende
commit
e47e9170de
66 gewijzigde bestanden met toevoegingen van 5616 en 1336 verwijderingen
  1. 1 1
      dev-dist/sw.js
  2. 5 1
      src/components/TheSearch/index.tsx
  3. BIN
      src/components/layout/images/classHistoryIcon.png
  4. 9 1
      src/components/layout/layoutSilder.tsx
  5. 22 10
      src/components/layout/layoutTop.tsx
  6. 8 10
      src/components/layout/modals/placeholderTone.tsx
  7. 52 0
      src/router/routes/index.ts
  8. 43 0
      src/views/content-information/api.ts
  9. 161 0
      src/views/content-information/content-instrument/components/list/index.module.less
  10. 125 0
      src/views/content-information/content-instrument/components/list/index.tsx
  11. 73 0
      src/views/content-information/content-instrument/components/list/search-group-resources.tsx
  12. 423 0
      src/views/content-information/content-instrument/detail.module.less
  13. 298 0
      src/views/content-information/content-instrument/detail.tsx
  14. 147 0
      src/views/content-information/content-instrument/index.module.less
  15. 88 0
      src/views/content-information/content-instrument/index.tsx
  16. 293 0
      src/views/content-information/content-knowledge/index.module.less
  17. 216 0
      src/views/content-information/content-knowledge/index.tsx
  18. 168 0
      src/views/content-information/content-music/components/list/index.module.less
  19. 128 0
      src/views/content-information/content-music/components/list/index.tsx
  20. 139 0
      src/views/content-information/content-music/components/list/search-group-resources.tsx
  21. 296 0
      src/views/content-information/content-music/detail.module.less
  22. 284 0
      src/views/content-information/content-music/detail.tsx
  23. 147 0
      src/views/content-information/content-music/index.module.less
  24. 84 0
      src/views/content-information/content-music/index.tsx
  25. 163 0
      src/views/content-information/content-musician/components/list/index.module.less
  26. 126 0
      src/views/content-information/content-musician/components/list/index.tsx
  27. 73 0
      src/views/content-information/content-musician/components/list/search-group-resources.tsx
  28. 147 0
      src/views/content-information/content-musician/index.module.less
  29. 87 0
      src/views/content-information/content-musician/index.tsx
  30. BIN
      src/views/content-information/images/icon-add-t.png
  31. BIN
      src/views/content-information/images/icon-arrow.png
  32. BIN
      src/views/content-information/images/icon-pan.png
  33. BIN
      src/views/content-information/images/icon-plus-t.png
  34. BIN
      src/views/content-information/images/icon-t.png
  35. BIN
      src/views/home/img/f1-1.png
  36. BIN
      src/views/home/img/f1.png
  37. BIN
      src/views/home/img/f2-1.png
  38. BIN
      src/views/home/img/f2.png
  39. BIN
      src/views/home/img/f3-1.png
  40. BIN
      src/views/home/img/f3.png
  41. BIN
      src/views/home/img/f4-1.png
  42. BIN
      src/views/home/img/f4.png
  43. BIN
      src/views/home/img/icon-bk.png
  44. BIN
      src/views/home/img/icon-class.png
  45. BIN
      src/views/home/img/icon-echats.png
  46. BIN
      src/views/home/img/icon-left-window.png
  47. BIN
      src/views/home/img/icon-tag.png
  48. BIN
      src/views/home/img/left-bg.png
  49. BIN
      src/views/home/img/t1-1.png
  50. BIN
      src/views/home/img/t1-2.png
  51. BIN
      src/views/home/img/t1-3.png
  52. BIN
      src/views/home/img/t1-4.png
  53. BIN
      src/views/home/img/t1.png
  54. BIN
      src/views/home/img/t2-1.png
  55. BIN
      src/views/home/img/t2-3.png
  56. BIN
      src/views/home/img/t2-4.png
  57. BIN
      src/views/home/img/t2.png
  58. BIN
      src/views/home/img/teacher-man.png
  59. BIN
      src/views/home/img/teacher-woman.png
  60. BIN
      src/views/home/img/编组 17备份@2x.png
  61. BIN
      src/views/home/img/路径 13@2x(1).png
  62. 617 0
      src/views/home/index copy.tsx
  63. 899 0
      src/views/home/index.module copy.less
  64. 180 802
      src/views/home/index.module.less
  65. 111 509
      src/views/home/index.tsx
  66. 3 2
      src/views/xiaoku-music/component/play-item/index.module.less

+ 1 - 1
dev-dist/sw.js

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

+ 5 - 1
src/components/TheSearch/index.tsx

@@ -15,6 +15,10 @@ export default defineComponent({
     border: {
       type: Boolean,
       default: true
+    },
+    placeholder: {
+      type: String,
+      default: '请输入搜索关键词'
     }
   },
   emits: ['search'],
@@ -26,7 +30,7 @@ export default defineComponent({
       <NInput
         class={[styles.TheSearch, props.border ? '' : styles.noBorder]}
         round={props.round}
-        placeholder="请输入搜索关键词"
+        placeholder={props.placeholder}
         clearable
         v-model:value={searchData.value}
         onClear={() => emit('search', '')}

BIN
src/components/layout/images/classHistoryIcon.png


+ 9 - 1
src/components/layout/layoutSilder.tsx

@@ -34,7 +34,15 @@ export default defineComponent({
         normalIcon: indexNormal,
         isActive: true,
         id: 1,
-        path: '/'
+        path: '/',
+        lightList: [
+          '/content-instruments',
+          '/content-instruments-detail',
+          '/content-musician',
+          '/content-music',
+          '/content-music-detail',
+          '/content-knowledge'
+        ]
       },
       {
         activeIcon: classIcon,

+ 22 - 10
src/components/layout/layoutTop.tsx

@@ -18,6 +18,7 @@ import boxBg from './images/boxBg.png';
 import { useRouter } from 'vue-router';
 import { storeToRefs } from 'pinia';
 import opinionIcon from './images/opinionIcon.png';
+import classHistoryIcon from './images/classHistoryIcon.png';
 import 'animate.css';
 import ForgotPassword from '/src/views/setting/modal/forgotPassword';
 import ImGroup from './imGroup';
@@ -89,22 +90,21 @@ export default defineComponent({
       window.removeEventListener('message', onImMessage);
     });
 
-
-    const imglist = [inFront,inBack,submitBtn,sealing,boxBg]
-    const loadImg = (imgList:any) => {
+    const imglist = [inFront, inBack, submitBtn, sealing, boxBg];
+    const loadImg = (imgList: any) => {
       for (let i = 0; i < imgList.length; i++) {
-        const img = new Image()
+        const img = new Image();
         // let currentSrc = ''
-        img.src = imgList[i]
+        img.src = imgList[i];
         img.onload = function (e) {
-          console.log('加载完毕', e,img.complete );
-        }
+          console.log('加载完毕', e, img.complete);
+        };
         img.onerror = function (e) {
           console.log('加载错误', e);
-        }
+        };
       }
-    }
-    loadImg(imglist)
+    };
+    loadImg(imglist);
     return () => (
       <>
         <div class={styles.layoutTop}>
@@ -119,6 +119,18 @@ export default defineComponent({
             </p>
           </div>
           <div class={styles.layoutRight}>
+            {/* <NTooltip>
+              {{
+                trigger: () => (
+                  <div class={styles.optons} onClick={() => {
+                    router.push('/')
+                  }}>
+                    <NImage src={classHistoryIcon} previewDisabled></NImage>
+                  </div>
+                ),
+                default: '上课记录'
+              }}
+            </NTooltip> */}
             <NTooltip>
               {{
                 trigger: () => (

+ 8 - 10
src/components/layout/modals/placeholderTone.tsx

@@ -2,11 +2,11 @@ import { defineComponent, ref, watch } from 'vue';
 import styles from './holder.module.less';
 import { NButton, NImage, NSpace } from 'naive-ui';
 import radiusIcon from '../images/radiusIcon.png';
-import moveTop from '@/views/login/images/moveTopBg.png'
-import dingPng from '@/views/login/images/ding.png'
-import closeAble from '@/views/login/images/closeAble.png'
+import moveTop from '@/views/login/images/moveTopBg.png';
+import dingPng from '@/views/login/images/ding.png';
+import closeAble from '@/views/login/images/closeAble.png';
 export default defineComponent({
-  props: ['item'],
+  props: ['item', 'message'],
   emits: ['close'],
   name: 'placeholderTone',
   setup(props, { emit }) {
@@ -19,21 +19,19 @@ export default defineComponent({
             emit('close')
           }} alt="" /> */}
           <h2>温馨提示</h2>
-          <p>调音器功能暂未开放,敬请期待!</p>
+          <p>{props.message || '调音器功能暂未开放,敬请期待!'}</p>
           {/* <NButton>确定</NButton> */}
           <NSpace style={{ padding: '25px 0 0 0' }} justify="center">
             <NButton
               {...{
-                id
-                  : 'submitBtn'
+                id: 'submitBtn'
               }}
               class={styles.submitAppBtn}
               round
               type="primary"
               onClick={() => {
-                emit('close')
-              }}
-            >
+                emit('close');
+              }}>
               我知道了
             </NButton>
           </NSpace>

+ 52 - 0
src/router/routes/index.ts

@@ -151,6 +151,58 @@ export const constantRoutes: RouteRecordRaw[] = [
         meta: {
           title: '制谱'
         }
+      },
+      {
+        path: '/content-instruments',
+        name: 'content-instruments',
+        component: () =>
+          import('@/views/content-information/content-instrument'),
+        meta: {
+          title: '乐器百科'
+        }
+      },
+      {
+        path: '/content-instruments-detail',
+        name: 'content-instruments-detail',
+        component: () =>
+          import('@/views/content-information/content-instrument/detail'),
+        meta: {
+          title: '乐器百科详情'
+        }
+      },
+      {
+        path: '/content-musician',
+        name: 'content-musician',
+        component: () => import('@/views/content-information/content-musician'),
+        meta: {
+          title: '音乐家'
+        }
+      },
+      {
+        path: '/content-music',
+        name: 'content-music',
+        component: () => import('@/views/content-information/content-music'),
+        meta: {
+          title: '曲目鉴赏'
+        }
+      },
+      {
+        path: '/content-music-detail',
+        name: 'content-music-detail',
+        component: () =>
+          import('@/views/content-information/content-music/detail'),
+        meta: {
+          title: '曲目鉴赏'
+        }
+      },
+      {
+        path: '/content-knowledge',
+        name: 'content-knowledge',
+        component: () =>
+          import('@/views/content-information/content-knowledge'),
+        meta: {
+          title: '乐理知识'
+        }
       }
     ]
   },

+ 43 - 0
src/views/content-information/api.ts

@@ -0,0 +1,43 @@
+import request from '@/utils/request';
+
+/**
+ * 分类列表
+ */
+export const api_knowledgeWikiCategoryType_page = (params: any) => {
+  return request.post('/edu-app/knowledgeWikiCategoryType/page', {
+    data: params
+  });
+};
+
+/**
+ * 分页列表
+ */
+export const api_knowledgeWiki_page = (params: any) => {
+  return request.post('/edu-app/knowledgeWiki/page', {
+    data: params
+  });
+};
+
+/**
+ * 详情
+ */
+export const api_knowledgeWiki_detail = (params: any) => {
+  return request.get('/edu-app/knowledgeWiki/detail/' + params.id, {});
+};
+
+/**
+ * 知识详情
+ */
+export const api_lessonCoursewareDetail_listKnowledge = (params: any) => {
+  return request.post('/edu-app/lessonCoursewareDetail/listKnowledge', {
+    data: params
+  });
+};
+/**
+ * 知识详情
+ */
+export const api_lessonCoursewareKnowledgeDetail = (params: any) => {
+  return request.get(
+    '/edu-app/lessonCoursewareKnowledgeDetail/detail/' + params.id
+  );
+};

+ 161 - 0
src/views/content-information/content-instrument/components/list/index.module.less

@@ -0,0 +1,161 @@
+.searchGroup {
+  position: relative;
+  padding: 0;
+
+
+  .btnType {
+    gap: 0px 24px !important;
+
+    :global {
+      .n-button {
+        height: 37px;
+        padding: 0 24px;
+        font-size: 18px;
+        color: rgba(0, 0, 0, .6);
+
+        &.n-button--primary-type {
+          font-weight: bold;
+          color: #fff;
+        }
+      }
+    }
+  }
+
+
+  .inputSearch {
+    width: 360px;
+    height: 42px;
+    font-size: 16px;
+    --n-height: 42px !important;
+
+    img {
+      width: 18px;
+      height: 18px;
+    }
+
+    :global {
+      .n-input-wrapper {
+        padding-left: 12px;
+        padding-right: 4px;
+        height: 42px !important;
+      }
+
+      .n-button {
+        height: 34px;
+        font-size: 15px;
+        font-weight: 500;
+        width: auto;
+      }
+    }
+  }
+
+  .searchCatatory {
+    display: flex;
+    justify-content: space-between;
+    padding-bottom: 20px;
+
+    .addTrain {
+      height: 37px;
+      border-radius: 8px;
+      font-size: 18px;
+      background-color: #E8F4FF;
+      color: #0378EC;
+
+      img {
+        width: 16px;
+        height: 16px;
+        margin-right: 8px;
+      }
+    }
+  }
+}
+
+.list {
+  margin-top: 12px;
+  display: flex;
+  flex-flow: row wrap;
+  justify-content: flex-start;
+  gap: 45px 0;
+  min-height: 232px;
+  margin-left: -22px;
+  margin-right: -22px;
+
+  .itemWrap {
+    width: calc(100% / 6);
+    padding-bottom: calc(100% / 6 * 0.84913);
+    position: relative;
+
+    .itemWrapBox {
+      position: absolute;
+      left: 0;
+      top: 0;
+      width: 100%;
+      height: 100%;
+      padding: 0 22px;
+    }
+  }
+
+  .itemCard {
+    position: relative;
+    cursor: pointer;
+
+    &:hover {
+      .itemImgSection {
+        background: linear-gradient(360deg, #DBF1FF 0%, #E7F9FF 100%);
+        box-shadow: 2px 2 8px 0px rgba(0, 0, 0, 0.1);
+        border-radius: 13px;
+        border: 3px solid rgba(0, 122, 254, 1);
+        box-sizing: border-box;
+        transition: all .2s ease;
+      }
+    }
+
+    .itemTag {
+      position: absolute;
+      right: 0;
+      top: 0;
+      display: inline-block;
+      font-size: 12px;
+      font-weight: 600;
+      color: #FFFFFF;
+      line-height: 17px;
+      text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.1);
+      line-height: 23px;
+      padding: 0 7px;
+      background: linear-gradient(135deg, #02BAFF 0%, #007AFE 100%);
+      box-shadow: 2px 2 8px 0px rgba(0, 0, 0, 0.1);
+      border-radius: 0px 13px 0px 13px;
+    }
+
+    .itemImgSection {
+      width: 100%;
+      height: 197px;
+      background: linear-gradient(360deg, #DBF1FF 0%, #E7F9FF 100%);
+      box-shadow: 2px 2px 8px 0px rgba(0, 0, 0, 0.1);
+      border-radius: 13px;
+      overflow: hidden;
+
+      .img {
+        width: 100%;
+        height: 100%;
+        height: 197px;
+
+        display: flex;
+
+        img {
+          width: 100%;
+          height: 100%;
+        }
+      }
+    }
+
+    .itemTitle {
+      padding-top: 10px;
+      font-size: 18px;
+      font-weight: 600;
+      color: #131415;
+      line-height: 25px;
+      text-align: center;
+    }
+  }
+}

+ 125 - 0
src/views/content-information/content-instrument/components/list/index.tsx

@@ -0,0 +1,125 @@
+import { PropType, defineComponent, onMounted, reactive } from 'vue';
+import styles from './index.module.less';
+import SearchGroupResources from './search-group-resources';
+import { NImage, NSpin } from 'naive-ui';
+import TheEmpty from '/src/components/TheEmpty';
+import Pagination from '/src/components/pagination';
+import { api_knowledgeWiki_page } from '../../../api';
+import { useRouter } from 'vue-router';
+
+export default defineComponent({
+  name: 'instrument-list',
+  props: {
+    categoryId: {
+      type: String,
+      default: ''
+    },
+    categoryChildList: {
+      type: Array as PropType<any>,
+      default: () => []
+    }
+  },
+  setup(props) {
+    const router = useRouter();
+    const state = reactive({
+      searchWord: '',
+      loading: false,
+      pageTotal: 0,
+      pagination: {
+        page: 1,
+        rows: 20
+      },
+      searchGroup: {
+        type: 'INSTRUMENT', //
+        keyword: '',
+        wikiCategoryId: props.categoryId
+      },
+      tableList: [] as any,
+      teachingStatus: false,
+      show: false,
+      item: {} as any
+    });
+
+    const getList = async () => {
+      state.loading = true;
+      try {
+        const { data } = await api_knowledgeWiki_page({
+          ...state.pagination,
+          ...state.searchGroup
+        });
+        state.tableList = data.rows || [];
+        state.pageTotal = Number(data.total);
+      } catch {
+        //
+      }
+      state.loading = false;
+    };
+
+    const onSearch = async (item: any) => {
+      state.pagination.page = 1;
+      state.searchGroup = Object.assign(state.searchGroup, item);
+      getList();
+    };
+
+    onMounted(() => {
+      getList();
+    });
+
+    return () => (
+      <div class={styles.instrumentList}>
+        <SearchGroupResources
+          categoryChildList={props.categoryChildList}
+          onSearch={(item: any) => onSearch(item)}
+        />
+
+        <NSpin v-model:show={state.loading} style={{ 'min-height': '50vh' }}>
+          <div class={styles.list}>
+            {state.tableList.map((item: any) => (
+              <div
+                class={styles.itemWrap}
+                onClick={() => {
+                  router.push({
+                    path: '/content-instruments-detail',
+                    query: {
+                      id: item.id,
+                      name: item.name
+                    }
+                  });
+                }}>
+                <div class={styles.itemWrapBox}>
+                  <div class={styles.itemCard}>
+                    <span class={styles.itemTag}>
+                      {item.knowledgeWikiCategoryName}
+                    </span>
+                    <div class={styles.itemImgSection}>
+                      <NImage
+                        src={item.avatar}
+                        class={styles.img}
+                        objectFit="cover"
+                        previewDisabled
+                      />
+                    </div>
+                    <div class={styles.itemTitle}>{item.name}</div>
+                  </div>
+                </div>
+              </div>
+            ))}
+
+            {!state.loading && state.tableList.length <= 0 && (
+              <TheEmpty
+                style={{ minHeight: '50vh' }}
+                description="暂无乐器百科"
+              />
+            )}
+          </div>
+        </NSpin>
+        <Pagination
+          v-model:page={state.pagination.page}
+          v-model:pageSize={state.pagination.rows}
+          v-model:pageTotal={state.pageTotal}
+          onList={getList}
+        />
+      </div>
+    );
+  }
+});

+ 73 - 0
src/views/content-information/content-instrument/components/list/search-group-resources.tsx

@@ -0,0 +1,73 @@
+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: () => []
+    }
+  },
+  emits: ['search', 'add'],
+  expose: ['init'],
+  setup(props, { emit }) {
+    // const catchStore = useCatchStore();
+    const forms = reactive({
+      keyword: '',
+      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}>
+            <NButton
+              type={forms.wikiCategoryId === '' ? 'primary' : 'default'}
+              secondary={forms.wikiCategoryId === '' ? false : true}
+              round
+              size="small"
+              focusable={false}
+              onClick={() => {
+                forms.wikiCategoryId = '';
+                onSearch();
+              }}>
+              全部
+            </NButton>
+            {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>
+    );
+  }
+});

+ 423 - 0
src/views/content-information/content-instrument/detail.module.less

@@ -0,0 +1,423 @@
+.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;
+
+  }
+}
+
+.content {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+  background: #DDF2FF;
+  border-radius: 20px;
+  // max-height: 90vh;
+}
+
+.tools {
+  padding: 20px;
+  display: flex;
+  align-items: center;
+  flex-shrink: 0;
+
+  :global {
+    .n-input {
+      margin-left: auto;
+      width: 361px;
+    }
+
+    .n-input__input-el {
+      height: 100%;
+      line-height: 100%;
+    }
+  }
+}
+
+.contentWrap {
+  position: relative;
+  flex: 1;
+  display: flex;
+  padding: 20px 55px 20px 20px;
+  overflow: hidden;
+  gap: 0 32px;
+}
+
+.musicList {
+  background-color: #fff;
+  border-radius: 16px;
+
+  width: 512px;
+  min-width: 294px;
+  height: 100%;
+  overflow-x: hidden;
+  overflow-y: auto;
+  min-width: 330Px;
+
+  &::-webkit-scrollbar {
+    width: 0;
+    display: none;
+  }
+
+  .instrumentGroup {
+    padding-top: 27px;
+    padding-bottom: 20px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+
+    .instrumentImg {
+      width: 125px;
+      height: 125px;
+      overflow: hidden;
+      border-radius: 50%;
+    }
+
+    .instrumentName {
+      padding: 13px 0 5px;
+      font-size: 18px;
+      font-weight: 600;
+      color: #131415;
+      line-height: 25px;
+      letter-spacing: 1px;
+    }
+
+    .instrumentTag {
+      font-size: 13px;
+      color: #777777;
+      line-height: 18px;
+    }
+  }
+
+
+
+  .wrapList {
+    width: 512px;
+    padding: 0 17px;
+    min-width: 294px;
+    min-height: 100%;
+    // background: #fff;
+    border-radius: 16px;
+
+
+    .titlec {
+      padding: 20px 0;
+      font-size: 18px;
+      font-weight: 600;
+      color: #000000;
+      line-height: 25px;
+      border-top: 1px solid #F2F2F2;
+    }
+  }
+
+  .empty {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    height: 50vh;
+    // height: 100%;
+  }
+}
+
+.itemContainer {
+  width: 100%;
+  border-radius: 16px;
+  padding: 4px 8px;
+  // background-color: #fff;
+
+  &:first-child {
+    padding-top: 8px;
+  }
+
+  &:last-child {
+    // border-radius: 0 0 16px 16px;
+    padding-bottom: 8px;
+  }
+}
+
+.item {
+  position: relative;
+  display: flex;
+  align-items: center;
+  padding: 10px;
+  border-radius: 12px;
+
+  cursor: pointer;
+
+  &:hover {
+    background-color: rgba(0, 0, 0, .05);
+  }
+
+  &.active {
+    background-color: #DDF2FF;
+
+    .arrow {
+      opacity: 1;
+    }
+  }
+
+  .img {
+    position: relative;
+    width: 60px;
+    height: 60px;
+    border-radius: 8px;
+    margin-right: 12px;
+    box-shadow: 0 0 10px 4px rgba(27, 35, 55, .1);
+    overflow: hidden;
+    flex-shrink: 0;
+
+    :global {
+      .n-image {
+        width: 60px;
+        height: 60px;
+      }
+    }
+
+    img {
+      transition: opacity .3s;
+      opacity: 0;
+      height: 100%;
+      width: 100%;
+    }
+
+    img[data-loaded="true"] {
+      opacity: 1;
+    }
+  }
+
+  .title {
+    flex: 1;
+    overflow: hidden;
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+
+    .titleName {
+      font-size: 17px;
+      font-weight: 600;
+      color: #131415;
+      line-height: 28px;
+      width: 100%;
+    }
+
+    .titleDes {
+      font-size: 14px;
+      font-weight: 400;
+      color: #777777;
+      line-height: 20px;
+      max-width: 100%;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      overflow: hidden;
+    }
+  }
+
+  .btn {
+    margin-left: auto;
+    width: 84px;
+    height: 40px;
+    background: linear-gradient(to right, #44CAFF, #259DFE);
+    border: none;
+    padding: 0;
+    font-weight: bold !important;
+    flex-shrink: 0;
+    min-width: 62px;
+    min-height: 30px;
+
+    :global {
+      .n-button__content {
+        &>img {
+          margin-left: 10px;
+          width: 9px;
+          height: 12px;
+        }
+      }
+    }
+  }
+
+  .arrow {
+    position: absolute;
+    top: 50%;
+    right: 12px;
+    transform: translate(124%, -50%);
+    opacity: 0;
+  }
+
+  .showPlayLoading {
+    opacity: 0;
+  }
+
+}
+
+.loadingWrap {
+  display: flex;
+  justify-content: center;
+  min-height: 80px;
+}
+
+.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;
+
+  &::-webkit-scrollbar {
+    width: 0;
+    display: none;
+  }
+
+
+  .musicTitle {
+    padding: 27px 27px 13px;
+    font-size: 18px;
+    font-weight: 600;
+    color: #000000;
+    line-height: 25px;
+  }
+
+  .musicContent {
+    flex: 1;
+    overflow-y: auto;
+    height: 100%;
+    padding: 0 27px;
+
+    &>img {
+      width: 100%;
+    }
+
+    section,
+    &>div {
+      font-size: inherit !important;
+    }
+  }
+}
+
+.staffImgs {
+  flex: 1;
+  overflow-y: auto;
+  height: 100%;
+  padding: 0 30px;
+
+  &>img {
+    width: 100%;
+  }
+}
+
+
+:global {
+
+  .van-fade-enter-active,
+  .van-fade-leave-active {
+    transition: all 0.3s;
+  }
+
+  .van-fade-enter-from,
+  .van-fade-leave-to {
+    opacity: 0;
+  }
+}
+
+.changeSizeSection {
+  position: absolute;
+  right: 10px;
+  bottom: 27px;
+  width: 35px;
+  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;
+  }
+
+  .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;
+    }
+
+  }
+}

+ 298 - 0
src/views/content-information/content-instrument/detail.tsx

@@ -0,0 +1,298 @@
+import {
+  NBreadcrumb,
+  NBreadcrumbItem,
+  NButton,
+  NImage,
+  NSlider,
+  NSpace,
+  NSpin
+} from 'naive-ui';
+import { computed, defineComponent, onMounted, reactive } 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 { useRoute, useRouter } from 'vue-router';
+import PlayLoading from '../../xiaoku-music/component/play-loading';
+import TheNoticeBar from '/src/components/TheNoticeBar';
+import TheEmpty from '/src/components/TheEmpty';
+import PlayItem from '../../xiaoku-music/component/play-item';
+import { api_knowledgeWiki_detail } from '../api';
+import { state } from '/src/state';
+
+export default defineComponent({
+  name: 'instrument-detail',
+  setup() {
+    const route = useRoute();
+    const router = useRouter();
+    const forms = reactive({
+      page: 1,
+      rows: 20,
+      status: true,
+      name: '', // 关键词
+      type: route.query.type
+    });
+    const data = reactive({
+      loading: false,
+      finshed: false,
+      reshing: false,
+      details: {} as any,
+      list: [] as any,
+      listActive: 0,
+      playState: 'pause' as 'play' | 'pause',
+      showPlayer: false,
+      showPreivew: false,
+      previewUrl: '',
+      showCloseBtn: true,
+      fontSize: 18 // 默认18
+    });
+
+    /** 选中的item */
+    const activeItem = computed(() => {
+      return data.list[data.listActive] || {};
+    });
+
+    /** 播放曲目 */
+    const handlePlay = (item: any) => {
+      const index = data.list.findIndex((_item: any) => _item.id === item.id);
+      if (index > -1) {
+        if (data.listActive === index) {
+          data.playState = data.playState === 'play' ? 'pause' : 'play';
+        } else {
+          data.playState = 'play';
+        }
+        data.showPlayer = true;
+        data.listActive = index;
+      }
+    };
+
+    /** 音频控制 */
+    const handleChangeAudio = (
+      type: 'play' | 'pause' | 'pre' | 'next' | 'favitor'
+    ) => {
+      if (type === 'play') {
+        data.playState = 'play';
+      } else if (type === 'pause') {
+        data.playState = 'pause';
+      } else if (type === 'pre') {
+        if (data.list[data.listActive - 1]) {
+          handlePlay(data.list[data.listActive - 1]);
+        }
+      } else if (type === 'next') {
+        if (data.list[data.listActive + 1]) {
+          handlePlay(data.list[data.listActive + 1]);
+        }
+      }
+    };
+
+    const getDetail = async () => {
+      data.loading = true;
+      let res = {} as any;
+      try {
+        res = await api_knowledgeWiki_detail({ id: route.query.id });
+      } catch (error) {
+        console.log(error);
+      }
+      if (data.reshing) {
+        data.list = [];
+        data.reshing = false;
+      }
+
+      data.finshed = true;
+      data.list = res.data.knowledgeWikiResources || [];
+      data.list.forEach((item: any) => {
+        item.audioFileUrl = item.url;
+      });
+      const knowledgeWikiCategories = res.data.knowledgeWikiCategories || [];
+      res.data.knowledgeName =
+        knowledgeWikiCategories.length > 0
+          ? knowledgeWikiCategories[0].name
+          : '';
+      data.details = res.data;
+      data.loading = false;
+    };
+
+    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>
+
+        <div class={[styles.wrap, data.showPlayer ? styles.wrapBottom : '']}>
+          <div class={styles.content}>
+            <div class={styles.contentWrap}>
+              <div class={[styles.musicList, 'musicList-container']}>
+                <div class={styles.wrapList}>
+                  <div class={styles.instrumentGroup}>
+                    <NImage
+                      class={styles.instrumentImg}
+                      src={data.details?.avatar}
+                    />
+
+                    <p class={styles.instrumentName}>{data.details.name}</p>
+                    <p class={styles.instrumentTag}>
+                      {data.details.knowledgeName}
+                    </p>
+                  </div>
+
+                  <div class={styles.titlec}>代表作</div>
+
+                  {data.list.map((item: any, index: any) => {
+                    return (
+                      <div class={styles.itemContainer}>
+                        <div
+                          class={[
+                            styles.item
+                            // data.listActive === index && styles.active
+                          ]}
+                          onClick={(e: Event) => {
+                            e.stopPropagation();
+                            handlePlay(item);
+                          }}>
+                          <div class={styles.img}>
+                            <NImage
+                              lazy
+                              objectFit="cover"
+                              previewDisabled={true}
+                              src={item.titleImg || icon_default}
+                              onLoad={e => {
+                                (e.target as any).dataset.loaded = 'true';
+                              }}
+                            />
+                            <PlayLoading
+                              class={[
+                                data.listActive === index &&
+                                data.playState === 'play'
+                                  ? ''
+                                  : styles.showPlayLoading
+                              ]}
+                            />
+                          </div>
+                          <div class={styles.title}>
+                            <div class={styles.titleName}>
+                              <TheNoticeBar text={item.name} />
+                            </div>
+                          </div>
+
+                          <NButton
+                            color="#259CFE"
+                            textColor="#fff"
+                            round
+                            class={styles.btn}
+                            type="primary"
+                            onClick={(e: Event) => {
+                              e.stopPropagation();
+                              handlePlay(item);
+                            }}>
+                            播放
+                            <img
+                              src={
+                                data.listActive === index &&
+                                data.playState === 'play'
+                                  ? icon_pause
+                                  : icon_play
+                              }
+                            />
+                          </NButton>
+
+                          <img class={styles.arrow} src={icon_arrow} />
+                        </div>
+                      </div>
+                    );
+                  })}
+                  {!data.finshed && (
+                    <div class={styles.loadingWrap}>
+                      <NSpin show={true}></NSpin>
+                    </div>
+                  )}
+                  {!data.loading && data.list.length === 0 && (
+                    <div class={styles.empty}>
+                      <TheEmpty description="暂无代表作"></TheEmpty>
+                    </div>
+                  )}
+                </div>
+              </div>
+
+              <div class={styles.musicStaff}>
+                <div class={styles.musicTitle}>乐器简介</div>
+                <div
+                  class={styles.musicContent}
+                  v-html={data.details?.intros}
+                  style={{ fontSize: data.fontSize + 'px' }}></div>
+              </div>
+
+              <div class={styles.changeSizeSection}>
+                <img src={iconT} class={styles.iconT} />
+                <img
+                  src={iconAddT}
+                  class={styles.iconAddT}
+                  onClick={() => {
+                    if (data.fontSize >= 32) return;
+                    data.fontSize += 1;
+                  }}
+                />
+                <NSlider
+                  v-model:value={data.fontSize}
+                  vertical
+                  min={12}
+                  max={32}
+                />
+                <img
+                  src={iconPlusT}
+                  class={styles.iconPlusT}
+                  onClick={() => {
+                    if (data.fontSize <= 12) return;
+                    data.fontSize -= 1;
+                  }}
+                />
+              </div>
+            </div>
+          </div>
+        </div>
+
+        {data.list.length !== 0 && (
+          <PlayItem
+            show={data.showPlayer}
+            playState={data.playState}
+            item={activeItem.value}
+            onChange={value => handleChangeAudio(value)}
+          />
+        )}
+      </div>
+    );
+  }
+});

+ 147 - 0
src/views/content-information/content-instrument/index.module.less

@@ -0,0 +1,147 @@
+.container {
+
+  .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-tabs-tab-pad {
+      width: 80px !important;
+    }
+
+    .n-tabs-nav {
+      padding: 0px 20px 24px;
+    }
+
+    .n-tabs-tab {
+      color: #8B8D98;
+      font-size: max(22px, 14Px);
+      padding-top: 0;
+      padding-bottom: 6px;
+      line-height: 22px;
+
+      &.n-tabs-tab--active {
+        font-weight: 600 !important;
+        color: #131415 !important;
+      }
+    }
+
+    .n-tabs-tab__label {
+      z-index: 10;
+    }
+
+    .n-tabs-bar {
+      height: 10px;
+      background: linear-gradient(90deg, #77BBFF 0%, rgba(163, 231, 255, 0.22) 100%);
+      z-index: 0;
+      bottom: 2px;
+    }
+
+    .n-tab-pane {
+      padding: 0 12px 0 !important;
+    }
+
+    .n-pagination {
+      margin-top: 36px !important;
+    }
+  }
+
+  &> :global(.n-space) {
+    height: 36px;
+    flex-shrink: 0;
+  }
+
+  .separator {
+    width: 9px;
+    height: 15px;
+    margin: 0 16px;
+  }
+}
+
+.wrap {
+  padding-top: 12px;
+  flex: 1;
+  transition: padding 0.3s;
+  // overflow: hidden;
+}
+
+.listWrap {
+  padding: 32px 20px;
+  background-color: #fff;
+  border-radius: 20px;
+  min-height: 100%;
+  // min-height: calc(100% - 104px);
+
+  :global {
+    .n-tabs-tab-pad {
+      width: 80px !important;
+    }
+
+    .n-tabs-nav {
+      padding: 0px 20px 24px;
+    }
+
+    .n-tabs-tab {
+      color: #8B8D98;
+      font-size: max(22px, 14Px);
+      padding-top: 0;
+      padding-bottom: 6px;
+      line-height: 22px;
+
+      &.n-tabs-tab--active {
+        font-weight: 600 !important;
+        color: #131415 !important;
+      }
+    }
+
+    .n-tabs-tab__label {
+      z-index: 10;
+    }
+
+    .n-tabs-bar {
+      height: 10px;
+      background: linear-gradient(90deg, #77BBFF 0%, rgba(163, 231, 255, 0.22) 100%);
+      z-index: 0;
+      bottom: 2px;
+    }
+
+    .n-tab-pane {
+      padding: 0 12px 0 !important;
+    }
+
+    .n-pagination {
+      margin-top: 36px !important;
+    }
+  }
+}

+ 88 - 0
src/views/content-information/content-instrument/index.tsx

@@ -0,0 +1,88 @@
+import {
+  NBreadcrumb,
+  NBreadcrumbItem,
+  NSpace,
+  NTabPane,
+  NTabs
+} from 'naive-ui';
+import { defineComponent, reactive } from 'vue';
+import styles from './index.module.less';
+import icon_back from '../../xiaoku-music/images/icon_back.png';
+// import icon_separator from '../../xiaoku-music/images/icon_separator.png';
+import { useRoute, useRouter } from 'vue-router';
+import List from './components/list';
+import { api_knowledgeWikiCategoryType_page } from '../api';
+
+export default defineComponent({
+  name: 'content-instrument',
+  setup() {
+    const route = useRoute();
+    const router = useRouter();
+    const state = reactive({
+      tabValue: '',
+      categoryList: [] as any
+    });
+
+    const getCategoryList = async () => {
+      try {
+        const { data } = await api_knowledgeWikiCategoryType_page({
+          type: 'INSTRUMENT',
+          page: 1,
+          rows: 99
+        });
+
+        state.categoryList = data.rows || [];
+        if (state.categoryList.length) {
+          state.tabValue = 'name-' + state.categoryList[0].id;
+        }
+      } catch {
+        //
+      }
+    };
+
+    getCategoryList();
+    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({ path: '/' })}
+          />
+          <NBreadcrumb separator="">
+            <NBreadcrumbItem>乐器百科</NBreadcrumbItem>
+          </NBreadcrumb>
+        </NSpace>
+
+        <div class={styles.wrap}>
+          <div class={styles.listWrap}>
+            <NTabs
+              defaultValue="myResources"
+              paneClass={styles.paneTitle}
+              justifyContent="center"
+              // animated
+              paneWrapperClass={styles.paneWrapperContainer}
+              // onUpdate:value={(val: any) => {
+              //   tab.value = val;
+              // }}
+              v-model:value={state.tabValue}>
+              {state.categoryList.map((category: any) => (
+                <NTabPane
+                  name={`name-${category.id}`}
+                  tab={category.name}
+                  // displayDirective="show:lazy"
+                >
+                  <List
+                    categoryId={category.id}
+                    categoryChildList={category.childrenList}
+                  />
+                </NTabPane>
+              ))}
+            </NTabs>
+          </div>
+        </div>
+      </div>
+    );
+  }
+});

+ 293 - 0
src/views/content-information/content-knowledge/index.module.less

@@ -0,0 +1,293 @@
+.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);
+  }
+
+
+  .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: 15px;
+
+      .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;
+  }
+
+  :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: 27px;
+  width: 35px;
+  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;
+  }
+
+  .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;
+    }
+
+  }
+}

+ 216 - 0
src/views/content-information/content-knowledge/index.tsx

@@ -0,0 +1,216 @@
+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;
+      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;
+            getDetail();
+          }
+        }
+      } catch {
+        //
+      }
+      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}>
+                  <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>
+                    {!show.value && state.tableList.length <= 0 && <TheEmpty />}
+                  </NSpin>
+                </div>
+              </div>
+
+              <div class={styles.musicStaff}>
+                <NSpin show={content.value} ref={musicContentRef}>
+                  {/* <div class={styles.musicTitle}>{state.details?.name}</div> */}
+                  <div
+                    class={styles.musicContent}
+                    v-html={state.details?.desc}
+                    style={{ fontSize: state.fontSize + 'px' }}></div>
+                </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>
+    );
+  }
+});

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

@@ -0,0 +1,168 @@
+.searchGroup {
+  position: relative;
+  padding: 0;
+
+
+  .btnType {
+    gap: 0px 24px !important;
+
+    :global {
+      .n-button {
+        height: 37px;
+        padding: 0 24px;
+        font-size: 18px;
+        color: rgba(0, 0, 0, .6);
+
+        &.n-button--primary-type {
+          font-weight: bold;
+          color: #fff;
+        }
+      }
+    }
+  }
+
+
+  .inputSearch {
+    width: 360px;
+    height: 42px;
+    font-size: 16px;
+    --n-height: 42px !important;
+
+    img {
+      width: 18px;
+      height: 18px;
+    }
+
+    :global {
+      .n-input-wrapper {
+        padding-left: 12px;
+        padding-right: 4px;
+        height: 42px !important;
+      }
+
+      .n-button {
+        height: 34px;
+        font-size: 15px;
+        font-weight: 500;
+        width: auto;
+      }
+    }
+  }
+
+  .searchCatatory {
+    display: flex;
+    justify-content: space-between;
+    margin-bottom: 20px;
+
+    &.border {
+      padding-bottom: 24px;
+      border-bottom: 1px solid #F2F2F2;
+    }
+
+    .addTrain {
+      height: 37px;
+      border-radius: 8px;
+      font-size: 18px;
+      background-color: #E8F4FF;
+      color: #0378EC;
+
+      img {
+        width: 16px;
+        height: 16px;
+        margin-right: 8px;
+      }
+    }
+  }
+}
+
+.list {
+  margin-top: 12px;
+  display: flex;
+  flex-flow: row wrap;
+  justify-content: flex-start;
+  gap: 20px 0;
+  min-height: 232px;
+  margin-left: -10px;
+  margin-right: -10px;
+
+  .itemWrap {
+    width: calc(100% / 3);
+    padding-bottom: calc(100% / 3 * 0.1957894);
+    position: relative;
+    height: 0;
+
+    .itemWrapBox {
+      position: absolute;
+      left: 0;
+      top: 0;
+      width: 100%;
+      height: 100%;
+      padding: 0 10px;
+    }
+  }
+
+  .itemCard {
+    position: relative;
+    // cursor: pointer;
+    height: 100%;
+    background: #F4F4F4;
+    border-radius: 13px;
+    transition: all .2s ease;
+    border: 2px solid #F4F4F4;
+
+    &:hover {
+      border: 2px solid rgba(0, 122, 254, 1);
+      transition: all .2s ease;
+    }
+
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 0 17px;
+
+    .musicBg {
+      width: 50px;
+      height: 50px;
+      border-radius: 18px;
+
+      margin-right: 10px;
+    }
+
+    .itemName {
+      display: flex;
+      align-items: center;
+    }
+
+
+    .btn {
+      background: linear-gradient(73deg, #5BECFF 0%, #259CFE 100%) !important;
+      border: none !important;
+
+
+      :global {
+        .n-button__border {
+          border: none;
+        }
+      }
+
+      &:hover,
+      &:focus,
+      &:active {
+        :global {
+          .n-button__state-border {
+            border: none;
+          }
+        }
+      }
+    }
+
+    .iconArrow {
+      display: inline-block;
+      margin-left: 8px;
+      width: 8px;
+      height: 10px;
+      background: url('../../../images/icon-arrow.png') no-repeat center;
+      background-size: contain;
+    }
+  }
+}

+ 128 - 0
src/views/content-information/content-music/components/list/index.tsx

@@ -0,0 +1,128 @@
+import { PropType, defineComponent, onMounted, reactive } from 'vue';
+import styles from './index.module.less';
+import SearchGroupResources from './search-group-resources';
+import { NButton, NImage, NSpin } from 'naive-ui';
+import TheEmpty from '/src/components/TheEmpty';
+import Pagination from '/src/components/pagination';
+import musicBg from '../../../../xiaoku-music/images/icon_default.png';
+import { api_knowledgeWiki_page } from '../../../api';
+import { useRouter } from 'vue-router';
+
+export default defineComponent({
+  name: 'music-list',
+  props: {
+    categoryId: {
+      type: String,
+      default: ''
+    },
+    categoryChildList: {
+      type: Array as PropType<any>,
+      default: () => []
+    }
+  },
+  setup(props) {
+    const router = useRouter();
+    const state = reactive({
+      searchWord: '',
+      loading: false,
+      pageTotal: 0,
+      pagination: {
+        page: 1,
+        rows: 20
+      },
+      searchGroup: {
+        type: 'MUSIC', //
+        keyword: '',
+        wikiCategoryId: props.categoryId
+      },
+      tableList: [] as any,
+      teachingStatus: false,
+      show: false,
+      item: {} as any
+    });
+
+    const getList = async () => {
+      state.loading = true;
+      try {
+        const { data } = await api_knowledgeWiki_page({
+          ...state.pagination,
+          ...state.searchGroup
+        });
+        state.tableList = data.rows || [];
+        state.pageTotal = Number(data.total);
+      } catch {
+        //
+      }
+      state.loading = false;
+    };
+
+    const onSearch = async (item: any) => {
+      state.pagination.page = 1;
+      state.searchGroup = Object.assign(state.searchGroup, item);
+      getList();
+    };
+
+    onMounted(() => {
+      getList();
+    });
+
+    return () => (
+      <div class={styles.instrumentList}>
+        <SearchGroupResources
+          categoryChildList={props.categoryChildList}
+          onSearch={(item: any) => onSearch(item)}
+        />
+
+        <NSpin v-model:show={state.loading} style={{ 'min-height': '50vh' }}>
+          <div class={styles.list}>
+            {state.tableList.map((item: any) => (
+              <div class={styles.itemWrap}>
+                <div class={styles.itemWrapBox}>
+                  <div class={styles.itemCard}>
+                    <div class={styles.itemName}>
+                      <img
+                        src={item.avatar || musicBg}
+                        class={styles.musicBg}
+                      />
+
+                      <span class={styles.name}>{item.name}</span>
+                    </div>
+
+                    <NButton
+                      class={styles.btn}
+                      round
+                      type={'primary'}
+                      onClick={() => {
+                        router.push({
+                          path: '/content-music-detail',
+                          query: {
+                            id: item.id,
+                            name: item.name
+                          }
+                        });
+                      }}>
+                      播放<i class={styles.iconArrow}></i>
+                    </NButton>
+                  </div>
+                </div>
+              </div>
+            ))}
+
+            {!state.loading && state.tableList.length <= 0 && (
+              <TheEmpty
+                style={{ minHeight: '50vh' }}
+                description="暂无音乐人"
+              />
+            )}
+          </div>
+        </NSpin>
+        <Pagination
+          v-model:page={state.pagination.page}
+          v-model:pageSize={state.pagination.rows}
+          v-model:pageTotal={state.pageTotal}
+          onList={getList}
+        />
+      </div>
+    );
+  }
+});

+ 139 - 0
src/views/content-information/content-music/components/list/search-group-resources.tsx

@@ -0,0 +1,139 @@
+import { PropType, computed, defineComponent, onMounted, reactive } from 'vue';
+import styles from './index.module.less';
+import { NButton, NForm, NFormItem, NPopselect, NSpace } from 'naive-ui';
+import TheSearch from '/src/components/TheSearch';
+export default defineComponent({
+  name: 'search-group',
+  props: {
+    categoryChildList: {
+      type: Array as PropType<any>,
+      default: () => []
+    }
+  },
+  emits: ['search', 'add'],
+  expose: ['init'],
+  setup(props, { emit }) {
+    // const catchStore = useCatchStore();
+    const forms = reactive({
+      keyword: '',
+      wikiCategoryId: '',
+      wikiCategoryIdChild: ''
+    });
+
+    const onSearch = () => {
+      emit('search', forms);
+    };
+
+    const childList = computed(() => {
+      const categoryChildList = props.categoryChildList || [];
+      const child = categoryChildList.find(
+        (item: any) => item.id === forms.wikiCategoryId
+      );
+      console.log(child, 'child');
+      if (child && child.childrenList.length) {
+        child.childrenList.forEach((child: any) => {
+          const i = child.childrenList;
+          i.forEach((j: any) => {
+            j.label = j.name;
+            j.value = j.id;
+          });
+        });
+        return child.childrenList || [];
+      }
+      return [];
+    });
+
+    return () => (
+      <div class={styles.searchGroup}>
+        <div
+          class={[
+            styles.searchCatatory,
+            childList.value.length > 0 ? styles.border : ''
+          ]}>
+          <NSpace size="small" class={styles.btnType}>
+            <NButton
+              type={forms.wikiCategoryId === '' ? 'primary' : 'default'}
+              secondary={forms.wikiCategoryId === '' ? false : true}
+              round
+              size="small"
+              focusable={false}
+              onClick={() => {
+                forms.wikiCategoryId = '';
+                onSearch();
+              }}>
+              全部
+            </NButton>
+            {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>
+        <NForm labelAlign="left" labelPlacement="left">
+          {childList.value.length > 0 && (
+            <div class={[styles.collapsSection]}>
+              <NFormItem>
+                <div class={[styles.collapseWrap]}>
+                  <NSpace class={[styles.spaceSection]}>
+                    {childList.value.map((music: any) => (
+                      <>
+                        {/* {music.childrenList.length > 0 ? (
+                          <NPopselect
+                            options={music.childrenList}
+                            trigger="click">
+                            <NButton round size="small">
+                              {music.name}
+                              <i class={styles.iconArray}></i>
+                            </NButton>
+                          </NPopselect>
+                        ) : ( */}
+                        <NButton
+                          // secondary={forms.wikiCategoryIdChild === music.id}
+                          // quaternary={forms.wikiCategoryIdChild !== music.id}
+                          strong
+                          round
+                          size="small"
+                          focusable={false}
+                          type={
+                            forms.wikiCategoryIdChild === music.id
+                              ? 'primary'
+                              : 'default'
+                          }
+                          onClick={() => {
+                            forms.wikiCategoryIdChild = music.id;
+                            onSearch();
+                          }}>
+                          {music.name}
+                        </NButton>
+                        {/* )} */}
+                      </>
+                    ))}
+                  </NSpace>
+                </div>
+              </NFormItem>
+            </div>
+          )}
+        </NForm>
+      </div>
+    );
+  }
+});

+ 296 - 0
src/views/content-information/content-music/detail.module.less

@@ -0,0 +1,296 @@
+.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;
+}
+
+.content {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+  background: #DDF2FF;
+  border-radius: 20px;
+  // max-height: 90vh;
+}
+
+.contentWrap {
+  position: relative;
+  flex: 1;
+  display: flex;
+  padding: 20px 55px 20px 20px;
+  overflow: hidden;
+  gap: 0 32px;
+  width: calc(100vw - 164px);
+}
+
+.contentMusic {
+  background: #fff;
+  width: 100%;
+  overflow-y: auto;
+  height: 100%;
+  border-radius: 13px;
+  // overflow: hidden;
+}
+
+
+.musicTop {
+  position: sticky;
+  top: 0;
+  background-color: #fff;
+  padding: 27px 22px;
+}
+
+.musicTop,
+.musicInfo {
+  display: flex;
+  align-items: center;
+}
+
+.musicImg {
+  position: relative;
+  width: 77px;
+  height: 77px;
+  border-radius: 2px;
+  z-index: 9;
+  margin-right: 54px;
+  margin-left: 31px;
+
+  .img {
+    position: relative;
+    z-index: 9;
+    width: 77px;
+    height: 77px;
+    border-radius: 2px;
+  }
+
+  .iconPan {
+    position: absolute;
+    right: -33px;
+    top: 4px;
+    width: 73px;
+    height: 73px;
+    z-index: 0;
+  }
+
+  &::before {
+    content: ' ';
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 10;
+    display: inline-block;
+    width: 5px;
+    height: 77px;
+    background: linear-gradient(270deg, rgba(0, 0, 0, 0.18) 0%, rgba(255, 255, 255, 0) 100%);
+  }
+
+  &::after {
+    content: ' ';
+    position: absolute;
+    left: -31px;
+    bottom: 0;
+    z-index: 8;
+    width: 148px;
+    height: 16px;
+    background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.3) 100%);
+    filter: blur(2.3328px);
+    border-radius: 50%;
+  }
+}
+
+.musicInfo {
+  width: 500px;
+
+  .name {
+    font-size: 18px;
+    font-weight: 600;
+    color: #131415;
+    line-height: 25px;
+    padding-bottom: 12px;
+  }
+
+  .c {
+    font-size: 13px;
+    color: #777777;
+    line-height: 18px;
+
+    span {
+      margin-right: 20px;
+    }
+  }
+}
+
+.audio {
+  flex: 1;
+  display: flex;
+  align-items: center;
+}
+
+.playBtns {
+  display: flex;
+  align-items: center;
+
+  :global {
+    .n-button {
+      width: 40px;
+      height: 40px;
+
+      img {
+        width: 100%;
+        height: 100%;
+      }
+    }
+  }
+
+  .playBtn {
+    width: 50px;
+    height: 50px;
+    background: linear-gradient(to right bottom, #44CAFE, #007AFE);
+
+    img {
+      display: block;
+      // width: 18px;
+      height: 20px;
+    }
+  }
+}
+
+.timeWrap {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  margin-left: 27px;
+
+  .timeProgress {
+    margin-right: 24px;
+    border-radius: 6px;
+    --n-handle-size: 20px !important;
+    --n-rail-height: 8px !important;
+  }
+
+  .time {
+    color: #777777;
+    font-size: 15px;
+    width: 90px;
+    white-space: nowrap;
+    flex-shrink: 0;
+  }
+}
+
+.musicContent {
+  flex: 1;
+  width: calc(100% - 54px);
+  box-sizing: content-box;
+  margin: 0 27px 0;
+  padding-top: 20px;
+  border-top: 1px solid #EBEBEB;
+
+  &>img {
+    width: 100%;
+  }
+
+  section,
+  &>div {
+    font-size: inherit !important;
+  }
+
+  video {
+    width: 60%;
+    margin: 0 auto !important;
+    display: block;
+  }
+}
+
+.changeSizeSection {
+  position: absolute;
+  right: 10px;
+  bottom: 27px;
+  width: 35px;
+  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;
+  }
+
+  .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;
+    }
+  }
+}

+ 284 - 0
src/views/content-information/content-music/detail.tsx

@@ -0,0 +1,284 @@
+import {
+  NBreadcrumb,
+  NBreadcrumbItem,
+  NButton,
+  NSlider,
+  NSpace
+} from 'naive-ui';
+import {
+  computed,
+  defineComponent,
+  onMounted,
+  reactive,
+  ref,
+  watch
+} from 'vue';
+import styles from './detail.module.less';
+import icon_back from '../../xiaoku-music/images/icon_back.png';
+import icon_separator from '../../xiaoku-music/images/icon_separator.png';
+import { useRoute, useRouter } from 'vue-router';
+import musicBg from '../../xiaoku-music/images/icon_default.png';
+import iconPan from '../images/icon-pan.png';
+import icon_play from '../../xiaoku-music/images/icon_play.png';
+import icon_pause from '../../xiaoku-music/images/icon_pause.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 { getSecondRPM } from '/src/utils';
+import { api_knowledgeWiki_detail } from '../api';
+import TheEmpty from '/src/components/TheEmpty';
+
+export default defineComponent({
+  name: 'instrument-detail',
+  setup() {
+    const route = useRoute();
+    const router = useRouter();
+    const state = reactive({
+      playState: 'pause',
+      loading: false,
+      finshed: false,
+      reshing: false,
+      details: {} as any,
+      list: [] as any,
+      fontSize: 18
+    });
+    let timer = null as any;
+    const audioData = reactive({
+      isFirst: true,
+      duration: 0,
+      currentTime: 0
+    });
+    const audioRef = ref();
+
+    const time = computed(() => {
+      return `${getSecondRPM(audioData.currentTime)} / ${getSecondRPM(
+        audioData.duration
+      )}`;
+    });
+
+    /** 改变时间 */
+    const handleChangeTime = (val: number) => {
+      audioRef.value.pause();
+      audioData.currentTime = val;
+      clearTimeout(timer);
+      timer = setTimeout(() => {
+        audioRef.value.currentTime = val;
+        if (state.playState === 'play') {
+          audioRef.value.play();
+        }
+        timer = null;
+      }, 300);
+    };
+
+    /** 加载成功 */
+    const onLoadedmetadata = () => {
+      audioData.duration = audioRef.value.duration;
+      if (audioData.isFirst) {
+        audioData.isFirst = false;
+        return;
+      }
+      if (state.playState === 'play') {
+        audioRef.value.play();
+      }
+    };
+
+    watch(
+      () => state.playState,
+      val => {
+        console.log(val, 'val');
+        if (val === 'play') {
+          audioRef.value.play();
+        } else {
+          audioRef.value.pause();
+        }
+      }
+    );
+    /** 播放曲目 */
+    const handlePlay = (item: any) => {
+      const index = state.list.findIndex((_item: any) => _item.id === item.id);
+      if (index > -1) {
+        state.playState = state.playState === 'play' ? 'pause' : 'play';
+      }
+    };
+
+    /** 音频控制 */
+    const handleChangeAudio = (
+      type: 'play' | 'pause' | 'pre' | 'next' | 'favitor'
+    ) => {
+      if (type === 'play') {
+        state.playState = 'play';
+      } else if (type === 'pause') {
+        state.playState = 'pause';
+      }
+    };
+    const getDetail = async () => {
+      state.loading = true;
+      let res = {} as any;
+      try {
+        res = await api_knowledgeWiki_detail({ id: route.query.id });
+      } catch (error) {
+        console.log(error);
+      }
+      if (state.reshing) {
+        state.list = [];
+        state.reshing = false;
+      }
+
+      state.finshed = true;
+      state.list = res.data.knowledgeWikiResources || [];
+      state.list.forEach((item: any) => {
+        item.audioFileUrl = item.url;
+      });
+      const knowledgeWikiCategories = res.data.knowledgeWikiCategories || [];
+      res.data.knowledgeName =
+        knowledgeWikiCategories.length > 0
+          ? knowledgeWikiCategories[0].name
+          : '';
+      const knowledgeWikiResources = res.data.knowledgeWikiResources || [];
+      res.data.audioFileUrl =
+        knowledgeWikiResources.length > 0 ? knowledgeWikiResources[0].url : '';
+      state.details = res.data;
+
+      state.loading = false;
+    };
+
+    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={() => router.push({ path: '/content-music' })}
+          />
+          <NBreadcrumb separator="">
+            <NBreadcrumbItem
+              onClick={() => router.push({ path: '/content-music' })}>
+              曲目鉴赏
+            </NBreadcrumbItem>
+            <img class={styles.separator} src={icon_separator} />
+            <NBreadcrumbItem>{route.query.name}</NBreadcrumbItem>
+          </NBreadcrumb>
+        </NSpace>
+
+        <div class={[styles.wrap]}>
+          <div class={styles.content}>
+            <div class={styles.contentWrap}>
+              <div class={styles.contentMusic}>
+                <div class={styles.musicTop}>
+                  <div class={styles.musicInfo}>
+                    <div class={styles.musicImg}>
+                      <img
+                        src={state.details.avatar || musicBg}
+                        class={styles.img}
+                      />
+                      <img src={iconPan} class={styles.iconPan} />
+                    </div>
+
+                    <div class={styles.info}>
+                      <div class={styles.name}>{state.details.name}</div>
+                      <div class={styles.c}>
+                        <span>作曲:{state.details.composers}</span>
+                        <span>作词:{state.details.lyricists}</span>
+                      </div>
+                    </div>
+                  </div>
+
+                  {state.details.audioFileUrl ? (
+                    <div class={styles.audio}>
+                      <div class={styles.playBtns}>
+                        <NButton
+                          color="rgba(57,130,246,1)"
+                          class={styles.playBtn}
+                          circle
+                          bordered={false}
+                          onClick={() => {
+                            //
+                            handleChangeAudio(
+                              state.playState === 'pause' ? 'play' : 'pause'
+                            );
+                          }}>
+                          <img
+                            style={{
+                              display: state.playState === 'pause' ? '' : 'none'
+                            }}
+                            src={icon_play}
+                          />
+                          <img
+                            style={{
+                              display: state.playState === 'play' ? '' : 'none'
+                            }}
+                            src={icon_pause}
+                          />
+                        </NButton>
+                      </div>
+                      <div class={styles.timeWrap}>
+                        <NSlider
+                          tooltip={false}
+                          step={0.01}
+                          class={styles.timeProgress}
+                          value={audioData.currentTime}
+                          max={audioData.duration}
+                          onUpdate:value={val => handleChangeTime(val)}
+                        />
+                        <div class={styles.time}>{time.value}</div>
+                        <audio
+                          ref={audioRef}
+                          src={state.details.audioFileUrl}
+                          onLoadedmetadata={onLoadedmetadata}
+                          onEnded={() => {
+                            // emit('change', 'pause');
+                          }}
+                          onTimeupdate={() => {
+                            if (timer) return;
+                            audioData.currentTime = audioRef.value?.currentTime;
+                          }}></audio>
+                      </div>
+                    </div>
+                  ) : (
+                    ''
+                  )}
+                </div>
+
+                <div
+                  class={styles.musicContent}
+                  v-html={state.details.intros}
+                  style={{ fontSize: state.fontSize + 'px' }}></div>
+                {!state.loading && !state.details.intros && <TheEmpty />}
+              </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>
+    );
+  }
+});

+ 147 - 0
src/views/content-information/content-music/index.module.less

@@ -0,0 +1,147 @@
+.container {
+
+  .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-tabs-tab-pad {
+      width: 80px !important;
+    }
+
+    .n-tabs-nav {
+      padding: 0px 20px 24px;
+    }
+
+    .n-tabs-tab {
+      color: #8B8D98;
+      font-size: max(22px, 14Px);
+      padding-top: 0;
+      padding-bottom: 6px;
+      line-height: 22px;
+
+      &.n-tabs-tab--active {
+        font-weight: 600 !important;
+        color: #131415 !important;
+      }
+    }
+
+    .n-tabs-tab__label {
+      z-index: 10;
+    }
+
+    .n-tabs-bar {
+      height: 10px;
+      background: linear-gradient(90deg, #77BBFF 0%, rgba(163, 231, 255, 0.22) 100%);
+      z-index: 0;
+      bottom: 2px;
+    }
+
+    .n-tab-pane {
+      padding: 0 12px 0 !important;
+    }
+
+    .n-pagination {
+      margin-top: 36px !important;
+    }
+  }
+
+  &> :global(.n-space) {
+    height: 36px;
+    flex-shrink: 0;
+  }
+
+  .separator {
+    width: 9px;
+    height: 15px;
+    margin: 0 16px;
+  }
+}
+
+.wrap {
+  padding-top: 12px;
+  flex: 1;
+  transition: padding 0.3s;
+  // overflow: hidden;
+}
+
+.listWrap {
+  padding: 32px 20px;
+  background-color: #fff;
+  border-radius: 20px;
+  min-height: 100%;
+  width: calc(100vw - 164px); // min-height: calc(100% - 104px);
+
+  :global {
+    .n-tabs-tab-pad {
+      width: 80px !important;
+    }
+
+    .n-tabs-nav {
+      padding: 0px 20px 24px;
+    }
+
+    .n-tabs-tab {
+      color: #8B8D98;
+      font-size: max(22px, 14Px);
+      padding-top: 0;
+      padding-bottom: 6px;
+      line-height: 22px;
+
+      &.n-tabs-tab--active {
+        font-weight: 600 !important;
+        color: #131415 !important;
+      }
+    }
+
+    .n-tabs-tab__label {
+      z-index: 10;
+    }
+
+    .n-tabs-bar {
+      height: 10px;
+      background: linear-gradient(90deg, #77BBFF 0%, rgba(163, 231, 255, 0.22) 100%);
+      z-index: 0;
+      bottom: 2px;
+    }
+
+    .n-tab-pane {
+      padding: 0 12px 0 !important;
+    }
+
+    .n-pagination {
+      margin-top: 36px !important;
+    }
+  }
+}

+ 84 - 0
src/views/content-information/content-music/index.tsx

@@ -0,0 +1,84 @@
+import {
+  NBreadcrumb,
+  NBreadcrumbItem,
+  NSpace,
+  NTabPane,
+  NTabs
+} from 'naive-ui';
+import { defineComponent, reactive } from 'vue';
+import styles from './index.module.less';
+import icon_back from '../../xiaoku-music/images/icon_back.png';
+// import icon_separator from '../../xiaoku-music/images/icon_separator.png';
+import { useRouter } from 'vue-router';
+import List from './components/list';
+import { api_knowledgeWikiCategoryType_page } from '../api';
+
+// 164px 244px
+export default defineComponent({
+  name: 'content-music',
+  setup() {
+    const router = useRouter();
+    const state = reactive({
+      tabValue: '',
+      categoryList: [] as any
+    });
+
+    const getCategoryList = async () => {
+      try {
+        const { data } = await api_knowledgeWikiCategoryType_page({
+          type: 'MUSIC',
+          page: 1,
+          rows: 99
+        });
+
+        state.categoryList = data.rows || [];
+        if (state.categoryList.length) {
+          state.tabValue = 'name-' + state.categoryList[0].id;
+        }
+      } catch {
+        //
+      }
+    };
+
+    getCategoryList();
+    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({ path: '/' })}
+          />
+          <NBreadcrumb separator="">
+            <NBreadcrumbItem>曲目鉴赏</NBreadcrumbItem>
+          </NBreadcrumb>
+        </NSpace>
+
+        <div class={styles.wrap}>
+          <div class={styles.listWrap}>
+            <NTabs
+              defaultValue="myResources"
+              paneClass={styles.paneTitle}
+              justifyContent="center"
+              paneWrapperClass={styles.paneWrapperContainer}
+              v-model:value={state.tabValue}>
+              {state.categoryList.map((category: any) => (
+                <NTabPane
+                  name={`name-${category.id}`}
+                  tab={category.name}
+                  // displayDirective="show:lazy"
+                >
+                  <List
+                    categoryId={category.id}
+                    categoryChildList={category.childrenList}
+                  />
+                </NTabPane>
+              ))}
+            </NTabs>
+          </div>
+        </div>
+      </div>
+    );
+  }
+});

+ 163 - 0
src/views/content-information/content-musician/components/list/index.module.less

@@ -0,0 +1,163 @@
+.searchGroup {
+  position: relative;
+  padding: 0;
+
+
+  .btnType {
+    gap: 0px 24px !important;
+
+    :global {
+      .n-button {
+        height: 37px;
+        padding: 0 24px;
+        font-size: 18px;
+        color: rgba(0, 0, 0, .6);
+
+        &.n-button--primary-type {
+          font-weight: bold;
+          color: #fff;
+        }
+      }
+    }
+  }
+
+
+  .inputSearch {
+    width: 360px;
+    height: 42px;
+    font-size: 16px;
+    --n-height: 42px !important;
+
+    img {
+      width: 18px;
+      height: 18px;
+    }
+
+    :global {
+      .n-input-wrapper {
+        padding-left: 12px;
+        padding-right: 4px;
+        height: 42px !important;
+      }
+
+      .n-button {
+        height: 34px;
+        font-size: 15px;
+        font-weight: 500;
+        width: auto;
+      }
+    }
+  }
+
+  .searchCatatory {
+    display: flex;
+    justify-content: space-between;
+    padding-bottom: 20px;
+
+    .addTrain {
+      height: 37px;
+      border-radius: 8px;
+      font-size: 18px;
+      background-color: #E8F4FF;
+      color: #0378EC;
+
+      img {
+        width: 16px;
+        height: 16px;
+        margin-right: 8px;
+      }
+    }
+  }
+}
+
+.list {
+  margin-top: 12px;
+  display: flex;
+  flex-flow: row wrap;
+  justify-content: flex-start;
+  gap: 45px 0;
+  min-height: 232px;
+  margin-left: -22px;
+  margin-right: -22px;
+
+  .itemWrap {
+    width: calc(100% / 6);
+    padding-bottom: calc(100% / 6 * 0.8755555);
+    position: relative;
+
+    .itemWrapBox {
+      position: absolute;
+      left: 0;
+      top: 0;
+      width: 100%;
+      height: 100%;
+      padding: 0 22px;
+    }
+  }
+
+  .itemCard {
+    position: relative;
+    cursor: pointer;
+
+    &:hover {
+      .itemImgSection {
+        background: linear-gradient(360deg, #DBF1FF 0%, #E7F9FF 100%);
+        box-shadow: 2px 2 8px 0px rgba(0, 0, 0, 0.1);
+        border-radius: 13px;
+        border: 3px solid rgba(0, 122, 254, 1);
+        box-sizing: border-box;
+        transition: all .2s ease;
+      }
+    }
+
+    .itemTag {
+      position: absolute;
+      right: 0;
+      top: 0;
+      display: inline-block;
+      font-size: 12px;
+      font-weight: 600;
+      color: #FFFFFF;
+      line-height: 17px;
+      text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.1);
+      line-height: 23px;
+      padding: 0 7px;
+      background: linear-gradient(135deg, #02BAFF 0%, #007AFE 100%);
+      box-shadow: 2px 2 8px 0px rgba(0, 0, 0, 0.1);
+      border-radius: 0px 13px 0px 13px;
+    }
+
+    .itemImgSection {
+      width: 100%;
+      height: 225px;
+      background: linear-gradient(360deg, #DBF1FF 0%, #E7F9FF 100%);
+      box-shadow: 2px 2px 8px 0px rgba(0, 0, 0, 0.1);
+      border-radius: 13px;
+      overflow: hidden;
+      transition: all .2s ease;
+
+
+
+      .img {
+        width: 100%;
+        height: 100%;
+        height: 225px;
+        display: flex;
+
+        img {
+          width: 100%;
+          height: 100%;
+        }
+      }
+    }
+
+    .itemTitle {
+      padding-top: 10px;
+      font-size: 18px;
+      font-weight: 600;
+      color: #131415;
+      line-height: 25px;
+      text-align: center;
+    }
+  }
+}

+ 126 - 0
src/views/content-information/content-musician/components/list/index.tsx

@@ -0,0 +1,126 @@
+import { PropType, defineComponent, onMounted, reactive } from 'vue';
+import styles from './index.module.less';
+import SearchGroupResources from './search-group-resources';
+import { NImage, NSpin } from 'naive-ui';
+import TheEmpty from '/src/components/TheEmpty';
+import Pagination from '/src/components/pagination';
+import { api_knowledgeWiki_page } from '../../../api';
+import { useRouter } from 'vue-router';
+
+export default defineComponent({
+  name: 'musician-list',
+  props: {
+    categoryId: {
+      type: String,
+      default: ''
+    },
+    categoryChildList: {
+      type: Array as PropType<any>,
+      default: () => []
+    }
+  },
+  setup(props) {
+    const router = useRouter();
+    const state = reactive({
+      searchWord: '',
+      loading: false,
+      pageTotal: 0,
+      pagination: {
+        page: 1,
+        rows: 20
+      },
+      searchGroup: {
+        type: 'MUSICIAN', //
+        keyword: '',
+        wikiCategoryId: props.categoryId
+      },
+      tableList: [] as any,
+      teachingStatus: false,
+      show: false,
+      item: {} as any
+    });
+
+    const getList = async () => {
+      state.loading = true;
+      try {
+        const { data } = await api_knowledgeWiki_page({
+          ...state.pagination,
+          ...state.searchGroup
+        });
+        state.tableList = data.rows || [];
+        state.pageTotal = Number(data.total);
+      } catch {
+        //
+      }
+      state.loading = false;
+    };
+
+    const onSearch = async (item: any) => {
+      state.pagination.page = 1;
+      state.searchGroup = Object.assign(state.searchGroup, item);
+      getList();
+    };
+
+    onMounted(() => {
+      getList();
+    });
+
+    return () => (
+      <div class={styles.instrumentList}>
+        <SearchGroupResources
+          categoryChildList={props.categoryChildList}
+          onSearch={(item: any) => onSearch(item)}
+        />
+
+        <NSpin v-model:show={state.loading} style={{ 'min-height': '50vh' }}>
+          <div class={styles.list}>
+            {state.tableList.map((item: any) => (
+              <div
+                class={styles.itemWrap}
+                onClick={() => {
+                  router.push({
+                    path: '/content-instruments-detail',
+                    query: {
+                      type: 'MUSICIAN',
+                      id: item.id,
+                      name: item.name
+                    }
+                  });
+                }}>
+                <div class={styles.itemWrapBox}>
+                  <div class={styles.itemCard}>
+                    <span class={styles.itemTag}>
+                      {item.knowledgeWikiCategoryName}
+                    </span>
+                    <div class={styles.itemImgSection}>
+                      <NImage
+                        src={item.avatar}
+                        class={styles.img}
+                        objectFit="cover"
+                        previewDisabled
+                      />
+                    </div>
+                    <div class={styles.itemTitle}>{item.name}</div>
+                  </div>
+                </div>
+              </div>
+            ))}
+
+            {!state.loading && state.tableList.length <= 0 && (
+              <TheEmpty
+                style={{ minHeight: '50vh' }}
+                description="暂无音乐人"
+              />
+            )}
+          </div>
+        </NSpin>
+        <Pagination
+          v-model:page={state.pagination.page}
+          v-model:pageSize={state.pagination.rows}
+          v-model:pageTotal={state.pageTotal}
+          onList={getList}
+        />
+      </div>
+    );
+  }
+});

+ 73 - 0
src/views/content-information/content-musician/components/list/search-group-resources.tsx

@@ -0,0 +1,73 @@
+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: () => []
+    }
+  },
+  emits: ['search', 'add'],
+  expose: ['init'],
+  setup(props, { emit }) {
+    // const catchStore = useCatchStore();
+    const forms = reactive({
+      keyword: '',
+      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}>
+            <NButton
+              type={forms.wikiCategoryId === '' ? 'primary' : 'default'}
+              secondary={forms.wikiCategoryId === '' ? false : true}
+              round
+              size="small"
+              focusable={false}
+              onClick={() => {
+                forms.wikiCategoryId = '';
+                onSearch();
+              }}>
+              全部
+            </NButton>
+            {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>
+    );
+  }
+});

+ 147 - 0
src/views/content-information/content-musician/index.module.less

@@ -0,0 +1,147 @@
+.container {
+
+  .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-tabs-tab-pad {
+      width: 80px !important;
+    }
+
+    .n-tabs-nav {
+      padding: 0px 20px 24px;
+    }
+
+    .n-tabs-tab {
+      color: #8B8D98;
+      font-size: max(22px, 14Px);
+      padding-top: 0;
+      padding-bottom: 6px;
+      line-height: 22px;
+
+      &.n-tabs-tab--active {
+        font-weight: 600 !important;
+        color: #131415 !important;
+      }
+    }
+
+    .n-tabs-tab__label {
+      z-index: 10;
+    }
+
+    .n-tabs-bar {
+      height: 10px;
+      background: linear-gradient(90deg, #77BBFF 0%, rgba(163, 231, 255, 0.22) 100%);
+      z-index: 0;
+      bottom: 2px;
+    }
+
+    .n-tab-pane {
+      padding: 0 12px 0 !important;
+    }
+
+    .n-pagination {
+      margin-top: 36px !important;
+    }
+  }
+
+  &> :global(.n-space) {
+    height: 36px;
+    flex-shrink: 0;
+  }
+
+  .separator {
+    width: 9px;
+    height: 15px;
+    margin: 0 16px;
+  }
+}
+
+.wrap {
+  padding-top: 12px;
+  flex: 1;
+  transition: padding 0.3s;
+  // overflow: hidden;
+}
+
+.listWrap {
+  padding: 32px 20px;
+  background-color: #fff;
+  border-radius: 20px;
+  min-height: 100%;
+  // min-height: calc(100% - 104px);
+
+  :global {
+    .n-tabs-tab-pad {
+      width: 80px !important;
+    }
+
+    .n-tabs-nav {
+      padding: 0px 20px 24px;
+    }
+
+    .n-tabs-tab {
+      color: #8B8D98;
+      font-size: max(22px, 14Px);
+      padding-top: 0;
+      padding-bottom: 6px;
+      line-height: 22px;
+
+      &.n-tabs-tab--active {
+        font-weight: 600 !important;
+        color: #131415 !important;
+      }
+    }
+
+    .n-tabs-tab__label {
+      z-index: 10;
+    }
+
+    .n-tabs-bar {
+      height: 10px;
+      background: linear-gradient(90deg, #77BBFF 0%, rgba(163, 231, 255, 0.22) 100%);
+      z-index: 0;
+      bottom: 2px;
+    }
+
+    .n-tab-pane {
+      padding: 0 12px 0 !important;
+    }
+
+    .n-pagination {
+      margin-top: 36px !important;
+    }
+  }
+}

+ 87 - 0
src/views/content-information/content-musician/index.tsx

@@ -0,0 +1,87 @@
+import {
+  NBreadcrumb,
+  NBreadcrumbItem,
+  NSpace,
+  NTabPane,
+  NTabs
+} from 'naive-ui';
+import { defineComponent, reactive } from 'vue';
+import styles from './index.module.less';
+import icon_back from '../../xiaoku-music/images/icon_back.png';
+// import icon_separator from '../../xiaoku-music/images/icon_separator.png';
+import { useRoute, useRouter } from 'vue-router';
+import List from './components/list';
+import { api_knowledgeWikiCategoryType_page } from '../api';
+
+export default defineComponent({
+  name: 'content-musician',
+  setup() {
+    const router = useRouter();
+    const state = reactive({
+      tabValue: '',
+      categoryList: [] as any
+    });
+
+    const getCategoryList = async () => {
+      try {
+        const { data } = await api_knowledgeWikiCategoryType_page({
+          type: 'MUSICIAN',
+          page: 1,
+          rows: 99
+        });
+
+        state.categoryList = data.rows || [];
+        if (state.categoryList.length) {
+          state.tabValue = 'name-' + state.categoryList[0].id;
+        }
+      } catch {
+        //
+      }
+    };
+
+    getCategoryList();
+    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({ path: '/' })}
+          />
+          <NBreadcrumb separator="">
+            <NBreadcrumbItem>音乐家</NBreadcrumbItem>
+          </NBreadcrumb>
+        </NSpace>
+
+        <div class={styles.wrap}>
+          <div class={styles.listWrap}>
+            <NTabs
+              defaultValue="myResources"
+              paneClass={styles.paneTitle}
+              justifyContent="center"
+              // animated
+              paneWrapperClass={styles.paneWrapperContainer}
+              // onUpdate:value={(val: any) => {
+              //   tab.value = val;
+              // }}
+              v-model:value={state.tabValue}>
+              {state.categoryList.map((category: any) => (
+                <NTabPane
+                  name={`name-${category.id}`}
+                  tab={category.name}
+                  // displayDirective="show:lazy"
+                >
+                  <List
+                    categoryId={category.id}
+                    categoryChildList={category.childrenList}
+                  />
+                </NTabPane>
+              ))}
+            </NTabs>
+          </div>
+        </div>
+      </div>
+    );
+  }
+});

BIN
src/views/content-information/images/icon-add-t.png


BIN
src/views/content-information/images/icon-arrow.png


BIN
src/views/content-information/images/icon-pan.png


BIN
src/views/content-information/images/icon-plus-t.png


BIN
src/views/content-information/images/icon-t.png


BIN
src/views/home/img/f1-1.png


BIN
src/views/home/img/f1.png


BIN
src/views/home/img/f2-1.png


BIN
src/views/home/img/f2.png


BIN
src/views/home/img/f3-1.png


BIN
src/views/home/img/f3.png


BIN
src/views/home/img/f4-1.png


BIN
src/views/home/img/f4.png


BIN
src/views/home/img/icon-bk.png


BIN
src/views/home/img/icon-class.png


BIN
src/views/home/img/icon-echats.png


BIN
src/views/home/img/icon-left-window.png


BIN
src/views/home/img/icon-tag.png


BIN
src/views/home/img/left-bg.png


BIN
src/views/home/img/t1-1.png


BIN
src/views/home/img/t1-2.png


BIN
src/views/home/img/t1-3.png


BIN
src/views/home/img/t1-4.png


BIN
src/views/home/img/t1.png


BIN
src/views/home/img/t2-1.png


BIN
src/views/home/img/t2-3.png


BIN
src/views/home/img/t2-4.png


BIN
src/views/home/img/t2.png


BIN
src/views/home/img/teacher-man.png


BIN
src/views/home/img/teacher-woman.png


BIN
src/views/home/img/编组 17备份@2x.png


BIN
src/views/home/img/路径 13@2x(1).png


+ 617 - 0
src/views/home/index copy.tsx

@@ -0,0 +1,617 @@
+import { defineComponent, onMounted, reactive, ref } from 'vue';
+import styles from './index.module.less';
+import {
+  NImage,
+  NButton,
+  NPopselect,
+  NModal,
+  useMessage,
+  NSpin,
+  NSelect
+} from 'naive-ui';
+import headerD from './images/headerD.png';
+import defultHeade from '@/components/layout/images/teacherIcon.png';
+import blackBoardBg from './images/blackboard_bg.png';
+import teacherMan from './images/teacher_man.png';
+import teacherWoman from './images/teacher_woman.png';
+
+import homeText1 from './images/home/home-text-1.png';
+import homeText2 from './images/home/home-text-2.png';
+import iconTo from './images/icon-to.png';
+import t1 from './images/t1.png';
+import t2 from './images/t2.png';
+import t3 from './images/t3.png';
+import { useRouter } from 'vue-router';
+import { useUserStore } from '/src/store/modules/users';
+// import SelectClass from './modals/selectClass';
+import dayjs from 'dayjs';
+import { gradeToCN, weekToCN } from '/src/utils/contants';
+import { useCatchStore } from '/src/store/modules/catchData';
+import TeachGroup from './modals/teachGroup';
+import {
+  classGroupList,
+  courseSchedulePage,
+  getGradeLevelList,
+  getGradeYearList
+} from './api';
+import TheEmpty from '/src/components/TheEmpty';
+import HomeGuide from '/src/custom-plugins/guide-page/home-guide';
+import TimerMeter from '/src/components/timerMeter';
+import { vaildUrl } from '/src/utils/urlUtils';
+import { px2vw } from '/src/utils';
+import PlaceholderTone from '@/components/layout/modals/placeholderTone';
+import PreviewWindow from '../preview-window';
+import UpdatePassword from '/src/components/layout/modals/update-password';
+import AttendClass from '../prepare-lessons/model/attend-class';
+import { useResizeObserver } from '@vueuse/core';
+// import { state } from '/src/state';
+export const formatDateToDay = () => {
+  const hours = dayjs().hour();
+  if (hours < 12) {
+    return '早上好'; //如果小时数小于12则输出“早上好!”
+  } else if (hours > 12 && hours < 18) {
+    return '下午好'; //如果小时数大于12并且小于18,输入“下午好!”
+  } else {
+    return '晚上好'; //如果上面两个条件都不符合,则输出“晚上好!”
+  }
+};
+
+export default defineComponent({
+  name: 'home-page',
+  setup() {
+    const catchStore = useCatchStore();
+    const router = useRouter();
+    const userStore = useUserStore();
+    const showUpdatePassword = ref(false);
+    const showModalBeat = ref(false);
+    const showModalTone = ref(false);
+    const showModalTime = ref(false);
+    const forms = reactive({
+      showAttendClass: false,
+      // useStatus: false,
+      studentList: [] as any,
+      bookVersionId: null,
+      classGroupId: null,
+      category: null,
+      subjectId: null,
+      musicTagList: [] as any,
+      loading: false,
+      list: [] as any,
+      unit: null,
+      unitList: [],
+      subjectList: [] as any,
+      gradeList: [] as any,
+      classLoading: false,
+      total: 0, // 上课数量
+      // 上次上课的数据
+      lastClassSelect: {
+        currentClass: null,
+        name: '',
+        upgradeFlag: false, // 是否为历史班
+        gradeYear: null as any,
+        gradeLevel: null as any
+      },
+      classSelect: {
+        currentGradeNum: null,
+        currentClass: null,
+        name: '',
+        upgradeFlag: false, // 是否为历史班
+        gradeLevel: null as any,
+        gradeYear: null
+      } as any,
+      popSelectOptions: [] as any,
+      popSelectYearList: [] as any,
+      popSelectLevelList: [] as any,
+      showGuide: false,
+      showPreview: false,
+      itemPreview: {} as any,
+      homeLeftHeight: 'auto'
+    });
+    const teachList = ref({} as any);
+
+    // 获取年级班级
+    const getClassList = async () => {
+      try {
+        const { data } = await classGroupList({
+          gradeLevel: forms.classSelect.gradeLevel,
+          gradeYear: forms.classSelect.gradeYear
+        });
+        const cList = data || [];
+        const gradeList: any = [];
+        const popSelectOptions: any = [];
+        // getLastClassRecode()
+        cList.forEach((item: any, index: number) => {
+          // 判断是否已经有班级了
+          if (index === 0) {
+            if (forms.lastClassSelect.currentClass) {
+              forms.classSelect.currentClass =
+                forms.lastClassSelect.currentClass;
+              forms.classSelect.name = forms.lastClassSelect.name;
+              forms.classSelect.upgradeFlag = forms.lastClassSelect.upgradeFlag;
+            } else {
+              const temp = item.classGroupList[0];
+              forms.classSelect.currentGradeNum = item.currentGradeNum;
+              forms.classSelect.currentClass = temp.id;
+              forms.classSelect.name = temp.name;
+            }
+          }
+
+          const classList: any = [];
+          item.classGroupList.forEach((i: any) => {
+            classList.push({
+              label: i.currentClass + '班',
+              value: i.id,
+              lastStudy: i.lastStudy
+            });
+
+            popSelectOptions.push({
+              label: i.name,
+              value: i.id,
+              currentGradeNum: item.currentGradeNum,
+              lastStudy: i.lastStudy
+            });
+          });
+
+          gradeList.push({
+            label: gradeToCN[item.currentGradeNum],
+            value: item.currentGradeNum,
+            childrens: classList
+          });
+        });
+        forms.popSelectOptions = popSelectOptions;
+        forms.gradeList = gradeList;
+      } catch {
+        //
+      }
+    };
+    const getLastClassRecode = async () => {
+      const { data } = await courseSchedulePage({
+        page: 1,
+        rows: 1,
+        teacherId: userStore.getUserInfo.id
+      });
+      if (data.rows.length > 0 && data.rows[0]) {
+        const tempRow = data.rows[0];
+        // forms.lastClassSelect.currentClass = tempRow.classGroupId;
+        // forms.lastClassSelect.name = tempRow.classGroupName;
+        forms.lastClassSelect = {
+          currentClass: tempRow.classGroupId,
+          name: tempRow.classGroupName,
+          upgradeFlag: tempRow.upgradeFlag,
+          gradeYear: tempRow.gradeYear + '',
+          gradeLevel: tempRow.gradeLevel + ''
+        };
+      }
+    };
+
+    // 获取学年
+    const getYearList = async () => {
+      try {
+        const { data } = await getGradeYearList();
+        const temp = data || [];
+        temp.forEach((i: any) => {
+          i.name = i.name + '学年';
+        });
+        forms.popSelectYearList = temp || [];
+        if (temp.length > 0) {
+          if (forms.lastClassSelect.gradeYear) {
+            forms.classSelect.gradeYear = forms.lastClassSelect.gradeYear;
+          } else {
+            forms.classSelect.gradeYear = temp[0].id;
+          }
+        }
+      } catch (e: any) {
+        //
+      }
+    };
+    // 获取学级
+    const getLevelList = async () => {
+      try {
+        const { data } = await getGradeLevelList();
+        const temp = data || [];
+        temp.forEach((i: any) => {
+          i.name = i.name + '级';
+        });
+        temp.unshift({
+          id: '',
+          name: '全部学级'
+        });
+        forms.popSelectLevelList = temp || [];
+        if (temp.length > 0) {
+          if (forms.lastClassSelect.gradeLevel) {
+            forms.classSelect.gradeLevel =
+              forms.lastClassSelect.gradeLevel + '';
+          } else {
+            forms.classSelect.gradeLevel = temp[0].id;
+          }
+        }
+      } catch {
+        //
+      }
+    };
+
+    const getCourseSchedulePage = async () => {
+      forms.classLoading = true;
+      try {
+        const { data } = await courseSchedulePage({
+          classGroupId: forms.classSelect.currentClass,
+          gradeLevel: forms.classSelect.gradeLevel,
+          gradeYear: forms.classSelect.gradeYear,
+          page: 1,
+          rows: 4,
+          teacherId: userStore.getUserInfo.id
+        });
+
+        const result = data.rows || [];
+        forms.total = data.total || 0;
+        const dateTime: any = {};
+        result.forEach((item: any) => {
+          const tempTime = dayjs(item.classDate).format('MM-DD');
+          if (!dateTime[tempTime]) {
+            dateTime[tempTime] = [];
+          }
+
+          const lessonCourseware = item.lessonCoursewareJson
+            ? JSON.parse(item.lessonCoursewareJson)
+            : {};
+          dateTime[tempTime].push({
+            classGroup: forms.classSelect.name,
+            teacherName: item.teacherName,
+            conent:
+              lessonCourseware.lessonCoursewareName +
+              ' | ' +
+              lessonCourseware.lessonCoursewareDetailName +
+              ' | ' +
+              lessonCourseware.lessonCoursewareKnowledgeDetailName,
+            image: item.teacherAvatar,
+            subjectName: item.subjectName
+          });
+        });
+
+        teachList.value = dateTime;
+      } catch (e: any) {
+        //
+        console.log(e);
+      }
+
+      forms.classLoading = false;
+    };
+
+    onMounted(async () => {
+      useResizeObserver(
+        document.querySelector('#homeInfoLeft-home') as any,
+        (entries: any) => {
+          const entry = entries[0];
+          const { height } = entry.contentRect;
+          forms.homeLeftHeight = height + 'px';
+        }
+      );
+
+      forms.classLoading = true;
+      await getLastClassRecode();
+
+      await getYearList();
+      await getLevelList();
+      await getClassList();
+      // await catchStore.getSubjects();
+
+      await getCourseSchedulePage();
+
+      if (!userStore.getUserInfo.account.updatePasswordFlag) {
+        showUpdatePassword.value = true;
+      } else {
+        forms.showGuide = true;
+      }
+
+      forms.classLoading = false;
+    });
+    return () => (
+      <div class={styles.homeWrap}>
+        <div class={styles.homeInfoLeft} id="homeInfoLeft-home">
+          <div class={styles.homeBanner}>
+            <div class={styles.applyInfo} id="home-1">
+              <div class={styles.centerInfo} id="home-0"></div>
+
+              <div class={styles.userInfo}>
+                <div class={styles.userName}>
+                  Hi,{userStore.getUserInfo?.nickname} {formatDateToDay()}~
+                </div>
+              </div>
+              {userStore.getUserInfo.gender === 1 ? (
+                <img src={teacherMan} class={styles.teacherMan} />
+              ) : (
+                <img src={teacherWoman} class={styles.teacherWoman} />
+              )}
+
+              <div class={styles.blackborad}>
+                <img src={blackBoardBg} class={styles.blackBoardBg} />
+              </div>
+              <div class={styles.applyContainer}>
+                <div class={[styles.applyItem, styles.applyItem1]}>
+                  <p>合理的规划教学内容,让学生更好掌握知识</p>
+                  <div
+                    class={[styles.applyBtn, styles.applyBtn1]}
+                    onClick={() => {
+                      // 备课
+                      router.push({
+                        path: '/prepare-lessons'
+                      });
+                    }}>
+                    <img src={homeText1} />
+                  </div>
+                </div>
+                <div class={[styles.applyItem, styles.applyItem2]}>
+                  <p>从这里开始,带领学生在知识的海洋中遨游</p>
+                  <div
+                    class={[styles.applyBtn, styles.applyBtn2]}
+                    onClick={() => {
+                      forms.showAttendClass = true;
+                    }}>
+                    <img src={homeText2} />
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+
+          <div class={styles.toolContainer}>
+            <div class={styles.toolTips}>
+              <div class={styles.toolTitle}>工具箱</div>
+              <div class={styles.toolContent}>
+                这里是常用的教学辅助工具,可帮助学生集中注意力、提高演奏效率,使演奏更完整平稳。让您在课堂上完成更好的教学。
+              </div>
+            </div>
+            <img src={iconTo} class={styles.iconTo} />
+            <div class={styles.toolFunction} id="home-3">
+              <div class={[styles.toolItem, styles.item1]}>
+                <img src={t1} />
+                {/* <p class={styles.toolMemo}>提升效率,练习好节奏</p> */}
+                <NButton
+                  class={styles.btn1}
+                  onClick={() => {
+                    showModalBeat.value = true;
+                  }}>
+                  节拍器
+                </NButton>
+              </div>
+              <div class={[styles.toolItem, styles.item2]}>
+                <img src={t2} />
+                {/* <p class={styles.toolMemo}>精准调音,一劳永逸</p> */}
+                <NButton
+                  class={styles.btn2}
+                  onClick={() => {
+                    showModalTone.value = true;
+                  }}>
+                  调音器
+                </NButton>
+              </div>
+              <div class={[styles.toolItem, styles.item3]}>
+                <img src={t3} />
+                {/* <p class={styles.toolMemo}>创造时间,集中注意力</p> */}
+                <NButton
+                  class={styles.btn3}
+                  onClick={() => {
+                    showModalTime.value = true;
+                  }}>
+                  计时器
+                </NButton>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div
+          class={styles.homeInfoRight}
+          style={{ height: forms.homeLeftHeight }}>
+          <div class={styles.rightTeachingWrap}>
+            <div class={styles.headerContainer}>
+              <div
+                class={styles.HeaderWrap}
+                onClick={() => router.push('/setting')}>
+                <NImage
+                  previewDisabled
+                  class={styles.headerD}
+                  src={headerD}></NImage>
+                <NImage
+                  previewDisabled
+                  class={styles.defultHeade}
+                  src={userStore.getUserInfo.avatar || defultHeade}></NImage>
+              </div>
+            </div>
+            <div class={styles.headerInfo}>
+              <p class={styles.headerTitle}>{userStore.getUserInfo.nickname}</p>
+              {userStore.getUserInfo.schoolInfos &&
+                userStore.getUserInfo.schoolInfos.length > 0 && (
+                  <p class={styles.headerSubTitle}>
+                    {userStore.getUserInfo.schoolInfos[0].name}
+                    {/* | 音乐老师 */}
+                  </p>
+                )}
+            </div>
+            <div class={styles.rightTeachingWrapTitle}>
+              <h3 class={styles.rightTitle}>
+                <div class={styles.titleDot}></div>上课记录
+              </h3>
+
+              <div class={styles.classSearchList}>
+                <NSelect
+                  v-model:value={forms.classSelect.gradeYear}
+                  class={styles.lookMoreSearch}
+                  placeholder="全部学年"
+                  options={forms.popSelectYearList}
+                  labelField="name"
+                  valueField="id"
+                  onUpdate:value={async (val: any) => {
+                    forms.classSelect.gradeYear = val;
+                    forms.lastClassSelect.currentClass = null;
+                    forms.classSelect.currentClass = null;
+                    await getClassList();
+                    await getCourseSchedulePage();
+                  }}></NSelect>
+                <NSelect
+                  v-model:value={forms.classSelect.gradeLevel}
+                  class={styles.lookMoreSearch}
+                  placeholder="全部学级"
+                  options={forms.popSelectLevelList}
+                  labelField="name"
+                  valueField="id"
+                  onUpdate:value={async (val: any) => {
+                    forms.classSelect.gradeLevel = val;
+                    forms.lastClassSelect.currentClass = null;
+                    forms.classSelect.currentClass = null;
+                    await getClassList();
+                    await getCourseSchedulePage();
+                  }}></NSelect>
+                <NSelect
+                  v-model:value={forms.classSelect.currentClass}
+                  class={styles.lookMoreSearch}
+                  placeholder="选择班级"
+                  options={forms.popSelectOptions}
+                  onUpdate:value={(val: any) => {
+                    forms.popSelectOptions.forEach((item: any) => {
+                      if (item.value === val) {
+                        forms.classSelect.currentGradeNum =
+                          item.currentGradeNum;
+                        forms.classSelect.currentClass = item.value;
+                        forms.classSelect.name = item.label;
+                        forms.classSelect.upgradeFlag = item.upgradeFlag;
+                        getCourseSchedulePage();
+                      }
+                    });
+                  }}></NSelect>
+              </div>
+            </div>
+            <NSpin show={forms.classLoading} style={{ minHeight: '40vh' }}>
+              {Object.keys(teachList.value).length > 0 && (
+                <div class={styles.teachListWrap}>
+                  {Object.keys(teachList.value).map(key => (
+                    <TeachGroup
+                      list={teachList.value[key]}
+                      keys={key}></TeachGroup>
+                  ))}
+                </div>
+              )}
+
+              {Object.keys(teachList.value).length <= 0 &&
+                !forms.classLoading && <TheEmpty />}
+            </NSpin>
+
+            {forms.total > 4 && (
+              <div class={styles.teachListWrapWall}>
+                <span
+                  onClick={() => {
+                    // setTabsCaches('attendclass', 'tabName', {
+                    //   path: '/classDetail'
+                    // });
+                    sessionStorage.setItem('classDetailTabs', 'attendclass');
+                    router.push({
+                      path: '/classDetail',
+                      query: {
+                        name: forms.classSelect.name,
+                        id: forms.classSelect.currentClass,
+                        gradeYear: forms.classSelect.gradeYear,
+                        upgradeFlag: forms.classSelect.upgradeFlag ? 1 : 0 // 是否为历史班
+                      }
+                    });
+                  }}>
+                  查看全部
+                </span>
+              </div>
+            )}
+          </div>
+        </div>
+
+        <NModal
+          class={['modalTitle background']}
+          title={'节拍器'}
+          preset="card"
+          v-model:show={showModalBeat.value}
+          style={{ width: '687px' }}>
+          <div class={styles.modeWrap}>
+            <iframe
+              src={`${vaildUrl()}/metronome/?id=${new Date().getTime()}`}
+              scrolling="no"
+              frameborder="0"
+              width="100%"
+              height={'650px'}></iframe>
+          </div>
+        </NModal>
+
+        <NModal
+          v-model:show={showModalTime.value}
+          class={['modalTitle background']}
+          title={'计时器'}
+          preset="card"
+          style={{ width: px2vw(772) }}>
+          <div>
+            <TimerMeter></TimerMeter>
+          </div>
+        </NModal>
+
+        <NModal class={['background']} v-model:show={showModalTone.value}>
+          <div>
+            <PlaceholderTone
+              onClose={() => {
+                showModalTone.value = false;
+              }}></PlaceholderTone>
+          </div>
+        </NModal>
+
+        {/* 弹窗查看 */}
+        <PreviewWindow
+          v-model:show={forms.showPreview}
+          type="attend"
+          params={forms.itemPreview}
+        />
+
+        {forms.showGuide ? <HomeGuide></HomeGuide> : null}
+
+        <NModal
+          v-model:show={showUpdatePassword.value}
+          class={['modalTitle', styles.showUpdatePassword]}
+          style="--n-title-font-weight: 600;"
+          preset="card"
+          title={'修改密码'}
+          closable={false}
+          maskClosable={false}
+          closeOnEsc={false}>
+          <UpdatePassword
+            onSubmit={() => {
+              // 密码更新成功
+              showUpdatePassword.value = true;
+              forms.showGuide = true;
+              userStore.logout().then(() => {
+                // 移除标签页
+                router
+                  .replace({
+                    name: 'login'
+                  })
+                  .finally(() => location.reload());
+              });
+            }}
+          />
+        </NModal>
+
+        <NModal
+          v-model:show={forms.showAttendClass}
+          preset="card"
+          showIcon={false}
+          class={['modalTitle background', styles.attendClassModal]}
+          title={'选择班级'}
+          blockScroll={false}>
+          <AttendClass
+            onClose={() => (forms.showAttendClass = false)}
+            type="change"
+            onConfirm={(item: any) => {
+              router.push({
+                path: '/prepare-lessons',
+                query: {
+                  ...item
+                }
+              });
+            }}
+          />
+        </NModal>
+      </div>
+    );
+  }
+});

+ 899 - 0
src/views/home/index.module copy.less

@@ -0,0 +1,899 @@
+.homeWrap {
+  display: flex;
+  flex-direction: row;
+  // align-items: center;
+  // justify-content: space-between;
+  align-content: stretch;
+  // min-height: 100%;
+  // height: 100%;
+}
+
+.homeInfoLeft {
+  display: flex;
+  flex-direction: column;
+  width: 1286px;
+  // height: 100%;
+}
+
+.homeBanner {
+  border-radius: 20px;
+  background-color: #fff;
+  position: relative;
+  margin-bottom: 20px;
+  padding: 25px 20px;
+}
+
+.welcomeInfo {
+  padding-bottom: 30px;
+
+
+  .userInfo {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    color: #131415;
+    padding-bottom: 14px;
+
+    .userName {
+      font-size: 26px;
+      font-family: Alibaba-PuHuiTi-B, Alibaba-PuHuiTi;
+      font-weight: bold;
+      line-height: 35px;
+    }
+
+    .userTime {
+      display: flex;
+      align-items: center;
+      font-size: 20px;
+      font-weight: 600;
+      line-height: 28px;
+
+      &::before {
+        content: ' ';
+        display: inline-block;
+        width: 18px;
+        height: 18px;
+        background: url('./images/icon-date.png') no-repeat center;
+        background-size: contain;
+        margin-right: 10px;
+      }
+    }
+  }
+
+  .userTips {
+    font-size: 18px;
+    color: #787D7F;
+    line-height: 25px;
+  }
+
+  .guide_btn {
+    margin-left: 16px;
+    --n-height: 40px !important;
+
+    i {
+      display: inline-block;
+      width: 12px;
+      height: 12px;
+      background: url('./images/icon-white-arrow.svg') no-repeat center;
+      background-size: contain;
+      margin-left: 4px;
+    }
+  }
+}
+
+.applyInfo {
+  background: #E6F2FF;
+  border-radius: 20px;
+  position: relative;
+  display: flex;
+  align-items: center;
+  height: 490px;
+  background: url('./images/home/home-bg-1.png') no-repeat right bottom, url('./images/home/home-bg-2.png') no-repeat left top #E6F2FF;
+  background-size: 69px, 68px 61px;
+
+  .userName {
+    left: 218px;
+    top: 28px;
+    position: absolute;
+    font-size: 26px;
+    font-family: Alibaba-PuHuiTi-B, Alibaba-PuHuiTi;
+    font-weight: bold;
+    line-height: 35px;
+
+  }
+
+  .teacherWoman {
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    z-index: 9;
+    width: 238px;
+    height: 518px;
+
+    img {
+      width: inherit;
+      height: inherit;
+    }
+  }
+
+  .teacherMan {
+    position: absolute;
+    left: -45px;
+    bottom: -26px;
+    z-index: 9;
+    width: 376px;
+    height: 538px;
+
+    img {
+      width: inherit;
+      height: inherit;
+    }
+  }
+
+  .blackborad {
+    padding-left: 182px;
+    padding-right: 60px;
+
+    .blackBoardBg {
+      width: 466px;
+      height: 298px;
+    }
+  }
+}
+
+.applyContainer {
+  width: 450px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  margin-top: -45px;
+  // padding: 24px 0;
+
+
+  .applyItem {
+    position: relative;
+    width: 211px;
+    height: 296px;
+    transition: all 0.2s ease;
+
+    &:hover {
+      transform: scale(1.05);
+      transition: all 0.2s ease;
+    }
+
+    p {
+      text-align: center;
+      font-size: 14px;
+      font-weight: 600;
+      color: #FFFFFF;
+      line-height: 20px;
+      padding: 175px 22px 0;
+    }
+
+    .applyBtn {
+      position: absolute;
+      bottom: 22px;
+      left: 50%;
+      transform: translate(-50%);
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      margin: 19px auto 0;
+      width: 158px;
+      height: 40px;
+      background: #FFFFFF;
+      border-radius: 10px;
+      cursor: pointer;
+    }
+
+    .applyBtn1 img {
+      width: 58px;
+      height: 20px;
+    }
+
+    .applyBtn2 img {
+      width: 77px;
+      height: 19px;
+    }
+  }
+
+  .applyItem1 {
+    background: url('./images/home/home-1.png') no-repeat center;
+    background-size: contain;
+  }
+
+  .applyItem2 {
+    background: url('./images/home/home-2.png') no-repeat center;
+    background-size: contain;
+  }
+
+}
+
+.toolContainer {
+  display: flex;
+  align-items: center;
+  background: url('./images/tool_bg.png') no-repeat left bottom #fff;
+  background-size: 86px 66px;
+  border-radius: 16px;
+  padding: 22px 29px 34px 54px;
+  flex: 1 auto;
+
+  .toolTips {
+    width: 370px;
+
+    .toolTitle {
+      display: flex;
+      align-items: center;
+      font-size: 24px;
+      font-weight: 600;
+      color: #131415;
+      padding-bottom: 24px;
+
+      &::before {
+        margin-right: 8px;
+        content: ' ';
+        display: inline-block;
+        width: 5px;
+        height: 16px;
+        background: #198CFE;
+      }
+    }
+
+    .toolContent {
+      font-size: 16px;
+      color: #787D7F;
+      line-height: 25px;
+      letter-spacing: 1px;
+      padding-bottom: 18px;
+    }
+  }
+
+  .iconTo {
+    margin: 0 120px 0 44px;
+    width: 38px;
+    height: 18px
+  }
+
+  .toolFunction {
+    display: flex;
+    align-items: center;
+
+    img {
+      width: 190px;
+      height: 190px;
+      // margin: 5px 13px 10px;
+    }
+
+    .toolItem {
+      width: 190px;
+      // background: #EBF5FF;
+      border-radius: 16px;
+      margin-right: 30px;
+      text-align: center;
+      line-height: 0;
+
+      &:last-child {
+        margin-right: 0;
+      }
+
+      // .toolMemo {
+      //   font-size: 16px;
+      //   color: #4A8FE0;
+      //   line-height: 22px;
+      //   text-align: center;
+      // }
+
+      .btn1,
+      .btn2,
+      .btn3 {
+        --n-border-radius: 9px !important;
+        --n-height: 38px !important;
+        --n-padding: 7px 28px !important;
+        --n-border: none !important;
+        --n-border-hover: none !important;
+        --n-border-pressed: none !important;
+        --n-border-focus: none !important;
+        --n-border-disabled: none !important;
+        --n-font-size: 18px !important;
+        font-weight: 600 !important;
+        color: #fff;
+        margin: 8px 0 0;
+      }
+
+
+      .btn1 {
+        background: linear-gradient(135deg, #51E7FF 0%, #2A7CFF 100%) !important;
+        --n-ripple-color: #51E7FF !important;
+      }
+
+      .btn2 {
+        background: linear-gradient(135deg, #FFA289 0%, #FF5177 100%);
+        --n-ripple-color: #FFA289 !important;
+      }
+
+      .btn3 {
+        background: linear-gradient(135deg, #FFC37B 0%, #FF6635 100%);
+        --n-ripple-color: #FFC37B !important;
+      }
+    }
+
+    // .item1 {
+    //   background: url('./images/t1_bg.png')no-repeat right bottom #EBF5FF;
+    //   background-size: 28px;
+    // }
+
+    // .item2 {
+    //   background: url('./images/t2_bg.png')no-repeat right bottom #FFF1EF;
+    //   background-size: 28px;
+
+    //   .toolMemo {
+    //     color: #F86C58;
+    //   }
+    // }
+
+    // .item3 {
+    //   background: url('./images/t3_bg.png')no-repeat right bottom #FFF7E2;
+    //   background-size: 28px;
+
+    //   .toolMemo {
+    //     color: #F28D1E;
+    //   }
+    // }
+  }
+}
+
+
+.beatImage {
+  cursor: pointer;
+
+  img {
+    width: 698px;
+  }
+}
+
+.homeInfoRight {
+  display: flex;
+  margin-left: 20px;
+  width: 450px;
+  position: relative;
+}
+
+// 学情
+.homeStudy {
+  background-color: #fff;
+
+  .homeStudyTitle {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    font-size: 20px;
+
+    font-weight: 600;
+    color: #131415;
+    line-height: 28px;
+
+    .homeStudyTitleDot {
+      width: 5px;
+      height: 16px;
+      background: #198cfe;
+      margin-right: 8px;
+    }
+  }
+
+  .homeStudyInfoList {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: space-between;
+    margin-top: 21px;
+
+    .homeStudyInfoTabs {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+
+      .homeStudyInfoTabItem {
+        cursor: pointer;
+        width: 112px;
+        height: 39px;
+        border-radius: 20px;
+        font-size: 18px;
+        font-weight: 600;
+        line-height: 39px;
+        text-align: center;
+        margin-right: 24px;
+        background: #f5f6fa;
+        color: rgba(0, 0, 0, 0.5);
+
+        &:hover {
+          background: #198cfe;
+          color: #ffffff;
+          opacity: 0.8;
+        }
+      }
+
+      .homeStudyInfoTabItem.active {
+        background: #198cfe;
+        color: #ffffff;
+      }
+    }
+
+    .homeStudyInfoDate {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      justify-content: flex-end;
+    }
+  }
+
+  .searchBtn {
+    width: 90px;
+    height: 43px;
+    background: #198cfe;
+    border-radius: 8px;
+    line-height: 41px;
+    font-weight: 600 !important;
+    font-size: 18px;
+  }
+
+  .resetBtn {
+    width: 90px;
+    height: 43px;
+    border-radius: 8px;
+    line-height: 41px;
+    font-weight: 600 !important;
+    font-size: 18px;
+  }
+}
+
+.homeTrainData {
+  margin-top: 40px;
+
+  .TrainDataTop {
+    margin-bottom: 40px;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: space-between;
+
+    .TrainDataTopLeft {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+
+      .TrainDataItem {
+        margin-right: 40px;
+
+        .TrainDataItemTitle {
+          display: flex;
+          flex-direction: row;
+          align-items: center;
+          text-align: center;
+          font-size: 13px;
+          font-weight: 400;
+          color: #777777;
+          line-height: 18px;
+          width: 100%;
+          justify-content: center;
+
+          span {
+            font-family: 'DINA';
+            font-size: 26px;
+            font-weight: 600;
+            color: #131415;
+            line-height: 28px;
+          }
+        }
+
+        .TrainDataItemsubTitle {
+          margin-top: 4px;
+          text-align: center;
+          font-size: 13px;
+          font-family: PingFangSC-Regular, PingFang SC;
+          font-weight: 400;
+          color: #777777;
+          line-height: 18px;
+        }
+      }
+    }
+
+    .TrainDataTopRight {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+
+      .DataTopRightItem {
+        cursor: pointer;
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-left: 30px;
+
+        &:hover {
+          opacity: 0.8;
+        }
+
+        .DataTopRightDot {
+          width: 16px;
+          height: 16px;
+          background: #3583fa;
+          border-radius: 4px;
+          margin-right: 6px;
+        }
+
+        .DataTopRightDot.DataTopRightDotBlue {
+          background: #edeef1;
+        }
+
+        .DataTopRightDot.red {
+          background: #ff7aa7;
+        }
+      }
+
+      .DataTopRightItem.DataTopRightItemDis {
+        .DataTopRightDot {
+          background: #f5f6fa;
+        }
+      }
+    }
+  }
+}
+
+
+.homeInfoRight {
+  // display: flex;
+  // flex-direction: column;
+
+  .rightTitle {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    font-weight: 600;
+    color: #131415;
+    font-size: 20px;
+
+    .titleDot {
+      width: 5px;
+      height: 16px;
+      background: #198cfe;
+      margin-right: 8px;
+    }
+  }
+
+  .headerContainer {
+    padding-top: 12px;
+    text-align: center;
+  }
+
+  .HeaderWrap {
+    position: relative;
+    display: inline-block;
+    cursor: pointer;
+
+    .headerD {
+      width: 237px;
+      height: 138px;
+    }
+
+    .defultHeade {
+      width: 116px;
+      height: 116px;
+      overflow: hidden;
+      border-radius: 50%;
+      position: absolute;
+      top: 11px;
+      left: 61px;
+    }
+  }
+
+  .headerInfo {
+    text-align: center;
+    padding-bottom: 32px;
+    border-bottom: 1px solid #F2F2F2;
+    margin-bottom: 32px;
+
+    .headerTitle {
+      font-size: max(20px, 16px);
+      font-weight: 600;
+      color: #131415;
+      line-height: 28px;
+      letter-spacing: 1px;
+      padding: 20px 0 8px;
+    }
+
+    .headerSubTitle {
+      font-size: 14px;
+      font-weight: 400;
+      color: #707a92;
+      line-height: 20px;
+    }
+  }
+
+  .rightTeachingWrap {
+    overflow: hidden;
+    flex: 1;
+    background-color: #fff;
+    padding: 20px;
+    border-radius: 20px;
+
+    .rightTeachingWrapTitle {
+      display: flex;
+      flex-direction: row;
+      // align-items: center;
+      justify-content: space-between;
+      flex-direction: column;
+
+      .lookMore {
+        cursor: pointer;
+        display: flex;
+        align-items: center;
+        min-width: 114px;
+        border-radius: 8px;
+        border: 1px solid #DEDEDE;
+        font-size: 15px;
+        color: #131415;
+        padding: 7px 12px;
+
+        svg {
+          margin-left: 8px;
+          width: 16px;
+          height: 16px;
+        }
+      }
+
+      .classSearchList {
+        display: flex;
+        gap: 12px;
+        padding-top: 12px;
+
+        :global {
+          .n-base-selection {
+            --n-height: 35px !important;
+            --n-font-size: 15px !important;
+            --n-border: 1px solid #DEDEDE !important;
+            --n-border-radius: 8px !important;
+            max-width: 130px;
+          }
+        }
+      }
+    }
+  }
+}
+
+:global {
+  .n-base-select-menu .n-base-select-option.n-base-select-option--show-checkmark {
+    padding-right: var(--n-option-padding);
+  }
+
+  .n-empty {
+    --n-font-size: 14px !important;
+  }
+}
+
+.teachListWrap {
+  position: relative;
+
+
+}
+
+.teachListWrapWall {
+  position: absolute;
+  bottom: 0;
+  height: 159px;
+  width: 100%;
+  background: linear-gradient(180deg,
+      rgba(255, 255, 255, 0) 0%,
+      #ffffff 100%);
+  border-radius: 0px 0px 20px 20px;
+
+  span {
+    position: absolute;
+    bottom: 7px;
+    left: 0;
+    width: 100%;
+    text-align: center;
+    color: #1677FF;
+    font-size: 16px;
+
+    &::after {
+      content: ' ';
+      display: inline-block;
+      width: 12px;
+      height: 12px;
+      background: url('./images/blueArrow.png') no-repeat center;
+      background-size: contain;
+    }
+  }
+}
+
+.teachGroup {
+  margin-top: 12px;
+
+  .teachGroupTitle {
+    position: relative;
+    left: -10px;
+    font-size: 14px;
+    font-weight: 400;
+    color: #aaaaaa;
+    width: 60px;
+    text-align: center;
+    margin-bottom: 12px;
+  }
+
+  .teachGroupList {
+    padding-bottom: 12px;
+    margin-left: 20px;
+    border-left: 1px solid #d1e8ff;
+    min-height: 92px;
+    position: relative;
+
+    .teachGroupListDot {
+      width: 15px;
+      height: 15px;
+      background: #198cfe;
+      border: 4px solid #d1e8ff;
+      border-radius: 50%;
+      top: 28px;
+      left: -8px;
+      position: absolute;
+    }
+  }
+
+  .teachGroupItemWrap {
+    margin-left: 28px;
+    background: #f7f9ff;
+    border-radius: 12px;
+    display: flex;
+    flex-direction: row;
+    align-items: top;
+
+    &:nth-last-of-type(1) {
+      margin-bottom: 0;
+    }
+
+    margin-bottom: 12px;
+    padding: 10px;
+
+    .teachGroupItemLeft {
+      margin-right: 12px;
+      width: 50px;
+      height: 50px;
+      border-radius: 50%;
+      overflow: hidden;
+      border: 2px solid #198cfe;
+
+      .teachGroupItemHeader {
+        border: 2px solid #fff;
+        border-radius: 50%;
+        overflow: hidden;
+
+        img {
+          width: 44px;
+          height: 44px;
+        }
+      }
+    }
+
+    .teachGroupItemRight {
+      flex: 1;
+
+      .teachGroupItemName {
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        justify-content: space-between;
+        font-size: 16px;
+        margin-top: 2px;
+        font-weight: 600;
+        color: #131415;
+
+        span {
+          font-size: 13px;
+          font-weight: 400;
+          color: #1677ff;
+          line-height: 18px;
+        }
+      }
+
+      .teachGroupItemInfo {
+        font-size: 13px;
+        line-height: 26px;
+        color: rgba(0, 0, 0, 0.5);
+      }
+
+      .subjectName {
+        font-size: 14px;
+        font-weight: 400;
+        color: #FFFFFF;
+        background: #198CFE;
+        border-radius: 5px;
+        padding: 1px 8px;
+        margin-right: 4px;
+      }
+    }
+  }
+}
+
+.indDot,
+.endDot {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+}
+
+.indDot {
+  span {
+    border-radius: 50%;
+    width: 8px;
+    height: 8px;
+    background: #198cfe;
+    margin-right: 8px;
+  }
+}
+
+.endDot {
+  opacity: 0.7;
+  color: #aaaaaa;
+
+  span {
+    border-radius: 50%;
+    width: 8px;
+    height: 8px;
+    background: #aaaaaa;
+    margin-right: 8px;
+  }
+}
+
+.assignHomework {
+  width: 520px;
+}
+
+.assignHomeworkContainer {
+  padding: 24px 30px;
+
+
+  .updateBtnGroup {
+    padding: 0;
+    justify-content: center !important;
+
+    :global {
+      .n-button {
+        height: 48px !important;
+        min-width: 156px;
+      }
+    }
+  }
+}
+
+.tableWrap {
+  margin-top: 40px;
+}
+
+.showModalTone {
+  width: 500px;
+
+  .studentRemove {
+    padding: 32px 40px 46px;
+
+    p {
+      font-size: 18px;
+      color: #777777;
+      line-height: 30px;
+      text-align: center;
+
+      span {
+        color: #EA4132;
+      }
+    }
+  }
+}
+
+.attendClassModal {
+  width: 800px;
+  border-radius: 16px;
+  overflow: hidden;
+}
+
+.showUpdatePassword {
+  width: 514px;
+}

+ 180 - 802
src/views/home/index.module.less

@@ -1,899 +1,277 @@
-.homeWrap {
-  display: flex;
-  flex-direction: row;
-  // align-items: center;
-  // justify-content: space-between;
-  align-content: stretch;
-  // min-height: 100%;
-  // height: 100%;
+.attendClassModal {
+  width: 800px;
+  border-radius: 16px;
+  overflow: hidden;
 }
 
-.homeInfoLeft {
-  display: flex;
-  flex-direction: column;
-  width: 1286px;
-  // height: 100%;
+.showUpdatePassword {
+  width: 514px;
 }
 
-.homeBanner {
+.homeSection {
+  display: flex;
+  background: #FFFFFF;
   border-radius: 20px;
-  background-color: #fff;
-  position: relative;
-  margin-bottom: 20px;
-  padding: 25px 20px;
+  padding: 27px;
 }
 
-.welcomeInfo {
-  padding-bottom: 30px;
-
+.homeLeft {
+  display: flex;
+  position: relative;
+  background: url('./img/left-bg.png') no-repeat top center #FFFFFF;
+  background-size: cover;
+  border-radius: 10px;
+  padding: 63px 22px 22px;
+  width: 500px;
+  min-height: 690px;
+  flex-shrink: 0;
 
-  .userInfo {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    color: #131415;
-    padding-bottom: 14px;
+  .homeWindow {
+    width: 96px;
+    height: 23px;
+    background: url('./img/icon-left-window.png') no-repeat top center;
+    background-size: contain;
+    position: absolute;
+    left: 50%;
+    top: 20px;
+    margin-left: -48px;
+  }
 
-    .userName {
-      font-size: 26px;
-      font-family: Alibaba-PuHuiTi-B, Alibaba-PuHuiTi;
-      font-weight: bold;
-      line-height: 35px;
-    }
+  .homeUserInfo {
+    position: relative;
+    height: inherit;
+    background: rgba(255, 255, 255, 0.8);
+    border-radius: 13px;
+    border: 3px solid #FFFFFF;
 
-    .userTime {
-      display: flex;
-      align-items: center;
-      font-size: 20px;
-      font-weight: 600;
-      line-height: 28px;
-
-      &::before {
-        content: ' ';
-        display: inline-block;
-        width: 18px;
-        height: 18px;
-        background: url('./images/icon-date.png') no-repeat center;
-        background-size: contain;
-        margin-right: 10px;
-      }
+    .homeTag {
+      position: absolute;
+      right: 33px;
+      top: -6px;
+      width: 28px;
+      height: 35px;
+      background: url('./img/icon-tag.png') no-repeat top center;
+      background-size: contain;
     }
   }
 
-  .userTips {
-    font-size: 18px;
-    color: #787D7F;
+  .desc {
+    padding: 12px 34px 30px;
+    font-size: 15px;
+    color: rgba(0, 0, 0, 0.7);
     line-height: 25px;
+    letter-spacing: 1px;
   }
 
-  .guide_btn {
-    margin-left: 16px;
-    --n-height: 40px !important;
-
-    i {
-      display: inline-block;
-      width: 12px;
-      height: 12px;
-      background: url('./images/icon-white-arrow.svg') no-repeat center;
-      background-size: contain;
-      margin-left: 4px;
-    }
+  .homeEchats {
+    position: absolute;
+    bottom: 34px;
+    box-sizing: content-box;
+    display: block;
+    width: calc(100% - 68px);
+    margin: 54px 34px 0;
   }
-}
 
-.applyInfo {
-  background: #E6F2FF;
-  border-radius: 20px;
-  position: relative;
-  display: flex;
-  align-items: center;
-  height: 490px;
-  background: url('./images/home/home-bg-1.png') no-repeat right bottom, url('./images/home/home-bg-2.png') no-repeat left top #E6F2FF;
-  background-size: 69px, 68px 61px;
-
-  .userName {
-    left: 218px;
-    top: 28px;
+  .teacherMan {
     position: absolute;
-    font-size: 26px;
-    font-family: Alibaba-PuHuiTi-B, Alibaba-PuHuiTi;
-    font-weight: bold;
-    line-height: 35px;
-
+    bottom: 0;
+    right: -23px;
+    width: 314px;
+    height: 384px;
   }
 
   .teacherWoman {
     position: absolute;
-    left: 0;
     bottom: 0;
-    z-index: 9;
-    width: 238px;
-    height: 518px;
-
-    img {
-      width: inherit;
-      height: inherit;
-    }
+    right: 20px;
+    width: 218px;
+    height: 442px;
   }
+}
 
-  .teacherMan {
-    position: absolute;
-    left: -45px;
-    bottom: -26px;
-    z-index: 9;
-    width: 376px;
-    height: 538px;
-
-    img {
-      width: inherit;
-      height: inherit;
-    }
-  }
+.homeUsers {
+  display: flex;
+  align-items: center;
+  padding: 20px 34px;
 
-  .blackborad {
-    padding-left: 182px;
-    padding-right: 60px;
+  .userImg {
+    margin-right: 12px;
+    width: 56px;
+    height: 56px;
+    border: 2px solid #FFFFFF;
+    border-radius: 50%;
+  }
 
-    .blackBoardBg {
-      width: 466px;
-      height: 298px;
-    }
+  .userName {
+    font-size: 22px;
+    color: #131415;
+    line-height: 29px;
+    font-weight: bold;
   }
 }
 
-.applyContainer {
-  width: 450px;
+.homeBtnGroup {
   display: flex;
   align-items: center;
-  justify-content: space-between;
-  margin-top: -45px;
-  // padding: 24px 0;
+  justify-content: center;
 
+  .btnBk,
+  .btnClass {
+    width: 178px;
+    height: 64px;
+    cursor: pointer;
 
-  .applyItem {
-    position: relative;
-    width: 211px;
-    height: 296px;
-    transition: all 0.2s ease;
+    transition: all .2s ease;
 
     &:hover {
       transform: scale(1.05);
-      transition: all 0.2s ease;
-    }
-
-    p {
-      text-align: center;
-      font-size: 14px;
-      font-weight: 600;
-      color: #FFFFFF;
-      line-height: 20px;
-      padding: 175px 22px 0;
-    }
-
-    .applyBtn {
-      position: absolute;
-      bottom: 22px;
-      left: 50%;
-      transform: translate(-50%);
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      margin: 19px auto 0;
-      width: 158px;
-      height: 40px;
-      background: #FFFFFF;
-      border-radius: 10px;
-      cursor: pointer;
-    }
-
-    .applyBtn1 img {
-      width: 58px;
-      height: 20px;
+      transition: all .2s ease;
     }
+  }
 
-    .applyBtn2 img {
-      width: 77px;
-      height: 19px;
-    }
+  .btnClass {
+    margin-left: 8px;
   }
 
-  .applyItem1 {
-    background: url('./images/home/home-1.png') no-repeat center;
+  .btnBk {
+    background: url('./img/icon-bk.png') no-repeat center center;
     background-size: contain;
   }
 
-  .applyItem2 {
-    background: url('./images/home/home-2.png') no-repeat center;
+  .btnClass {
+    background: url('./img/icon-class.png') no-repeat center center;
     background-size: contain;
   }
-
 }
 
-.toolContainer {
-  display: flex;
-  align-items: center;
-  background: url('./images/tool_bg.png') no-repeat left bottom #fff;
-  background-size: 86px 66px;
-  border-radius: 16px;
-  padding: 22px 29px 34px 54px;
+.homeRight {
   flex: 1 auto;
+  margin-left: 26px;
 
-  .toolTips {
-    width: 370px;
-
-    .toolTitle {
-      display: flex;
-      align-items: center;
-      font-size: 24px;
-      font-weight: 600;
-      color: #131415;
-      padding-bottom: 24px;
-
-      &::before {
-        margin-right: 8px;
-        content: ' ';
-        display: inline-block;
-        width: 5px;
-        height: 16px;
-        background: #198CFE;
-      }
-    }
-
-    .toolContent {
-      font-size: 16px;
-      color: #787D7F;
-      line-height: 25px;
-      letter-spacing: 1px;
-      padding-bottom: 18px;
-    }
-  }
-
-  .iconTo {
-    margin: 0 120px 0 44px;
-    width: 38px;
-    height: 18px
-  }
-
-  .toolFunction {
+  .rightTop {
     display: flex;
-    align-items: center;
-
-    img {
-      width: 190px;
-      height: 190px;
-      // margin: 5px 13px 10px;
-    }
-
-    .toolItem {
-      width: 190px;
-      // background: #EBF5FF;
-      border-radius: 16px;
-      margin-right: 30px;
-      text-align: center;
-      line-height: 0;
-
-      &:last-child {
-        margin-right: 0;
-      }
-
-      // .toolMemo {
-      //   font-size: 16px;
-      //   color: #4A8FE0;
-      //   line-height: 22px;
-      //   text-align: center;
-      // }
-
-      .btn1,
-      .btn2,
-      .btn3 {
-        --n-border-radius: 9px !important;
-        --n-height: 38px !important;
-        --n-padding: 7px 28px !important;
-        --n-border: none !important;
-        --n-border-hover: none !important;
-        --n-border-pressed: none !important;
-        --n-border-focus: none !important;
-        --n-border-disabled: none !important;
-        --n-font-size: 18px !important;
-        font-weight: 600 !important;
-        color: #fff;
-        margin: 8px 0 0;
-      }
-
-
-      .btn1 {
-        background: linear-gradient(135deg, #51E7FF 0%, #2A7CFF 100%) !important;
-        --n-ripple-color: #51E7FF !important;
-      }
-
-      .btn2 {
-        background: linear-gradient(135deg, #FFA289 0%, #FF5177 100%);
-        --n-ripple-color: #FFA289 !important;
-      }
-
-      .btn3 {
-        background: linear-gradient(135deg, #FFC37B 0%, #FF6635 100%);
-        --n-ripple-color: #FFC37B !important;
-      }
-    }
-
-    // .item1 {
-    //   background: url('./images/t1_bg.png')no-repeat right bottom #EBF5FF;
-    //   background-size: 28px;
-    // }
-
-    // .item2 {
-    //   background: url('./images/t2_bg.png')no-repeat right bottom #FFF1EF;
-    //   background-size: 28px;
-
-    //   .toolMemo {
-    //     color: #F86C58;
-    //   }
-    // }
-
-    // .item3 {
-    //   background: url('./images/t3_bg.png')no-repeat right bottom #FFF7E2;
-    //   background-size: 28px;
-
-    //   .toolMemo {
-    //     color: #F28D1E;
-    //   }
-    // }
   }
-}
-
 
-.beatImage {
-  cursor: pointer;
-
-  img {
-    width: 698px;
-  }
-}
-
-.homeInfoRight {
-  display: flex;
-  margin-left: 20px;
-  width: 450px;
-  position: relative;
-}
-
-// 学情
-.homeStudy {
-  background-color: #fff;
-
-  .homeStudyTitle {
+  .topSection {
+    position: relative;
+    flex: 1;
     display: flex;
-    flex-direction: row;
     align-items: center;
-    font-size: 20px;
-
-    font-weight: 600;
-    color: #131415;
-    line-height: 28px;
-
-    .homeStudyTitleDot {
-      width: 5px;
-      height: 16px;
-      background: #198cfe;
-      margin-right: 8px;
-    }
-  }
+    flex-direction: column;
+    transition: all .2s ease;
+    cursor: pointer;
 
-  .homeStudyInfoList {
-    display: flex;
-    flex-direction: row;
-    align-items: center;
-    justify-content: space-between;
-    margin-top: 21px;
-
-    .homeStudyInfoTabs {
-      display: flex;
-      flex-direction: row;
-      align-items: center;
-
-      .homeStudyInfoTabItem {
-        cursor: pointer;
-        width: 112px;
-        height: 39px;
-        border-radius: 20px;
-        font-size: 18px;
-        font-weight: 600;
-        line-height: 39px;
-        text-align: center;
-        margin-right: 24px;
-        background: #f5f6fa;
-        color: rgba(0, 0, 0, 0.5);
-
-        &:hover {
-          background: #198cfe;
-          color: #ffffff;
-          opacity: 0.8;
-        }
-      }
-
-      .homeStudyInfoTabItem.active {
-        background: #198cfe;
-        color: #ffffff;
-      }
+    &::before {
+      content: '';
+      position: absolute;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      top: 0;
+      background: url('./img/t1-3.png') no-repeat top left, url('./img/t1-2.png') no-repeat bottom center;
+      background-size: 108px 91px, 100% 129px;
     }
 
-    .homeStudyInfoDate {
-      display: flex;
-      flex-direction: row;
-      align-items: center;
-      justify-content: flex-end;
+    &:last-child {
+      margin-left: 25px;
     }
-  }
 
-  .searchBtn {
-    width: 90px;
-    height: 43px;
-    background: #198cfe;
-    border-radius: 8px;
-    line-height: 41px;
-    font-weight: 600 !important;
-    font-size: 18px;
-  }
-
-  .resetBtn {
-    width: 90px;
-    height: 43px;
-    border-radius: 8px;
-    line-height: 41px;
-    font-weight: 600 !important;
-    font-size: 18px;
-  }
-}
-
-.homeTrainData {
-  margin-top: 40px;
-
-  .TrainDataTop {
-    margin-bottom: 40px;
-    display: flex;
-    flex-direction: row;
-    align-items: center;
-    justify-content: space-between;
-
-    .TrainDataTopLeft {
-      display: flex;
-      flex-direction: row;
-      align-items: center;
-
-      .TrainDataItem {
-        margin-right: 40px;
-
-        .TrainDataItemTitle {
-          display: flex;
-          flex-direction: row;
-          align-items: center;
-          text-align: center;
-          font-size: 13px;
-          font-weight: 400;
-          color: #777777;
-          line-height: 18px;
-          width: 100%;
-          justify-content: center;
-
-          span {
-            font-family: 'DINA';
-            font-size: 26px;
-            font-weight: 600;
-            color: #131415;
-            line-height: 28px;
-          }
-        }
-
-        .TrainDataItemsubTitle {
-          margin-top: 4px;
-          text-align: center;
-          font-size: 13px;
-          font-family: PingFangSC-Regular, PingFang SC;
-          font-weight: 400;
-          color: #777777;
-          line-height: 18px;
-        }
-      }
+    .tFun {
+      margin-top: 17px;
+      width: 258px;
+      height: 224px;
     }
 
-    .TrainDataTopRight {
-      display: flex;
-      flex-direction: row;
-      align-items: center;
-
-      .DataTopRightItem {
-        cursor: pointer;
-        display: flex;
-        flex-direction: row;
-        align-items: center;
-        margin-left: 30px;
-
-        &:hover {
-          opacity: 0.8;
-        }
-
-        .DataTopRightDot {
-          width: 16px;
-          height: 16px;
-          background: #3583fa;
-          border-radius: 4px;
-          margin-right: 6px;
-        }
-
-        .DataTopRightDot.DataTopRightDotBlue {
-          background: #edeef1;
-        }
-
-        .DataTopRightDot.red {
-          background: #ff7aa7;
-        }
-      }
-
-      .DataTopRightItem.DataTopRightItemDis {
-        .DataTopRightDot {
-          background: #f5f6fa;
-        }
-      }
+    .tTxt {
+      margin-top: -22px;
+      width: 196px;
+      height: 38px;
     }
-  }
-}
-
 
-.homeInfoRight {
-  // display: flex;
-  // flex-direction: column;
-
-  .rightTitle {
-    display: flex;
-    flex-direction: row;
-    align-items: center;
-    font-weight: 600;
-    color: #131415;
-    font-size: 20px;
-
-    .titleDot {
-      width: 5px;
-      height: 16px;
-      background: #198cfe;
-      margin-right: 8px;
+    .tTitle {
+      margin-top: 27px;
+      margin-bottom: 34px;
+      width: 336px;
+      height: 23px;
     }
-  }
 
-  .headerContainer {
-    padding-top: 12px;
-    text-align: center;
   }
 
-  .HeaderWrap {
-    position: relative;
-    display: inline-block;
-    cursor: pointer;
-
-    .headerD {
-      width: 237px;
-      height: 138px;
-    }
+  .topSection1 {
+    background: linear-gradient(135deg, #99BBFF 0%, #9CA6FF 20%, #A5A1FF 50%, #C686FF 100%);
+    border-radius: 17px;
 
-    .defultHeade {
-      width: 116px;
-      height: 116px;
-      overflow: hidden;
-      border-radius: 50%;
-      position: absolute;
-      top: 11px;
-      left: 61px;
+    &:hover {
+      box-shadow: 5px 5px 17px 0px #DCCBFF;
+      transform: scale(1.01);
+      transition: all .2s ease;
     }
   }
 
-  .headerInfo {
-    text-align: center;
-    padding-bottom: 32px;
-    border-bottom: 1px solid #F2F2F2;
-    margin-bottom: 32px;
-
-    .headerTitle {
-      font-size: max(20px, 16px);
-      font-weight: 600;
-      color: #131415;
-      line-height: 28px;
-      letter-spacing: 1px;
-      padding: 20px 0 8px;
-    }
+  .topSection2 {
+    background: linear-gradient(135deg, #FFA891 0%, #FF8EAB 22%, #FF96AE 50%, #FF7DAA 67%, #FF7ABC 100%);
 
-    .headerSubTitle {
-      font-size: 14px;
-      font-weight: 400;
-      color: #707a92;
-      line-height: 20px;
-    }
-  }
+    border-radius: 17px;
 
-  .rightTeachingWrap {
-    overflow: hidden;
-    flex: 1;
-    background-color: #fff;
-    padding: 20px;
-    border-radius: 20px;
-
-    .rightTeachingWrapTitle {
-      display: flex;
-      flex-direction: row;
-      // align-items: center;
-      justify-content: space-between;
-      flex-direction: column;
-
-      .lookMore {
-        cursor: pointer;
-        display: flex;
-        align-items: center;
-        min-width: 114px;
-        border-radius: 8px;
-        border: 1px solid #DEDEDE;
-        font-size: 15px;
-        color: #131415;
-        padding: 7px 12px;
-
-        svg {
-          margin-left: 8px;
-          width: 16px;
-          height: 16px;
-        }
-      }
-
-      .classSearchList {
-        display: flex;
-        gap: 12px;
-        padding-top: 12px;
-
-        :global {
-          .n-base-selection {
-            --n-height: 35px !important;
-            --n-font-size: 15px !important;
-            --n-border: 1px solid #DEDEDE !important;
-            --n-border-radius: 8px !important;
-            max-width: 130px;
-          }
-        }
-      }
+    &:hover {
+      box-shadow: 5px 5px 17px 0px #FFBBD5;
+      transform: scale(1.01);
+      transition: all .2s ease;
     }
-  }
-}
-
-:global {
-  .n-base-select-menu .n-base-select-option.n-base-select-option--show-checkmark {
-    padding-right: var(--n-option-padding);
-  }
-
-  .n-empty {
-    --n-font-size: 14px !important;
-  }
-}
-
-.teachListWrap {
-  position: relative;
-
 
-}
-
-.teachListWrapWall {
-  position: absolute;
-  bottom: 0;
-  height: 159px;
-  width: 100%;
-  background: linear-gradient(180deg,
-      rgba(255, 255, 255, 0) 0%,
-      #ffffff 100%);
-  border-radius: 0px 0px 20px 20px;
-
-  span {
-    position: absolute;
-    bottom: 7px;
-    left: 0;
-    width: 100%;
-    text-align: center;
-    color: #1677FF;
-    font-size: 16px;
-
-    &::after {
-      content: ' ';
-      display: inline-block;
-      width: 12px;
-      height: 12px;
-      background: url('./images/blueArrow.png') no-repeat center;
-      background-size: contain;
+    &::before {
+      content: '';
+      position: absolute;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      top: 0;
+      background: url('./img/t2-3.png') no-repeat top left, url('./img/t1-2.png') no-repeat bottom center;
+      background-size: 108px 91px, 100% 129px;
     }
   }
 }
 
-.teachGroup {
-  margin-top: 12px;
+.rightBottom {
+  display: flex;
+  align-items: center;
+  margin-top: 25px;
 
-  .teachGroupTitle {
-    position: relative;
-    left: -10px;
-    font-size: 14px;
-    font-weight: 400;
-    color: #aaaaaa;
-    width: 60px;
+  .bottomSection {
+    cursor: pointer;
+    margin-left: 23px;
+    padding-bottom: 38px;
+    flex: 1;
+    background: linear-gradient(135deg, #F4FDFF 0%, #E5E2FF 100%);
+    border-radius: 17px;
     text-align: center;
-    margin-bottom: 12px;
-  }
+    transition: all .2s ease;
 
-  .teachGroupList {
-    padding-bottom: 12px;
-    margin-left: 20px;
-    border-left: 1px solid #d1e8ff;
-    min-height: 92px;
-    position: relative;
-
-    .teachGroupListDot {
-      width: 15px;
-      height: 15px;
-      background: #198cfe;
-      border: 4px solid #d1e8ff;
-      border-radius: 50%;
-      top: 28px;
-      left: -8px;
-      position: absolute;
+    &:first-child {
+      margin-left: 0;
     }
-  }
 
-  .teachGroupItemWrap {
-    margin-left: 28px;
-    background: #f7f9ff;
-    border-radius: 12px;
-    display: flex;
-    flex-direction: row;
-    align-items: top;
-
-    &:nth-last-of-type(1) {
-      margin-bottom: 0;
+    &:hover {
+      transform: scale(1.02);
+      transition: all .2s ease;
     }
 
-    margin-bottom: 12px;
-    padding: 10px;
-
-    .teachGroupItemLeft {
-      margin-right: 12px;
-      width: 50px;
-      height: 50px;
-      border-radius: 50%;
-      overflow: hidden;
-      border: 2px solid #198cfe;
-
-      .teachGroupItemHeader {
-        border: 2px solid #fff;
-        border-radius: 50%;
-        overflow: hidden;
-
-        img {
-          width: 44px;
-          height: 44px;
-        }
-      }
+    .bFun {
+      padding: 23px 0 12px;
+      width: 100%;
     }
 
-    .teachGroupItemRight {
-      flex: 1;
-
-      .teachGroupItemName {
-        display: flex;
-        flex-direction: row;
-        align-items: center;
-        justify-content: space-between;
-        font-size: 16px;
-        margin-top: 2px;
-        font-weight: 600;
-        color: #131415;
-
-        span {
-          font-size: 13px;
-          font-weight: 400;
-          color: #1677ff;
-          line-height: 18px;
-        }
-      }
-
-      .teachGroupItemInfo {
-        font-size: 13px;
-        line-height: 26px;
-        color: rgba(0, 0, 0, 0.5);
-      }
-
-      .subjectName {
-        font-size: 14px;
-        font-weight: 400;
-        color: #FFFFFF;
-        background: #198CFE;
-        border-radius: 5px;
-        padding: 1px 8px;
-        margin-right: 4px;
-      }
+    .bTxt {
+      width: 148px;
+      height: 52px;
     }
-  }
-}
 
-.indDot,
-.endDot {
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-}
-
-.indDot {
-  span {
-    border-radius: 50%;
-    width: 8px;
-    height: 8px;
-    background: #198cfe;
-    margin-right: 8px;
-  }
-}
-
-.endDot {
-  opacity: 0.7;
-  color: #aaaaaa;
-
-  span {
-    border-radius: 50%;
-    width: 8px;
-    height: 8px;
-    background: #aaaaaa;
-    margin-right: 8px;
-  }
-}
-
-.assignHomework {
-  width: 520px;
-}
-
-.assignHomeworkContainer {
-  padding: 24px 30px;
-
-
-  .updateBtnGroup {
-    padding: 0;
-    justify-content: center !important;
-
-    :global {
-      .n-button {
-        height: 48px !important;
-        min-width: 156px;
-      }
+    .bTxt2 {
+      width: 74px;
     }
-  }
-}
-
-.tableWrap {
-  margin-top: 40px;
-}
-
-.showModalTone {
-  width: 500px;
 
-  .studentRemove {
-    padding: 32px 40px 46px;
-
-    p {
-      font-size: 18px;
-      color: #777777;
-      line-height: 30px;
-      text-align: center;
-
-      span {
-        color: #EA4132;
-      }
+    .bTxt3 {
+      width: 98px;
     }
   }
-}
-
-.attendClassModal {
-  width: 800px;
-  border-radius: 16px;
-  overflow: hidden;
-}
-
-.showUpdatePassword {
-  width: 514px;
 }

+ 111 - 509
src/views/home/index.tsx

@@ -1,49 +1,38 @@
 import { defineComponent, onMounted, reactive, ref } from 'vue';
 import styles from './index.module.less';
-import {
-  NImage,
-  NButton,
-  NPopselect,
-  NModal,
-  useMessage,
-  NSpin,
-  NSelect
-} from 'naive-ui';
-import headerD from './images/headerD.png';
+import { NImage, NModal } from 'naive-ui';
 import defultHeade from '@/components/layout/images/teacherIcon.png';
-import blackBoardBg from './images/blackboard_bg.png';
-import teacherMan from './images/teacher_man.png';
-import teacherWoman from './images/teacher_woman.png';
+import teacherMan from './img/teacher-man.png';
+import teacherWoman from './img/teacher-woman.png';
+import iconEchats from './img/icon-echats.png';
+import t1 from './img/t1.png';
+import t11 from './img/t1-1.png';
+import t12 from './img/t1-4.png';
+
+import t2 from './img/t2.png';
+import t21 from './img/t2-1.png';
+import t22 from './img/t2-4.png';
+
+import f1 from './img/f1.png';
+import f11 from './img/f1-1.png';
+
+import f2 from './img/f2.png';
+import f21 from './img/f2-1.png';
+
+import f3 from './img/f3.png';
+import f31 from './img/f3-1.png';
+
+import f4 from './img/f4.png';
+import f41 from './img/f4-1.png';
 
-import homeText1 from './images/home/home-text-1.png';
-import homeText2 from './images/home/home-text-2.png';
-import iconTo from './images/icon-to.png';
-import t1 from './images/t1.png';
-import t2 from './images/t2.png';
-import t3 from './images/t3.png';
 import { useRouter } from 'vue-router';
 import { useUserStore } from '/src/store/modules/users';
 // import SelectClass from './modals/selectClass';
 import dayjs from 'dayjs';
-import { gradeToCN, weekToCN } from '/src/utils/contants';
-import { useCatchStore } from '/src/store/modules/catchData';
-import TeachGroup from './modals/teachGroup';
-import {
-  classGroupList,
-  courseSchedulePage,
-  getGradeLevelList,
-  getGradeYearList
-} from './api';
-import TheEmpty from '/src/components/TheEmpty';
-import HomeGuide from '/src/custom-plugins/guide-page/home-guide';
-import TimerMeter from '/src/components/timerMeter';
-import { vaildUrl } from '/src/utils/urlUtils';
-import { px2vw } from '/src/utils';
-import PlaceholderTone from '@/components/layout/modals/placeholderTone';
-import PreviewWindow from '../preview-window';
 import UpdatePassword from '/src/components/layout/modals/update-password';
 import AttendClass from '../prepare-lessons/model/attend-class';
 import { useResizeObserver } from '@vueuse/core';
+import PlaceholderTone from '/src/components/layout/modals/placeholderTone';
 // import { state } from '/src/state';
 export const formatDateToDay = () => {
   const hours = dayjs().hour();
@@ -59,223 +48,20 @@ export const formatDateToDay = () => {
 export default defineComponent({
   name: 'home-page',
   setup() {
-    const catchStore = useCatchStore();
     const router = useRouter();
     const userStore = useUserStore();
     const showUpdatePassword = ref(false);
-    const showModalBeat = ref(false);
     const showModalTone = ref(false);
-    const showModalTime = ref(false);
     const forms = reactive({
       showAttendClass: false,
-      // useStatus: false,
-      studentList: [] as any,
-      bookVersionId: null,
-      classGroupId: null,
-      category: null,
-      subjectId: null,
-      musicTagList: [] as any,
       loading: false,
+      message: '',
       list: [] as any,
       unit: null,
-      unitList: [],
-      subjectList: [] as any,
-      gradeList: [] as any,
       classLoading: false,
-      total: 0, // 上课数量
-      // 上次上课的数据
-      lastClassSelect: {
-        currentClass: null,
-        name: '',
-        upgradeFlag: false, // 是否为历史班
-        gradeYear: null as any,
-        gradeLevel: null as any
-      },
-      classSelect: {
-        currentGradeNum: null,
-        currentClass: null,
-        name: '',
-        upgradeFlag: false, // 是否为历史班
-        gradeLevel: null as any,
-        gradeYear: null
-      } as any,
-      popSelectOptions: [] as any,
-      popSelectYearList: [] as any,
-      popSelectLevelList: [] as any,
       showGuide: false,
-      showPreview: false,
-      itemPreview: {} as any,
       homeLeftHeight: 'auto'
     });
-    const teachList = ref({} as any);
-
-    // 获取年级班级
-    const getClassList = async () => {
-      try {
-        const { data } = await classGroupList({
-          gradeLevel: forms.classSelect.gradeLevel,
-          gradeYear: forms.classSelect.gradeYear
-        });
-        const cList = data || [];
-        const gradeList: any = [];
-        const popSelectOptions: any = [];
-        // getLastClassRecode()
-        cList.forEach((item: any, index: number) => {
-          // 判断是否已经有班级了
-          if (index === 0) {
-            if (forms.lastClassSelect.currentClass) {
-              forms.classSelect.currentClass =
-                forms.lastClassSelect.currentClass;
-              forms.classSelect.name = forms.lastClassSelect.name;
-              forms.classSelect.upgradeFlag = forms.lastClassSelect.upgradeFlag;
-            } else {
-              const temp = item.classGroupList[0];
-              forms.classSelect.currentGradeNum = item.currentGradeNum;
-              forms.classSelect.currentClass = temp.id;
-              forms.classSelect.name = temp.name;
-            }
-          }
-
-          const classList: any = [];
-          item.classGroupList.forEach((i: any) => {
-            classList.push({
-              label: i.currentClass + '班',
-              value: i.id,
-              lastStudy: i.lastStudy
-            });
-
-            popSelectOptions.push({
-              label: i.name,
-              value: i.id,
-              currentGradeNum: item.currentGradeNum,
-              lastStudy: i.lastStudy
-            });
-          });
-
-          gradeList.push({
-            label: gradeToCN[item.currentGradeNum],
-            value: item.currentGradeNum,
-            childrens: classList
-          });
-        });
-        forms.popSelectOptions = popSelectOptions;
-        forms.gradeList = gradeList;
-      } catch {
-        //
-      }
-    };
-    const getLastClassRecode = async () => {
-      const { data } = await courseSchedulePage({
-        page: 1,
-        rows: 1,
-        teacherId: userStore.getUserInfo.id
-      });
-      if (data.rows.length > 0 && data.rows[0]) {
-        const tempRow = data.rows[0];
-        // forms.lastClassSelect.currentClass = tempRow.classGroupId;
-        // forms.lastClassSelect.name = tempRow.classGroupName;
-        forms.lastClassSelect = {
-          currentClass: tempRow.classGroupId,
-          name: tempRow.classGroupName,
-          upgradeFlag: tempRow.upgradeFlag,
-          gradeYear: tempRow.gradeYear + '',
-          gradeLevel: tempRow.gradeLevel + ''
-        };
-      }
-    };
-
-    // 获取学年
-    const getYearList = async () => {
-      try {
-        const { data } = await getGradeYearList();
-        const temp = data || [];
-        temp.forEach((i: any) => {
-          i.name = i.name + '学年';
-        });
-        forms.popSelectYearList = temp || [];
-        if (temp.length > 0) {
-          if (forms.lastClassSelect.gradeYear) {
-            forms.classSelect.gradeYear = forms.lastClassSelect.gradeYear;
-          } else {
-            forms.classSelect.gradeYear = temp[0].id;
-          }
-        }
-      } catch (e: any) {
-        //
-      }
-    };
-    // 获取学级
-    const getLevelList = async () => {
-      try {
-        const { data } = await getGradeLevelList();
-        const temp = data || [];
-        temp.forEach((i: any) => {
-          i.name = i.name + '级';
-        });
-        temp.unshift({
-          id: '',
-          name: '全部学级'
-        });
-        forms.popSelectLevelList = temp || [];
-        if (temp.length > 0) {
-          if (forms.lastClassSelect.gradeLevel) {
-            forms.classSelect.gradeLevel =
-              forms.lastClassSelect.gradeLevel + '';
-          } else {
-            forms.classSelect.gradeLevel = temp[0].id;
-          }
-        }
-      } catch {
-        //
-      }
-    };
-
-    const getCourseSchedulePage = async () => {
-      forms.classLoading = true;
-      try {
-        const { data } = await courseSchedulePage({
-          classGroupId: forms.classSelect.currentClass,
-          gradeLevel: forms.classSelect.gradeLevel,
-          gradeYear: forms.classSelect.gradeYear,
-          page: 1,
-          rows: 4,
-          teacherId: userStore.getUserInfo.id
-        });
-
-        const result = data.rows || [];
-        forms.total = data.total || 0;
-        const dateTime: any = {};
-        result.forEach((item: any) => {
-          const tempTime = dayjs(item.classDate).format('MM-DD');
-          if (!dateTime[tempTime]) {
-            dateTime[tempTime] = [];
-          }
-
-          const lessonCourseware = item.lessonCoursewareJson
-            ? JSON.parse(item.lessonCoursewareJson)
-            : {};
-          dateTime[tempTime].push({
-            classGroup: forms.classSelect.name,
-            teacherName: item.teacherName,
-            conent:
-              lessonCourseware.lessonCoursewareName +
-              ' | ' +
-              lessonCourseware.lessonCoursewareDetailName +
-              ' | ' +
-              lessonCourseware.lessonCoursewareKnowledgeDetailName,
-            image: item.teacherAvatar,
-            subjectName: item.subjectName
-          });
-        });
-
-        teachList.value = dateTime;
-      } catch (e: any) {
-        //
-        console.log(e);
-      }
-
-      forms.classLoading = false;
-    };
 
     onMounted(async () => {
       useResizeObserver(
@@ -288,20 +74,6 @@ export default defineComponent({
       );
 
       forms.classLoading = true;
-      await getLastClassRecode();
-
-      await getYearList();
-      await getLevelList();
-      await getClassList();
-      // await catchStore.getSubjects();
-
-      await getCourseSchedulePage();
-      // forms.subjectList = catchStore.getSubjectList.map((item: any) => {
-      //   return {
-      //     label: item.name,
-      //     value: item.id
-      //   };
-      // });
 
       if (!userStore.getUserInfo.account.updatePasswordFlag) {
         showUpdatePassword.value = true;
@@ -311,292 +83,122 @@ export default defineComponent({
 
       forms.classLoading = false;
     });
-    // const clearStorng = () => {
-    //   localStorage.removeItem('teacher-guideInfo');
-    //   forms.showGuide = false;
-    //   setTimeout(() => {
-    //     forms.showGuide = true;
-    //   }, 500);
-    // };
-
     return () => (
       <div class={styles.homeWrap}>
-        <div class={styles.homeInfoLeft} id="homeInfoLeft-home">
-          <div class={styles.homeBanner}>
-            <div class={styles.applyInfo} id="home-1">
-              <div class={styles.centerInfo} id="home-0"></div>
-
-              <div class={styles.userInfo}>
-                <div class={styles.userName}>
+        <div class={styles.homeSection}>
+          <div class={styles.homeLeft}>
+            <i class={styles.homeWindow}></i>
+            <div class={styles.homeUserInfo}>
+              <i class={styles.homeTag}></i>
+              <div class={styles.homeUsers}>
+                <NImage src={defultHeade} class={styles.userImg} />
+                <p class={styles.userName}>
                   Hi,{userStore.getUserInfo?.nickname} {formatDateToDay()}~
-                </div>
+                </p>
               </div>
-              {userStore.getUserInfo.gender === 1 ? (
-                <img src={teacherMan} class={styles.teacherMan} />
-              ) : (
-                <img src={teacherWoman} class={styles.teacherWoman} />
-              )}
+              <p class={styles.desc}>
+                点击下方按钮,您可以根据声部进行备课或是直接选择班级开始上课,更好的规划教学哦!
+              </p>
 
-              <div class={styles.blackborad}>
-                <img src={blackBoardBg} class={styles.blackBoardBg} />
-              </div>
-              <div class={styles.applyContainer}>
-                <div class={[styles.applyItem, styles.applyItem1]}>
-                  <p>合理的规划教学内容,让学生更好掌握知识</p>
-                  <div
-                    class={[styles.applyBtn, styles.applyBtn1]}
-                    onClick={() => {
-                      // 备课
-                      router.push({
-                        path: '/prepare-lessons'
-                      });
-                    }}>
-                    <img src={homeText1} />
-                  </div>
-                </div>
-                <div class={[styles.applyItem, styles.applyItem2]}>
-                  <p>从这里开始,带领学生在知识的海洋中遨游</p>
-                  <div
-                    class={[styles.applyBtn, styles.applyBtn2]}
-                    onClick={() => {
-                      forms.showAttendClass = true;
-                    }}>
-                    <img src={homeText2} />
-                  </div>
-                </div>
+              <div class={styles.homeBtnGroup}>
+                <div
+                  class={styles.btnBk}
+                  onClick={() => {
+                    // 备课
+                    router.push({
+                      path: '/prepare-lessons'
+                    });
+                  }}></div>
+                <div
+                  class={styles.btnClass}
+                  onClick={() => {
+                    forms.showAttendClass = true;
+                  }}></div>
               </div>
+
+              <img src={iconEchats} class={styles.homeEchats} />
             </div>
+
+            {userStore.getUserInfo.gender === 1 ? (
+              <img src={teacherMan} class={styles.teacherMan} />
+            ) : (
+              <img src={teacherWoman} class={styles.teacherWoman} />
+            )}
           </div>
 
-          <div class={styles.toolContainer}>
-            <div class={styles.toolTips}>
-              <div class={styles.toolTitle}>工具箱</div>
-              <div class={styles.toolContent}>
-                这里是常用的教学辅助工具,可帮助学生集中注意力、提高演奏效率,使演奏更完整平稳。让您在课堂上完成更好的教学。
+          <div class={styles.homeRight}>
+            <div class={styles.rightTop}>
+              <div
+                class={[styles.topSection, styles.topSection1]}
+                onClick={() => {
+                  forms.message = '听音练习功能暂未开放,敬请期待!';
+                  showModalTone.value = true;
+                }}>
+                <img src={t1} class={styles.tFun} />
+                <img src={t11} class={styles.tTxt} />
+                <img src={t12} class={styles.tTitle} />
               </div>
-            </div>
-            <img src={iconTo} class={styles.iconTo} />
-            <div class={styles.toolFunction} id="home-3">
-              <div class={[styles.toolItem, styles.item1]}>
-                <img src={t1} />
-                {/* <p class={styles.toolMemo}>提升效率,练习好节奏</p> */}
-                <NButton
-                  class={styles.btn1}
-                  onClick={() => {
-                    showModalBeat.value = true;
-                  }}>
-                  节拍器
-                </NButton>
+              <div
+                class={[styles.topSection, styles.topSection2]}
+                onClick={() => {
+                  forms.message = '节奏练习功能暂未开放,敬请期待!';
+                  showModalTone.value = true;
+                }}>
+                <img src={t2} class={styles.tFun} />
+                <img src={t21} class={styles.tTxt} />
+                <img src={t22} class={styles.tTitle} />
               </div>
-              <div class={[styles.toolItem, styles.item2]}>
-                <img src={t2} />
-                {/* <p class={styles.toolMemo}>精准调音,一劳永逸</p> */}
-                <NButton
-                  class={styles.btn2}
-                  onClick={() => {
-                    showModalTone.value = true;
-                  }}>
-                  调音器
-                </NButton>
+            </div>
+
+            <div class={styles.rightBottom}>
+              <div
+                class={styles.bottomSection}
+                onClick={() => {
+                  router.push('/content-instruments');
+                }}>
+                <img src={f1} class={styles.bFun} />
+                <img src={f11} class={styles.bTxt} />
               </div>
-              <div class={[styles.toolItem, styles.item3]}>
-                <img src={t3} />
-                {/* <p class={styles.toolMemo}>创造时间,集中注意力</p> */}
-                <NButton
-                  class={styles.btn3}
-                  onClick={() => {
-                    showModalTime.value = true;
-                  }}>
-                  计时器
-                </NButton>
+              <div
+                class={styles.bottomSection}
+                onClick={() => {
+                  router.push('/content-music');
+                }}>
+                <img src={f2} class={styles.bFun} />
+                <img src={f21} class={styles.bTxt} />
               </div>
-            </div>
-          </div>
-        </div>
-        <div
-          class={styles.homeInfoRight}
-          style={{ height: forms.homeLeftHeight }}>
-          <div class={styles.rightTeachingWrap}>
-            <div class={styles.headerContainer}>
               <div
-                class={styles.HeaderWrap}
-                onClick={() => router.push('/setting')}>
-                <NImage
-                  previewDisabled
-                  class={styles.headerD}
-                  src={headerD}></NImage>
-                <NImage
-                  previewDisabled
-                  class={styles.defultHeade}
-                  src={userStore.getUserInfo.avatar || defultHeade}></NImage>
+                class={styles.bottomSection}
+                onClick={() => {
+                  router.push('/content-musician');
+                }}>
+                <img src={f3} class={styles.bFun} />
+                <img src={f31} class={[styles.bTxt, styles.bTxt2]} />
               </div>
-            </div>
-            <div class={styles.headerInfo}>
-              <p class={styles.headerTitle}>{userStore.getUserInfo.nickname}</p>
-              {userStore.getUserInfo.schoolInfos &&
-                userStore.getUserInfo.schoolInfos.length > 0 && (
-                  <p class={styles.headerSubTitle}>
-                    {userStore.getUserInfo.schoolInfos[0].name}
-                    {/* | 音乐老师 */}
-                  </p>
-                )}
-            </div>
-            <div class={styles.rightTeachingWrapTitle}>
-              <h3 class={styles.rightTitle}>
-                <div class={styles.titleDot}></div>上课记录
-              </h3>
-
-              <div class={styles.classSearchList}>
-                <NSelect
-                  v-model:value={forms.classSelect.gradeYear}
-                  class={styles.lookMoreSearch}
-                  placeholder="全部学年"
-                  options={forms.popSelectYearList}
-                  labelField="name"
-                  valueField="id"
-                  onUpdate:value={async (val: any) => {
-                    forms.classSelect.gradeYear = val;
-                    forms.lastClassSelect.currentClass = null;
-                    forms.classSelect.currentClass = null;
-                    await getClassList();
-                    await getCourseSchedulePage();
-                  }}></NSelect>
-                <NSelect
-                  v-model:value={forms.classSelect.gradeLevel}
-                  class={styles.lookMoreSearch}
-                  placeholder="全部学级"
-                  options={forms.popSelectLevelList}
-                  labelField="name"
-                  valueField="id"
-                  onUpdate:value={async (val: any) => {
-                    forms.classSelect.gradeLevel = val;
-                    forms.lastClassSelect.currentClass = null;
-                    forms.classSelect.currentClass = null;
-                    await getClassList();
-                    await getCourseSchedulePage();
-                  }}></NSelect>
-                <NSelect
-                  v-model:value={forms.classSelect.currentClass}
-                  class={styles.lookMoreSearch}
-                  placeholder="选择班级"
-                  options={forms.popSelectOptions}
-                  onUpdate:value={(val: any) => {
-                    forms.popSelectOptions.forEach((item: any) => {
-                      if (item.value === val) {
-                        forms.classSelect.currentGradeNum =
-                          item.currentGradeNum;
-                        forms.classSelect.currentClass = item.value;
-                        forms.classSelect.name = item.label;
-                        forms.classSelect.upgradeFlag = item.upgradeFlag;
-                        getCourseSchedulePage();
-                      }
-                    });
-                  }}></NSelect>
+              <div
+                class={styles.bottomSection}
+                onClick={() => {
+                  router.push('/content-knowledge');
+                }}>
+                <img src={f4} class={styles.bFun} />
+                <img src={f41} class={[styles.bTxt, styles.bTxt3]} />
               </div>
             </div>
-            <NSpin show={forms.classLoading} style={{ minHeight: '40vh' }}>
-              {Object.keys(teachList.value).length > 0 && (
-                <div class={styles.teachListWrap}>
-                  {Object.keys(teachList.value).map(key => (
-                    <TeachGroup
-                      list={teachList.value[key]}
-                      keys={key}></TeachGroup>
-                  ))}
-                </div>
-              )}
-
-              {Object.keys(teachList.value).length <= 0 &&
-                !forms.classLoading && <TheEmpty />}
-            </NSpin>
-
-            {forms.total > 4 && (
-              <div class={styles.teachListWrapWall}>
-                <span
-                  onClick={() => {
-                    // setTabsCaches('attendclass', 'tabName', {
-                    //   path: '/classDetail'
-                    // });
-                    sessionStorage.setItem('classDetailTabs', 'attendclass');
-                    router.push({
-                      path: '/classDetail',
-                      query: {
-                        name: forms.classSelect.name,
-                        id: forms.classSelect.currentClass,
-                        gradeYear: forms.classSelect.gradeYear,
-                        upgradeFlag: forms.classSelect.upgradeFlag ? 1 : 0 // 是否为历史班
-                      }
-                    });
-                  }}>
-                  查看全部
-                </span>
-              </div>
-            )}
           </div>
         </div>
 
-        {/* <NModal
-          v-model:show={forms.useStatus}
-          preset="card"
-          showIcon={false}
-          class={['modalTitle background', styles.assignHomework]}
-          title={'选择班级'}
-          blockScroll={false}>
-          <SelectClass
-            useDetail={{
-              currentGradeNum: forms.classSelect.currentGradeNum,
-              classGroupId: forms.classSelect.currentClass
-            }}
-            gradeList={forms.gradeList}
-            onConfirm={(item: any) => onUseConfirm(item)}
-            onClose={() => (forms.useStatus = false)}
-          />
-        </NModal> */}
-
-        <NModal
-          class={['modalTitle background']}
-          title={'节拍器'}
-          preset="card"
-          v-model:show={showModalBeat.value}
-          style={{ width: '687px' }}>
-          <div class={styles.modeWrap}>
-            <iframe
-              src={`${vaildUrl()}/metronome/?id=${new Date().getTime()}`}
-              scrolling="no"
-              frameborder="0"
-              width="100%"
-              height={'650px'}></iframe>
-          </div>
-        </NModal>
-
-        <NModal
-          v-model:show={showModalTime.value}
-          class={['modalTitle background']}
-          title={'计时器'}
-          preset="card"
-          style={{ width: px2vw(772) }}>
-          <div>
-            <TimerMeter></TimerMeter>
-          </div>
-        </NModal>
+        {/* {forms.showGuide ? <HomeGuide></HomeGuide> : null} */}
 
         <NModal class={['background']} v-model:show={showModalTone.value}>
           <div>
             <PlaceholderTone
+              message={forms.message}
               onClose={() => {
                 showModalTone.value = false;
               }}></PlaceholderTone>
           </div>
         </NModal>
 
-        {/* 弹窗查看 */}
-        <PreviewWindow
-          v-model:show={forms.showPreview}
-          type="attend"
-          params={forms.itemPreview}
-        />
-
-        {forms.showGuide ? <HomeGuide></HomeGuide> : null}
-
         <NModal
           v-model:show={showUpdatePassword.value}
           class={['modalTitle', styles.showUpdatePassword]}

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

@@ -49,7 +49,8 @@
       opacity: 0;
       animation: rotateImg 6s linear infinite;
     }
-    &.imgRotate{
+
+    &.imgRotate {
       img {
         animation-play-state: paused;
       }
@@ -158,4 +159,4 @@
     white-space: nowrap;
     flex-shrink: 0;
   }
-}
+}