瀏覽代碼

样式改版

lex 2 年之前
父節點
當前提交
3f0f1d141e

二進制
src/common/images/icon-arrow.png


二進制
src/common/images/icon-play.png


二進制
src/common/images/icon-title.png


+ 12 - 3
src/views/music/album-detail/index.module.less

@@ -4,6 +4,11 @@
 }
 .detail {
   overflow: hidden;
+
+  --van-nav-bar-background-color: transparent;
+  --van-nav-bar-icon-color: #fff;
+  --van-nav-bar-text-color: #fff;
+  --van-nav-bar-title-text-color: #fff;
 }
 .base {
   :global(.van-sticky--fixed) {
@@ -107,8 +112,10 @@
   filter: blur(10px);
 }
 .musicContent {
-  position: relative;
+  position: absolute;
+  top: 0;
   height: 265px;
+  width: 100%;
   padding-top: 55px;
   z-index: 10;
   background-color: rgba(0, 0, 0, 0.6);
@@ -120,6 +127,7 @@
   position: relative;
   height: 100%;
   padding: 16px;
+  z-index: 11;
 }
 .alumWrap {
   display: flex;
@@ -173,11 +181,12 @@
 .alumnContainer {
   position: relative;
   padding: 0 16px;
-  margin-top: -16px;
+  // margin-top: -16px;
   z-index: 10;
   .alumnList {
     padding: 0 12px;
-    border-radius: 6px;
+    border-radius: 18px;
     background-color: #fff;
+    margin-bottom: 16px;
   }
 }

+ 108 - 117
src/views/music/album-detail/index.tsx

@@ -1,8 +1,8 @@
 import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue'
-import { useRoute } from 'vue-router'
+import { useRoute, useRouter } from 'vue-router'
 import request from '@/helpers/request'
 import ColHeader from '@/components/col-header'
-import { Button, Icon, Image, List, Sticky } from 'vant'
+import { Button, Icon, Image, List, NavBar, Sticky } from 'vant'
 import classNames from 'classnames'
 import Footer from '../album/footer'
 import FavoriteIcon from '../album/favorite.svg'
@@ -10,10 +10,15 @@ import FavoritedIcon from '../album/favorited.svg'
 import styles from './index.module.less'
 import Item from '../list/item'
 import { useRect } from '@vant/use'
+import { useEventListener, useWindowScroll } from '@vueuse/core'
 import { getRandomKey, musicBuy } from '../music'
 import { state } from '@/state'
 import IconPan from './pan.png'
 import oStart from './oStart.png'
+import Title from '../component/title'
+import Song from '../component/song'
+import ColResult from '@/components/col-result'
+import MusicGrid from '../component/music-grid'
 
 const noop = () => {}
 
@@ -27,9 +32,11 @@ export default defineComponent({
   },
   setup({ onItemClick }) {
     localStorage.setItem('behaviorId', getRandomKey())
+    const router = useRouter()
     const params = reactive({
       search: '',
-      page: 1
+      page: 1,
+      rows: 200
     })
     const albumDetail = ref<any>(null)
     const data = ref<any>(null)
@@ -40,7 +47,8 @@ export default defineComponent({
     const favorited = ref(0)
     const albumFavoriteCount = ref(0)
     const headers = ref(null)
-    let heights = ref(0)
+    const background = ref<string>('rgba(55, 205, 177, 0)')
+    const heightInfo = ref<any>('auto')
 
     const route = useRoute()
     const FetchList = async () => {
@@ -75,6 +83,14 @@ export default defineComponent({
 
     const favoriteLoading = ref(false)
 
+    onMounted(() => {
+      FetchList()
+      useEventListener(document, 'scroll', evt => {
+        const { y } = useWindowScroll()
+        background.value = `rgba(55, 205, 177, ${y.value / 100})`
+      })
+    })
+
     const toggleFavorite = async (id: number) => {
       favoriteLoading.value = true
       try {
@@ -88,132 +104,107 @@ export default defineComponent({
       favoriteLoading.value = false
     }
 
-    onMounted(() => {
-      nextTick(() => {
-        setTimeout(() => {
-          const { height } = useRect(headers as any)
-          console.log(height, 'height')
-          heights.value = height
-        }, 100)
-      })
-    })
-
     return () => {
-      // console.log(albumFavoriteCount.value)
       return (
         <div class={styles.detail}>
+          <div ref={headers}>
+            <ColHeader
+              background={background.value}
+              border={false}
+              color="#fff"
+              backIconColor="white"
+              onHeaderBack={() => {
+                nextTick(() => {
+                  const { height } = useRect(headers as any)
+                  heightInfo.value = height
+                })
+              }}
+            />
+          </div>
           <img class={styles.bgImg} src={albumDetail.value?.albumCoverUrl} />
-          <div class={styles.musicContent}>
-            <div class={styles.bg}>
-              <div class={styles.alumWrap}>
-                <div class={styles.img}>
-                  {/* <TheImage src={albumDetail.value?.albumCoverUrl} /> */}
-                  <Image
-                    class={styles.image}
-                    width="100%"
-                    height="100%"
-                    lazy-load
-                    fit="cover"
-                    src={albumDetail.value?.albumCoverUrl}
-                  />
+          <div class={styles.musicContent}></div>
+          <div class={styles.bg}>
+            <div class={styles.alumWrap}>
+              <div class={styles.img}>
+                <Image
+                  class={styles.image}
+                  width="100%"
+                  height="100%"
+                  fit="cover"
+                  src={albumDetail.value?.albumCoverUrl}
+                />
+              </div>
+              <div class={styles.alumDes}>
+                <div class={[styles.alumTitle, 'van-ellipsis']}>
+                  {albumDetail.value?.albumName}
                 </div>
-                <div class={styles.alumDes}>
-                  <div class={[styles.alumTitle, 'van-ellipsis']}>
-                    {albumDetail.value?.albumName}
-                  </div>
-                  <div class={styles.tags}>
-                    {albumDetail.value?.musicTagNames?.map((tag: any) => (
-                      <span class={styles.tag}>{tag}</span>
-                    ))}
-                  </div>
-                  <div class={[styles.des, 'van-multi-ellipsis--l3']}>
-                    {albumDetail.value?.albumDesc}
-                  </div>
+                <div class={styles.tags}>
+                  {albumDetail.value?.musicTagNames?.map((tag: any) => (
+                    <span class={styles.tag}>{tag}</span>
+                  ))}
+                </div>
+                <div
+                  class={[styles.des, 'van-multi-ellipsis--l3']}
+                  style={{
+                    height: '48px',
+                    lineHeight: '16px'
+                  }}
+                >
+                  {albumDetail.value?.albumDesc}
                 </div>
               </div>
-              <div class={styles.alumCollect}>
-                <img src={IconPan} />
-                <span>共{albumDetail.value?.musicSheetCount}首曲目</span>
-                <img class={styles.right} src={oStart} />
-                <span>{albumDetail.value?.albumFavoriteCount}人收藏</span>
-              </div>
+            </div>
+            <div class={styles.alumCollect}>
+              <img src={IconPan} />
+              <span>共{albumDetail.value?.musicSheetCount}首曲目</span>
+              <img class={styles.right} src={oStart} />
+              <span>{albumDetail.value?.albumFavoriteCount}人收藏</span>
             </div>
           </div>
-          {/* <Sticky
-            class={[styles.base, 'sticky']}
-            style={{
-              height: heights.value + 'px !important',
-              width: '100%'
-            }}
-          >
-            <div ref={headers}>
-              <ColHeader
-                class={styles.header}
-                background="transparent"
-                color="#fff"
-                title="专辑详情"
-                backIconColor="white"
-                border={false}
-                isFixed={false}
+          <div class={styles.alumnContainer}>
+            <div class={styles.alumnList}>
+              <Title title="曲目列表" isMore={false} />
+              <Song
+                list={rows.value}
+                onDetail={(item: any) => {
+                  if (onItemClick === noop || !onItemClick) {
+                    musicBuy(item, () => {}, {
+                      albumId: route.params.id
+                    })
+                  } else {
+                    onItemClick(item)
+                  }
+                }}
               />
-              <div class={styles.detailContent}>
-                <div class={classNames(styles.main, 'van-hairline--bottom')}>
-                  <Image
-                    class={styles.img}
-                    src={albumDetail.value?.albumCoverUrl}
-                  />
-                  <div class={styles.content}>
-                    <h4 class="van-ellipsis">{albumDetail.value?.albumName}</h4>
-                    <p class="van-multi-ellipsis--l3">
-                      {albumDetail.value?.albumDesc}
-                    </p>
-                  </div>
-                </div>
-                <div class={styles.footerBar}>
-                  <Footer
-                    musicSheetCount={albumDetail.value?.musicSheetCount}
-                    albumFavoriteCount={albumFavoriteCount.value}
-                  />
-                  {state.platformType === 'STUDENT' && (
-                    <Button
-                      class={styles.favoriteContaineer}
-                      loading={favoriteLoading.value}
-                      onClick={() => toggleFavorite(albumDetail.value?.id)}
-                      size="mini"
-                    >
-                      <Icon
-                        key={favorited.value}
-                        class={styles.favorite}
-                        name={favorited.value ? FavoritedIcon : FavoriteIcon}
-                      />{' '}
-                      <span>{favorited.value ? '已' : ''}收藏</span>
-                    </Button>
-                  )}
-                </div>
-              </div>
+
+              {rows.value && rows.value.length <= 0 && (
+                <ColResult btnStatus={false} tips="暂无曲目" />
+              )}
             </div>
-          </Sticky> */}
-          <List
-            loading={loading.value}
-            finished={finished.value}
-            finished-text="没有更多了"
-            onLoad={FetchList}
-          >
-            {rows.value.length
-              ? rows.value.map(item => (
-                  <Item
-                    data={item}
-                    onClick={() => {
-                      if (onItemClick === noop || !onItemClick) {
-                        musicBuy(item)
-                      } else {
-                        onItemClick(item)
-                      }
+
+            {albumDetail.value?.relatedMusicAlbum &&
+              albumDetail.value?.relatedMusicAlbum.length > 0 && (
+                <>
+                  <Title
+                    title="相关专辑"
+                    onMore={() => {
+                      router.push({
+                        path: '/music-album'
+                      })
                     }}
                   />
-                ))
-              : null}
-          </List>
+
+                  <MusicGrid
+                    list={albumDetail.value?.relatedMusicAlbum}
+                    onGoto={(n: any) =>
+                      router.push({
+                        path: '/music-album-detail/' + n.id
+                      })
+                    }
+                  />
+                </>
+              )}
+          </div>
         </div>
       )
     }

+ 58 - 0
src/views/music/component/music-grid/index.module.less

@@ -0,0 +1,58 @@
+.theMusicGrid {
+  :global {
+    .van-grid {
+      margin: 0 -4px;
+    }
+    .van-grid-item {
+      width: calc(100% / 3);
+    }
+    .van-grid-item__content {
+      display: block;
+      padding: 0 4px;
+      background-color: transparent;
+    }
+  }
+  .item {
+    margin-bottom: 15px;
+    .title {
+      font-size: 14px;
+      color: #333;
+      line-height: 20px;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+      margin-bottom: 2px;
+    }
+    .des {
+      font-size: 12px;
+      color: #999;
+      line-height: 16px;
+    }
+  }
+  .imgWrap {
+    position: relative;
+    // height: 110px;
+    height: calc((100vw - 48px) / 3);
+    border-radius: 6px;
+    overflow: hidden;
+    margin-bottom: 6px;
+    .model {
+      position: absolute;
+      left: 4px;
+      bottom: 4px;
+      background: rgba(67, 67, 67, 0.6);
+      backdrop-filter: blur(20px);
+      -webkit-backdrop-filter: blur(20px);
+      display: flex;
+      align-items: center;
+      padding: 4px 6px;
+      border-radius: 20px;
+      font-size: 12px;
+      color: #fff;
+      transform: scale(0.9);
+    }
+    .num {
+      margin-left: 3px;
+    }
+  }
+}

+ 44 - 0
src/views/music/component/music-grid/index.tsx

@@ -0,0 +1,44 @@
+import { Grid, GridItem, Icon, Image, Loading } from 'vant'
+import { defineComponent, PropType } from 'vue'
+import styles from './index.module.less'
+import IconXin from '@/assets/icon-xin.png'
+
+export default defineComponent({
+  name: 'TheMusicGrid',
+  props: {
+    list: {
+      type: Array as any,
+      default: () => []
+    }
+  },
+  emits: ['goto'],
+  setup(props, { emit }) {
+    return () => (
+      <div class={styles.theMusicGrid}>
+        <Grid border={false} columnNum={3}>
+          {props.list.map((n: any) => (
+            <GridItem>
+              <div class={styles.item} onClick={() => emit('goto', n)}>
+                <div class={styles.imgWrap}>
+                  <Image
+                    class={styles.image}
+                    width="100%"
+                    height="100%"
+                    fit="cover"
+                    src={n.albumCoverUrl}
+                  />
+                  <div class={styles.model}>
+                    <Icon name={IconXin} />
+                    <span class={styles.num}>{n.albumFavoriteCount}人</span>
+                  </div>
+                </div>
+                <div class={styles.title}>{n.albumName}</div>
+                <div class={styles.des}>共{n.musicSheetCount}首</div>
+              </div>
+            </GridItem>
+          ))}
+        </Grid>
+      </div>
+    )
+  }
+})

+ 65 - 0
src/views/music/component/song/index.module.less

@@ -0,0 +1,65 @@
+.theSong {
+  padding: 0 10px;
+  background-color: #fff;
+  border-radius: 8px;
+  box-shadow: 0px 2px 10px 0px rgba(229, 229, 229, 0.1);
+  .item {
+    display: flex;
+    align-items: center;
+    border-bottom: 1px solid #e8e8e8;
+    padding: 16px 0;
+  }
+  .item:last-child {
+    border: none;
+  }
+  .play {
+    flex-shrink: 0;
+  }
+  .content {
+    flex: 1;
+    .top {
+      display: flex;
+      align-items: center;
+      margin-bottom: 10px;
+    }
+    .tag {
+      flex-shrink: 0;
+      padding: 2px 4px;
+      border-radius: 4px;
+    }
+    .user {
+      display: flex;
+      align-items: center;
+      .name {
+        font-size: 12px;
+        color: #999;
+        line-height: 16px;
+        margin-right: 12px;
+      }
+      .tags {
+        & > span {
+          display: inline-block;
+          background: #effbf9;
+          border-radius: 20px;
+          color: var(--van-primary-color);
+          padding: 4px 8px;
+          margin-right: 4px;
+          font-size: 12px;
+          transform: scale(0.9);
+        }
+      }
+    }
+    .title {
+      max-width: 150px;
+      font-size: 16px;
+      font-weight: bold;
+      color: #1a1a1a;
+      margin: 0 6px;
+    }
+    .singer {
+      max-width: 50px;
+      font-size: 12px;
+      color: #999;
+    }
+  }
+}

+ 73 - 0
src/views/music/component/song/index.tsx

@@ -0,0 +1,73 @@
+import { Icon, NoticeBar, Tag } from 'vant'
+import { defineComponent, PropType } from 'vue'
+import styles from './index.module.less'
+import IconPlay from '@/common/images/icon-play.png'
+import { useRouter } from 'vue-router'
+export default defineComponent({
+  name: 'TheSong',
+  props: {
+    list: {
+      type: Array as PropType<any[]>,
+      default: () => []
+    }
+  },
+  emits: ['detail'],
+  setup(props, { emit }) {
+    const router = useRouter()
+    const colors: any = {
+      FREE: {
+        color: '#01B84F',
+        text: '免费'
+      },
+      VIP: {
+        color: '#CD863E',
+        text: '会员'
+      },
+      CHARGE: {
+        color: '#3591CE',
+        text: '点播'
+      }
+    }
+    return () => (
+      <div class={styles.theSong}>
+        {props.list.map((n: any) => (
+          <div class={styles.item} onClick={() => emit('detail', n)}>
+            <div class={styles.content}>
+              <div class={styles.top}>
+                <Tag
+                  style={{ color: colors[n.chargeType].color }}
+                  class={styles.tag}
+                  type="success"
+                  plain
+                >
+                  {colors[n.chargeType].text}
+                </Tag>
+                <span class={[styles.title, 'van-ellipsis']}>
+                  {n.musicSheetName}
+                </span>
+                <span class={[styles.singer, 'van-ellipsis']}>
+                  -{n.composer}
+                </span>
+              </div>
+              <div class={styles.user}>
+                {n.addName ? (
+                  <span class={styles.name}>上传者:{n.addName}</span>
+                ) : (
+                  <span class={styles.name}>作曲:{n.composer}</span>
+                )}
+                <div class={styles.tags}>
+                  {n?.subjectNames.split(',').map((name: any) => (
+                    <span>{name}</span>
+                  ))}
+                </div>
+              </div>
+            </div>
+            <div style={styles.play}>
+              <Icon name={IconPlay} size={28} />
+            </div>
+          </div>
+        ))}
+      </div>
+    )
+  }
+})

+ 29 - 0
src/views/music/component/title/index.module.less

@@ -0,0 +1,29 @@
+.theTitle {
+  display: flex;
+  align-items: center;
+  padding: 15px 0;
+  .title {
+    font-size: 18px;
+    font-weight: bold;
+    color: #1d1f26;
+  }
+  .img {
+    display: inline-block;
+    width: 21px;
+    height: 14px;
+    margin-left: 4px;
+  }
+  .more {
+    display: flex;
+    align-items: center;
+    margin-left: auto;
+    font-size: 16px;
+    color: #1d1f26;
+    font-weight: 400;
+    :global {
+      .van-icon {
+        margin-left: 6px;
+      }
+    }
+  }
+}

+ 35 - 0
src/views/music/component/title/index.tsx

@@ -0,0 +1,35 @@
+import { defineComponent } from 'vue'
+import styles from './index.module.less'
+import IconTitle from '@/common/images/icon-title.png'
+import { Icon } from 'vant'
+import IconArrow from '@/common/images/icon-arrow.png'
+
+export default defineComponent({
+  name: 'TheTitle',
+  props: {
+    title: {
+      type: String
+    },
+    isMore: {
+      type: Boolean,
+      default: true
+    },
+    onMore: {
+      type: Function
+    }
+  },
+  setup(props) {
+    return () => (
+      <div class={styles.theTitle}>
+        <div class={styles.title}>{props.title}</div>
+        <img src={IconTitle} class={styles.img} />
+        {props.isMore && (
+          <div class={styles.more} onClick={props.onMore}>
+            <span>更多</span>
+            <Icon name={IconArrow} size={17} />
+          </div>
+        )}
+      </div>
+    )
+  }
+})

+ 1 - 0
src/views/music/music.ts

@@ -22,6 +22,7 @@ export const musicBuy = (item: any, callBack?: any, moreQuery = {}) => {
       ...moreQuery
     }
   })
+  console.log(url)
   postMessage({
     api: 'openAccompanyWebView',
     content: {