Browse Source

添加页面

lex 2 years ago
parent
commit
8a836af408

+ 2 - 1
src/components/col-header/index.tsx

@@ -16,7 +16,8 @@ export default defineComponent({
     return {
       navigator: [
         { name: '首页', href: '/home', current: false },
-        { name: '谱库', href: '/musicLibrary', current: false },
+        { name: '专辑', href: '/albumibrary', current: false },
+        { name: '曲谱', href: '/musicLibrary', current: false },
         // { name: '视频课', href: '/videoDetailList', current: false },
         // { name: '云教练', href: '#', current: false },
         // { name: '社区', href: '#', current: false },

+ 3 - 3
src/components/hotSearch/index.tsx

@@ -4,7 +4,8 @@ import {
   reactive,
   onMounted,
   ref,
-  nextTick
+  nextTick,
+  getCurrentInstance
 } from 'vue'
 import { ElButton, ElTag } from 'element-plus'
 import classes from './index.module.less'
@@ -243,6 +244,7 @@ export default defineComponent({
               <div class={classes.tagWrap}>
                 {state.hotList.map((item: any) => {
                   //
+                  console.log(item.isCheck, 'isCheck')
                   return (
                     <tagItem
                       isSmall={true}
@@ -329,8 +331,6 @@ export default defineComponent({
                       <div class={[classes.chioseTagWrap, 'chioseTagWrap']}>
                         {tree.children.map((tag: any) => {
                           return (
-                            //  effect={isChiose(tag)}
-
                             <div
                               class={[
                                 classes.tags,

+ 31 - 19
src/components/musicLIstItem/index.module.less

@@ -62,7 +62,7 @@
   --music-list-item-charge-bg: #3f90d6;
   --music-list-item-charge-color: #3f90d6;
 
-  height: 188px;
+  // height: 188px;
   background: #ffffff;
   // border-radius: 12px;
   display: flex;
@@ -80,7 +80,7 @@
     .imgWrap {
       width: 88px;
       height: 88px;
-      margin-right: 30px;
+      margin-right: 24px;
       border-radius: 10px;
       overflow: hidden;
     }
@@ -94,26 +94,22 @@
         display: flex;
         align-items: center;
       }
+      .musicSheetName {
+        max-width: 250px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
       .authorName {
         font-weight: 400;
         color: #666;
         line-height: 22px;
         font-size: 16px;
-        margin-bottom: 7px;
-        margin-bottom: 13px;
-      }
-      .favoriteWrap {
-        display: flex;
-        flex-direction: row;
-        align-items: center;
-        font-size: 14px;
-        color: #999999;
-        line-height: 20px;
-        img {
-          width: 16px;
-          height: 16px;
-          margin-right: 10px;
-        }
+        margin-left: 12px;
+        max-width: 120px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
       }
     }
   }
@@ -121,14 +117,13 @@
     display: flex;
     flex-direction: row;
     align-items: center;
-    margin-top: 26px;
     height: 30px;
     .icon {
       width: 28px;
       height: 28px;
 
       border-radius: 50px;
-      margin-right: 12px;
+      // margin-right: 12px;
       border: 2px solid #2dc7aa;
       object-fit: cover;
     }
@@ -145,6 +140,23 @@
     align-items: flex-end;
     // justify-content: center;
     cursor: pointer;
+
+    .favoriteWrap {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      font-size: 14px;
+      color: #999999;
+      padding-bottom: 18px;
+      span {
+        padding-top: 3px;
+      }
+      img {
+        width: 22px;
+        height: 22px;
+        margin-left: 10px;
+      }
+    }
     .tagList {
       display: flex;
       flex-direction: row;

+ 30 - 68
src/components/musicLIstItem/index.tsx

@@ -12,7 +12,6 @@ import start from '@/common/images/start.png'
 import lineStart from '@/common/images/lineStart.png'
 import iconFine from '@/common/images/icon_fine.png'
 import iconAlbum from '@/common/images/icon_album_active.png'
-import { isArray } from 'lib/tool'
 
 type Props = {
   id?: Number
@@ -66,88 +65,51 @@ export default defineComponent({
         onClick={() => {
           props.onClick(state.item)
         }}
-        onMouseover={() => {
-          state.item.hoverTop = true
-        }}
-        onMouseout={() => {
-          state.item.hoverTop = false
-        }}
       >
         <div class={classes.itemWrap} onClick={() => gotoMusicDetail()}>
-          <div class={classes.leftWrap}>
-            <div class={classes.left}>
-              <div class={classes.imgWrap}>
-                <img src={state.item.titleImg || music} alt="" />
-              </div>
-              <div class={classes.textWrap}>
-                <p class={classes.musicName}>
-                  {state.item.exquisiteFlag === 1 && (
-                    <img src={iconFine} class={classes.iconFine} />
-                  )}
+          <div class={classes.left}>
+            <div class={classes.imgWrap}>
+              <img src={state.item.titleImg || music} alt="" />
+            </div>
+            <div class={classes.textWrap}>
+              <p class={classes.musicName}>
+                {state.item.exquisiteFlag === 1 && (
+                  <img src={iconFine} class={classes.iconFine} />
+                )}
 
-                  {state.item.albumNums > 0 && (
-                    <img src={iconAlbum} class={classes.iconAlbum} />
-                  )}
+                {state.item.albumNums > 0 && (
+                  <img src={iconAlbum} class={classes.iconAlbum} />
+                )}
 
+                <p class={classes.musicSheetName}>
                   {state.item.musicSheetName}
                 </p>
-                <p class={classes.authorName}>作曲:{state.item.composer}</p>
-                <div class={classes.favoriteWrap}>
-                  <img src={state.item.favorite ? lineStart : start} alt="" />
-                  <span>{state.item.favoriteCount | 0} 收藏</span>
-                </div>
+
+                <p class={classes.authorName}>—— 作曲:{state.item.composer}</p>
+              </p>
+
+              <div class={classes.authorInfo}>
+                <img
+                  class={classes.icon}
+                  src={state.item.addUserAvatar || icon}
+                  alt=""
+                />
+                <span class={classes.authorName}>
+                  {state.item.addName ? state.item.addName : '小酷有谱'}
+                </span>
               </div>
             </div>
-            <div class={classes.authorInfo}>
-              <img
-                class={classes.icon}
-                src={state.item.addUserAvatar || icon}
-                alt=""
-              />
-              <span class={classes.authorName}>
-                {state.item.addName ? state.item.addName : '小酷有谱'}
-              </span>
-            </div>
           </div>
+
           <div class={classes.right}>
-            <div class={[classes.touchButtonO]}>
-              {state.item.hoverTop ? (
-                <div
-                  class={[
-                    classes.touchButton,
-                    classes[state.item.chargeType?.toLocaleLowerCase()]
-                  ]}
-                >
-                  <p>查看详情</p>
-                </div>
-              ) : (
-                <>
-                  {Array.isArray(state.item.paymentType) &&
-                    state.item.paymentType.map((tag: string) => (
-                      <div
-                        class={[
-                          classes.touchButton,
-                          classes[tag?.toLocaleLowerCase()]
-                        ]}
-                      >
-                        <div class={classes.touchButtonWrap}>
-                          <img src={chargeImg[tag]} alt="" />
-                        </div>
-                        <div class={classes.touchButtonText}>
-                          {chargeTypes[tag] ? chargeTypes[tag] : '点播'}
-                        </div>
-                      </div>
-                    ))}
-                </>
-              )}
+            <div class={classes.favoriteWrap}>
+              <span>{state.item.favoriteCount | 0} 收藏</span>
+              <img src={state.item.favorite ? lineStart : start} alt="" />
             </div>
-            {/* <img class={classes.arrow} src={arrow} alt="" /> */}
             <div class={classes.tagList}>
               {state.item.subjectNames ? (
                 <div class={classes.tag}>{state.item.subjectNames}</div>
               ) : null}
-
-              {/* <div class={classes.tag}>圆号</div> */}
             </div>
           </div>
         </div>

+ 2 - 1
src/components/searchInput/index.module.less

@@ -13,7 +13,8 @@
   border-radius: 30px;
   overflow: hidden;
   cursor: pointer;
-  &:hover {
+  &:hover,
+  &.active {
     box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.1);
     .searchline,
     .searchBtn {

+ 6 - 1
src/components/searchInput/index.tsx

@@ -31,6 +31,10 @@ export default defineComponent({
       type: Object,
       default: {}
     },
+    showSearch: {
+      type: Boolean,
+      default: false
+    },
     holder: {
       type: String,
       default: '搜一搜你想练习的曲目'
@@ -138,13 +142,14 @@ export default defineComponent({
     }
     onMounted(() => {
       getSubjectList()
+      console.log(props.showSearch, 'showSearch')
     })
     // let classStyle = classes
 
     return () => (
       <>
         {/* props.isWhile ? classStyle.While : '' */}
-        <div class={[classes.wrap]}>
+        <div class={[classes.wrap, props.showSearch ? classes.active : '']}>
           <div class={classes.selectWrap} id="selectWrap">
             <ElSelect
               // clearable

+ 21 - 19
src/components/tagItem/index.tsx

@@ -1,11 +1,10 @@
-
-import { defineComponent , toRefs, reactive, onMounted, ref,watch } from 'vue'
+import { defineComponent, toRefs, reactive, onMounted, ref, watch } from 'vue'
 import { ElTag } from 'element-plus'
 import classes from './index.module.less'
 
 export default defineComponent({
   name: 'tagItem',
-  emits:['searchTag'],
+  emits: ['searchTag'],
   props: {
     title: {
       type: String,
@@ -15,44 +14,47 @@ export default defineComponent({
       type: Boolean,
       default: false
     },
-    item:{
+    item: {
       type: Object,
-      default: {isCheck:false}
+      default: { isCheck: false }
     },
-    isSmall:{
-      type:Boolean,
+    isSmall: {
+      type: Boolean,
       default: false
     }
   },
   setup(props, conent) {
     const state = reactive({
-      title:props.title,
-      isCheck:props.item.isCheck,
-      isSmall:props.isSmall
+      title: props.title,
+      isCheck: props.item.isCheck,
+      isSmall: props.isSmall
     })
-    const shioseTag =(key:string)=>{
-      conent.emit('searchTag',key)
+    const shioseTag = (key: string) => {
+      conent.emit('searchTag', key)
     }
     watch(
       () => props.item,
       item => {
-        console.log(item)
         state.isCheck = item.isCheck
       },
       {
-        deep:true
+        deep: true
       }
     )
-    const checkDrak = ()=>{
-
-      if(props.isChiose){
+    const checkDrak = () => {
+      if (props.isChiose) {
         state.isCheck = true
       }
     }
     return () => (
       <>
-      {/* effect={state.isCheck ? 'dark' : 'light'} */}
-        <div  onClick={()=>shioseTag(state.title)} class={[classes.tag,state.isSmall?classes.small:'']}>{state.title}</div>
+        {/* effect={state.isCheck ? 'dark' : 'light'} */}
+        <div
+          onClick={() => shioseTag(state.title)}
+          class={[classes.tag, state.isSmall ? classes.small : '']}
+        >
+          {state.title}
+        </div>
       </>
     )
   }

+ 12 - 1
src/router/routes-admin.ts

@@ -35,11 +35,22 @@ export default [
     }
   },
   {
+    path: '/albumibrary',
+    name: 'albumibrary',
+    component: () => import('@/views/albumLibrary/index'),
+    meta: {
+      title: '专辑',
+      highlightPath: '/albumibrary',
+      index: 2,
+      isdark: false
+    }
+  },
+  {
     path: '/musicLibrary',
     name: 'musicLibrary',
     component: () => import('@/views/musicLibrary/index'),
     meta: {
-      title: '谱库',
+      title: '谱',
       highlightPath: '/musicLibrary',
       index: 2,
       isdark: false

+ 217 - 0
src/views/albumLibrary/index.module.less

@@ -0,0 +1,217 @@
+.mySwiper {
+  min-height: 300px;
+  /deep/.swiper-slide {
+    min-height: 300px;
+  }
+}
+.title {
+  font-size: 20px;
+  color: red;
+}
+
+.w1200 {
+  width: 1002px !important;
+
+  margin: 0 auto;
+  .myTabWrap {
+    border-top: 1px solid #e8e8e8;
+    :global {
+      padding-top: 28px;
+      font-size: 20px;
+      .el-tabs__nav-wrap {
+        &::after {
+          height: 0px;
+        }
+      }
+      .el-tabs__item {
+        font-size: 20px;
+        // margin-bottom: 8px;
+        color: #666;
+        // margin-left: 40px;
+        width: 100px;
+        height: 48px;
+        line-height: 48px;
+        background: #fff;
+        border-radius: 23px;
+        text-align: center;
+        padding: 0;
+        color: #000;
+        margin-right: 20px;
+      }
+      .el-tabs__item.is-active {
+        color: #fff;
+        font-weight: 600;
+        width: 100px;
+        height: 48px;
+        line-height: 48px;
+        background: #2dc7aa;
+        border-radius: 23px;
+      }
+      .el-tabs__active-bar {
+        height: 0px;
+        background: #2dc7aa;
+        border-radius: 3px;
+      }
+      .el-tabs__header {
+        margin: 0 !important;
+      }
+    }
+  }
+}
+.section {
+  .hotSearch {
+    margin-top: 17px;
+  }
+  .hotAlbum {
+    // margin-top: 25px;
+    font-size: 22px;
+    font-weight: 600;
+    color: #333;
+    line-height: 30px;
+  }
+  padding: 24px 0 15px;
+  .titleWrap {
+    text-align: center;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    .dotImg {
+      width: 30px;
+      height: 20px;
+      margin-left: 6px;
+      position: relative;
+      top: 2px;
+    }
+    h4 {
+      margin: 0 10px;
+      font-size: 32px;
+      font-weight: 600;
+      color: #333333;
+      line-height: 45px;
+    }
+  }
+  .albumList {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    flex-wrap: wrap;
+    // margin-bottom: 25px;
+    justify-content: flex-start;
+    // margin-top: 20px;
+  }
+  .videoList {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    flex-wrap: wrap;
+    margin: 25px 0;
+  }
+  .videoNav {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: space-between;
+    padding: 0 2px;
+    margin-bottom: 14px;
+    h5 {
+      font-size: 22px;
+      font-weight: 600;
+      color: #333;
+      line-height: 30px;
+    }
+    .wrapRight {
+      display: flex;
+      flex-direction: row;
+      cursor: pointer;
+      span {
+        color: #666;
+      }
+      .arrow {
+        width: 20px;
+        height: 20px;
+        margin-left: 8px;
+      }
+    }
+  }
+}
+.hotSearch {
+  margin-top: 20px;
+}
+.mt25 {
+  margin-top: 25px;
+}
+.pb40 {
+  padding-bottom: 40px;
+}
+
+.tagList {
+  display: flex;
+  align-items: flex-start;
+  justify-content: space-between;
+  padding-bottom: 20px;
+
+  .tagContainer {
+    display: flex;
+    align-items: center;
+    flex-wrap: wrap;
+
+    &.hide {
+      height: 33px;
+      overflow: hidden;
+    }
+
+    .tagItem {
+      // padding-right: 60px;
+      position: relative;
+      margin-left: 4px;
+      margin-right: 46px;
+      padding-top: 5px;
+      padding-bottom: 5px;
+      font-size: 20px;
+      color: #999999;
+
+      &:hover,
+      &.active {
+        position: relative;
+        z-index: 1;
+        cursor: pointer;
+        color: #000;
+        font-weight: bold;
+        &:after {
+          position: absolute;
+          bottom: 2px;
+          left: -4px;
+          content: ' ';
+          height: 10px;
+          width: calc(100% + 8px);
+          background: rgba(45, 199, 170, 0.5);
+          border-radius: 5px;
+          z-index: -1;
+        }
+      }
+    }
+  }
+
+  .wrapRight {
+    display: flex;
+    flex-direction: row;
+    flex-shrink: 0;
+    cursor: pointer;
+    font-size: 16px;
+    padding-top: 10px;
+    align-items: center;
+    span {
+      color: #666;
+    }
+    .arrow {
+      transform: rotate(90deg);
+      width: 16px;
+      height: 16px;
+      margin-left: 8px;
+
+      &.active {
+        transform: rotate(-90deg);
+      }
+    }
+  }
+}

+ 216 - 0
src/views/albumLibrary/index.tsx

@@ -0,0 +1,216 @@
+// import { PaperClipIcon } from '@heroicons/vue/solid'
+import { defineComponent, toRefs, reactive, onMounted, ref } from 'vue'
+import arrow from '@/views/home/images/moreArrow.png'
+import styles from './index.module.less'
+import albumItem from './modals/albumItem'
+import hotSearch from '@/components/hotSearch'
+import { Swiper, SwiperSlide } from 'swiper/vue'
+import { Navigation, Pagination, Scrollbar, A11y } from 'swiper'
+import request from '@/helpers/request'
+import silder from '@/components/silder'
+import searchInput from '@/components/searchInput'
+import banner from '@/components/banner'
+import 'swiper/css'
+import 'swiper/css/navigation'
+import 'swiper/css/pagination'
+import 'swiper/css/scrollbar'
+import pagination from '@/components/pagination'
+import { useRoute, useRouter } from 'vue-router'
+import { state as baseState } from '@/state'
+import { SubjectEnum, useSubjectId } from '@/helpers/hooks'
+import { getUserType } from '@/helpers/utils'
+import ColEmpty from '@/components/col-empty'
+export default defineComponent({
+  name: 'musicLibrary',
+  components: {
+    albumItem,
+    hotSearch,
+    silder,
+    searchInput,
+    banner,
+    pagination,
+    ColEmpty
+  },
+  setup() {
+    let subjectId = 0
+    const subjectIds = baseState.user.data?.subjectId || ''
+    if (subjectIds) {
+      subjectId = Number(subjectIds.split(',')[0])
+    }
+    // 判断是否在默认的声部
+    const subjects: any = useSubjectId(SubjectEnum.SEARCH)
+    subjectId = subjects.id || subjectId
+    const state = reactive({
+      albumList: [],
+      musicList: [],
+      tagTree: [],
+      hideSearch: true,
+      isshowData: false,
+      pageInfo: {
+        // 分页规则
+        limit: 40, // 限制显示条数
+        page: 1, // 当前页
+        total: 0, // 总条数
+        page_size: [5, 10, 20, 40, 50] // 选择限制显示条数
+      },
+      searchs: {
+        albumStatus: 1,
+        albumTagIds: '',
+        search: '',
+        subject: subjectId || '',
+        page: 1,
+        rows: 10
+      }
+    })
+
+    const router = useRouter()
+    const getAlbumList = async () => {
+      try {
+        const res = await request.post('/api-website/open/music/album/list', {
+          data: {
+            ...state.searchs,
+            page: state.pageInfo.page,
+            rows: state.pageInfo.limit
+          },
+          params: {
+            clientType: getUserType()
+          }
+        })
+
+        state.albumList = res.data.rows
+        state.pageInfo.total = res.data.total
+        if (state.pageInfo.total == 0) {
+          state.isshowData = true
+        } else {
+          state.isshowData = false
+        }
+      } catch (e) {
+        console.log(e)
+      }
+    }
+
+    const getTagTree = async () => {
+      try {
+        const res = await request.get('/api-website/open/MusicTag/tree', {
+          params: {
+            type: 'ALBUM'
+          }
+        })
+        const tree = res.data || []
+        state.tagTree = [
+          {
+            name: '全部',
+            id: '',
+            isCheck: true
+          },
+          ...tree
+        ] as any
+      } catch (e) {
+        console.log(e)
+      }
+    }
+
+    const searchRust = (val: any) => {
+      // const smallTag = (val || ([] as any)).filter(tag => tag < 0)
+      const maxTag = (val || ([] as any)).filter(tag => tag > 0)
+      state.searchs.albumTagIds = maxTag.join(',') as string
+      startSearch(state.searchs)
+    }
+
+    const startSearch = (val: any) => {
+      state.searchs = { ...state.searchs, ...val }
+      getAlbumList()
+    }
+
+    onMounted(() => {
+      getTagTree()
+      getAlbumList()
+    })
+    return () => (
+      <div>
+        <banner></banner>
+        <div class="bg-white">
+          <div class={styles.w1200}>
+            <div class={styles.section}>
+              <div class={styles.tagList}>
+                <div
+                  class={[styles.tagContainer, state.hideSearch && styles.hide]}
+                >
+                  {state.tagTree.map((tag: any) => (
+                    <span
+                      class={[styles.tagItem, tag.isCheck && styles.active]}
+                      onClick={() => {
+                        state.tagTree.forEach((item: any) => {
+                          item.isCheck = false
+                        })
+                        tag.isCheck = true
+
+                        startSearch({ albumTagIds: tag.id })
+                      }}
+                    >
+                      {tag.name}
+                    </span>
+                  ))}
+                </div>
+                <div
+                  class={styles.wrapRight}
+                  onClick={() => {
+                    console.log(111)
+                    state.hideSearch = !state.hideSearch
+                  }}
+                >
+                  <span>{state.hideSearch ? '更多' : '收起'}</span>
+                  <img
+                    class={[styles.arrow, !state.hideSearch && styles.active]}
+                    src={arrow}
+                    alt=""
+                  />
+                </div>
+              </div>
+              <searchInput
+                isWhile={false}
+                type="search"
+                showSearch
+                placeholder="搜索你想练习的专辑"
+                searchVal={{ ...state.searchs }}
+                onStartSearch={(val: any) => {
+                  state.pageInfo.page = 1
+                  startSearch(val)
+                }}
+              ></searchInput>
+              <div class={styles.hotSearch}>
+                <hotSearch
+                  onSearchRust={(val: any) => searchRust(val)}
+                  onHotTag={(val: string) => {
+                    state.searchs.search = val
+                    getAlbumList()
+                  }}
+                  type={''}
+                  isChiose={true}
+                ></hotSearch>
+              </div>
+
+              {state.albumList && state.albumList.length > 0 && (
+                <div class={styles.albumList}>
+                  {state.albumList.map(item => {
+                    return <albumItem detail={item}></albumItem>
+                  })}
+                </div>
+              )}
+              {state.isshowData && <ColEmpty></ColEmpty>}
+            </div>
+
+            <pagination
+              total={state.pageInfo.total}
+              v-model:page={state.pageInfo.page}
+              v-model:limit={state.pageInfo.limit}
+              pageSizes={state.pageInfo.page_size}
+              pagination={getAlbumList}
+            />
+          </div>
+        </div>
+        <silder></silder>
+      </div>
+    )
+  }
+})

BIN
src/views/albumLibrary/modals/albumItem/images/hold.png


BIN
src/views/albumLibrary/modals/albumItem/images/lineStart.png


BIN
src/views/albumLibrary/modals/albumItem/images/pan.png


BIN
src/views/albumLibrary/modals/albumItem/images/player.png


BIN
src/views/albumLibrary/modals/albumItem/images/start.png


+ 132 - 0
src/views/albumLibrary/modals/albumItem/index.module.less

@@ -0,0 +1,132 @@
+.itemWrap {
+  margin-bottom: 30px;
+  margin-right: 18px;
+  position: relative;
+  .albumType {
+    position: absolute;
+    left: 0;
+    top: 0;
+    background: linear-gradient(180deg, #ff8900 0%, #ff5100 100%);
+    box-shadow: 0px 1px 2px 0px rgba(150, 13, 0, 0.11);
+    border-radius: 10px 0px 10px 0px;
+    font-size: 12px;
+    padding: 0 6px;
+    line-height: 20px;
+    color: #ffffff;
+    z-index: 9;
+  }
+  &:hover {
+    .hold {
+      // transform: translateY(-10px);
+      transition: linear 0.1s;
+      .masker {
+        // transition: all linear 0.2s;
+        visibility: visible;
+        img {
+          width: 48px;
+          height: 48px;
+          animation-name: showPaly;
+          animation-duration: 0.6s;
+          animation-timing-function: linear;
+          animation-fill-mode: forwards;
+          // animation-delay: 1s;
+        }
+      }
+      @keyframes showPaly {
+        0% {
+          transform: scale(0.5);
+        }
+        50% {
+          transform: scale(1.2);
+        }
+        100% {
+          transform: scale(1);
+        }
+      }
+      // img {
+      //   transform: scale(1.1);
+      //   transition: all 0.3s ease-in-out;
+      // }
+    }
+  }
+  .hold {
+    .masker {
+      visibility: hidden;
+      width: 186px;
+      height: 186px;
+      background-color: rgba(0, 0, 0, 0.4);
+      position: absolute;
+      top: 0;
+      left: 0;
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      justify-content: center;
+      position: absolute;
+      img {
+        width: 48px;
+        height: 48px;
+      }
+    }
+    position: relative;
+    width: 186px;
+    height: 186px;
+    border-radius: 10px;
+    overflow: hidden;
+    img {
+      width: 100%;
+      transition: all 0.3s ease-in-out;
+    }
+  }
+  cursor: pointer;
+  &:nth-child(5n) {
+    margin-right: 0;
+  }
+  .startImage {
+    width: 24px;
+    height: 24px;
+    z-index: 1000;
+    position: absolute;
+    top: 8px;
+    right: 8px;
+  }
+  h2 {
+    line-height: 30px;
+    font-size: 18px;
+    font-weight: 400;
+    color: #000;
+    line-height: 25px;
+    margin: 18px 0 3px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    width: 186px;
+  }
+
+  span {
+    color: #999;
+    font-size: 14px;
+  }
+  .itemBottom {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    img {
+      width: 18px;
+      margin-right: 4px;
+      // height: 18px;
+    }
+    .itemBottomR {
+      margin-right: 1px;
+    }
+    .itemBottomL,
+    .itemBottomR {
+      display: flex;
+      flex-direction: row;
+      justify-content: flex-start;
+      align-items: center;
+      font-size: 14px;
+      line-height: 20px;
+    }
+  }
+}

+ 97 - 0
src/views/albumLibrary/modals/albumItem/index.tsx

@@ -0,0 +1,97 @@
+import { defineComponent, toRefs, reactive, onMounted, ref, watch } from 'vue'
+
+import classes from './index.module.less'
+import hold from './images/hold.png'
+import start from './images/start.png'
+import lineStart from './images/lineStart.png'
+import pan from './images/pan.png'
+import player from './images/player.png'
+import { useRouter } from 'vue-router'
+export default defineComponent({
+  name: 'albumItem',
+  props: {
+    detail: {
+      type: Object,
+      default: {
+        albumCoverUrl: '',
+        albumDesc: '',
+        albumFavoriteCount: 0,
+        albumName: '',
+        albumStatus: 0,
+        albumTag: '',
+        auditVersion: 0,
+        createBy: 0,
+        createTime: '',
+        delFlag: null,
+        hotFlag: null,
+        id: 0,
+        musicSheetCount: 0,
+        musicTagNames: '',
+        sortNumber: 0,
+        topFlag: null,
+        updateBy: 34,
+        updateTime: '',
+        favorite: 0
+      } as any
+    }
+  },
+  setup(props) {
+    const state = reactive({
+      detail: props.detail
+    })
+    watch(
+      () => props.detail,
+      detail => {
+        state.detail = detail
+      }
+    )
+    const router = useRouter()
+    const gotoAlbum = () => {
+      if (state.detail && state.detail.id) {
+        router.push({ path: '/albumDetail', query: { id: state.detail.id } })
+      }
+    }
+    return () => (
+      <>
+        <div
+          class={classes.itemWrap}
+          onClick={() => {
+            gotoAlbum()
+          }}
+        >
+          {state.detail?.paymentType === 'CHARGE' && (
+            <span class={classes.albumType}>付费</span>
+          )}
+          <img
+            class={classes.startImage}
+            src={state.detail?.favorite ? lineStart : start}
+            alt=""
+          />
+          <div class={classes.hold}>
+            <div class={classes.masker}>
+              <img src={player} alt="" />
+            </div>
+            <img
+              src={
+                state.detail?.albumCoverUrl ? state.detail?.albumCoverUrl : hold
+              }
+              alt=""
+            />
+          </div>
+
+          <h2>{state.detail?.albumName}</h2>
+          <div class={classes.itemBottom}>
+            <div class={classes.itemBottomL}>
+              {/* <img src={pan} alt="" /> */}
+              <span>{state.detail?.musicSheetCount}首</span>
+            </div>
+            <div class={classes.itemBottomR}>
+              {/* <img src={start} alt="" /> */}
+              <span>{state.detail?.albumFavoriteCount}收藏</span>
+            </div>
+          </div>
+        </div>
+      </>
+    )
+  }
+})

+ 115 - 0
src/views/albumLibrary/modals/searchAlbum.tsx

@@ -0,0 +1,115 @@
+// import { PaperClipIcon } from '@heroicons/vue/solid'
+import { defineComponent, toRefs, reactive, onMounted, ref } from 'vue'
+import arrow from '@/components/musicLIstItem/images/arrow.png'
+import styles from '../index.module.less'
+import albumItem from './albumItem'
+import videoDetailItem from '@/components/videoDetailItem'
+import musicLIstItem from '@/components/musicLIstItem'
+import hotSearch from '@/components/hotSearch'
+import request from '@/helpers/request'
+import silder from '@/components/silder'
+import searchInput from '@/components/searchInput'
+import 'swiper/css'
+import 'swiper/css/navigation'
+import 'swiper/css/pagination'
+import 'swiper/css/scrollbar'
+import { ElTabPane, ElTabs } from 'element-plus'
+import pagination from '@/components/pagination'
+import ColEmpty from '@/components/col-empty'
+import { getUserType } from '@/helpers/utils'
+export default defineComponent({
+  name: 'searchdetail',
+  components: {
+    hotSearch,
+    silder,
+    searchInput,
+    albumItem,
+    pagination,
+    ColEmpty
+  },
+  setup() {
+    const state = reactive({
+      albumList: [],
+      musicList: [],
+      search: {},
+      isshowData: false,
+      pageInfo: {
+        // 分页规则
+        limit: 40, // 限制显示条数
+        page: 1, // 当前页
+        total: 0, // 总条数
+        page_size: [5, 10, 20, 40, 50] // 选择限制显示条数
+      }
+    })
+
+    const getAlbumList = async () => {
+      try {
+        const res = await request.post('/api-website/open/music/album/list', {
+          data: {
+            albumStatus: 1,
+            ...state.search,
+            page: state.pageInfo.page,
+            rows: state.pageInfo.limit,
+          },
+          params:{
+            clientType: getUserType()
+          }
+        })
+
+        state.albumList = res.data.rows
+        state.pageInfo.total = res.data.total
+        if (state.pageInfo.total == 0) {
+          state.isshowData = true
+        } else {
+          state.isshowData = false
+        }
+      } catch (e) {
+        console.log(e)
+      }
+    }
+    const getList = (val: any) => {
+      state.search = {
+        ...val,
+        idAndName: val.search,
+        subjectIds: val.subject,
+        exquisiteFlag: val.exquisiteFlag
+      }
+      state.pageInfo.page = 1
+      getAlbumList()
+    }
+    onMounted(() => {
+      // getAlbumList()
+      // getMusicList()
+    })
+    return {
+      ...toRefs(state),
+      getList,
+      getAlbumList
+    }
+  },
+  render() {
+    return (
+      <div>
+        <div>
+          <div class={styles.w1200}>
+            <div class={styles.section}>
+              <div class={styles.albumList}>
+                {this.albumList.map(item => {
+                  return <albumItem detail={item}></albumItem>
+                })}
+              </div>
+              {this.isshowData && <ColEmpty></ColEmpty>}
+            </div>
+          </div>
+        </div>
+        <pagination
+          total={this.pageInfo.total}
+          v-model:page={this.pageInfo.page}
+          v-model:limit={this.pageInfo.limit}
+          pageSizes={this.pageInfo.page_size}
+          pagination={this.getAlbumList}
+        />
+      </div>
+    )
+  }
+})

+ 134 - 0
src/views/albumLibrary/modals/searchMusic.tsx

@@ -0,0 +1,134 @@
+// import { PaperClipIcon } from '@heroicons/vue/solid'
+import { defineComponent, toRefs, reactive, onMounted, ref } from 'vue'
+import arrow from '@/components/musicLIstItem/images/arrow.png'
+import styles from '../index.module.less'
+import albumItem from '@/components/albumItem'
+import videoDetailItem from '@/components/videoDetailItem'
+import musicListItem from '@/components/musicLIstItem'
+import hotSearch from '@/components/hotSearch'
+import request from '@/helpers/request'
+import silder from '@/components/silder'
+import searchInput from '@/components/searchInput'
+import pagination from '@/components/pagination'
+import 'swiper/css'
+import 'swiper/css/navigation'
+import 'swiper/css/pagination'
+import 'swiper/css/scrollbar'
+import ColEmpty from '@/components/col-empty'
+import { ElTabPane, ElTabs } from 'element-plus'
+import { getUserType } from '@/helpers/utils'
+export default defineComponent({
+  name: 'searchMusic',
+  components: {
+    hotSearch,
+    silder,
+    searchInput,
+    albumItem,
+    musicListItem,
+    pagination,
+    ColEmpty
+  },
+  setup() {
+    const state = reactive({
+      musicList: [],
+      search: {},
+      isshowData: false,
+      pageInfo: {
+        // 分页规则
+        limit: 10, // 限制显示条数
+        page: 1, // 当前页
+        total: 0, // 总条数
+        page_size: [5, 10, 20, 40, 50] // 选择限制显示条数
+      }
+    })
+
+    // const getAlbumList = async () => {
+    //   try {
+    //     const res = await request.post('/api-website/open/music/album/list', {
+    //       data: {
+    //         albumStatus: 1,
+    //         page: 1,
+    //         rows: 10
+    //       }
+    //     })
+
+    //     state.albumList = res.data.rows
+    //   } catch (e) {
+    //     console.log(e)
+    //   }
+    // }
+    const getMusicList = async () => {
+      try {
+        const res = await request.post('/api-website/open/music/sheet/list', {
+          data: {
+            albumStatus: 'PASS',
+            ...state.search,
+            page: state.pageInfo.page,
+            rows: state.pageInfo.limit,
+            state: 1,
+          },
+          params:{
+            clientType: getUserType()
+          }
+        })
+
+        state.musicList = res.data.rows.map(n => {
+          if (typeof n.paymentType === "string") n.paymentType = n.paymentType.split(',')
+          return n
+        })
+        state.pageInfo.total = res.data.total
+        if (state.pageInfo.total == 0) {
+          state.isshowData = true
+        } else {
+          state.isshowData = false
+        }
+      } catch (e) {
+        console.log(e)
+      }
+    }
+    const getList = (val: any) => {
+      state.search = {
+        subjectIds: val.subject,
+        musicTagIds: val.albumTagIds,
+        exquisiteFlag: val.exquisiteFlag,
+        idAndName: val.search
+      }
+      state.pageInfo.page = 1
+      getMusicList()
+    }
+    onMounted(() => {
+      // getAlbumList()
+      // getList(state.search)
+    })
+    return {
+      ...toRefs(state),
+      getList,
+      getMusicList
+    }
+  },
+  render() {
+    return (
+      <div>
+        <div>
+          <div class={styles.w1200}>
+            <div class={styles.section}>
+              <div class={styles.musicList}>
+                {this.musicList.map(item => {
+                  return <musicListItem item={item}></musicListItem>
+                })}
+              </div>
+            </div>
+          </div>
+          {this.isshowData && <ColEmpty></ColEmpty>}
+        </div>
+        <pagination
+          total={this.pageInfo.total}
+          v-model:page={this.pageInfo.page}
+          v-model:limit={this.pageInfo.limit}
+          pageSizes={this.pageInfo.page_size}
+          pagination={this.getMusicList}
+        />
+      </div>
+    )
+  }
+})

+ 192 - 0
src/views/albumLibrary/searchdetail.tsx

@@ -0,0 +1,192 @@
+// import { PaperClipIcon } from '@heroicons/vue/solid'
+import {
+  defineComponent,
+  toRefs,
+  reactive,
+  onMounted,
+  ref,
+  nextTick,
+  watch
+} from 'vue'
+import arrow from '@/components/musicLIstItem/images/arrow.png'
+import styles from './index.module.less'
+import hotSearch from '@/components/hotSearch'
+import request from '@/helpers/request'
+import silder from '@/components/silder'
+import searchInput from '@/components/searchInput'
+import searchAlbum from './modals/searchAlbum'
+import searchMusic from './modals/searchMusic'
+import 'swiper/css'
+import 'swiper/css/navigation'
+import 'swiper/css/pagination'
+import 'swiper/css/scrollbar'
+import { ElTabPane, ElTabs } from 'element-plus'
+import { useRoute } from 'vue-router'
+import { SubjectEnum, useSubjectId } from '@/helpers/hooks'
+import { useAsyncState, useLocalStorage } from '@vueuse/core'
+export default defineComponent({
+  name: 'searchdetail',
+  components: {
+    hotSearch,
+    silder,
+    searchInput,
+    searchAlbum,
+    searchMusic
+  },
+  setup() {
+    const subjects: any = useSubjectId(SubjectEnum.SEARCH)
+    const state = reactive({
+      albumList: [],
+      musicList: [],
+      chiose: 'album',
+      searchs: {
+        albumTagIds: '',
+        search: '',
+        exquisiteFlag: null as any,
+        subject: subjects.id || ''
+      }
+    })
+    const route = useRoute()
+    const searchAlbumRef = ref()
+    const searchMusicRef = ref()
+    // const getAlbumList = async () => {
+    //   try {
+    //     const res = await request.post('/api-website/open/music/album/list', {
+    //       data: {
+    //         albumStatus: 1,
+    //         page: 1,
+    //         rows: 10
+    //       }
+    //     })
+
+    //     state.albumList = res.data.rows
+    //   } catch (e) {
+    //     console.log(e)
+    //   }
+    // }
+    // const getMusicList = async () => {
+    //   try {
+    //     const res = await request.post('/api-website/open/music/sheet/list', {
+    //       data: {
+    //         albumStatus: 'PASS',
+    //         page: 1,
+    //         rows: 5,
+    //         state: 1
+    //       }
+    //     })
+
+    //     state.musicList = res.data.rows
+    //   } catch (e) {
+    //     console.log(e)
+    //   }
+    // }
+    const searchRust = (val: any) => {
+      console.log(val, 'search')
+      const smallTag = (val || ([] as any)).filter(tag => tag < 0)
+      const maxTag = (val || ([] as any)).filter(tag => tag > 0)
+      state.searchs.albumTagIds = maxTag.join(',') as string
+      state.searchs.exquisiteFlag = null
+      if (smallTag[0] == -2) {
+        state.searchs.exquisiteFlag = 1
+      }
+      startSearch(state.searchs)
+    }
+    const startSearch = (val: any) => {
+      state.searchs = { ...state.searchs, ...val }
+      search()
+    }
+
+    const search = () => {
+      console.log(state.searchs, '1212')
+      if (state.chiose == 'album') {
+        searchAlbumRef.value.getList(state.searchs)
+      }
+      if (state.chiose == 'music') {
+        searchMusicRef.value.getList(state.searchs)
+      }
+    }
+
+    watch(
+      () => state.chiose,
+      chiose => {
+        nextTick(() => {
+          search()
+        })
+      }
+    )
+    onMounted(() => {
+      if (route.params.search) {
+        state.searchs.search = route.params.search as string
+      }
+      if (route.params.subject) {
+        state.searchs.subject = route.params.subject as string
+      }
+      if (route.params.type) {
+        state.chiose = route.params.type as string
+      }
+      nextTick(() => {
+        search()
+      })
+
+      // getAlbumList()
+      // getMusicList()
+    })
+    return {
+      ...toRefs(state),
+      startSearch,
+      searchRust,
+      searchAlbumRef,
+      searchMusicRef,
+      search
+    }
+  },
+  render() {
+    return (
+      <div>
+        <div class="">
+          <div class="wall" style={{ height: '60px' }}></div>
+          <div class={styles.w1200}>
+            <div class={styles.section}>
+              <searchInput
+                isWhile={true}
+                searchVal={{ ...this.searchs }}
+                onUpdate:searchVal={(val: any) => {
+                  console.log(val, '1212')
+                }}
+                type="search"
+                onStartSearch={(val: any) => {
+                  this.startSearch(val)
+                }}
+              ></searchInput>
+              <div class={styles.hotSearch}>
+                <hotSearch
+                  type={'search'}
+                  onSearchRust={(val: any) => this.searchRust(val)}
+                  onHotTag={(val: string) => {
+                    this.searchs.search = val
+                    this.search()
+                  }}
+                  isChiose={true}
+                ></hotSearch>
+              </div>
+              <div class={styles.myTabWrap}>
+                <ElTabs class={styles.myTab} v-model={this.chiose}>
+                  <ElTabPane label="专辑" name="album">
+                    {this.chiose == 'album' ? (
+                      <searchAlbum ref="searchAlbumRef" />
+                    ) : null}
+                  </ElTabPane>
+                  <ElTabPane label="乐谱" name="music">
+                    {this.chiose == 'music' ? (
+                      <searchMusic ref="searchMusicRef" />
+                    ) : null}
+                  </ElTabPane>
+                </ElTabs>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    )
+  }
+})

+ 124 - 23
src/views/home/index.tsx

@@ -34,7 +34,10 @@ export default defineComponent({
       albumList: [],
       videoList: [],
       search: '',
-      tagTree: []
+      tagTree: [],
+      tagTreeAlbum: [],
+      hotList: [],
+      musicList: []
     })
     const router = useRouter()
     const getAlbumList = async () => {
@@ -55,6 +58,28 @@ export default defineComponent({
         console.log(e)
       }
     }
+    const getMusicList = async () => {
+      try {
+        const res = await request.post('/api-website/open/music/sheet/list', {
+          data: {
+            albumStatus: 'PASS',
+            exquisiteFlag: 1,
+            page: 1,
+            rows: 5,
+            state: 1
+          }
+        })
+
+        // state.musicList = res.data.rows
+        state.musicList = res.data.rows.map(n => {
+          if (typeof n.paymentType === 'string')
+            n.paymentType = n.paymentType.split(',')
+          return n
+        })
+      } catch (e) {
+        console.log(e)
+      }
+    }
     const getVideoList = async () => {
       try {
         const res = await request.post(
@@ -76,16 +101,28 @@ export default defineComponent({
     const gotoSearch = (val: string, type: any) => {
       router.push({ name: 'searchdetail', params: { search: val, type } })
     }
-    const getTagTree = async () => {
+    const getTagTree = async (type = 'MUSIC') => {
       try {
-        const res = await request.get('/api-website/open/MusicTag/tree', {})
-        state.tagTree = res.data.splice(0, 2)
+        const res = await request.get('/api-website/open/MusicTag/tree', {
+          params: {
+            type: type
+          }
+        })
 
-        // state.hotList = res.data
+        if (type === 'MUSIC') {
+          const resHot = await request.get(
+            `/api-website/open/music/sheet/hotTag/${type}`
+          )
+          state.hotList = resHot.data || []
+          state.tagTree = res.data || []
+        } else {
+          state.tagTreeAlbum = res.data || []
+        }
       } catch (e) {
         console.log(e)
       }
     }
+
     const gotoVideoList = () => {
       router.push({ path: '/videoDetailList' })
     }
@@ -103,8 +140,9 @@ export default defineComponent({
     //
     onMounted(() => {
       getAlbumList()
-      getVideoList()
+      getMusicList()
       getTagTree()
+      getTagTree('ALBUM')
     })
     return () => (
       <div>
@@ -151,24 +189,69 @@ export default defineComponent({
                     <ElInput
                       placeholder="搜索你想要的曲目"
                       v-model={state.search}
-                      //  onKeyup={(e:any) => {
-                      //   if (e.keyCode === 13) {
-                      //     gotoSearch(state.search,'music')
-                      //   }
-                      // }}
-                      // onkeyup= { gotoSearch(state.search,'music')}
                     ></ElInput>
                   </div>
                   <div class={styles.chioseLineWrap}>
-                    {state.tagTree.map((tree: any) => {
-                      return (
-                        <div class={styles.chioseRow}>
-                          <p>{tree.name}:</p>
+                    <div class={styles.chioseRow}>
+                      <p>专辑分类:</p>
+                      <div class={[styles.chioseTagWrap, 'chioseTagWrap']}>
+                        {state.tagTreeAlbum.map((tag: any) => {
+                          return (
+                            <tagItem
+                              class={styles.tags}
+                              title={tag.name}
+                              onSearchTag={() => {
+                                gotoSearchTag(tag)
+                              }}
+                            >
+                              {/* {} */}
+                            </tagItem>
+                          )
+                        })}
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+
+            {state.musicList && state.musicList.length > 0 && (
+              <>
+                <div
+                  class={[styles.section, styles.pb40]}
+                  style="padding-top: 0"
+                >
+                  <div class={styles.albumMoudel}>
+                    <div class={styles.albumWrap} style="padding-right: 25px">
+                      <div class={[styles.titleWrap, styles.hotAlbum]}>
+                        <div class={[styles.titleWrapLeft]}>
+                          <h4>精品乐谱</h4>
+                          <img src={titleDot} class={styles.dotImg} alt="" />
+                        </div>
+                        <div
+                          class={[styles.titleWrapMore]}
+                          onClick={() => gotoSearch('', 'album')}
+                        >
+                          <span>更多</span>
+                          <img src={moreArrow} alt="" />
+                        </div>
+                      </div>
+
+                      <div class={styles.musicList}>
+                        {state.musicList.map(item => {
+                          return <musicLIstItem item={item}></musicLIstItem>
+                        })}
+                      </div>
+                      <div class={styles.line}></div>
+                    </div>
+
+                    <div class={styles.albumSearch}>
+                      <div class={styles.chioseLineWrap}>
+                        <div class={styles.chioseRow} style="margin-top: 0">
+                          <p>曲谱分类:</p>
                           <div class={[styles.chioseTagWrap, 'chioseTagWrap']}>
-                            {tree.children.map((tag: any) => {
+                            {state.tagTree.map((tag: any) => {
                               return (
-                                //  effect={isChiose(tag)}
-
                                 <tagItem
                                   class={styles.tags}
                                   title={tag.name}
@@ -182,12 +265,30 @@ export default defineComponent({
                             })}
                           </div>
                         </div>
-                      )
-                    })}
+                        <div class={styles.chioseRow}>
+                          <p>热门搜索:</p>
+                          <div class={[styles.chioseTagWrap, 'chioseTagWrap']}>
+                            {state.hotList.map((tag: any) => {
+                              return (
+                                <tagItem
+                                  class={styles.tags}
+                                  title={tag.key}
+                                  onSearchTag={() => {
+                                    gotoSearchTag(tag)
+                                  }}
+                                >
+                                  {/* {} */}
+                                </tagItem>
+                              )
+                            })}
+                          </div>
+                        </div>
+                      </div>
+                    </div>
                   </div>
                 </div>
-              </div>
-            </div>
+              </>
+            )}
           </div>
         </div>
         {/* <div class="bg-white">

+ 1 - 1
src/views/muiscDetial/index.tsx

@@ -230,7 +230,7 @@ export default defineComponent({
       }
     )
     const setAccompanyUrl = () => {
-      let url = vaildTeachingUrl()
+      const url = 'https://dev.colexiu.com'
       state.accompanyUrl =
         url +
         `/accompany/colxiu-website.html?id=${state.id}&part-index=${state.subjectId}`

+ 2 - 2
src/views/user-info/music-class/item.tsx

@@ -75,7 +75,7 @@ export default defineComponent({
             </div>
             <div class={classes.textWrap}>
               <p>
-                {Array.isArray(state.item.paymentType) &&
+                {/* {Array.isArray(state.item.paymentType) &&
                   state.item.paymentType.map((tag: string) => (
                     <div
                       class={[
@@ -85,7 +85,7 @@ export default defineComponent({
                     >
                       {chargeTypes[tag] ? chargeTypes[tag] : '点播'}
                     </div>
-                  ))}
+                  ))} */}
                 {state.item.exquisiteFlag === 1 && (
                   <img src={iconFine} class={classes.iconFine} />
                 )}