├── .gitignore
├── README.md
├── auto-imports.d.ts
├── components.d.ts
├── docs
├── assets
│ ├── Album.402a1341.js
│ ├── Artist.0d846367.js
│ ├── Artist.dfdd0cc6.css
│ ├── ArtistDetail.3bc343f2.css
│ ├── ArtistDetail.a9400840.js
│ ├── Category.0252e828.js
│ ├── CoverPlay.33350ebd.css
│ ├── CoverPlay.d639e45b.js
│ ├── DJ.e0f4dc6a.js
│ ├── Discover.38e1e773.js
│ ├── Fm.46f05eb0.js
│ ├── IconPark.402beefe.js
│ ├── Music.70c8366c.js
│ ├── Music.e9b17b81.css
│ ├── Mv.34913284.js
│ ├── Mv.8cac6744.css
│ ├── OpticalDisk.4907c891.png
│ ├── Picked.0c25147a.js
│ ├── PlayList.1f8f2eb4.css
│ ├── PlayList.7ad8eb52.js
│ ├── PlayOne.e72f474c.js
│ ├── PlayTwo.fe71fa6d.js
│ ├── Right.083d6647.js
│ ├── Root.9a2da039.js
│ ├── Root.e6a672cb.css
│ ├── SongListItem.6fa5a73e.css
│ ├── SongListItem.f4bd4734.js
│ ├── TopList.33e44e27.js
│ ├── Video.94189c43.js
│ ├── el-avatar.00087837.css
│ ├── el-image-viewer.a8b12883.js
│ ├── el-image-viewer.ac997372.css
│ ├── el-popper.24515e58.css
│ ├── el-tab-pane.29573fb9.css
│ ├── index.373df683.js
│ ├── index.eec43999.css
│ ├── logo.601c4b06.png
│ ├── music.991378cb.js
│ ├── mvDetail.aa81123a.js
│ ├── plugin-vue_export-helper.21dcd24c.js
│ ├── vendor.77ac5f7b.css
│ ├── vendor.9760fa8a.js
│ └── video.3500c715.js
├── favicon.ico
└── index.html
├── env.d.ts
├── index.html
├── package.json
├── postcss.config.js
├── public
└── favicon.ico
├── src
├── App.vue
├── Host.vue
├── assets
│ ├── base.scss
│ ├── img
│ │ ├── OpticalDisk.png
│ │ ├── index.ts
│ │ └── logo.png
│ ├── logo.svg
│ └── theme.scss
├── components
│ ├── common
│ │ ├── Banner.vue
│ │ ├── CoverPlay.vue
│ │ ├── IconPark.vue
│ │ ├── MoreText.vue
│ │ ├── SongListItem.vue
│ │ └── Title.vue
│ └── layout
│ │ ├── footer
│ │ ├── Footer.vue
│ │ ├── PlayerAction.vue
│ │ ├── PlayerController.vue
│ │ ├── PlayerSlider.vue
│ │ ├── PlayerSong.vue
│ │ └── PlayerVolumeSlider.vue
│ │ ├── header
│ │ ├── Header.vue
│ │ ├── SearchPop.vue
│ │ ├── SearchSuggest.vue
│ │ └── UserInfo.vue
│ │ ├── menu
│ │ ├── Menu.vue
│ │ ├── MenuList.vue
│ │ └── useMenu.ts
│ │ └── playList
│ │ ├── PlayList.vue
│ │ └── PlayListSongItem.vue
├── main.ts
├── models
│ ├── album.ts
│ ├── artist.ts
│ ├── artist_detail.ts
│ ├── banner.ts
│ ├── dj.ts
│ ├── mv.ts
│ ├── personalized.ts
│ ├── playlist.ts
│ ├── playlist_cat.ts
│ ├── playlist_hot.ts
│ ├── search.ts
│ ├── song.ts
│ ├── song_url.ts
│ ├── toplist_detail.ts
│ ├── user.ts
│ └── video.ts
├── router
│ ├── index.ts
│ └── pages.ts
├── stores
│ ├── common.ts
│ ├── dj.ts
│ ├── host.ts
│ ├── music.ts
│ ├── personalized.ts
│ ├── player.ts
│ ├── search.ts
│ ├── user.ts
│ └── video.ts
├── utils
│ ├── api.ts
│ ├── extend.ts
│ ├── http.ts
│ └── number.ts
└── views
│ ├── Root.vue
│ ├── album
│ ├── Album.vue
│ └── Info.vue
│ ├── artist
│ ├── Album.vue
│ ├── ArtistDetail.vue
│ ├── Desc.vue
│ ├── Info.vue
│ ├── Songs.vue
│ └── Video.vue
│ ├── discover
│ ├── Discover.vue
│ ├── DjProgram.vue
│ ├── Mv.vue
│ ├── Personalized.vue
│ └── PersonalizedNewSong.vue
│ ├── dj
│ └── DJ.vue
│ ├── music
│ ├── Music.vue
│ ├── MusicController.ts
│ ├── artist
│ │ └── Artist.vue
│ ├── category
│ │ ├── Category.vue
│ │ ├── PlaylistHighqualityTags.vue
│ │ └── PlaylistHot.vue
│ ├── picked
│ │ ├── Picked.vue
│ │ └── Video.vue
│ └── toplist
│ │ └── TopList.vue
│ ├── mv
│ └── mvDetail.vue
│ ├── playlist
│ ├── Info.vue
│ ├── PlayList.vue
│ └── SongList.vue
│ └── video
│ └── Video.vue
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.vite-config.json
├── ui
├── image-20220310123410770.png
├── image-20220310123456071.png
├── image-20220310123530635.png
├── image-20220310123545606.png
├── image-20220310123634367.png
├── image-20220310123650090.png
├── image-20220310123711552.png
├── image-20220310123718015.png
├── image-20220310123722684.png
└── image-20220310123738142.png
├── vite.config.ts
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | .DS_Store
12 | dist
13 | dist-ssr
14 | coverage
15 | *.local
16 |
17 | /cypress/videos/
18 | /cypress/screenshots/
19 |
20 | # Editor directories and files
21 | .vscode
22 | !.vscode/extensions.json
23 | .idea
24 | *.suo
25 | *.ntvs*
26 | *.njsproj
27 | *.sln
28 | *.sw?
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # VUE3-MUSIC
4 |
5 | 基于 VUE3+TS 开发的音乐播放器,界面模仿QQ音乐mac客户端。
6 |
7 | 在线体验:[https://smallruraldog.github.io/vue3-music](https://smallruraldog.github.io/vue3-music)
8 |
9 | 将浏览器大小设置成1050*670,体验效果更好!界面是自适应的,使用[tailwindcss.com](https://www.tailwindcss.com)来实现
10 |
11 | 手机端未适配,后期会使用[Flutter](https://flutter.dev)单独开发手机客户端,使用[Electron](https://www.electronjs.org)打包桌面客户端并内置API服务
12 |
13 | 在线演示为了安全考虑,不提供API接口服务,需要准备好自己的API服务地址,并且是HTTPS的,没有HTTPS的服务,可以本地运行,首次打开时会要求设置API地址
14 |
15 |
16 | ## 本地安装
17 |
18 | ```
19 | git clone https://github.com/SmallRuralDog/vue3-music.git
20 | cd vue3-music
21 | yarn
22 | yarn run dev
23 | ```
24 |
25 | ## 网易云音乐API
26 |
27 | 需要运行API服务才能正常体验
28 |
29 | [开发文档](https://binaryify.github.io/NeteaseCloudMusicApi)
30 |
31 |
32 | ## UI
33 |
34 |
35 |
36 | 
37 |
38 | 
39 |
40 | 
41 |
42 | 
43 |
44 | 
45 |
46 | 
47 |
48 | 
49 |
50 | 
51 |
52 | ## PS
53 |
54 | 通过此开源项目学习VUE3的强大..加油!
55 |
--------------------------------------------------------------------------------
/auto-imports.d.ts:
--------------------------------------------------------------------------------
1 | // Generated by 'unplugin-auto-import'
2 | // We suggest you to commit this file into source control
3 | declare global {
4 |
5 | }
6 | export {}
7 |
--------------------------------------------------------------------------------
/components.d.ts:
--------------------------------------------------------------------------------
1 | // generated by unplugin-vue-components
2 | // We suggest you to commit this file into source control
3 | // Read more: https://github.com/vuejs/vue-next/pull/3399
4 |
5 | declare module 'vue' {
6 | export interface GlobalComponents {
7 | Banner: typeof import('./src/components/common/Banner.vue')['default']
8 | CoverPlay: typeof import('./src/components/common/CoverPlay.vue')['default']
9 | ElAffix: typeof import('element-plus/es')['ElAffix']
10 | ElAlert: typeof import('element-plus/es')['ElAlert']
11 | ElAvatar: typeof import('element-plus/es')['ElAvatar']
12 | ElBadge: typeof import('element-plus/es')['ElBadge']
13 | ElButton: typeof import('element-plus/es')['ElButton']
14 | ElDialog: typeof import('element-plus/es')['ElDialog']
15 | ElDrawer: typeof import('element-plus/es')['ElDrawer']
16 | ElEmpty: typeof import('element-plus/es')['ElEmpty']
17 | ElImage: typeof import('element-plus/es')['ElImage']
18 | ElInput: typeof import('element-plus/es')['ElInput']
19 | ElPopover: typeof import('element-plus/es')['ElPopover']
20 | ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
21 | ElSlider: typeof import('element-plus/es')['ElSlider']
22 | ElSpace: typeof import('element-plus/es')['ElSpace']
23 | ElTabPane: typeof import('element-plus/es')['ElTabPane']
24 | ElTabs: typeof import('element-plus/es')['ElTabs']
25 | Footer: typeof import('./src/components/layout/footer/Footer.vue')['default']
26 | Header: typeof import('./src/components/layout/header/Header.vue')['default']
27 | IconPark: typeof import('./src/components/common/IconPark.vue')['default']
28 | Loading: typeof import('element-plus/es')['ElLoadingDirective']
29 | Menu: typeof import('./src/components/layout/menu/Menu.vue')['default']
30 | MenuList: typeof import('./src/components/layout/menu/MenuList.vue')['default']
31 | MoreText: typeof import('./src/components/common/MoreText.vue')['default']
32 | PlayerAction: typeof import('./src/components/layout/footer/PlayerAction.vue')['default']
33 | PlayerController: typeof import('./src/components/layout/footer/PlayerController.vue')['default']
34 | PlayerSlider: typeof import('./src/components/layout/footer/PlayerSlider.vue')['default']
35 | PlayerSong: typeof import('./src/components/layout/footer/PlayerSong.vue')['default']
36 | PlayerVolumeSlider: typeof import('./src/components/layout/footer/PlayerVolumeSlider.vue')['default']
37 | PlayList: typeof import('./src/components/layout/playList/PlayList.vue')['default']
38 | PlayListSongItem: typeof import('./src/components/layout/playList/PlayListSongItem.vue')['default']
39 | SearchPop: typeof import('./src/components/layout/header/SearchPop.vue')['default']
40 | SearchSuggest: typeof import('./src/components/layout/header/SearchSuggest.vue')['default']
41 | SongListItem: typeof import('./src/components/common/SongListItem.vue')['default']
42 | Title: typeof import('./src/components/common/Title.vue')['default']
43 | UserInfo: typeof import('./src/components/layout/header/UserInfo.vue')['default']
44 | }
45 | }
46 |
47 | export { }
48 |
--------------------------------------------------------------------------------
/docs/assets/Album.402a1341.js:
--------------------------------------------------------------------------------
1 | import{c as p,g as u,h as f,i as e,H as i,j as s,u as r,D as m,C as g,o as w,$ as B,a0 as C,k as d,l as k,I as E,G as F,q as L}from"./vendor.9760fa8a.js";/* empty css */import{A as $}from"./index.373df683.js";import{_}from"./IconPark.402beefe.js";import{P as V}from"./PlayOne.e72f474c.js";import{L as j}from"./PlayTwo.fe71fa6d.js";import{M as z,S as D}from"./SongListItem.f4bd4734.js";import"./plugin-vue_export-helper.21dcd24c.js";const M={class:"flex items-stretch"},T=["src"],A={class:"pl-5 flex flex-col justify-between py-1 flex-1"},N={class:"flex flex-col justify-between flex-1"},H={class:"text-2xl font-bold"},P={class:"flex items-center text-xs text-gray-600"},S={class:""},q={class:"text-xs text-gray-500 leading-normal"},I={class:"justify-self-stretch mt-5 gap-x-2 flex items-center"},U={class:"w-32 button"},G=e("span",null,"\u64AD\u653E\u5168\u90E8",-1),O={class:"w-32 button-outline"},R=e("span",null,"\u6536\u85CF",-1),J={class:"button-outline w-8"},K=p({props:{album:null},setup(a){return(l,o)=>(u(),f("div",M,[e("img",{src:a.album.picUrl,alt:"",class:"w-44 h-44 object-cover rounded-xl flex-shrink-0"},null,8,T),e("div",A,[e("div",N,[e("div",H,i(a.album.name),1),e("div",P,[e("span",S,i(a.album.artist.name),1)]),e("div",q,i(a.album.publishTime.toDate()),1)]),e("div",I,[e("button",U,[s(_,{icon:r(V),size:"22",class:"mr-1"},null,8,["icon"]),G]),e("button",O,[s(_,{icon:r(j),size:"18",class:"mr-1"},null,8,["icon"]),R]),e("button",J,[s(_,{icon:r(z)},null,8,["icon"])])])])]))}}),Q={key:0,class:"p-5"},W=e("div",{class:"flex text-xs text-gray-400 py-2"},[e("div",{class:"flex-auto"},"\u6B4C\u66F2"),e("div",{class:"w-1/3"},"\u6B4C\u624B"),e("div",{class:"w-20"},"\u65F6\u957F")],-1),X=["innerHTML"],ne=p({setup(a){const l=m(),o=m([]),x=m("songs"),h=g(),v=Number(h.query.id);return w(async()=>{const{album:b,songs:n}=await $(v);l.value=b,o.value=n}),(b,n)=>{const c=B,y=C;return l.value?(u(),f("div",Q,[s(K,{album:l.value},null,8,["album"]),s(y,{class:"mt-3",modelValue:x.value,"onUpdate:modelValue":n[0]||(n[0]=t=>x.value=t)},{default:d(()=>[s(c,{lazy:"",label:`\u6B4C\u66F2 ${o.value.length}`,name:"songs"},{default:d(()=>[W,(u(!0),f(E,null,F(o.value,t=>(u(),L(D,{key:t.id,song:t,"show-ar-name":""},null,8,["song"]))),128))]),_:1},8,["label"]),s(c,{lazy:"",label:"\u8BC4\u8BBA",name:"comments"}),s(c,{lazy:"",label:"\u4E13\u8F91\u8BE6\u60C5",name:"desc"},{default:d(()=>{var t;return[e("div",{class:"text-xs text-slate-500 leading-7",style:{"white-space":"pre-wrap"},innerHTML:(t=l.value)==null?void 0:t.description},null,8,X)]}),_:1})]),_:1},8,["modelValue"])])):k("",!0)}}});export{ne as default};
2 |
--------------------------------------------------------------------------------
/docs/assets/Artist.0d846367.js:
--------------------------------------------------------------------------------
1 | import{c as B,V as D,a2 as F,F as w,D as A,r as b,o as S,a3 as j,n as q,g as i,h as l,i as s,I as r,G as m,j as d,u as o,k as _,H as k,J as z,m as I}from"./vendor.9760fa8a.js";import{p as L}from"./index.373df683.js";import{_ as M}from"./plugin-vue_export-helper.21dcd24c.js";const G={class:"pb-5"},H={class:"flex-shrink-0 text-slate-400"},J={class:"ml-3"},R=["onClick"],T={class:"grid grid-flow-row grid-cols-6 xl:grid-cols-8 2xl:grid-cols-10 gap-5"},U=["onClick"],V=["src"],$={class:"mt-2 text-sm"},K={class:"py-10"},N=I("\u52A0\u8F7D\u66F4\u591A"),O=B({setup(P){const p=D(F,{direction:"vertical"}),g=w(),u=A([]),e=b({init:!1,loading:!1,page:1,limit:60,initial:"-1",type:-1,area:-1}),y=async()=>{e.loading=!0;try{const t=await L(e);e.page===1?u.value=t:u.value.push(...t),e.init=!0,e.loading=!1}catch{e.page--}},v=()=>{e.page++,y()};S(y);const f=(t,c)=>{console.log(t,c),e.page=1,t==="type"&&(e.type=c),t==="area"&&(e.area=c),t==="initial"&&(e.initial=c),y()},x=[{name:"\u8BED\u79CD",key:"area",list:[{key:-1,name:"\u5168\u90E8"},{key:7,name:"\u534E\u8BED"},{key:96,name:"\u6B27\u7F8E"},{key:8,name:"\u65E5\u672C"},{key:16,name:"\u97E9\u56FD"},{key:0,name:"\u5176\u4ED6"}]},{name:"\u5206\u7C7B",key:"type",list:[{key:-1,name:"\u5168\u90E8"},{key:1,name:"\u7537\u6B4C\u624B"},{key:2,name:"\u5973\u6B4C\u624B"},{key:3,name:"\u4E50\u961F\u7EC4\u5408"}]},{name:"\u7B5B\u9009",key:"initial",list:[{key:"-1",name:"\u70ED\u95E8"},{key:"a",name:"A"},{key:"b",name:"B"},{key:"c",name:"C"},{key:"d",name:"D"},{key:"e",name:"E"},{key:"f",name:"F"},{key:"g",name:"G"},{key:"h",name:"H"},{key:"i",name:"I"},{key:"j",name:"J"},{key:"k",name:"K"},{key:"l",name:"L"},{key:"m",name:"M"},{key:"n",name:"N"},{key:"o",name:"O"},{key:"p",name:"P"},{key:"q",name:"Q"},{key:"r",name:"R"},{key:"s",name:"S"},{key:"t",name:"T"},{key:"u",name:"U"},{key:"v",name:"V"},{key:"w",name:"W"},{key:"x",name:"X"},{key:"y",name:"Y"},{key:"z",name:"Z"},{key:"0",name:"#"}]}];return(t,c)=>{const h=j,E=q;return i(),l(r,null,[s("div",G,[(i(),l(r,null,m(x,a=>s("div",{key:a.key,class:"flex text-xs mb-5"},[s("div",H,k(a.name)+"\uFF1A",1),s("div",J,[d(h,{wrap:"",size:10,spacer:o(p)},{default:_(()=>[(i(!0),l(r,null,m(a.list,(n,C)=>(i(),l("div",{type:"text",class:z(["hover-text px-1 py-0.5",{active:n.key===o(e).type&&a.key==="type"||n.key===o(e).area&&a.key==="area"||n.key===o(e).initial&&a.key==="initial"}]),key:C,onClick:Q=>f(a.key,n.key)},k(n.name),11,R))),128))]),_:2},1032,["spacer"])])])),64))]),s("div",T,[(i(!0),l(r,null,m(u.value,a=>(i(),l("div",{key:a.id,class:"flex items-center flex-col",onClick:n=>o(g).push({name:"artistDetail",query:{id:a.id}})},[s("img",{src:a.img1v1Url+"?param=120y120",alt:"",class:"rounded-full cursor-pointer w-full aspect-square object-cover bg-dc"},null,8,V),s("div",$,k(a.name),1)],8,U))),128))]),s("div",K,[d(E,{type:"text",class:"text-center w-full",onClick:v,loading:o(e).loading},{default:_(()=>[N]),_:1},8,["loading"])])],64)}}});var Z=M(O,[["__scopeId","data-v-1cc54718"]]);export{Z as default};
2 |
--------------------------------------------------------------------------------
/docs/assets/Artist.dfdd0cc6.css:
--------------------------------------------------------------------------------
1 | .el-space{display:inline-flex;vertical-align:top}.el-space__item{display:flex;flex-wrap:wrap}.el-space__item>*{flex:1}.el-space--vertical{flex-direction:column}.active[data-v-1cc54718]{border-radius:.25rem;--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}
2 |
--------------------------------------------------------------------------------
/docs/assets/ArtistDetail.3bc343f2.css:
--------------------------------------------------------------------------------
1 | :root{--el-loading-spinner-size:42px;--el-loading-fullscreen-spinner-size:50px}.el-loading-parent--relative{position:relative!important}.el-loading-parent--hidden{overflow:hidden!important}.el-loading-mask{position:absolute;z-index:2000;background-color:#ffffffe6;margin:0;top:0;right:0;bottom:0;left:0;transition:opacity var(--el-transition-duration)}.el-loading-mask.is-fullscreen{position:fixed}.el-loading-mask.is-fullscreen .el-loading-spinner{margin-top:calc((0px - var(--el-loading-fullscreen-spinner-size))/ 2)}.el-loading-mask.is-fullscreen .el-loading-spinner .circular{height:var(--el-loading-fullscreen-spinner-size);width:var(--el-loading-fullscreen-spinner-size)}.el-loading-spinner{top:50%;margin-top:calc((0px - var(--el-loading-spinner-size))/ 2);width:100%;text-align:center;position:absolute}.el-loading-spinner .el-loading-text{color:var(--el-color-primary);margin:3px 0;font-size:14px}.el-loading-spinner .circular{display:inline;height:var(--el-loading-spinner-size);width:var(--el-loading-spinner-size);animation:loading-rotate 2s linear infinite}.el-loading-spinner .path{animation:loading-dash 1.5s ease-in-out infinite;stroke-dasharray:90,150;stroke-dashoffset:0;stroke-width:2;stroke:var(--el-color-primary);stroke-linecap:round}.el-loading-spinner i{color:var(--el-color-primary)}.el-loading-fade-enter-from,.el-loading-fade-leave-to{opacity:0}@keyframes loading-rotate{to{transform:rotate(360deg)}}@keyframes loading-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40px}to{stroke-dasharray:90,150;stroke-dashoffset:-120px}}.el-empty{--el-empty-padding:40px 0;--el-empty-image-width:160px;--el-empty-description-margin-top:20px;--el-empty-bottom-margin-top:20px;--el-empty-fill-color-0:var(--el-color-white);--el-empty-fill-color-1:#fcfcfd;--el-empty-fill-color-2:#f8f9fb;--el-empty-fill-color-3:#f7f8fc;--el-empty-fill-color-4:#eeeff3;--el-empty-fill-color-5:#edeef2;--el-empty-fill-color-6:#e9ebef;--el-empty-fill-color-7:#e5e7e9;--el-empty-fill-color-8:#e0e3e9;--el-empty-fill-color-9:#d5d7de;display:flex;justify-content:center;align-items:center;flex-direction:column;text-align:center;box-sizing:border-box;padding:var(--el-empty-padding)}.el-empty__image{width:var(--el-empty-image-width)}.el-empty__image img{-webkit-user-select:none;user-select:none;width:100%;height:100%;vertical-align:top;object-fit:contain}.el-empty__image svg{fill:var(--el-svg-monochrome-grey);width:100%;height:100%;vertical-align:top}.el-empty__description{margin-top:var(--el-empty-description-margin-top)}.el-empty__description p{margin:0;font-size:var(--el-font-size-base);color:var(--el-text-color-secondary)}.el-empty__bottom{margin-top:var(--el-empty-bottom-margin-top)}.artist-detail .el-tabs__nav-wrap:after{height:0}.artist-detail .el-tabs__header{margin:0}
2 |
--------------------------------------------------------------------------------
/docs/assets/Category.0252e828.js:
--------------------------------------------------------------------------------
1 | import{c as v,F as h,D as x,o as C,g as a,h as s,i as r,I as f,G as k,H as m,r as w,n as $,j as g,u as c,k as B,l as D,J as E,m as P}from"./vendor.9760fa8a.js";import{q,r as F,P as H}from"./index.373df683.js";import{_ as N}from"./CoverPlay.d639e45b.js";import"./el-image-viewer.a8b12883.js";import"./IconPark.402beefe.js";import"./PlayOne.e72f474c.js";const V={class:"grid grid-flow-row grid-cols-8 2xl:grid-cols-12 gap-2.5"},T=["onClick"],A=v({emits:["catChange"],setup(b,{emit:i}){const u=d=>{i("catChange",d)};h();const t=x();return C(async()=>{t.value=await q()}),(d,o)=>(a(),s("div",V,[r("div",{class:"button-dc",onClick:o[0]||(o[0]=n=>u("\u5168\u90E8"))},"\u5168\u90E8"),(a(!0),s(f,null,k(t.value,n=>(a(),s("div",{key:n.id,class:"button-dc",onClick:l=>u(n.name)},m(n.name),9,T))),128))]))}}),I={class:"py-5 text-xl"},M={class:"gap-5 grid grid-flow-row grid-cols-3 lg:grid-cols-5 2xl:grid-cols-7"},j=["onClick"],z={class:"mt-2 text-xs text-main leading-5"},G={class:"mt-2 text-xs text-main truncate text-dc"},J={key:0,class:"py-10"},L=P("\u52A0\u8F7D\u66F4\u591A"),X=v({setup(b){const i=x(),u=h(),t=w({init:!1,loading:!1,limit:35,before:0,more:!1,cat:"\u5168\u90E8"}),d=l=>{t.cat=l,t.before=0,t.more=!1,o()},o=async()=>{var l;t.loading=!0;try{const{playlists:_,lasttime:p,more:e}=await F({limit:t.limit,before:t.before,cat:t.cat});t.before<=0?i.value=_:(l=i.value)==null||l.push(..._),t.init=!0,t.loading=!1,t.before=p,t.more=e}catch{}},n=()=>{o()};return C(o),(l,_)=>{const p=$;return a(),s(f,null,[g(A,{onCatChange:d}),r("div",I,m(c(t).cat)+"\u6B4C\u5355",1),r("div",M,[(a(!0),s(f,null,k(i.value,(e,y)=>(a(),s("div",{key:y,class:E({"item-1":y===0}),onClick:R=>c(u).push({name:c(H).playlist,query:{id:e.id}})},[g(N,{name:e.name,"pic-url":e.coverImgUrl,"play-count":e.playCount,"show-play-count":""},null,8,["name","pic-url","play-count"]),r("div",z,m(e.name),1),r("div",G,m(e.creator.nickname),1)],10,j))),128))]),c(t).more?(a(),s("div",J,[g(p,{type:"text",class:"text-center w-full",onClick:n,loading:c(t).loading},{default:B(()=>[L]),_:1},8,["loading"])])):D("",!0)],64)}}});export{X as default};
2 |
--------------------------------------------------------------------------------
/docs/assets/CoverPlay.33350ebd.css:
--------------------------------------------------------------------------------
1 | .cover-play-image{position:relative;cursor:pointer;overflow:hidden;border-radius:.5rem;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.cover-play-image:hover{--tw-translate-y: -.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cover-play-image .mask{position:absolute;top:0px;right:0px;bottom:0px;left:0px;background-color:rgb(0 0 0 / var(--tw-bg-opacity));--tw-bg-opacity: 0;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.5s}.cover-play-image .play-count{position:absolute;bottom:.25rem;right:.25rem;display:flex;--tw-scale-x: .9;--tw-scale-y: .9;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));align-items:center;border-radius:9999px;background-color:rgb(0 0 0 / var(--tw-bg-opacity));--tw-bg-opacity: .8;padding:.125rem .5rem;font-size:.75rem;line-height:1rem;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity));transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.cover-play-image:hover .mask{--tw-bg-opacity: .5 }.cover-play-image:hover .mask .play-icon{opacity:1}.cover-play-image:hover .play-count{opacity:0}
2 |
--------------------------------------------------------------------------------
/docs/assets/CoverPlay.d639e45b.js:
--------------------------------------------------------------------------------
1 | import{j as t,c,R as r,g as o,h as a,i as n,u as l,H as u,l as d,J as m}from"./vendor.9760fa8a.js";import{P as h}from"./el-image-viewer.a8b12883.js";import{g as k}from"./index.373df683.js";import{I as y,_ as i}from"./IconPark.402beefe.js";import{P as f}from"./PlayOne.e72f474c.js";var C=y("headset",!1,function(e){return t("svg",{width:e.size,height:e.size,viewBox:"0 0 48 48",fill:"none"},[t("path",{d:"M42 30V24.4615C42 14.2655 33.9411 6 24 6C14.0589 6 6 14.2655 6 24.4615V30",stroke:e.colors[0],"stroke-width":e.strokeWidth,"stroke-linecap":e.strokeLinecap,"stroke-linejoin":e.strokeLinejoin},null),t("path",{d:"M34 32C34 29.7909 35.7909 28 38 28H42V42H38C35.7909 42 34 40.2091 34 38V32Z",fill:e.colors[1],stroke:e.colors[0],"stroke-width":e.strokeWidth,"stroke-linejoin":e.strokeLinejoin},null),t("path",{d:"M42 32H44C45.1046 32 46 32.8954 46 34V36C46 37.1046 45.1046 38 44 38H42V32Z",fill:e.colors[0]},null),t("path",{d:"M6 32H4C2.89543 32 2 32.8954 2 34V36C2 37.1046 2.89543 38 4 38H6V32Z",fill:e.colors[0]},null),t("path",{d:"M6 28H10C12.2091 28 14 29.7909 14 32V38C14 40.2091 12.2091 42 10 42H6V28Z",fill:e.colors[1],stroke:e.colors[0],"stroke-width":e.strokeWidth,"stroke-linejoin":e.strokeLinejoin},null)])});const v={class:"mask flex justify-center items-center"},V={key:0,class:"play-count"},B=c({props:{picUrl:null,playCount:null,name:null,showPlayCount:{type:Boolean},onPlay:null,video:{type:Boolean}},setup(e){return(g,H)=>{const s=r;return o(),a("div",{class:m(["cover-play-image",{"aspect-square":!e.video,"aspect-video":e.video}])},[t(s,{src:e.picUrl,alt:e.name,class:"w-full bg-gray-50 object-cover"},null,8,["src","alt"]),n("div",v,[t(i,{icon:l(f),theme:"filled",class:"text-white play-icon opacity-0 transition-opacity hover:text-teal-400",size:50,onClick:e.onPlay},null,8,["icon","onClick"])]),e.showPlayCount?(o(),a("div",V,[t(i,{icon:e.video?l(h):l(C),class:"mr-1",size:12},null,8,["icon"]),n("text",null,u(l(k)(e.playCount||0)),1)])):d("",!0)],2)}}});export{B as _};
2 |
--------------------------------------------------------------------------------
/docs/assets/DJ.e0f4dc6a.js:
--------------------------------------------------------------------------------
1 | import{_ as r}from"./plugin-vue_export-helper.21dcd24c.js";const e={};function _(c,n){return null}var a=r(e,[["render",_]]);export{a as default};
2 |
--------------------------------------------------------------------------------
/docs/assets/Discover.38e1e773.js:
--------------------------------------------------------------------------------
1 | import{c as d,F as f,t as g,o as x,g as o,h as n,j as e,i as t,I as p,G as h,J as k,u as i,H as _}from"./vendor.9760fa8a.js";import{_ as v,B as C,a as B}from"./Mv.34913284.js";import{_ as z}from"./CoverPlay.d639e45b.js";import{u as l}from"./music.991378cb.js";import{c as S}from"./index.373df683.js";import"./plugin-vue_export-helper.21dcd24c.js";import"./IconPark.402beefe.js";import"./Right.083d6647.js";import"./video.3500c715.js";import"./el-image-viewer.a8b12883.js";import"./PlayOne.e72f474c.js";const b={class:"grid grid-flow-row grid-cols-3 lg:grid-cols-5 gap-5 2xl:grid-cols-10"},E=["onClick"],F={class:"mt-2 text-xs text-main truncate"},N=d({setup(m){const r=f(),{personalized:a}=g(l()),{getPersonalized:u}=l();return x(async()=>{u()}),(y,$)=>(o(),n("div",null,[e(v,{title:"\u4F60\u7684\u4E13\u5C5E\u6B4C\u5355"}),t("div",b,[(o(!0),n(p,null,h(i(a).sampleSize(10),(s,c)=>(o(),n("div",{key:c,class:k({"item-1":c===0}),onClick:w=>i(r).push({name:"playlist",query:{id:s.id}})},[e(z,{name:s.name,"pic-url":s.picUrl,"play-count":s.playCount,"show-play-count":""},null,8,["name","pic-url","play-count"]),t("div",F,_(s.name),1)],10,E))),128))])]))}}),P={class:"grid grid-flow-row grid-cols-2 2xl:grid-cols-5 gap-y-2.5 gap-x-5 cursor-pointer"},j=["onClick"],A=["src"],M={class:"px-2 text-xs flex-auto flex flex-col w-1/3"},R={class:"text-xs flex-1 truncate"},U={class:"mt-1.5 text-dc"},V=d({setup(m){const{play:r}=S();f();const{personalizedNewSong:a}=g(l()),{getPersonalizedNewSong:u}=l();return x(async()=>{await u()}),(y,$)=>(o(),n(p,null,[e(v,{title:"\u63A8\u8350\u65B0\u97F3\u4E50"}),t("div",P,[(o(!0),n(p,null,h(i(a),(s,c)=>(o(),n("div",{key:c,class:"hover-bg-view transition-all flex items-center",onClick:w=>i(r)(s.id)},[t("img",{src:s.picUrl,alt:"",class:"w-12 h-12 object-cover rounded flex-shrink-0"},null,8,A),t("div",M,[t("div",R,_(s.name),1),t("div",U,_(s.song.artists[0].name),1)])],8,j))),128))])],64))}}),q={class:"px-5"},D=t("h1",{class:"text-3xl font-bold pt-8 pb-4"},"\u63A8\u8350",-1),Y=d({setup(m){return(r,a)=>(o(),n("div",q,[D,e(C,{"per-page":3}),e(N),e(V),e(B)]))}});export{Y as default};
2 |
--------------------------------------------------------------------------------
/docs/assets/Fm.46f05eb0.js:
--------------------------------------------------------------------------------
1 | import{I as i}from"./IconPark.402beefe.js";import{j as t}from"./vendor.9760fa8a.js";var l=i("fm",!1,function(e){return t("svg",{width:e.size,height:e.size,viewBox:"0 0 48 48",fill:"none"},[t("circle",{cx:"24",cy:"22",r:"4",fill:e.colors[1],stroke:e.colors[0],"stroke-width":e.strokeWidth,"stroke-linecap":e.strokeLinecap,"stroke-linejoin":e.strokeLinejoin},null),t("path",{d:"M21.5238 33.0539C22.7619 31.6487 25.2381 31.6486 26.4762 33.0539C27.7143 34.4592 26.4763 43.3608 25.6508 44.2975C24.8254 45.2342 23.1746 45.2342 22.3492 44.2975C21.5238 43.3608 20.2857 34.4591 21.5238 33.0539Z",fill:e.colors[1],stroke:e.colors[0],"stroke-width":e.strokeWidth,"stroke-linecap":e.strokeLinecap,"stroke-linejoin":e.strokeLinejoin},null),t("path",{d:"M30.9668 30.513C33.4289 28.4957 35 25.4313 35 22C35 15.9249 30.0751 11 24 11C17.9249 11 13 15.9249 13 22C13 25.4313 14.5711 28.4957 17.0332 30.513",stroke:e.colors[0],"stroke-width":e.strokeWidth,"stroke-linecap":e.strokeLinecap,"stroke-linejoin":e.strokeLinejoin},null),t("path",{d:"M31.9258 38.1656C37.8928 35.2345 42 29.0969 42 22C42 12.0589 33.9411 4 24 4C14.0589 4 6 12.0589 6 22C6 29.0969 10.1072 35.2345 16.0742 38.1656",stroke:e.colors[0],"stroke-width":e.strokeWidth,"stroke-linecap":e.strokeLinecap,"stroke-linejoin":e.strokeLinejoin},null)])});export{l as F};
2 |
--------------------------------------------------------------------------------
/docs/assets/IconPark.402beefe.js:
--------------------------------------------------------------------------------
1 | import{T as F,j as L,c as d,g as y,q as j,U as v}from"./vendor.9760fa8a.js";var W={size:"1em",strokeWidth:4,strokeLinecap:"round",strokeLinejoin:"round",rtl:!1,theme:"outline",colors:{outline:{fill:"#333",background:"transparent"},filled:{fill:"#333",background:"#FFF"},twoTone:{fill:"#333",twoTone:"#2F88FF"},multiColor:{outStrokeColor:"#333",outFillColor:"#2F88FF",innerStrokeColor:"#FFF",innerFillColor:"#43CCF8"}},prefix:"i"};function z(){return"icon-"+((1+Math.random())*4294967296|0).toString(16).substring(1)}function g(t,i,r){var e=typeof i.fill=="string"?[i.fill]:i.fill||[],o=[],n=i.theme||r.theme;switch(n){case"outline":o.push(typeof e[0]=="string"?e[0]:"currentColor"),o.push("none"),o.push(typeof e[0]=="string"?e[0]:"currentColor"),o.push("none");break;case"filled":o.push(typeof e[0]=="string"?e[0]:"currentColor"),o.push(typeof e[0]=="string"?e[0]:"currentColor"),o.push("#FFF"),o.push("#FFF");break;case"two-tone":o.push(typeof e[0]=="string"?e[0]:"currentColor"),o.push(typeof e[1]=="string"?e[1]:r.colors.twoTone.twoTone),o.push(typeof e[0]=="string"?e[0]:"currentColor"),o.push(typeof e[1]=="string"?e[1]:r.colors.twoTone.twoTone);break;case"multi-color":o.push(typeof e[0]=="string"?e[0]:"currentColor"),o.push(typeof e[1]=="string"?e[1]:r.colors.multiColor.outFillColor),o.push(typeof e[2]=="string"?e[2]:r.colors.multiColor.innerStrokeColor),o.push(typeof e[3]=="string"?e[3]:r.colors.multiColor.innerFillColor);break}return{size:i.size||r.size,strokeWidth:i.strokeWidth||r.strokeWidth,strokeLinecap:i.strokeLinecap||r.strokeLinecap,strokeLinejoin:i.strokeLinejoin||r.strokeLinejoin,colors:o,id:t}}var x=Symbol("icon-context");function w(t,i,r){var e={name:"icon-"+t,props:["size","strokeWidth","strokeLinecap","strokeLinejoin","theme","fill","spin"],setup:function(n){var u=z(),s=F(x,W);return function(){var a=n.size,c=n.strokeWidth,p=n.strokeLinecap,k=n.strokeLinejoin,h=n.theme,f=n.fill,C=n.spin,m=g(u,{size:a,strokeWidth:c,strokeLinecap:p,strokeLinejoin:k,theme:h,fill:f},s),l=[s.prefix+"-icon"];return l.push(s.prefix+"-icon-"+t),i&&s.rtl&&l.push(s.prefix+"-icon-rtl"),C&&l.push(s.prefix+"-icon-spin"),L("span",{class:l.join(" ")},[r(m)])}}};return e}const I=d({props:{icon:null,theme:null,size:null,spin:{type:Boolean},fill:null,strokeLinecap:null,strokeLinejoin:null,strokeWidth:null},setup(t){return(i,r)=>(y(),j(v(t.icon),{theme:t.theme,size:t.size,spin:t.spin,fill:t.fill,strokeLinecap:t.strokeLinecap,strokeLinejoin:t.strokeLinejoin,strokeWidth:t.strokeWidth},null,8,["theme","size","spin","fill","strokeLinecap","strokeLinejoin","strokeWidth"]))}});export{w as I,I as _};
2 |
--------------------------------------------------------------------------------
/docs/assets/Music.70c8366c.js:
--------------------------------------------------------------------------------
1 | import{F as C,C as k,D as v,w as x,c as B,$ as h,a0 as E,a1 as T,p as V,g as l,h as i,j as o,k as m,i as c,I as g,G as w,q as F,u,M}from"./vendor.9760fa8a.js";/* empty css */function R(){const r=[{label:"\u7CBE\u9009",name:"picked"},{label:"\u6709\u58F0\u7535\u53F0",name:"dt"},{label:"\u6392\u884C",name:"toplist"},{label:"\u6B4C\u624B",name:"artist"},{label:"\u5206\u7C7B\u6B4C\u5355",name:"category"},{label:"\u6570\u5B57\u4E13\u8F91",name:"zj"}],s=C(),e=k(),n=v(e.name);return x(()=>e.name,a=>{n.value=a}),{menus:r,currentMenu:n,onTabClick:({props:a})=>{s.push({name:a.name,replace:!0})}}}const y={class:"pl-5 pr-5 music"},j=c("h1",{class:"text-3xl font-bold pt-8 pb-4"},"\u97F3\u4E50\u9986",-1),A={class:"bg-view"},N={class:"mt-5"},D=B({setup(r){const{menus:s,currentMenu:e,onTabClick:n}=R();return(_,a)=>{const p=h,d=E,b=T,f=V("RouterView");return l(),i("div",y,[j,o(b,{target:".music",offset:56},{default:m(()=>[c("div",A,[o(d,{modelValue:u(e),"onUpdate:modelValue":a[0]||(a[0]=t=>M(e)?e.value=t:null),onTabClick:u(n)},{default:m(()=>[(l(!0),i(g,null,w(u(s),t=>(l(),F(p,{key:t.name,label:t.label,name:t.name,class:"text-main"},null,8,["label","name"]))),128))]),_:1},8,["modelValue","onTabClick"])])]),_:1}),c("div",N,[o(f)])])}}});export{D as default};
2 |
--------------------------------------------------------------------------------
/docs/assets/Music.e9b17b81.css:
--------------------------------------------------------------------------------
1 | .el-affix--fixed{position:fixed}.music .el-tabs__nav-wrap:after{height:0}.music .el-tabs__header{margin:0}
2 |
--------------------------------------------------------------------------------
/docs/assets/Mv.8cac6744.css:
--------------------------------------------------------------------------------
1 | @font-face{font-family:swiper-icons;src:url(data:application/font-woff;charset=utf-8;base64,\ d09GRgABAAAAAAZgABAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAAGRAAAABoAAAAci6qHkUdERUYAAAWgAAAAIwAAACQAYABXR1BPUwAABhQAAAAuAAAANuAY7+xHU1VCAAAFxAAAAFAAAABm2fPczU9TLzIAAAHcAAAASgAAAGBP9V5RY21hcAAAAkQAAACIAAABYt6F0cBjdnQgAAACzAAAAAQAAAAEABEBRGdhc3AAAAWYAAAACAAAAAj//wADZ2x5ZgAAAywAAADMAAAD2MHtryVoZWFkAAABbAAAADAAAAA2E2+eoWhoZWEAAAGcAAAAHwAAACQC9gDzaG10eAAAAigAAAAZAAAArgJkABFsb2NhAAAC0AAAAFoAAABaFQAUGG1heHAAAAG8AAAAHwAAACAAcABAbmFtZQAAA/gAAAE5AAACXvFdBwlwb3N0AAAFNAAAAGIAAACE5s74hXjaY2BkYGAAYpf5Hu/j+W2+MnAzMYDAzaX6QjD6/4//Bxj5GA8AuRwMYGkAPywL13jaY2BkYGA88P8Agx4j+/8fQDYfA1AEBWgDAIB2BOoAeNpjYGRgYNBh4GdgYgABEMnIABJzYNADCQAACWgAsQB42mNgYfzCOIGBlYGB0YcxjYGBwR1Kf2WQZGhhYGBiYGVmgAFGBiQQkOaawtDAoMBQxXjg/wEGPcYDDA4wNUA2CCgwsAAAO4EL6gAAeNpj2M0gyAACqxgGNWBkZ2D4/wMA+xkDdgAAAHjaY2BgYGaAYBkGRgYQiAHyGMF8FgYHIM3DwMHABGQrMOgyWDLEM1T9/w8UBfEMgLzE////P/5//f/V/xv+r4eaAAeMbAxwIUYmIMHEgKYAYjUcsDAwsLKxc3BycfPw8jEQA/gZBASFhEVExcQlJKWkZWTl5BUUlZRVVNXUNTQZBgMAAMR+E+gAEQFEAAAAKgAqACoANAA+AEgAUgBcAGYAcAB6AIQAjgCYAKIArAC2AMAAygDUAN4A6ADyAPwBBgEQARoBJAEuATgBQgFMAVYBYAFqAXQBfgGIAZIBnAGmAbIBzgHsAAB42u2NMQ6CUAyGW568x9AneYYgm4MJbhKFaExIOAVX8ApewSt4Bic4AfeAid3VOBixDxfPYEza5O+Xfi04YADggiUIULCuEJK8VhO4bSvpdnktHI5QCYtdi2sl8ZnXaHlqUrNKzdKcT8cjlq+rwZSvIVczNiezsfnP/uznmfPFBNODM2K7MTQ45YEAZqGP81AmGGcF3iPqOop0r1SPTaTbVkfUe4HXj97wYE+yNwWYxwWu4v1ugWHgo3S1XdZEVqWM7ET0cfnLGxWfkgR42o2PvWrDMBSFj/IHLaF0zKjRgdiVMwScNRAoWUoH78Y2icB/yIY09An6AH2Bdu/UB+yxopYshQiEvnvu0dURgDt8QeC8PDw7Fpji3fEA4z/PEJ6YOB5hKh4dj3EvXhxPqH/SKUY3rJ7srZ4FZnh1PMAtPhwP6fl2PMJMPDgeQ4rY8YT6Gzao0eAEA409DuggmTnFnOcSCiEiLMgxCiTI6Cq5DZUd3Qmp10vO0LaLTd2cjN4fOumlc7lUYbSQcZFkutRG7g6JKZKy0RmdLY680CDnEJ+UMkpFFe1RN7nxdVpXrC4aTtnaurOnYercZg2YVmLN/d/gczfEimrE/fs/bOuq29Zmn8tloORaXgZgGa78yO9/cnXm2BpaGvq25Dv9S4E9+5SIc9PqupJKhYFSSl47+Qcr1mYNAAAAeNptw0cKwkAAAMDZJA8Q7OUJvkLsPfZ6zFVERPy8qHh2YER+3i/BP83vIBLLySsoKimrqKqpa2hp6+jq6RsYGhmbmJqZSy0sraxtbO3sHRydnEMU4uR6yx7JJXveP7WrDycAAAAAAAH//wACeNpjYGRgYOABYhkgZgJCZgZNBkYGLQZtIJsFLMYAAAw3ALgAeNolizEKgDAQBCchRbC2sFER0YD6qVQiBCv/H9ezGI6Z5XBAw8CBK/m5iQQVauVbXLnOrMZv2oLdKFa8Pjuru2hJzGabmOSLzNMzvutpB3N42mNgZGBg4GKQYzBhYMxJLMlj4GBgAYow/P/PAJJhLM6sSoWKfWCAAwDAjgbRAAB42mNgYGBkAIIbCZo5IPrmUn0hGA0AO8EFTQAA);font-weight:400;font-style:normal}:root{--swiper-theme-color:#007aff}.swiper{margin-left:auto;margin-right:auto;position:relative;overflow:hidden;list-style:none;padding:0;z-index:1}.swiper-vertical>.swiper-wrapper{flex-direction:column}.swiper-wrapper{position:relative;width:100%;height:100%;z-index:1;display:flex;transition-property:transform;box-sizing:content-box}.swiper-android .swiper-slide,.swiper-wrapper{transform:translateZ(0)}.swiper-pointer-events{touch-action:pan-y}.swiper-pointer-events.swiper-vertical{touch-action:pan-x}.swiper-slide{flex-shrink:0;width:100%;height:100%;position:relative;transition-property:transform}.swiper-slide-invisible-blank{visibility:hidden}.swiper-autoheight,.swiper-autoheight .swiper-slide{height:auto}.swiper-autoheight .swiper-wrapper{align-items:flex-start;transition-property:transform,height}.swiper-backface-hidden .swiper-slide{transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden}.swiper-3d,.swiper-3d.swiper-css-mode .swiper-wrapper{perspective:1200px}.swiper-3d .swiper-cube-shadow,.swiper-3d .swiper-slide,.swiper-3d .swiper-slide-shadow,.swiper-3d .swiper-slide-shadow-bottom,.swiper-3d .swiper-slide-shadow-left,.swiper-3d .swiper-slide-shadow-right,.swiper-3d .swiper-slide-shadow-top,.swiper-3d .swiper-wrapper{transform-style:preserve-3d}.swiper-3d .swiper-slide-shadow,.swiper-3d .swiper-slide-shadow-bottom,.swiper-3d .swiper-slide-shadow-left,.swiper-3d .swiper-slide-shadow-right,.swiper-3d .swiper-slide-shadow-top{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:10}.swiper-3d .swiper-slide-shadow{background:rgba(0,0,0,.15)}.swiper-3d .swiper-slide-shadow-left{background-image:linear-gradient(to left,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-3d .swiper-slide-shadow-right{background-image:linear-gradient(to right,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-3d .swiper-slide-shadow-top{background-image:linear-gradient(to top,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-3d .swiper-slide-shadow-bottom{background-image:linear-gradient(to bottom,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-css-mode>.swiper-wrapper{overflow:auto;scrollbar-width:none;-ms-overflow-style:none}.swiper-css-mode>.swiper-wrapper::-webkit-scrollbar{display:none}.swiper-css-mode>.swiper-wrapper>.swiper-slide{scroll-snap-align:start start}.swiper-horizontal.swiper-css-mode>.swiper-wrapper{-ms-scroll-snap-type:x mandatory;scroll-snap-type:x mandatory}.swiper-vertical.swiper-css-mode>.swiper-wrapper{-ms-scroll-snap-type:y mandatory;scroll-snap-type:y mandatory}.swiper-centered>.swiper-wrapper:before{content:"";flex-shrink:0;order:9999}.swiper-centered.swiper-horizontal>.swiper-wrapper>.swiper-slide:first-child{-webkit-margin-start:var(--swiper-centered-offset-before);margin-inline-start:var(--swiper-centered-offset-before)}.swiper-centered.swiper-horizontal>.swiper-wrapper:before{height:100%;min-height:1px;width:var(--swiper-centered-offset-after)}.swiper-centered.swiper-vertical>.swiper-wrapper>.swiper-slide:first-child{-webkit-margin-before:var(--swiper-centered-offset-before);margin-block-start:var(--swiper-centered-offset-before)}.swiper-centered.swiper-vertical>.swiper-wrapper:before{width:100%;min-width:1px;height:var(--swiper-centered-offset-after)}.swiper-centered>.swiper-wrapper>.swiper-slide{scroll-snap-align:center center}.swiper[data-v-0afd57ba]{margin-left:-.625rem;margin-right:-.625rem}.swiper .swiper-slide[data-v-0afd57ba]{width:100%;padding-left:.625rem;padding-right:.625rem}@media (min-width: 1024px){.swiper .swiper-slide[data-v-0afd57ba]{width:50%}}@media (min-width: 1280px){.swiper .swiper-slide[data-v-0afd57ba]{width:33.333333%}}@media (min-width: 1536px){.swiper .swiper-slide[data-v-0afd57ba]{width:25%}}.banner-image[data-v-0afd57ba]{cursor:pointer;border-radius:.5rem;-o-object-fit:cover;object-fit:cover;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.banner-image[data-v-0afd57ba]:hover{opacity:.8;--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}
2 |
--------------------------------------------------------------------------------
/docs/assets/OpticalDisk.4907c891.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SmallRuralDog/vue3-music/578f4b34889fff4f6c5a6a24662be6fd24255ac3/docs/assets/OpticalDisk.4907c891.png
--------------------------------------------------------------------------------
/docs/assets/Picked.0c25147a.js:
--------------------------------------------------------------------------------
1 | import{_ as g,B as C,a as j}from"./Mv.34913284.js";import{u as m}from"./video.3500c715.js";import{_ as f}from"./CoverPlay.d639e45b.js";import{c as _,t as v,F as P,o as h,g as r,h as s,j as e,i as l,I as u,G as $,u as i,H as y,d as w,D as B}from"./vendor.9760fa8a.js";import{P as D,o as z}from"./index.373df683.js";import"./plugin-vue_export-helper.21dcd24c.js";import"./IconPark.402beefe.js";import"./Right.083d6647.js";import"./el-image-viewer.a8b12883.js";import"./PlayOne.e72f474c.js";const S={class:"grid grid-flow-row grid-cols-2 lg:grid-cols-4 gap-5"},E=["onClick"],F={class:"truncate text-xs mt-2"},V=_({setup(o){const{personalizedPrivateContent:a}=v(m()),{getPersonalizedPrivateContent:c}=m(),d=P();return h(async()=>{await c()}),(k,x)=>(r(),s(u,null,[e(g,{title:"\u72EC\u5BB6\u653E\u9001",class:"mt-5"}),l("div",S,[(r(!0),s(u,null,$(i(a),t=>(r(),s("div",{key:t.id,onClick:n=>i(d).push({name:i(D).mvDetail,query:{id:t.id}})},[e(f,{"pic-url":t.sPicUrl,video:"",name:t.name},null,8,["pic-url","name"]),l("div",F,y(t.name),1)],8,E))),128))])],64))}}),p=w("personalized",()=>{const o=B([]);return{djProgram:o,getDjProgram:async()=>{o.value.length||(o.value=await z())}}}),q={class:"grid grid-flow-row grid-cols-3 lg:grid-cols-6 gap-5"},N=["onClick"],R={class:"truncate text-xs mt-2"},U=_({setup(o){const{djProgram:a}=v(p()),{getDjProgram:c}=p(),d=P();return h(async()=>{await c()}),(k,x)=>{const t=g;return r(),s(u,null,[e(t,{title:"\u63A8\u8350\u7535\u53F0",class:"mt-5"}),l("div",q,[(r(!0),s(u,null,$(i(a),n=>(r(),s("div",{key:n.id,onClick:A=>i(d).push({name:"video",query:{id:n.id}})},[e(f,{"pic-url":n.picUrl,name:n.name,"play-count":0},null,8,["pic-url","name"]),l("div",R,y(n.name),1)],8,N))),128))])],64)}}}),Q=_({setup(o){return(a,c)=>(r(),s("div",null,[e(C),e(V),e(U),e(j)]))}});export{Q as default};
2 |
--------------------------------------------------------------------------------
/docs/assets/PlayList.1f8f2eb4.css:
--------------------------------------------------------------------------------
1 | .playlist .el-tabs__nav-wrap:after{height:0}.playlist .el-tabs__header{margin:0}
2 |
--------------------------------------------------------------------------------
/docs/assets/PlayList.7ad8eb52.js:
--------------------------------------------------------------------------------
1 | import{c as y,D as r,g as l,h as n,I as p,H as i,i as e,m as $,N as E,j as c,G as w,u as _,e as F,q as D,k as f,l as B,a4 as L,n as P,C as V,o as N,$ as S,a0 as z}from"./vendor.9760fa8a.js";/* empty css */import{c as j,s as M,t as T}from"./index.373df683.js";/* empty css */import{_ as h}from"./IconPark.402beefe.js";import{M as I,S as U}from"./SongListItem.f4bd4734.js";import{P as q}from"./PlayOne.e72f474c.js";import{L as G}from"./PlayTwo.fe71fa6d.js";import"./plugin-vue_export-helper.21dcd24c.js";const H={class:"leading-5"},O={key:0},R={key:1},J=y({props:{text:null,end:null},setup(t){const u=t,o=r(!1),s=r(!1);return u.text&&u.text.length>u.end&&(o.value=!0),(a,d)=>(l(),n("div",H,[o.value?(l(),n(p,{key:0},[s.value?(l(),n("span",R,i(t.text)+"...",1)):(l(),n("span",O,i(t.text.substring(0,t.end))+"...",1)),e("span",{class:"ml-5 text-gray-700 hover-text",onClick:d[0]||(d[0]=x=>s.value=!s.value)},"["+i(s.value?"\u6536\u8D77":"\u8BE6\u60C5")+"]",1)],64)):(l(),n(p,{key:1},[$(i(t.text),1)],64))]))}}),K={class:"flex items-stretch"},Q=["src"],W={class:"pl-5 flex flex-col justify-between py-1 flex-1"},X={class:"text-2xl font-bold"},Y={class:"flex items-center text-xs text-dc pb-2 pt-3"},Z={class:"ml-2"},tt={class:"ml-5 flex text-dc"},et={class:"text-xs text-gray-500 leading-normal"},st={class:"justify-self-stretch mt-5 gap-x-2 flex items-center"},lt=e("span",null,"\u64AD\u653E\u5168\u90E8",-1),at={class:"w-32 button-outline"},nt=e("span",null,"\u6536\u85CF",-1),ot={class:"button-outline w-8"},ct=y({props:{playlist:null,playAll:null},setup(t){return(u,o)=>{const s=E;return l(),n("div",K,[e("img",{src:t.playlist.coverImgUrl,alt:"",class:"w-44 h-44 object-cover rounded-xl flex-shrink-0"},null,8,Q),e("div",W,[e("div",null,[e("div",X,i(t.playlist.name),1),e("div",Y,[c(s,{src:t.playlist.creator.avatarUrl,size:"small",round:""},null,8,["src"]),e("span",Z,i(t.playlist.creator.nickname),1),e("div",tt,[(l(!0),n(p,null,w(t.playlist.tags,a=>(l(),n("div",{class:"ml-2 hover-text",key:a},"#"+i(a),1))),128))])]),e("div",et,[c(J,{text:t.playlist.description,end:90},null,8,["text"])])]),e("div",st,[e("button",{class:"w-32 button",onClick:o[0]||(o[0]=(...a)=>t.playAll&&t.playAll(...a))},[c(h,{icon:_(q),size:"22",class:"mr-1"},null,8,["icon"]),lt]),e("button",at,[c(h,{icon:_(G),size:"18",class:"mr-1"},null,8,["icon"]),nt]),e("button",ot,[c(h,{icon:_(I)},null,8,["icon"])])])])])}}}),ut={class:"mt-2"},it=L('
\u6B4C\u66F2
\u6B4C\u624B
\u4E13\u8F91
\u65F6\u957F
',1),rt={class:"text-sm"},dt={key:0,class:"flex justify-center py-5"},mt=$("\u52A0\u8F7D\u66F4\u591A"),vt=y({props:{songs:null},setup(t){const u=t,o=r(10),s=r(1),a=F(()=>s.value-u.songs.length/o.value>=0),d=()=>{s.value=s.value+1};return(x,g)=>{const b=P;return l(),n("div",ut,[it,e("div",rt,[(l(!0),n(p,null,w(t.songs.slice(0,o.value*s.value),m=>(l(),D(U,{key:m.id,song:m,"show-ar-name":"","show-al-name":""},null,8,["song"]))),128))]),t.songs.length>o.value&&!_(a)?(l(),n("div",dt,[c(b,{type:"text",class:"text-center w-full",onClick:d},{default:f(()=>[mt]),_:1})])):B("",!0)])}}});const _t={class:"playlist"},pt={key:0,class:"p-5"},Bt=y({setup(t){const u=r("tracks"),o=V(),s=r(),a=r([]),{pushPlayList:d,play:x}=j(),g=()=>{d(!0,...a.value),x(a.value.first().id)};return N(()=>{const m=Number(o.query.id);M(m).then(v=>{s.value=v}),T(m).then(v=>{a.value=v})}),(m,v)=>{const k=S,C=z;return l(),n("div",_t,[s.value?(l(),n("div",pt,[c(ct,{playlist:s.value,"play-all":()=>g()},null,8,["playlist","play-all"]),c(C,{class:"mt-3",modelValue:u.value,"onUpdate:modelValue":v[0]||(v[0]=A=>u.value=A)},{default:f(()=>[c(k,{lazy:"",label:`\u6B4C\u66F2 ${a.value.length}`,name:"tracks"},{default:f(()=>[c(vt,{songs:a.value},null,8,["songs"])]),_:1},8,["label"]),c(k,{lazy:"",label:"\u8BC4\u8BBA",name:"comments"})]),_:1},8,["modelValue"])])):B("",!0)])}}});export{Bt as default};
2 |
--------------------------------------------------------------------------------
/docs/assets/PlayOne.e72f474c.js:
--------------------------------------------------------------------------------
1 | import{I as t}from"./IconPark.402beefe.js";import{j as o}from"./vendor.9760fa8a.js";var n=t("play-one",!0,function(e){return o("svg",{width:e.size,height:e.size,viewBox:"0 0 48 48",fill:"none"},[o("path",{d:"M15 24V11.8756L25.5 17.9378L36 24L25.5 30.0622L15 36.1244V24Z",fill:e.colors[1],stroke:e.colors[0],"stroke-width":e.strokeWidth,"stroke-linejoin":e.strokeLinejoin},null)])});export{n as P};
2 |
--------------------------------------------------------------------------------
/docs/assets/PlayTwo.fe71fa6d.js:
--------------------------------------------------------------------------------
1 | import{I as t}from"./IconPark.402beefe.js";import{j as i}from"./vendor.9760fa8a.js";var n=t("down-two",!1,function(e){return i("svg",{width:e.size,height:e.size,viewBox:"0 0 48 48",fill:"none"},[i("path",{d:"M5 24L24 42L43 24H31V6H17V24H5Z",fill:e.colors[1],stroke:e.colors[0],"stroke-width":e.strokeWidth,"stroke-linecap":e.strokeLinecap,"stroke-linejoin":e.strokeLinejoin},null)])}),r=t("like",!1,function(e){return i("svg",{width:e.size,height:e.size,viewBox:"0 0 48 48",fill:"none"},[i("path",{d:"M15 8C8.92487 8 4 12.9249 4 19C4 30 17 40 24 42.3262C31 40 44 30 44 19C44 12.9249 39.0751 8 33 8C29.2797 8 25.9907 9.8469 24 12.6738C22.0093 9.8469 18.7203 8 15 8Z",fill:e.colors[1],stroke:e.colors[0],"stroke-width":e.strokeWidth,"stroke-linecap":e.strokeLinecap,"stroke-linejoin":e.strokeLinejoin},null)])}),c=t("more-two",!1,function(e){return i("svg",{width:e.size,height:e.size,viewBox:"0 0 48 48",fill:"none"},[i("path",{d:"M24 44C35.0457 44 44 35.0457 44 24C44 12.9543 35.0457 4 24 4C12.9543 4 4 12.9543 4 24C4 35.0457 12.9543 44 24 44Z",fill:e.colors[1],stroke:e.colors[0],"stroke-width":e.strokeWidth,"stroke-linejoin":e.strokeLinejoin},null),i("circle",{cx:"14",cy:"24",r:"3",fill:e.colors[2]},null),i("circle",{cx:"24",cy:"24",r:"3",fill:e.colors[2]},null),i("circle",{cx:"34",cy:"24",r:"3",fill:e.colors[2]},null)])}),s=t("play-two",!0,function(e){return i("svg",{width:e.size,height:e.size,viewBox:"0 0 48 48",fill:"none"},[i("rect",{x:"6",y:"6",width:"36",height:"36",rx:"3",fill:e.colors[1],stroke:e.colors[0],"stroke-width":e.strokeWidth,"stroke-linecap":e.strokeLinecap,"stroke-linejoin":e.strokeLinejoin},null),i("path",{d:"M18.5 24V16.2058L25.25 20.1029L32 24L25.25 27.8971L18.5 31.7942V24Z",fill:e.colors[3],stroke:e.colors[2],"stroke-width":e.strokeWidth,"stroke-linejoin":e.strokeLinejoin},null)])});export{n as D,r as L,c as M,s as P};
2 |
--------------------------------------------------------------------------------
/docs/assets/Right.083d6647.js:
--------------------------------------------------------------------------------
1 | import{I as i}from"./IconPark.402beefe.js";import{j as t}from"./vendor.9760fa8a.js";var n=i("right",!0,function(e){return t("svg",{width:e.size,height:e.size,viewBox:"0 0 48 48",fill:"none"},[t("path",{d:"M19 12L31 24L19 36",stroke:e.colors[0],"stroke-width":e.strokeWidth,"stroke-linecap":e.strokeLinecap,"stroke-linejoin":e.strokeLinejoin},null)])});export{n as R};
2 |
--------------------------------------------------------------------------------
/docs/assets/SongListItem.6fa5a73e.css:
--------------------------------------------------------------------------------
1 | .song-item[data-v-938b689c]{padding-top:.625rem;padding-bottom:.625rem;padding-left:.125rem}.song-item:hover .icon-action[data-v-938b689c]{display:inline-block}.playing[data-v-938b689c]{--tw-bg-opacity: 1;background-color:rgb(236 253 245 / var(--tw-bg-opacity))}@media (prefers-color-scheme: dark){.playing[data-v-938b689c]{--tw-bg-opacity: 1;background-color:rgb(41 37 36 / var(--tw-bg-opacity))}}
2 |
--------------------------------------------------------------------------------
/docs/assets/SongListItem.f4bd4734.js:
--------------------------------------------------------------------------------
1 | import{I as v,_ as l}from"./IconPark.402beefe.js";import{j as i,c as x,F as w,s as g,g as a,h as u,i as s,u as t,H as r,q as y,l as d,J as m}from"./vendor.9760fa8a.js";import{c as f,P as A,e as z}from"./index.373df683.js";import{_ as D}from"./plugin-vue_export-helper.21dcd24c.js";import{L as N,P as B,D as L,M as C}from"./PlayTwo.fe71fa6d.js";import{P as j}from"./PlayOne.e72f474c.js";var P=v("add",!1,function(e){return i("svg",{width:e.size,height:e.size,viewBox:"0 0 48 48",fill:"none"},[i("rect",{x:"6",y:"6",width:"36",height:"36",rx:"3",fill:e.colors[1],stroke:e.colors[0],"stroke-width":e.strokeWidth,"stroke-linejoin":e.strokeLinejoin},null),i("path",{d:"M24 16V32",stroke:e.colors[2],"stroke-width":e.strokeWidth,"stroke-linecap":e.strokeLinecap,"stroke-linejoin":e.strokeLinejoin},null),i("path",{d:"M16 24L32 24",stroke:e.colors[2],"stroke-width":e.strokeWidth,"stroke-linecap":e.strokeLinecap,"stroke-linejoin":e.strokeLinejoin},null)])}),Q=v("more",!1,function(e){return i("svg",{width:e.size,height:e.size,viewBox:"0 0 48 48",fill:"none"},[i("circle",{cx:"12",cy:"24",r:"3",fill:e.colors[0]},null),i("circle",{cx:"24",cy:"24",r:"3",fill:e.colors[0]},null),i("circle",{cx:"36",cy:"24",r:"3",fill:e.colors[0]},null)])});const F={class:"flex-shrink-0 flex-1 flex items-center justify-between pr-5"},M={class:"items-center flex flex-1 w-10 flex-shrink-0"},$={class:"truncate",style:{"max-width":"75%"}},b={class:"hidden icon-action flex-shrink-0"},I={class:"flex items-center gap-x-1.5 text-gray-400 ml-2"},S={class:"w-9/12 truncate"},q={class:"w-9/12 truncate"},T={class:"w-20 flex-shrink-0"},V={class:"w-20 truncate"},W=x({props:{song:null,showArName:{type:Boolean},showAlName:{type:Boolean}},setup(e){const c=w(),{play:h}=f(),{id:k}=g(f());return(E,n)=>(a(),u("div",{class:m(["flex song-item items-center w-full hover-bg-main",{playing:t(k)===e.song.id}]),onDblclick:n[4]||(n[4]=o=>t(h)(e.song.id))},[s("div",F,[s("div",M,[i(l,{icon:t(N),size:"16",class:"text-gray-500 mr-1 cursor-pointer hover:text-red-400"},null,8,["icon"]),s("div",$,[s("small",null,r(e.song.name),1)]),e.song.mv>0?(a(),y(l,{key:0,class:"ml-2 text-orange-400 cursor-pointer",size:"16",icon:t(B),onClick:n[0]||(n[0]=o=>t(c).push({name:t(A).mvDetail,query:{id:e.song.mv}}))},null,8,["icon"])):d("",!0)]),s("div",b,[s("div",I,[i(l,{title:"\u64AD\u653E",icon:t(j),size:"20",class:"hover-text",onClick:n[1]||(n[1]=o=>t(h)(e.song.id))},null,8,["icon"]),i(l,{title:"\u6DFB\u52A0\u5230",icon:t(P),size:"16",class:"hover-text"},null,8,["icon"]),i(l,{title:"\u4E0B\u8F7D",icon:t(L),size:"16",class:"hover-text"},null,8,["icon"]),i(l,{title:"\u66F4\u591A\u64CD\u4F5C",icon:t(C),size:"16",class:"hover-text"},null,8,["icon"])])])]),e.showArName?(a(),u("div",{key:0,class:m(["flex-shrink-0",{"w-1/4":e.showAlName,"w-1/3":!e.showAlName}])},[s("div",S,[s("small",{class:"truncate max-w-full hover-text",onClick:n[2]||(n[2]=o=>t(c).push({name:"artistDetail",query:{id:e.song.ar.first().id}}))},r(e.song.ar.first().name),1)])],2)):d("",!0),e.showAlName?(a(),u("div",{key:1,class:m(["flex-shrink-0",{"w-1/4":e.showArName,"w-1/3":!e.showArName}])},[s("div",q,[s("small",{class:"truncate hover-text",onClick:n[3]||(n[3]=o=>t(c).push({name:"album",query:{id:e.song.al.id}}))},r(e.song.al.name),1)])],2)):d("",!0),s("div",T,[s("div",V,[s("small",null,r(t(z)(e.song.dt/1e3)),1)])])],34))}});var U=D(W,[["__scopeId","data-v-938b689c"]]);export{Q as M,U as S};
2 |
--------------------------------------------------------------------------------
/docs/assets/TopList.33e44e27.js:
--------------------------------------------------------------------------------
1 | import{c as g,t as v,F as y,o as k,g as o,h as e,i as t,I as c,G as a,u,j as _,H as l}from"./vendor.9760fa8a.js";import{_ as p}from"./CoverPlay.d639e45b.js";import{u as x}from"./music.991378cb.js";import"./el-image-viewer.a8b12883.js";import"./IconPark.402beefe.js";import"./index.373df683.js";import"./PlayOne.e72f474c.js";const C=t("div",{class:"text-xl pb-5 font-bold"},"\u5B98\u65B9\u699C",-1),w={class:"grid grid-flow-row grid-cols-2 2xl:grid-cols-4 gap-5"},b=["onClick"],B={class:"px-5 flex-1 flex-shrink-0 flex flex-col"},D={class:"text-xl font-bold"},I={class:"text-xs text-main mt-2"},L={class:"mt-2"},$={class:"flex"},F={class:"mr-1"},M={class:"flex-auto w-20 truncate"},N=t("div",{class:"text-xl py-5 font-bold"},"\u7279\u8272\u699C",-1),R={class:"grid grid-flow-row grid-cols-5 2xl:grid-cols-10 gap-5"},S=["onClick"],U={class:"text-xs mt-2"},A=g({setup(V){const{topListDetailData:i}=v(x()),{getTopListDetailData:f}=x(),m=y();k(async()=>{await f()});const r=d=>{m.push({name:"playlist",query:{id:d.id}})};return(d,j)=>(o(),e(c,null,[C,t("div",w,[(o(!0),e(c,null,a(u(i).slice(0,4),s=>(o(),e("div",{key:s.id,class:"flex bg-dc rounded-lg items-center cursor-pointer",onClick:n=>r(s)},[_(p,{name:s.name,"pic-url":s.coverImgUrl,"play-count":s.playCount,class:"w-36 flex-shrink-0","show-play-count":""},null,8,["name","pic-url","play-count"]),t("div",B,[t("div",D,l(s.name),1),t("div",I,[(o(!0),e(c,null,a(s.tracks,(n,h)=>(o(),e("div",L,[t("div",$,[t("span",F,l(h+1),1),t("div",M,l(n.first)+" - "+l(n.second),1)])]))),256))])])],8,b))),128))]),N,t("div",R,[(o(!0),e(c,null,a(u(i).slice(4),s=>(o(),e("div",{key:s.id,onClick:n=>r(s)},[_(p,{name:s.name,"pic-url":s.coverImgUrl,"play-count":s.playCount},null,8,["name","pic-url","play-count"]),t("div",U,l(s.name),1)],8,S))),128))])],64))}});export{A as default};
2 |
--------------------------------------------------------------------------------
/docs/assets/Video.94189c43.js:
--------------------------------------------------------------------------------
1 | import{c as y,t as b,D as E,r as V,o as $,K as B,O as D,g as o,h as s,i as e,j as a,k as c,I as d,G as p,u as n,J as f,H as u}from"./vendor.9760fa8a.js";/* empty css */import{u as x}from"./video.3500c715.js";import{_ as G}from"./IconPark.402beefe.js";import{B as S}from"./index.373df683.js";import{_ as R}from"./CoverPlay.d639e45b.js";import{R as j}from"./Right.083d6647.js";import"./el-image-viewer.a8b12883.js";import"./PlayOne.e72f474c.js";const L={class:"p-5 video-page"},N={class:"flex items-center justify-between"},z={class:"button-outline px-5"},F=e("span",{class:"mr-2"},"\u5168\u90E8\u89C6\u9891",-1),H={class:"h-96 py-5 pl-5"},I={class:"text-xs gap-5 grid grid-flow-row grid-cols-5"},J=["onClick"],K={class:"text-xs flex gap-x-4"},M=["onClick"],O={class:"grid grid-flow-row grid-cols-3 gap-5 mt-5"},P={class:"text-xs mt-3 truncate"},et=y({setup(U){const{videoGroup:_}=b(x()),{getVideoGroup:h}=x(),v=E([]),i=V({page:1,id:0}),m=async()=>{v.value=await S(i.id,i.page-1)},r=l=>{console.log(l),i.id=l,i.page=1,m()};return $(()=>{h(),m()}),(l,g)=>{const k=B,C=D;return o(),s("div",L,[e("div",N,[a(C,{width:"60%",placement:"bottom-start","popper-style":"padding:0;"},{reference:c(()=>[e("button",z,[F,a(G,{icon:n(j)},null,8,["icon"])])]),default:c(()=>[e("div",null,[e("div",{class:"text-xl pt-5 pl-5 hover-text",onClick:g[0]||(g[0]=t=>r(0))},"\u5168\u90E8\u89C6\u9891"),e("div",H,[a(k,null,{default:c(()=>[e("div",I,[(o(!0),s(d,null,p(n(_),t=>(o(),s("div",{class:f(["hover-text",{"text-active":n(i).id===t.id}]),key:t.id,onClick:w=>r(t.id)},u(t.name),11,J))),128))])]),_:1})])])]),_:1}),e("div",K,[(o(!0),s(d,null,p(n(_).slice(0,8),t=>(o(),s("div",{class:f(["hover-text",{"text-active":n(i).id===t.id}]),onClick:w=>r(t.id),key:t.id},u(t.name),11,M))),128))])]),e("div",O,[(o(!0),s(d,null,p(v.value,({data:t})=>(o(),s("div",{key:t.vid},[a(R,{"pic-url":t.coverUrl,video:""},null,8,["pic-url"]),e("div",P,u(t.title),1)]))),128))])])}}});export{et as default};
2 |
--------------------------------------------------------------------------------
/docs/assets/el-avatar.00087837.css:
--------------------------------------------------------------------------------
1 | .el-avatar{--el-avatar-text-color:#fff;--el-avatar-bg-color:#c0c4cc;--el-avatar-text-size:14px;--el-avatar-icon-size:18px;--el-avatar-border-radius:var(--el-border-radius-base);--el-avatar-size-large:56px;--el-avatar-size-default:40px;--el-avatar-size-small:24px;display:inline-flex;justify-content:center;align-items:center;box-sizing:border-box;text-align:center;overflow:hidden;color:var(--el-avatar-text-color);background:var(--el-avatar-bg-color);width:var(--el-avatar-size);height:var(--el-avatar-size);font-size:var(--el-avatar-text-size)}.el-avatar>img{display:block;height:100%}.el-avatar--circle{border-radius:50%}.el-avatar--square{border-radius:var(--el-avatar-border-radius)}.el-avatar--icon{font-size:var(--el-avatar-icon-size)}.el-avatar--small{--el-avatar-size:24px}.el-avatar--default{--el-avatar-size:40px}.el-avatar--large{--el-avatar-size:56px}
2 |
--------------------------------------------------------------------------------
/docs/assets/el-image-viewer.a8b12883.js:
--------------------------------------------------------------------------------
1 | import{I as i}from"./IconPark.402beefe.js";import{j as t}from"./vendor.9760fa8a.js";var r=i("play",!0,function(e){return t("svg",{width:e.size,height:e.size,viewBox:"0 0 48 48",fill:"none"},[t("path",{d:"M24 44C35.0457 44 44 35.0457 44 24C44 12.9543 35.0457 4 24 4C12.9543 4 4 12.9543 4 24C4 35.0457 12.9543 44 24 44Z",fill:e.colors[1],stroke:e.colors[0],"stroke-width":e.strokeWidth,"stroke-linejoin":e.strokeLinejoin},null),t("path",{d:"M20 24V17.0718L26 20.5359L32 24L26 27.4641L20 30.9282V24Z",fill:e.colors[3],stroke:e.colors[2],"stroke-width":e.strokeWidth,"stroke-linejoin":e.strokeLinejoin},null)])});export{r as P};
2 |
--------------------------------------------------------------------------------
/docs/assets/el-image-viewer.ac997372.css:
--------------------------------------------------------------------------------
1 | .el-image__error,.el-image__inner,.el-image__placeholder{width:100%;height:100%}.el-image{position:relative;display:inline-block;overflow:hidden}.el-image__inner{vertical-align:top}.el-image__placeholder{background:var(--el-bg-color)}.el-image__error{display:flex;justify-content:center;align-items:center;font-size:14px;background:var(--el-bg-color);color:var(--el-text-color-placeholder);vertical-align:middle}.el-image__preview{cursor:pointer}.el-image-viewer__wrapper{position:fixed;top:0;right:0;bottom:0;left:0}.el-image-viewer__btn{position:absolute;z-index:1;display:flex;align-items:center;justify-content:center;border-radius:50%;opacity:.8;cursor:pointer;box-sizing:border-box;-webkit-user-select:none;user-select:none}.el-image-viewer__btn .el-icon{font-size:inherit;cursor:pointer}.el-image-viewer__close{top:40px;right:40px;width:40px;height:40px;font-size:40px}.el-image-viewer__canvas{width:100%;height:100%;display:flex;justify-content:center;align-items:center;-webkit-user-select:none;user-select:none}.el-image-viewer__actions{left:50%;bottom:30px;transform:translate(-50%);width:282px;height:44px;padding:0 23px;background-color:var(--el-text-color-regular);border-color:#fff;border-radius:22px}.el-image-viewer__actions__inner{width:100%;height:100%;text-align:justify;cursor:default;font-size:23px;color:#fff;display:flex;align-items:center;justify-content:space-around}.el-image-viewer__prev{top:50%;transform:translateY(-50%);left:40px;width:44px;height:44px;font-size:24px;color:#fff;background-color:var(--el-text-color-regular);border-color:#fff}.el-image-viewer__next{top:50%;transform:translateY(-50%);right:40px;text-indent:2px;width:44px;height:44px;font-size:24px;color:#fff;background-color:var(--el-text-color-regular);border-color:#fff}.el-image-viewer__close{width:44px;height:44px;font-size:24px;color:#fff;background-color:var(--el-text-color-regular);border-color:#fff}.el-image-viewer__mask{position:absolute;width:100%;height:100%;top:0;left:0;opacity:.5;background:#000}.viewer-fade-enter-active{animation:viewer-fade-in var(--el-transition-duration)}.viewer-fade-leave-active{animation:viewer-fade-out var(--el-transition-duration)}@keyframes viewer-fade-in{0%{transform:translate3d(0,-20px,0);opacity:0}to{transform:translateZ(0);opacity:1}}@keyframes viewer-fade-out{0%{transform:translateZ(0);opacity:1}to{transform:translate3d(0,-20px,0);opacity:0}}
2 |
--------------------------------------------------------------------------------
/docs/assets/el-popper.24515e58.css:
--------------------------------------------------------------------------------
1 | .el-scrollbar{--el-scrollbar-opacity:.3;--el-scrollbar-bg-color:var(--el-text-color-secondary);--el-scrollbar-hover-opacity:.5;--el-scrollbar-hover-bg-color:var(--el-text-color-secondary);overflow:hidden;position:relative;height:100%}.el-scrollbar__wrap{overflow:auto;height:100%}.el-scrollbar__wrap--hidden-default{scrollbar-width:none}.el-scrollbar__wrap--hidden-default::-webkit-scrollbar{display:none}.el-scrollbar__thumb{position:relative;display:block;width:0;height:0;cursor:pointer;border-radius:inherit;background-color:var(--el-scrollbar-bg-color,var(--el-text-color-secondary));transition:var(--el-transition-duration) background-color;opacity:var(--el-scrollbar-opacity,.3)}.el-scrollbar__thumb:hover{background-color:var(--el-scrollbar-hover-bg-color,var(--el-text-color-secondary));opacity:var(--el-scrollbar-hover-opacity,.5)}.el-scrollbar__bar{position:absolute;right:2px;bottom:2px;z-index:1;border-radius:4px}.el-scrollbar__bar.is-vertical{width:6px;top:2px}.el-scrollbar__bar.is-vertical>div{width:100%}.el-scrollbar__bar.is-horizontal{height:6px;left:2px}.el-scrollbar__bar.is-horizontal>div{height:100%}.el-scrollbar-fade-enter-active{transition:opacity .34s ease-out}.el-scrollbar-fade-leave-active{transition:opacity .12s ease-out}.el-scrollbar-fade-enter-from,.el-scrollbar-fade-leave-active{opacity:0}.el-popover{--el-popover-bg-color:var(--el-color-white);--el-popover-font-size:var(--el-font-size-base);--el-popover-border-color:var(--el-border-color-lighter);--el-popover-padding:12px;--el-popover-padding-large:18px 20px;--el-popover-title-font-size:16px;--el-popover-title-text-color:var(--el-text-color-primary);--el-popover-border-radius:4px}.el-popover.el-popper{background:var(--el-popover-bg-color);min-width:150px;border-radius:var(--el-popover-border-radius);border:1px solid var(--el-popover-border-color);padding:var(--el-popover-padding);z-index:var(--el-index-popper);color:var(--el-text-color-regular);line-height:1.4;text-align:justify;font-size:var(--el-popover-font-size);box-shadow:var(--el-box-shadow-light);word-break:break-all}.el-popover.el-popper--plain{padding:var(--el-popover-padding-large)}.el-popover__title{color:var(--el-popover-title-text-color);font-size:var(--el-popover-title-font-size);line-height:1;margin-bottom:12px}.el-popover__reference:focus:hover,.el-popover__reference:focus:not(.focusing){outline-width:0}.el-popover.el-popper:focus,.el-popover.el-popper:focus:active{outline-width:0}.el-popper{--el-popper-border-radius:var(--el-popover-border-radius, 4px);position:absolute;border-radius:var(--el-popper-border-radius);padding:5px 11px;z-index:2000;font-size:12px;line-height:20px;min-width:10px;word-wrap:break-word;visibility:visible}.el-popper.is-dark{color:var(--el-color-white);background:var(--el-text-color-primary);border:1px solid var(--el-text-color-primary)}.el-popper.is-dark .el-popper__arrow:before{border:1px solid var(--el-text-color-primary);background:var(--el-text-color-primary);right:0}.el-popper.is-light{background:var(--el-color-white);border:1px solid var(--el-border-color-light)}.el-popper.is-light .el-popper__arrow:before{border:1px solid var(--el-border-color-light);background:var(--el-color-white);right:0}.el-popper.is-pure{padding:0}.el-popper__arrow{position:absolute;width:10px;height:10px;z-index:-1}.el-popper__arrow:before{position:absolute;width:10px;height:10px;z-index:-1;content:" ";transform:rotate(45deg);background:var(--el-text-color-primary);box-sizing:border-box}.el-popper[data-popper-placement^=top]>.el-popper__arrow{bottom:-5px}.el-popper[data-popper-placement^=top]>.el-popper__arrow:before{border-bottom-right-radius:2px}.el-popper[data-popper-placement^=bottom]>.el-popper__arrow{top:-5px}.el-popper[data-popper-placement^=bottom]>.el-popper__arrow:before{border-top-left-radius:2px}.el-popper[data-popper-placement^=left]>.el-popper__arrow{right:-5px}.el-popper[data-popper-placement^=left]>.el-popper__arrow:before{border-top-right-radius:2px}.el-popper[data-popper-placement^=right]>.el-popper__arrow{left:-5px}.el-popper[data-popper-placement^=right]>.el-popper__arrow:before{border-bottom-left-radius:2px}.el-popper[data-popper-placement^=top] .el-popper__arrow:before{border-top-color:transparent!important;border-left-color:transparent!important}.el-popper[data-popper-placement^=bottom] .el-popper__arrow:before{border-bottom-color:transparent!important;border-right-color:transparent!important}.el-popper[data-popper-placement^=left] .el-popper__arrow:before{border-left-color:transparent!important;border-bottom-color:transparent!important}.el-popper[data-popper-placement^=right] .el-popper__arrow:before{border-right-color:transparent!important;border-top-color:transparent!important}
2 |
--------------------------------------------------------------------------------
/docs/assets/logo.601c4b06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SmallRuralDog/vue3-music/578f4b34889fff4f6c5a6a24662be6fd24255ac3/docs/assets/logo.601c4b06.png
--------------------------------------------------------------------------------
/docs/assets/music.991378cb.js:
--------------------------------------------------------------------------------
1 | import{d as i,D as s}from"./vendor.9760fa8a.js";import{h as r,i as l,j as u}from"./index.373df683.js";const p=i("music",()=>{const e=s([]),n=async()=>{e.value.length||(e.value=await r())},a=s([]),o=async()=>{a.value.length||(a.value=await l())},t=s([]);return{topListDetailData:e,getTopListDetailData:n,personalized:a,getPersonalized:o,personalizedNewSong:t,getPersonalizedNewSong:async()=>{t.value.length||(t.value=await u())}}});export{p as u};
2 |
--------------------------------------------------------------------------------
/docs/assets/mvDetail.aa81123a.js:
--------------------------------------------------------------------------------
1 | import{c as n,C as u}from"./index.373df683.js";import{c as r,C as i,D as d,o as _,b as m,g as p,h as v,i as e,l as f}from"./vendor.9760fa8a.js";const h={key:0,class:"p-5"},x={class:"flex gap-x-5"},y={class:"flex-1"},B=["src"],k=e("div",{class:"hidden w-80 flex-shrink-0 xl:block"},[e("div",null,"\u5927\u5BB6\u90FD\u5728\u770B")],-1),U=r({setup(C){const t=i(),a=Number(t.query.id),{setPlay:c,setPause:l}=n(),s=d();return _(async()=>{s.value=await u(a),l()}),m(()=>{setTimeout(()=>{c()},1e3)}),(b,w)=>{var o;return s.value?(p(),v("div",h,[e("div",x,[e("div",y,[e("video",{class:"aspect-video w-full",src:(o=s.value)==null?void 0:o.url,autoplay:"",controls:""},null,8,B)]),k])])):f("",!0)}}});export{U as default};
2 |
--------------------------------------------------------------------------------
/docs/assets/plugin-vue_export-helper.21dcd24c.js:
--------------------------------------------------------------------------------
1 | var a=(t,o)=>{const r=t.__vccOpts||t;for(const[e,_]of o)r[e]=_;return r};export{a as _};
2 |
--------------------------------------------------------------------------------
/docs/assets/video.3500c715.js:
--------------------------------------------------------------------------------
1 | import{d as u,D as e}from"./vendor.9760fa8a.js";import{k as l,l as d,m as v,n as c}from"./index.373df683.js";const f=u("video",()=>{const t=e([]),a=async()=>{t.value.length||(t.value=await l())},n=e([]),s=async()=>{n.value.length||(n.value=await d(4))},o=e([]),r=async()=>{o.value.length||(o.value=await v())},i=e([]);return{videoTimelineRecommend:t,getVideoTimelineRecommend:a,personalizedPrivateContent:n,getPersonalizedPrivateContent:s,personalizedMv:o,getPersonalizedMv:r,videoGroup:i,getVideoGroup:async()=>{i.value.length||(i.value=await c())}}});export{f as u};
2 |
--------------------------------------------------------------------------------
/docs/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SmallRuralDog/vue3-music/578f4b34889fff4f6c5a6a24662be6fd24255ac3/docs/favicon.ico
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | VUE3-MUSIC
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | VUE3-MUSIC
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue3-ts-music",
3 | "version": "1.0.0",
4 | "license": "MIT",
5 | "scripts": {
6 | "dev": "vite",
7 | "build": "vue-tsc --noEmit && vite build",
8 | "preview": "vite preview --port 5050",
9 | "typecheck": "vue-tsc --noEmit"
10 | },
11 | "dependencies": {
12 | "@icon-park/vue-next": "^1.3.6",
13 | "axios": "^0.26.0",
14 | "dayjs": "^1.10.8",
15 | "element-plus": "^2.0.4",
16 | "lodash": "^4.17.21",
17 | "pinia": "^2.0.11",
18 | "swiper": "^8.0.6",
19 | "vue": "^3.2.31",
20 | "vue-router": "^4.0.12"
21 | },
22 | "devDependencies": {
23 | "@types/lodash": "^4.14.179",
24 | "@types/lodash-es": "*",
25 | "@types/node": "^16.11.25",
26 | "@vitejs/plugin-vue": "^2.2.2",
27 | "@vitejs/plugin-vue-jsx": "^1.3.7",
28 | "@vue/tsconfig": "^0.1.3",
29 | "@vueuse/components": "^7.7.0",
30 | "@vueuse/core": "^7.7.0",
31 | "autoprefixer": "^10.4.2",
32 | "postcss": "^8.4.7",
33 | "sass": "^1.49.9",
34 | "tailwindcss": "^3.0.23",
35 | "typescript": "~4.5.5",
36 | "unplugin-auto-import": "^0.6.1",
37 | "unplugin-vue-components": "^0.17.21",
38 | "vite": "^2.8.4",
39 | "vue-tsc": "^0.31.4"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SmallRuralDog/vue3-music/578f4b34889fff4f6c5a6a24662be6fd24255ac3/public/favicon.ico
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
20 |
--------------------------------------------------------------------------------
/src/assets/base.scss:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | :root {
6 | --el-color-primary: #34d399 !important;
7 | --el-color-primary-light-1: #065f46 !important;
8 | --el-color-primary-light-2: #047857 !important;
9 | --el-color-primary-light-3: #059669 !important;
10 | --el-color-primary-light-4: #10b981 !important;
11 | --el-color-primary-light-5: #34d399 !important;
12 | --el-color-primary-light-6: #6ee7b7 !important;
13 | --el-color-primary-light-7: #a7f3d0 !important;
14 | --el-color-primary-light-8: #d1fae5 !important;
15 | --el-color-primary-light-9: #ecfdf5 !important;
16 | --el-color-primary-dark-2: #337ecc !important;
17 | --el-text-color-primary: text-slate-700;
18 | }
19 |
20 | @media (prefers-color-scheme: dark) {
21 | :root {
22 | --el-color-primary: #059669 !important;
23 |
24 | --el-color-primary-light-9: #57534e !important;
25 |
26 | --el-border-color-base: #57534e !important;
27 | --el-text-color-regular: #e2e8f0 !important;
28 | --el-text-color-primary: text-slate-200 !important;
29 | --el-bg-color: #474648 !important;
30 | --el-color-white: #1e1e1f !important;
31 | --el-border-color-lighter: #474648 !important;
32 | --el-border-color-light: #474648 !important;
33 |
34 | --el-popover-bg-color: #292524 !important;
35 | }
36 | }
37 |
38 | html, body {
39 | font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB',
40 | 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
41 | @apply text-slate-700 bg-white;
42 | @apply dark:bg-[#1e1e1f] dark:text-slate-100;
43 | }
44 |
45 | .hover-text {
46 | @apply hover:text-emerald-400 cursor-pointer;
47 | }
48 |
49 | .badge {
50 | .el-badge__content.is-fixed {
51 | @apply scale-75 bg-white text-slate-500 text-xs bg-opacity-50 border-0 left-2 -top-2;
52 | }
53 | }
54 |
55 | .el-popover.el-popper {
56 | min-width: auto;
57 | }
58 |
59 | .el-tabs__nav-wrap::after {
60 | height: 0 !important;
61 | }
62 |
63 | .el-tabs__header {
64 | @apply m-0;
65 | }
66 |
--------------------------------------------------------------------------------
/src/assets/img/OpticalDisk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SmallRuralDog/vue3-music/578f4b34889fff4f6c5a6a24662be6fd24255ac3/src/assets/img/OpticalDisk.png
--------------------------------------------------------------------------------
/src/assets/img/index.ts:
--------------------------------------------------------------------------------
1 | import Logo from './logo.png'
2 | import OpticalDisk from './OpticalDisk.png'
3 |
4 | export {
5 | Logo,
6 | OpticalDisk
7 | }
8 |
--------------------------------------------------------------------------------
/src/assets/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SmallRuralDog/vue3-music/578f4b34889fff4f6c5a6a24662be6fd24255ac3/src/assets/img/logo.png
--------------------------------------------------------------------------------
/src/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/theme.scss:
--------------------------------------------------------------------------------
1 | .bg-main {
2 | @apply bg-gray-50;
3 | @apply dark:bg-[#171718];
4 | }
5 |
6 | .hover-bg-main {
7 | @apply hover:bg-gray-200;
8 | @apply dark:hover:bg-stone-700;
9 | }
10 |
11 | .bg-dc {
12 | @apply bg-gray-100;
13 | @apply dark:bg-stone-800;
14 | }
15 |
16 | .bg-view {
17 | @apply bg-white;
18 | @apply dark:bg-[#1e1e1f];
19 | }
20 |
21 | .hover-bg-view {
22 | @apply hover:bg-stone-100;
23 | @apply dark:hover:bg-stone-800;
24 | }
25 |
26 | .bg-active {
27 | @apply bg-emerald-400 text-white;
28 | }
29 | .text-active{
30 | @apply text-emerald-400;
31 | }
32 |
33 | .text-main {
34 | @apply text-slate-700;
35 | @apply dark:text-slate-200;
36 | }
37 |
38 | .text-dc {
39 | @apply text-slate-400;
40 | @apply dark:text-slate-400;
41 | }
42 |
43 | .button {
44 | @apply flex bg-emerald-600 rounded-full justify-center items-center h-8 text-sm transition-all;
45 | @apply text-white;
46 | @apply hover:bg-emerald-700;
47 | }
48 |
49 | .button-outline {
50 | @apply flex rounded-full justify-center items-center h-8 text-sm transition-all border;
51 | @apply hover:border-emerald-500 hover:text-emerald-500;
52 | }
53 |
54 | .button-sm{
55 | @apply h-7 text-xs;
56 | }
57 |
58 | .button-dc{
59 | @apply flex bg-[#e6e6e6] rounded justify-center items-center h-8 text-sm transition-all cursor-pointer;
60 | @apply dark:bg-[#303031] dark:text-white;
61 | @apply hover:text-emerald-500;
62 | }
63 |
--------------------------------------------------------------------------------
/src/components/common/Banner.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
31 |
32 |
45 |
--------------------------------------------------------------------------------
/src/components/common/CoverPlay.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
13 |
14 | {{ useNumberFormat(playCount || 0) }}
15 |
16 |
17 |
18 |
19 |
20 |
34 |
35 |
61 |
--------------------------------------------------------------------------------
/src/components/common/IconPark.vue:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
20 |
--------------------------------------------------------------------------------
/src/components/common/MoreText.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ text.substring(0, end) }}...
5 | {{ text }}...
6 | [{{ isShow ? '收起' : '详情' }}]
7 |
8 | {{ text }}
9 |
10 |
11 |
12 |
25 |
26 |
29 |
--------------------------------------------------------------------------------
/src/components/common/SongListItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
9 |
10 | {{ song.name }}
11 |
12 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | {{
28 | song.ar.first().name
29 | }}
30 |
31 |
32 |
33 |
34 | {{
35 | song.al.name
36 | }}
37 |
38 |
39 |
40 |
41 | {{ useFormatDuring(song.dt / 1000) }}
42 |
43 |
44 |
45 |
46 |
47 |
67 |
68 |
82 |
--------------------------------------------------------------------------------
/src/components/common/Title.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
16 |
17 |
20 |
--------------------------------------------------------------------------------
/src/components/layout/footer/Footer.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
25 |
28 |
--------------------------------------------------------------------------------
/src/components/layout/footer/PlayerAction.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ useFormatDuring(currentTime) }} / {{ useFormatDuring(duration) }}
5 |
6 |
7 |
8 |
9 | {{ playListCount }}
10 |
11 |
12 |
13 |
14 |
23 |
24 |
27 |
--------------------------------------------------------------------------------
/src/components/layout/footer/PlayerController.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
30 |
31 |
32 |
37 |
--------------------------------------------------------------------------------
/src/components/layout/footer/PlayerSlider.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
17 |
18 |
56 |
--------------------------------------------------------------------------------
/src/components/layout/footer/PlayerSong.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
5 |
6 |
7 |
试听
9 |
10 |
{{ song.name || '开源云音乐' }}
11 |
- {{ song.ar?.first().name || `SmallRuralDog` }}
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
35 |
36 |
46 |
--------------------------------------------------------------------------------
/src/components/layout/footer/PlayerVolumeSlider.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
{{ volume }}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
24 |
29 |
--------------------------------------------------------------------------------
/src/components/layout/header/Header.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
44 |
57 |
--------------------------------------------------------------------------------
/src/components/layout/header/SearchPop.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
14 |
15 |
16 |
热门搜索
17 |
18 |
21 |
22 | {{ index + 1 }}.
23 | {{ item.searchWord }}
24 |
25 |
{{ item.score.numberFormat() }}
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
64 |
67 |
--------------------------------------------------------------------------------
/src/components/layout/header/SearchSuggest.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ getTitle(order) }}
4 |
6 | {{ item.name }}
7 | - {{ item.artists.first()?.name }}
8 |
9 |
12 | {{ item.name }}
13 | - {{ item.artist.name }}
14 |
15 |
18 |
19 | {{ item.name }}
20 |
21 |
24 |
25 |
{{ item.name }}
26 |
27 |
28 |
29 |
30 |
64 |
67 |
--------------------------------------------------------------------------------
/src/components/layout/header/UserInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ profile.nickname }}
5 | 点击登录
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
43 |
44 |
47 |
--------------------------------------------------------------------------------
/src/components/layout/menu/Menu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/components/layout/menu/MenuList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ menuItem.name }}
5 |
12 |
13 | {{ menu.name }}
14 |
15 |
16 |
17 |
18 |
19 |
28 |
29 |
30 |
43 |
--------------------------------------------------------------------------------
/src/components/layout/menu/useMenu.ts:
--------------------------------------------------------------------------------
1 | import {ref, watch} from "vue";
2 | import {Planet, Music, VideoOne, Fm, Like, Computer, DownloadThree, PlayTwo} from '@icon-park/vue-next'
3 | import {useRoute, useRouter} from "vue-router";
4 |
5 | interface IMenu {
6 | name: string;
7 | key: string;
8 | icon: any;
9 | theme: 'outline' | 'filled' | 'two-tone' | 'multi-color',
10 | }
11 |
12 | interface IMenus {
13 | name: string,
14 | menus: IMenu[],
15 | }
16 |
17 | export function useMenu() {
18 | const menus: IMenus[] = [
19 | {
20 | name: "在线音乐",
21 | menus: [
22 | {
23 | name: "推荐",
24 | key: "discover",
25 | icon: Planet,
26 | theme: 'outline',
27 | },
28 | {
29 | name: "音乐馆",
30 | key: "music",
31 | icon: Music,
32 | theme: 'outline',
33 | },
34 | {
35 | name: "视频",
36 | key: "video",
37 | icon: VideoOne,
38 | theme: 'outline',
39 | },
40 | {
41 | name: "电台",
42 | key: "dj",
43 | icon: Fm,
44 | theme: 'outline',
45 | },
46 | ]
47 | },
48 | {
49 | name: "我的音乐",
50 | menus: [
51 | {
52 | name: "我喜欢",
53 | key: "love",
54 | icon: Like,
55 | theme: 'outline',
56 | },
57 | {
58 | name: "本地歌曲",
59 | key: "local",
60 | icon: Computer,
61 | theme: 'outline',
62 | },
63 | {
64 | name: "下载歌曲",
65 | key: "download",
66 | icon: DownloadThree,
67 | theme: 'outline',
68 | },
69 | {
70 | name: "最近播放",
71 | key: "recently",
72 | icon: PlayTwo,
73 | theme: 'outline'
74 | },
75 | ]
76 | }
77 | ];
78 |
79 | const route = useRoute();
80 |
81 | const currentKey = ref(route.meta.menu);
82 |
83 | const router = useRouter();
84 |
85 | watch(
86 | () => route.meta.menu,
87 | (menu) => {
88 | currentKey.value = menu;
89 | }
90 | );
91 |
92 | const click = async (menu: IMenu) => {
93 | await router.push({name: menu.key, replace: true,})
94 | };
95 |
96 | return {
97 | menus,
98 | click,
99 | currentKey,
100 | };
101 | }
102 |
--------------------------------------------------------------------------------
/src/components/layout/playList/PlayList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
播放列表
6 |
7 |
共 {{ playListCount }} 首歌曲
8 |
9 |
10 | 清空
11 |
12 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
35 |
42 |
--------------------------------------------------------------------------------
/src/components/layout/playList/PlayListSongItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
{{ song.name }}
8 |
10 |
11 |
{{ song.ar.first().name }}
12 |
13 |
14 |
15 | {{ useFormatDuring(song.dt / 1000) }}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
36 |
41 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import { createPinia } from 'pinia'
3 | import '@/assets/base.scss'
4 | import '@/assets/theme.scss'
5 | import App from './App.vue'
6 | import router from './router'
7 | import "@/utils/extend"
8 |
9 | const app = createApp(App)
10 |
11 | app.use(createPinia())
12 | app.use(router)
13 |
14 | app.mount('#app')
15 |
--------------------------------------------------------------------------------
/src/models/album.ts:
--------------------------------------------------------------------------------
1 | import type {Artist} from "@/models/artist";
2 |
3 | export interface Album {
4 | songs: any[];
5 | paid: boolean;
6 | onSale: boolean;
7 | mark: number;
8 | blurPicUrl: string;
9 | companyId: number;
10 | alias: string[];
11 | artists: Artist[];
12 | copyrightId: number;
13 | picId: number;
14 | artist: Artist;
15 | publishTime: number;
16 | company: string;
17 | briefDesc: string;
18 | picUrl: string;
19 | commentThreadId: string;
20 | pic: number;
21 | tags: string;
22 | description: string;
23 | status: number;
24 | subType: string;
25 | name: string;
26 | id: number;
27 | type: string;
28 | size: number;
29 | picId_str: string;
30 | }
31 |
--------------------------------------------------------------------------------
/src/models/artist.ts:
--------------------------------------------------------------------------------
1 | export interface Artist {
2 | albumSize: number;
3 | alias: string[];
4 | briefDesc: string;
5 | fansCount: number;
6 | followed: boolean;
7 | id: number;
8 | img1v1Id: number;
9 | img1v1Id_str: string;
10 | img1v1Url: string;
11 | musicSize: number;
12 | name: string;
13 | picId: number;
14 | picId_str: string;
15 | picUrl: string;
16 | topicPerson: number;
17 | trans: string;
18 | }
19 |
20 | export interface Mv {
21 | id: number;
22 | name: string;
23 | status: number;
24 | artistName: string;
25 | artist: Artist;
26 | imgurl16v9: string;
27 | imgurl: string;
28 | duration: number;
29 | playCount: number;
30 | publishTime: string;
31 | subed: boolean;
32 | }
33 |
--------------------------------------------------------------------------------
/src/models/artist_detail.ts:
--------------------------------------------------------------------------------
1 | export interface ArtistDetail {
2 | videoCount: number;
3 | identify: ArtistDetailIdentify;
4 | artist: ArtistDetailArtist;
5 | blacklist: boolean;
6 | preferShow: number;
7 | showPriMsg: boolean;
8 | secondaryExpertIdentiy: ArtistDetailSecondaryExpertIdentiy[];
9 | }
10 | export interface ArtistDetailIdentify {
11 | imageUrl?: any;
12 | imageDesc: string;
13 | actionUrl: string;
14 | }
15 | export interface ArtistDetailArtistRank {
16 | rank: number;
17 | type: number;
18 | }
19 | export interface ArtistDetailArtist {
20 | id: number;
21 | cover: string;
22 | name: string;
23 | transNames: string[];
24 | identities: string[];
25 | identifyTag?: any;
26 | briefDesc: string;
27 | rank: ArtistDetailArtistRank;
28 | albumSize: number;
29 | musicSize: number;
30 | mvSize: number;
31 | }
32 | export interface ArtistDetailSecondaryExpertIdentiy {
33 | expertIdentiyId: number;
34 | expertIdentiyName: string;
35 | expertIdentiyCount: number;
36 | }
37 |
38 |
39 | export interface ArtistDesc {
40 | introduction: ArtistDescIntroduction[];
41 | briefDesc: string;
42 | count: number;
43 | topicData: ArtistDescTopicData[];
44 | }
45 | export interface ArtistDescIntroduction {
46 | ti: string;
47 | txt: string;
48 | }
49 | export interface ArtistDescTopicDataTopicContent {
50 | type: number;
51 | id: number;
52 | content: string;
53 | }
54 | export interface ArtistDescTopicDataTopic {
55 | id: number;
56 | addTime: number;
57 | mainTitle: string;
58 | title: string;
59 | content: ArtistDescTopicDataTopicContent[];
60 | userId: number;
61 | cover: number;
62 | headPic: number;
63 | shareContent: string;
64 | wxTitle: string;
65 | showComment: boolean;
66 | status: number;
67 | seriesId: number;
68 | pubTime: number;
69 | readCount: number;
70 | tags: string[];
71 | pubImmidiatly: boolean;
72 | auditor: string;
73 | auditTime: number;
74 | auditStatus: number;
75 | startText: string;
76 | delReason: string;
77 | showRelated: boolean;
78 | fromBackend: boolean;
79 | rectanglePic: number;
80 | updateTime: number;
81 | reward: boolean;
82 | summary: string;
83 | memo?: any;
84 | adInfo: string;
85 | categoryId: number;
86 | hotScore: number;
87 | recomdTitle: string;
88 | recomdContent: string;
89 | number: number;
90 | }
91 | export interface ArtistDescTopicDataCreatorExperts {
92 | 1: string;
93 | }
94 | export interface ArtistDescTopicDataCreator {
95 | userId: number;
96 | userType: number;
97 | nickname: string;
98 | avatarImgId: number;
99 | avatarUrl: string;
100 | backgroundImgId: number;
101 | backgroundUrl: string;
102 | signature: string;
103 | createTime: number;
104 | userName: string;
105 | accountType: number;
106 | shortUserName: string;
107 | birthday: number;
108 | authority: number;
109 | gender: number;
110 | accountStatus: number;
111 | province: number;
112 | city: number;
113 | authStatus: number;
114 | description?: any;
115 | detailDescription?: any;
116 | defaultAvatar: boolean;
117 | expertTags?: any;
118 | experts: ArtistDescTopicDataCreatorExperts;
119 | djStatus: number;
120 | locationStatus: number;
121 | vipType: number;
122 | followed: boolean;
123 | mutual: boolean;
124 | authenticated: boolean;
125 | lastLoginTime: number;
126 | lastLoginIP: string;
127 | remarkName?: any;
128 | viptypeVersion: number;
129 | authenticationTypes: number;
130 | avatarDetail?: any;
131 | anchor: boolean;
132 | }
133 | export interface ArtistDescTopicData {
134 | topic: ArtistDescTopicDataTopic;
135 | creator: ArtistDescTopicDataCreator;
136 | shareCount: number;
137 | commentCount: number;
138 | likedCount: number;
139 | liked: boolean;
140 | rewardCount: number;
141 | rewardMoney: number;
142 | relatedResource?: any;
143 | rectanglePicUrl: string;
144 | coverUrl: string;
145 | categoryId: number;
146 | categoryName: string;
147 | reward: boolean;
148 | shareContent: string;
149 | wxTitle: string;
150 | addTime: number;
151 | seriesId: number;
152 | showComment: boolean;
153 | showRelated: boolean;
154 | memo?: any;
155 | summary: string;
156 | recmdTitle: string;
157 | recmdContent: string;
158 | commentThreadId: string;
159 | mainTitle: string;
160 | tags: string[];
161 | readCount: number;
162 | url: string;
163 | title: string;
164 | id: number;
165 | number: number;
166 | }
167 |
--------------------------------------------------------------------------------
/src/models/banner.ts:
--------------------------------------------------------------------------------
1 | export interface Banner {
2 | pic:string
3 | targetId:number
4 | targetType:number
5 | typeTitle:string
6 | bannerId:number
7 | }
8 |
--------------------------------------------------------------------------------
/src/models/dj.ts:
--------------------------------------------------------------------------------
1 | export interface DJBanner {
2 | targetId: number;
3 | targetType: number;
4 | pic: string;
5 | url: string;
6 | typeTitle: string;
7 | exclusive: boolean;
8 | }
9 |
--------------------------------------------------------------------------------
/src/models/mv.ts:
--------------------------------------------------------------------------------
1 | export interface MvUrl {
2 | id: number;
3 | url: string;
4 | r: number;
5 | size: number;
6 | md5: string;
7 | code: number;
8 | expi: number;
9 | fee: number;
10 | mvFee: number;
11 | st: number;
12 | promotionVo?: any;
13 | msg: string;
14 | }
15 |
--------------------------------------------------------------------------------
/src/models/personalized.ts:
--------------------------------------------------------------------------------
1 | export interface Personalized {
2 | id: number;
3 | type: number;
4 | name: string;
5 | copywriter: string;
6 | picUrl: string;
7 | canDislike: boolean;
8 | trackNumberUpdateTime: number;
9 | playCount: number;
10 | trackCount: number;
11 | highQuality: boolean;
12 | alg: string;
13 | }
14 |
15 |
16 | export interface PersonalizedNewSong {
17 | id: number;
18 | type: number;
19 | name: string;
20 | picUrl: string;
21 | canDislike: boolean;
22 | song: PNSSong;
23 | alg: string;
24 | }
25 |
26 | export interface PNSSongArtists {
27 | name: string;
28 | id: number;
29 | picId: number;
30 | img1v1Id: number;
31 | briefDesc: string;
32 | picUrl: string;
33 | img1v1Url: string;
34 | albumSize: number;
35 | alias: any[];
36 | trans: string;
37 | musicSize: number;
38 | topicPerson: number;
39 | }
40 |
41 | export interface PNSSongAlbumArtist {
42 | name: string;
43 | id: number;
44 | picId: number;
45 | img1v1Id: number;
46 | briefDesc: string;
47 | picUrl: string;
48 | img1v1Url: string;
49 | albumSize: number;
50 | alias: any[];
51 | trans: string;
52 | musicSize: number;
53 | topicPerson: number;
54 | }
55 |
56 | export interface PNSSongAlbumArtists {
57 | name: string;
58 | id: number;
59 | picId: number;
60 | img1v1Id: number;
61 | briefDesc: string;
62 | picUrl: string;
63 | img1v1Url: string;
64 | albumSize: number;
65 | alias: any[];
66 | trans: string;
67 | musicSize: number;
68 | topicPerson: number;
69 | }
70 |
71 | export interface PNSSongAlbum {
72 | name: string;
73 | id: number;
74 | type: string;
75 | size: number;
76 | picId: number;
77 | blurPicUrl: string;
78 | companyId: number;
79 | pic: number;
80 | picUrl: string;
81 | publishTime: number;
82 | description: string;
83 | tags: string;
84 | company: string;
85 | briefDesc: string;
86 | artist: PNSSongAlbumArtist;
87 | songs: any[];
88 | alias: any[];
89 | status: number;
90 | copyrightId: number;
91 | commentThreadId: string;
92 | artists: PNSSongAlbumArtists[];
93 | subType: string;
94 | onSale: boolean;
95 | mark: number;
96 | picId_str: string;
97 | }
98 |
99 | export interface PNSSongBMusic {
100 | id: number;
101 | size: number;
102 | extension: string;
103 | sr: number;
104 | dfsId: number;
105 | bitrate: number;
106 | playTime: number;
107 | volumeDelta: number;
108 | }
109 |
110 | export interface PNSSongHMusic {
111 | id: number;
112 | size: number;
113 | extension: string;
114 | sr: number;
115 | dfsId: number;
116 | bitrate: number;
117 | playTime: number;
118 | volumeDelta: number;
119 | }
120 |
121 | export interface PNSSongMMusic {
122 | id: number;
123 | size: number;
124 | extension: string;
125 | sr: number;
126 | dfsId: number;
127 | bitrate: number;
128 | playTime: number;
129 | volumeDelta: number;
130 | }
131 |
132 | export interface PNSSongLMusic {
133 | id: number;
134 | size: number;
135 | extension: string;
136 | sr: number;
137 | dfsId: number;
138 | bitrate: number;
139 | playTime: number;
140 | volumeDelta: number;
141 | }
142 |
143 | export interface PNSSongPrivilegeFreeTrialPrivilege {
144 | resConsumable: boolean;
145 | userConsumable: boolean;
146 | }
147 |
148 | export interface PNSSongPrivilegeChargeInfoList {
149 | rate: number;
150 | chargeType: number;
151 | }
152 |
153 | export interface PNSSongPrivilege {
154 | id: number;
155 | fee: number;
156 | payed: number;
157 | st: number;
158 | pl: number;
159 | dl: number;
160 | sp: number;
161 | cp: number;
162 | subp: number;
163 | cs: boolean;
164 | maxbr: number;
165 | fl: number;
166 | toast: boolean;
167 | flag: number;
168 | preSell: boolean;
169 | playMaxbr: number;
170 | downloadMaxbr: number;
171 | freeTrialPrivilege: PNSSongPrivilegeFreeTrialPrivilege;
172 | chargeInfoList: PNSSongPrivilegeChargeInfoList[];
173 | }
174 |
175 | export interface PNSSong {
176 | name: string;
177 | id: number;
178 | position: number;
179 | alias: any[];
180 | status: number;
181 | fee: number;
182 | copyrightId: number;
183 | disc: string;
184 | no: number;
185 | artists: PNSSongArtists[];
186 | album: PNSSongAlbum;
187 | starred: boolean;
188 | popularity: number;
189 | score: number;
190 | starredNum: number;
191 | duration: number;
192 | playedNum: number;
193 | dayPlays: number;
194 | hearTime: number;
195 | ringtone: string;
196 | copyFrom: string;
197 | commentThreadId: string;
198 | ftype: number;
199 | rtUrls: any[];
200 | copyright: number;
201 | mark: number;
202 | originCoverType: number;
203 | single: number;
204 | mvid: number;
205 | bMusic: PNSSongBMusic;
206 | rtype: number;
207 | hMusic: PNSSongHMusic;
208 | mMusic: PNSSongMMusic;
209 | lMusic: PNSSongLMusic;
210 | exclusive: boolean;
211 | privilege: PNSSongPrivilege;
212 | }
213 |
214 | export interface PersonalizedMv {
215 | id: number;
216 | type: number;
217 | name: string;
218 | copywriter: string;
219 | picUrl: string;
220 | canDislike: boolean;
221 | trackNumberUpdateTime?: any;
222 | duration: number;
223 | playCount: number;
224 | subed: boolean;
225 | artists: {
226 | id: number;
227 | name: string;
228 | }[];
229 | artistName: string;
230 | artistId: number;
231 | alg: string;
232 | }
233 | export interface DjProgram {
234 | id: number;
235 | type: number;
236 | name: string;
237 | copywriter: string;
238 | picUrl: string;
239 | canDislike: boolean;
240 | trackNumberUpdateTime?: any;
241 | }
242 |
--------------------------------------------------------------------------------
/src/models/playlist.ts:
--------------------------------------------------------------------------------
1 | export interface PlayListDetail {
2 | id: number;
3 | name: string;
4 | coverImgId: number;
5 | coverImgUrl: string;
6 | coverImgId_str: string;
7 | adType: number;
8 | userId: number;
9 | createTime: number;
10 | status: number;
11 | opRecommend: boolean;
12 | highQuality: boolean;
13 | newImported: boolean;
14 | updateTime: number;
15 | trackCount: number;
16 | specialType: number;
17 | privacy: number;
18 | trackUpdateTime: number;
19 | commentThreadId: string;
20 | playCount: number;
21 | trackNumberUpdateTime: number;
22 | subscribedCount: number;
23 | cloudTrackCount: number;
24 | ordered: boolean;
25 | description: string;
26 | tags: string[];
27 | updateFrequency?: any;
28 | backgroundCoverId: number;
29 | backgroundCoverUrl?: any;
30 | titleImage: number;
31 | titleImageUrl?: any;
32 | englishTitle?: any;
33 | officialPlaylistType?: any;
34 | subscribers: PlayListDetailSubscribers[];
35 | subscribed: boolean;
36 | creator: PlayListDetailCreator;
37 | tracks: PlayListDetailTracks[];
38 | videoIds?: any;
39 | videos?: any;
40 | trackIds: PlayListDetailTrackIds[];
41 | shareCount: number;
42 | commentCount: number;
43 | remixVideo?: any;
44 | sharedUsers?: any;
45 | historySharedUsers?: any;
46 | }
47 |
48 | export interface PlayListDetailSubscribers {
49 | defaultAvatar: boolean;
50 | province: number;
51 | authStatus: number;
52 | followed: boolean;
53 | avatarUrl: string;
54 | accountStatus: number;
55 | gender: number;
56 | city: number;
57 | birthday: number;
58 | userId: number;
59 | userType: number;
60 | nickname: string;
61 | signature: string;
62 | description: string;
63 | detailDescription: string;
64 | avatarImgId: number;
65 | backgroundImgId: number;
66 | backgroundUrl: string;
67 | authority: number;
68 | mutual: boolean;
69 | expertTags?: any;
70 | experts?: any;
71 | djStatus: number;
72 | vipType: number;
73 | remarkName?: any;
74 | authenticationTypes: number;
75 | avatarDetail?: any;
76 | avatarImgIdStr: string;
77 | backgroundImgIdStr: string;
78 | anchor: boolean;
79 | avatarImgId_str: string;
80 | }
81 |
82 | export interface PlayListDetailCreatorAvatarDetail {
83 | userType: number;
84 | identityLevel: number;
85 | identityIconUrl: string;
86 | }
87 |
88 | export interface PlayListDetailCreator {
89 | defaultAvatar: boolean;
90 | province: number;
91 | authStatus: number;
92 | followed: boolean;
93 | avatarUrl: string;
94 | accountStatus: number;
95 | gender: number;
96 | city: number;
97 | birthday: number;
98 | userId: number;
99 | userType: number;
100 | nickname: string;
101 | signature: string;
102 | description: string;
103 | detailDescription: string;
104 | avatarImgId: number;
105 | backgroundImgId: number;
106 | backgroundUrl: string;
107 | authority: number;
108 | mutual: boolean;
109 | expertTags?: any;
110 | experts?: any;
111 | djStatus: number;
112 | vipType: number;
113 | remarkName?: any;
114 | authenticationTypes: number;
115 | avatarDetail: PlayListDetailCreatorAvatarDetail;
116 | avatarImgIdStr: string;
117 | backgroundImgIdStr: string;
118 | anchor: boolean;
119 | avatarImgId_str: string;
120 | }
121 |
122 | export interface PlayListDetailTracksAr {
123 | id: number;
124 | name: string;
125 | tns: any[];
126 | alias: any[];
127 | }
128 |
129 | export interface PlayListDetailTracksAl {
130 | id: number;
131 | name: string;
132 | picUrl: string;
133 | tns: any[];
134 | pic_str: string;
135 | pic: number;
136 | }
137 |
138 | export interface PlayListDetailTracksH {
139 | br: number;
140 | fid: number;
141 | size: number;
142 | vd: number;
143 | }
144 |
145 | export interface PlayListDetailTracksM {
146 | br: number;
147 | fid: number;
148 | size: number;
149 | vd: number;
150 | }
151 |
152 | export interface PlayListDetailTracksL {
153 | br: number;
154 | fid: number;
155 | size: number;
156 | vd: number;
157 | }
158 |
159 | export interface PlayListDetailTracks {
160 | name: string;
161 | id: number;
162 | pst: number;
163 | t: number;
164 | ar: PlayListDetailTracksAr[];
165 | alia: any[];
166 | pop: number;
167 | st: number;
168 | rt: string;
169 | fee: number;
170 | v: number;
171 | crbt?: any;
172 | cf: string;
173 | al: PlayListDetailTracksAl;
174 | dt: number;
175 | h: PlayListDetailTracksH;
176 | m: PlayListDetailTracksM;
177 | l: PlayListDetailTracksL;
178 | a?: any;
179 | cd: string;
180 | no: number;
181 | rtUrl?: any;
182 | ftype: number;
183 | rtUrls: any[];
184 | djId: number;
185 | copyright: number;
186 | s_id: number;
187 | mark: number;
188 | originCoverType: number;
189 | originSongSimpleData?: any;
190 | single: number;
191 | noCopyrightRcmd?: any;
192 | cp: number;
193 | mv: number;
194 | rtype: number;
195 | rurl?: any;
196 | mst: number;
197 | publishTime: number;
198 | }
199 |
200 | export interface PlayListDetailTrackIds {
201 | id: number;
202 | v: number;
203 | t: number;
204 | at: number;
205 | alg?: any;
206 | uid: number;
207 | rcmdReason: string;
208 | sc?: any;
209 | }
210 |
211 |
212 |
213 | export interface PlaylistHighqualityTag {
214 | id: number;
215 | name: string;
216 | type: number;
217 | category: number;
218 | hot: boolean;
219 | }
220 |
--------------------------------------------------------------------------------
/src/models/playlist_cat.ts:
--------------------------------------------------------------------------------
1 | export interface PlayListCat {
2 | name: string;
3 | resourceCount: number;
4 | imgId: number;
5 | imgUrl?: any;
6 | type: number;
7 | category: number;
8 | resourceType: number;
9 | hot: boolean;
10 | activity: boolean;
11 | }
12 |
--------------------------------------------------------------------------------
/src/models/playlist_hot.ts:
--------------------------------------------------------------------------------
1 | export interface PlayListHot {
2 | playlistTag: PlayListHotPlaylistTag;
3 | activity: boolean;
4 | position: number;
5 | category: number;
6 | hot: boolean;
7 | createTime: number;
8 | usedCount: number;
9 | name: string;
10 | id: number;
11 | type: number;
12 | }
13 |
14 | export interface PlayListHotPlaylistTag {
15 | id: number;
16 | name: string;
17 | category: number;
18 | usedCount: number;
19 | type: number;
20 | position: number;
21 | createTime: number;
22 | highQuality: number;
23 | highQualityPos: number;
24 | officialPos: number;
25 | }
26 |
--------------------------------------------------------------------------------
/src/models/search.ts:
--------------------------------------------------------------------------------
1 | export interface SearchHotDetail {
2 | searchWord: string;
3 | score: number;
4 | content: string;
5 | source: number;
6 | iconType: number;
7 | iconUrl?: string;
8 | url: string;
9 | alg: string;
10 | }
11 |
12 | export interface SearchSuggest {
13 | albums: SearchSuggestAlbums[];
14 | artists: SearchSuggestArtists[];
15 | songs: SearchSuggestSongs[];
16 | playlists: SearchSuggestPlaylists[];
17 | order: string[];
18 | }
19 | export interface SearchSuggestAlbumsArtist {
20 | id: number;
21 | name: string;
22 | picUrl: string;
23 | alias: string[];
24 | albumSize: number;
25 | picId: number;
26 | img1v1Url: string;
27 | img1v1: number;
28 | alia: string[];
29 | trans?: any;
30 | }
31 | export interface SearchSuggestAlbums {
32 | id: number;
33 | name: string;
34 | artist: SearchSuggestAlbumsArtist;
35 | publishTime: number;
36 | size: number;
37 | copyrightId: number;
38 | status: number;
39 | picId: number;
40 | mark: number;
41 | }
42 | export interface SearchSuggestArtists {
43 | id: number;
44 | name: string;
45 | picUrl: string;
46 | alias: string[];
47 | albumSize: number;
48 | picId: number;
49 | img1v1Url: string;
50 | img1v1: number;
51 | transNames: string[];
52 | alia: string[];
53 | trans: string;
54 | }
55 | export interface SearchSuggestSongsArtists {
56 | id: number;
57 | name: string;
58 | picUrl?: any;
59 | alias: any[];
60 | albumSize: number;
61 | picId: number;
62 | img1v1Url: string;
63 | img1v1: number;
64 | trans?: any;
65 | }
66 | export interface SearchSuggestSongsAlbumArtist {
67 | id: number;
68 | name: string;
69 | picUrl?: any;
70 | alias: any[];
71 | albumSize: number;
72 | picId: number;
73 | img1v1Url: string;
74 | img1v1: number;
75 | trans?: any;
76 | }
77 | export interface SearchSuggestSongsAlbum {
78 | id: number;
79 | name: string;
80 | artist: SearchSuggestSongsAlbumArtist;
81 | publishTime: number;
82 | size: number;
83 | copyrightId: number;
84 | status: number;
85 | picId: number;
86 | mark: number;
87 | }
88 | export interface SearchSuggestSongs {
89 | id: number;
90 | name: string;
91 | artists: SearchSuggestSongsArtists[];
92 | album: SearchSuggestSongsAlbum;
93 | duration: number;
94 | copyrightId: number;
95 | status: number;
96 | alias: any[];
97 | rtype: number;
98 | ftype: number;
99 | mvid: number;
100 | fee: number;
101 | rUrl?: any;
102 | mark: number;
103 | }
104 | export interface SearchSuggestPlaylists {
105 | id: number;
106 | name: string;
107 | coverImgUrl: string;
108 | creator?: any;
109 | subscribed: boolean;
110 | trackCount: number;
111 | userId: number;
112 | playCount: number;
113 | bookCount: number;
114 | specialType: number;
115 | officialTags?: any;
116 | action?: any;
117 | actionType?: any;
118 | description?: any;
119 | highQuality: boolean;
120 | }
121 |
--------------------------------------------------------------------------------
/src/models/song.ts:
--------------------------------------------------------------------------------
1 | export interface Song {
2 | name: string;
3 | id: number;
4 | pst: number;
5 | t: number;
6 | ar: SongAr[];
7 | alia: string[];
8 | pop: number;
9 | st: number;
10 | rt?: any;
11 | fee: number;
12 | v: number;
13 | crbt?: any;
14 | cf: string;
15 | al: SongAl;
16 | dt: number;
17 | h: SongH;
18 | m: SongM;
19 | l: SongL;
20 | a?: any;
21 | cd: string;
22 | no: number;
23 | rtUrl?: any;
24 | ftype: number;
25 | rtUrls: any[];
26 | djId: number;
27 | copyright: number;
28 | s_id: number;
29 | mark: number;
30 | originCoverType: number;
31 | originSongSimpleData?: any;
32 | tagPicList?: any;
33 | resourceState: boolean;
34 | version: number;
35 | songJumpInfo?: any;
36 | entertainmentTags?: any;
37 | single: number;
38 | noCopyrightRcmd?: any;
39 | rtype: number;
40 | rurl?: any;
41 | mst: number;
42 | cp: number;
43 | mv: number;
44 | publishTime: number;
45 | }
46 |
47 | export interface SongAr {
48 | id: number;
49 | name: string;
50 | tns: any[];
51 | alias: any[];
52 | }
53 |
54 | export interface SongAl {
55 | id: number;
56 | name: string;
57 | picUrl: string;
58 | tns: any[];
59 | pic_str: string;
60 | pic: number;
61 | }
62 |
63 | export interface SongH {
64 | br: number;
65 | fid: number;
66 | size: number;
67 | vd: number;
68 | }
69 |
70 | export interface SongM {
71 | br: number;
72 | fid: number;
73 | size: number;
74 | vd: number;
75 | }
76 |
77 | export interface SongL {
78 | br: number;
79 | fid: number;
80 | size: number;
81 | vd: number;
82 | }
83 |
--------------------------------------------------------------------------------
/src/models/song_url.ts:
--------------------------------------------------------------------------------
1 | export interface SongUrl {
2 | id: number;
3 | url: string;
4 | br: number;
5 | size: number;
6 | md5: string;
7 | code: number;
8 | expi: number;
9 | type: string;
10 | gain: number;
11 | fee: number;
12 | payed: number;
13 | flag: number;
14 | canExtend: boolean;
15 | freeTrialPrivilege: RootObjectFreeTrialPrivilege;
16 | freeTimeTrialPrivilege: RootObjectFreeTimeTrialPrivilege;
17 | urlSource: number;
18 | freeTrialInfo:{
19 | start:number
20 | end:number
21 | }
22 | }
23 |
24 | export interface RootObjectFreeTrialPrivilege {
25 | resConsumable: boolean;
26 | userConsumable: boolean;
27 | }
28 |
29 | export interface RootObjectFreeTimeTrialPrivilege {
30 | resConsumable: boolean;
31 | userConsumable: boolean;
32 | type: number;
33 | remainTime: number;
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/src/models/toplist_detail.ts:
--------------------------------------------------------------------------------
1 | export interface TopListDetail {
2 | subscribers: any[];
3 | subscribed?: any;
4 | creator?: any;
5 | artists?: any;
6 | tracks: TopListDetailTracks[];
7 | updateFrequency: string;
8 | backgroundCoverId: number;
9 | backgroundCoverUrl?: any;
10 | titleImage: number;
11 | titleImageUrl?: any;
12 | englishTitle?: any;
13 | opRecommend: boolean;
14 | recommendInfo?: any;
15 | subscribedCount: number;
16 | cloudTrackCount: number;
17 | userId: number;
18 | highQuality: boolean;
19 | createTime: number;
20 | specialType: number;
21 | coverImgId: number;
22 | newImported: boolean;
23 | anonimous: boolean;
24 | updateTime: number;
25 | trackCount: number;
26 | coverImgUrl: string;
27 | commentThreadId: string;
28 | trackUpdateTime: number;
29 | totalDuration: number;
30 | privacy: number;
31 | playCount: number;
32 | trackNumberUpdateTime: number;
33 | adType: number;
34 | description: string;
35 | ordered: boolean;
36 | tags: any[];
37 | status: number;
38 | name: string;
39 | id: number;
40 | coverImgId_str: string;
41 | ToplistType: string;
42 | }
43 | export interface TopListDetailTracks {
44 | first: string;
45 | second: string;
46 | }
47 |
--------------------------------------------------------------------------------
/src/models/user.ts:
--------------------------------------------------------------------------------
1 | export interface UserProfile {
2 | userId: number;
3 | userType: number;
4 | nickname: string;
5 | avatarImgId: number;
6 | avatarUrl: string;
7 | backgroundImgId: number;
8 | backgroundUrl: string;
9 | signature?: any;
10 | createTime: number;
11 | userName: string;
12 | accountType: number;
13 | shortUserName: string;
14 | birthday: number;
15 | authority: number;
16 | gender: number;
17 | accountStatus: number;
18 | province: number;
19 | city: number;
20 | authStatus: number;
21 | description?: any;
22 | detailDescription?: any;
23 | defaultAvatar: boolean;
24 | expertTags?: any;
25 | experts?: any;
26 | djStatus: number;
27 | locationStatus: number;
28 | vipType: number;
29 | followed: boolean;
30 | mutual: boolean;
31 | authenticated: boolean;
32 | lastLoginTime: number;
33 | lastLoginIP: string;
34 | remarkName?: any;
35 | viptypeVersion: number;
36 | authenticationTypes: number;
37 | avatarDetail?: any;
38 | anchor: boolean;
39 | }
40 |
--------------------------------------------------------------------------------
/src/models/video.ts:
--------------------------------------------------------------------------------
1 | export interface Video {
2 | type: number;
3 | displayed: boolean;
4 | alg: string;
5 | extAlg?: any;
6 | data: VideoData;
7 | }
8 | export interface VideoDataResolutions {
9 | resolution: number;
10 | size: number;
11 | }
12 | export interface VideoDataCreator {
13 | defaultAvatar: boolean;
14 | province: number;
15 | authStatus: number;
16 | followed: boolean;
17 | avatarUrl: string;
18 | accountStatus: number;
19 | gender: number;
20 | city: number;
21 | birthday: number;
22 | userId: number;
23 | userType: number;
24 | nickname: string;
25 | signature: string;
26 | description: string;
27 | detailDescription: string;
28 | avatarImgId: number;
29 | backgroundImgId: number;
30 | backgroundUrl: string;
31 | authority: number;
32 | mutual: boolean;
33 | expertTags?: any;
34 | experts?: any;
35 | djStatus: number;
36 | vipType: number;
37 | remarkName?: any;
38 | avatarImgIdStr: string;
39 | backgroundImgIdStr: string;
40 | }
41 | export interface VideoDataUrlInfo {
42 | id: string;
43 | url: string;
44 | size: number;
45 | validityTime: number;
46 | needPay: boolean;
47 | payInfo?: any;
48 | r: number;
49 | }
50 | export interface VideoDataVideoGroup {
51 | id: number;
52 | name: string;
53 | alg?: any;
54 | }
55 | export interface VideoDataRelateSongAr {
56 | id: number;
57 | name: string;
58 | tns: any[];
59 | alias: any[];
60 | }
61 | export interface VideoDataRelateSongAl {
62 | id: number;
63 | name: string;
64 | picUrl: string;
65 | tns: any[];
66 | pic: number;
67 | }
68 | export interface VideoDataRelateSongH {
69 | br: number;
70 | fid: number;
71 | size: number;
72 | vd: number;
73 | }
74 | export interface VideoDataRelateSongM {
75 | br: number;
76 | fid: number;
77 | size: number;
78 | vd: number;
79 | }
80 | export interface VideoDataRelateSongL {
81 | br: number;
82 | fid: number;
83 | size: number;
84 | vd: number;
85 | }
86 | export interface VideoDataRelateSongPrivilege {
87 | id: number;
88 | fee: number;
89 | payed: number;
90 | st: number;
91 | pl: number;
92 | dl: number;
93 | sp: number;
94 | cp: number;
95 | subp: number;
96 | cs: boolean;
97 | maxbr: number;
98 | fl: number;
99 | toast: boolean;
100 | flag: number;
101 | preSell: boolean;
102 | }
103 | export interface VideoDataRelateSong {
104 | name: string;
105 | id: number;
106 | pst: number;
107 | t: number;
108 | ar: VideoDataRelateSongAr[];
109 | alia: any[];
110 | pop: number;
111 | st: number;
112 | rt: string;
113 | fee: number;
114 | v: number;
115 | crbt?: any;
116 | cf: string;
117 | al: VideoDataRelateSongAl;
118 | dt: number;
119 | h: VideoDataRelateSongH;
120 | m: VideoDataRelateSongM;
121 | l: VideoDataRelateSongL;
122 | a?: any;
123 | cd: string;
124 | no: number;
125 | rtUrl?: any;
126 | ftype: number;
127 | rtUrls: any[];
128 | djId: number;
129 | copyright: number;
130 | s_id: number;
131 | rtype: number;
132 | rurl?: any;
133 | mst: number;
134 | cp: number;
135 | mv: number;
136 | publishTime: number;
137 | privilege: VideoDataRelateSongPrivilege;
138 | }
139 | export interface VideoData {
140 | alg: string;
141 | scm: string;
142 | threadId: string;
143 | coverUrl: string;
144 | height: number;
145 | width: number;
146 | title: string;
147 | description?: any;
148 | commentCount: number;
149 | shareCount: number;
150 | resolutions: VideoDataResolutions[];
151 | creator: VideoDataCreator;
152 | urlInfo: VideoDataUrlInfo;
153 | videoGroup: VideoDataVideoGroup[];
154 | previewUrl?: any;
155 | previewDurationms: number;
156 | hasRelatedGameAd: boolean;
157 | markTypes: number[];
158 | relateSong: VideoDataRelateSong[];
159 | relatedInfo?: any;
160 | videoUserLiveInfo?: any;
161 | vid: string;
162 | durationms: number;
163 | playTime: number;
164 | praisedCount: number;
165 | praised: boolean;
166 | subscribed: boolean;
167 | }
168 |
169 | export interface PersonalizedPrivateContent {
170 | id: number;
171 | url: string;
172 | picUrl: string;
173 | sPicUrl: string;
174 | type: number;
175 | copywriter: string;
176 | name: string;
177 | time: number;
178 | }
179 |
180 | export interface VideoGroup {
181 | id: number;
182 | name: string;
183 | url?: any;
184 | relatedVideoType?: any;
185 | selectTab: boolean;
186 | abExtInfo?: any;
187 | }
188 |
--------------------------------------------------------------------------------
/src/router/index.ts:
--------------------------------------------------------------------------------
1 | import {createRouter, createWebHistory, createWebHashHistory} from 'vue-router'
2 | import {Pages} from "@/router/pages";
3 |
4 | const router = createRouter({
5 | history: createWebHashHistory(import.meta.env.BASE_URL),
6 | routes: [
7 | {
8 | path: '/',
9 | name: Pages.home,
10 | component: () => import('@/views/Root.vue'),
11 | redirect: {name: Pages.discover},
12 | children: [
13 | {
14 | path: 'discover',
15 | name: 'discover',
16 | component: () => import("@/views/discover/Discover.vue"),
17 | meta: {
18 | menu: 'discover',
19 | keepAlive: true,
20 | }
21 | },
22 | {
23 | path: 'music',
24 | name: 'music',
25 | component: () => import('@/views/music/Music.vue'),
26 | redirect: {name: 'picked'},
27 | meta: {
28 | menu: 'music'
29 | },
30 | children: [
31 | {
32 | path: 'picked',
33 | name: 'picked',
34 | component: () => import("@/views/music/picked/Picked.vue"),
35 | meta: {
36 | menu: 'music',
37 | keepAlive: true,
38 | }
39 | },
40 | {
41 | path: 'toplist',
42 | name: 'toplist',
43 | component: () => import("@/views/music/toplist/TopList.vue"),
44 | meta: {
45 | menu: 'music',
46 | keepAlive: true,
47 | }
48 | },
49 | {
50 | path: 'artist',
51 | name: 'artist',
52 | component: () => import('@/views/music/artist/Artist.vue'),
53 | meta: {
54 | menu: 'music',
55 | title: '歌手',
56 | keepAlive: true,
57 | }
58 | },
59 | {
60 | path: Pages.category,
61 | name: Pages.category,
62 | component: () => import('@/views/music/category/Category.vue'),
63 | meta: {
64 | menu: 'music',
65 | title: '分类歌单',
66 | keepAlive: true,
67 | }
68 | }
69 | ]
70 | },
71 | {
72 | path: 'playlist',
73 | name: 'playlist',
74 | component: () => import('@/views/playlist/PlayList.vue'),
75 | },
76 | {
77 | path: 'artistDetail',
78 | name: 'artistDetail',
79 | component: () => import('@/views/artist/ArtistDetail.vue'),
80 | },
81 | {
82 | path: 'album',
83 | name: 'album',
84 | component: () => import('@/views/album/Album.vue'),
85 | },
86 | {
87 | path: 'video',
88 | name: 'video',
89 | component: () => import('@/views/video/Video.vue'),
90 | meta: {
91 | menu: 'video',
92 | title: '视频',
93 | keepAlive: true,
94 | }
95 | },
96 | {
97 | path: 'dj',
98 | name: 'dj',
99 | component: () => import('@/views/dj/DJ.vue'),
100 | meta: {
101 | menu: 'dj',
102 | title: '电台',
103 | keepAlive: true,
104 | }
105 | },
106 | {
107 | path: Pages.mvDetail,
108 | name: Pages.mvDetail,
109 | component: () => import('@/views/mv/mvDetail.vue'),
110 | }
111 | ],
112 | },
113 | ]
114 | })
115 |
116 | export default router
117 |
--------------------------------------------------------------------------------
/src/router/pages.ts:
--------------------------------------------------------------------------------
1 | export const Pages = {
2 | home: 'home',
3 | discover: 'discover',
4 | music: 'music',
5 | picked: 'picked',
6 | toplist: 'toplist',
7 | category: 'category',
8 | artist: 'artist',
9 | playlist: 'playlist',
10 | artistDetail: 'artistDetail',
11 | mvDetail: 'mvDetail',
12 | album: 'album',
13 | video: 'video',
14 | dj: 'dj',
15 | }
16 |
--------------------------------------------------------------------------------
/src/stores/common.ts:
--------------------------------------------------------------------------------
1 | import { defineStore } from "pinia";
2 | import { ref } from "vue";
3 | import { useBanner } from "@/utils/api";
4 | import type { Banner } from "@/models/banner";
5 |
6 | export const useCommonStore = defineStore("common", () => {
7 | const banners = ref([]);
8 |
9 | const getBanners = async () => {
10 | if (banners.value.length) return;
11 | banners.value = await useBanner();
12 | };
13 |
14 | return {
15 | banners,
16 | getBanners,
17 | };
18 | });
19 |
--------------------------------------------------------------------------------
/src/stores/dj.ts:
--------------------------------------------------------------------------------
1 | import type { DJBanner } from "@/models/dj";
2 | import { defineStore } from "pinia";
3 | import { ref } from "vue";
4 |
5 | export const useDJStore = defineStore("dj", () => {
6 |
7 | const djBanners = ref([])
8 |
9 | })
--------------------------------------------------------------------------------
/src/stores/host.ts:
--------------------------------------------------------------------------------
1 | import {defineStore} from "pinia";
2 |
3 | export const useHostStore = defineStore('host', {
4 | state: () => {
5 | return {
6 | base_url: localStorage.getItem('BASE_URL') || '',
7 |
8 | }
9 | },
10 | getters: {
11 | isInit: state => {
12 | return state.base_url != ''
13 | }
14 | },
15 | actions: {
16 | init() {
17 |
18 | },
19 | setHost(host: string) {
20 | localStorage.setItem('BASE_URL', host)
21 | location.reload()
22 | }
23 | }
24 | })
25 |
--------------------------------------------------------------------------------
/src/stores/music.ts:
--------------------------------------------------------------------------------
1 | import {defineStore} from "pinia";
2 | import {ref} from "vue";
3 | import {usePersonalized, usePersonalizedNewSong, useTopListDetail} from "@/utils/api";
4 | import type {Personalized, PersonalizedNewSong} from "@/models/personalized";
5 | import type {TopListDetail} from "@/models/toplist_detail";
6 |
7 | export const useMusicStore = defineStore('music', () => {
8 |
9 | const topListDetailData = ref([])
10 | const getTopListDetailData = async () => {
11 | if (topListDetailData.value.length) return;
12 | topListDetailData.value = await useTopListDetail()
13 | }
14 |
15 |
16 | const personalized = ref([]);
17 | const getPersonalized = async () => {
18 | if (personalized.value.length) return;
19 | personalized.value = await usePersonalized()
20 | }
21 |
22 |
23 | const personalizedNewSong = ref([]);
24 | const getPersonalizedNewSong = async () => {
25 | if (personalizedNewSong.value.length) return;
26 | personalizedNewSong.value = await usePersonalizedNewSong()
27 | }
28 |
29 |
30 | return {
31 | topListDetailData,
32 | getTopListDetailData,
33 |
34 | personalized,
35 | getPersonalized,
36 |
37 | personalizedNewSong,
38 | getPersonalizedNewSong
39 | }
40 | })
41 |
--------------------------------------------------------------------------------
/src/stores/personalized.ts:
--------------------------------------------------------------------------------
1 | import {defineStore} from "pinia";
2 | import {ref} from "vue";
3 | import {usePersonalizedDjProgram} from "@/utils/api";
4 | import type {DjProgram} from "@/models/personalized";
5 |
6 | export const usePersonalizedStore = defineStore('personalized', () => {
7 |
8 | const djProgram = ref([])
9 | const getDjProgram = async () => {
10 | if (djProgram.value.length) return;
11 | djProgram.value = await usePersonalizedDjProgram()
12 | }
13 |
14 |
15 | return {
16 | djProgram, getDjProgram,
17 | }
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/src/stores/player.ts:
--------------------------------------------------------------------------------
1 | import {defineStore, storeToRefs} from "pinia";
2 | import {useDetail, useSongUrl} from "@/utils/api";
3 | import {onMounted, onUnmounted, toRefs, watch} from "vue";
4 | import type {Song} from "@/models/song";
5 | import type {SongUrl} from "@/models/song_url";
6 |
7 | const KEYS = {
8 | volume: 'PLAYER-VOLUME'
9 | }
10 |
11 | export const usePlayerStore = defineStore({
12 | id: "player",
13 | state: () => ({
14 | audio: new Audio(),
15 | loopType: 0,//循环模式 0 单曲循环 1 列表循环 2随机播放
16 | volume: localStorage.getItem(KEYS.volume)?.toInt() || 60,//音量
17 | playList: [] as Song[],//播放列表,
18 | showPlayList: false,
19 | id: 0,
20 | url: '',
21 | songUrl: {} as SongUrl,
22 | song: {} as Song,
23 | isPlaying: false, //是否播放中
24 | isPause: false,//是否暂停
25 | sliderInput: false,//是否正在拖动进度条
26 | ended: false,//是否播放结束
27 | muted: false,//是否静音
28 | currentTime: 0,//当前播放时间
29 | duration: 0,//总播放时长
30 | }),
31 | getters: {
32 | playListCount: state => {
33 | return state.playList.length;
34 | },
35 | thisIndex: state => {
36 | return state.playList.findIndex(song => song.id === state.id);
37 | },
38 | nextSong(state): Song {
39 | const {thisIndex, playListCount} = this
40 | if (thisIndex === playListCount - 1) {
41 | return state.playList.first();
42 | } else {
43 | const nextIndex: number = thisIndex + 1
44 | return state.playList[nextIndex];
45 | }
46 | },
47 | prevSong(state): Song {
48 | const {thisIndex} = this
49 | if (thisIndex === 0) {
50 | return state.playList.last();
51 | } else {
52 | const prevIndex: number = thisIndex - 1
53 | return state.playList[prevIndex];
54 | }
55 | }
56 | },
57 | actions: {
58 | init() {
59 | this.audio.volume = this.volume / 100;
60 | },
61 | //播放列表里面添加音乐
62 | pushPlayList(replace: boolean, ...list: Song[]) {
63 | if (replace) {
64 | this.playList = list;
65 | return;
66 | }
67 | list.forEach(song => {
68 | if (this.playList.filter(s => s.id == song.id).length <= 0) {
69 | this.playList.push(song)
70 | }
71 | })
72 | },
73 | clearPlayList() {
74 | this.songUrl = {} as SongUrl
75 | this.url = ''
76 | this.id = 0;
77 | this.song = {} as Song
78 | this.isPlaying = false;
79 | this.isPause = false;
80 | this.sliderInput = false;
81 | this.ended = false;
82 | this.muted = false;
83 | this.currentTime = 0;
84 | this.playList = [] as Song[];
85 | this.showPlayList = false;
86 | this.audio.load();
87 | setTimeout(() => {
88 | this.duration = 0;
89 | }, 500)
90 | },
91 | async play(id: number) {
92 | if (id == this.id) return;
93 | this.isPlaying = false
94 | const data = await useSongUrl(id)
95 | this.audio.src = data.url;
96 | this.audio.play().then(res => {
97 | this.isPlaying = true
98 | this.songUrl = data
99 | this.url = data.url
100 | this.id = id;
101 | this.songDetail()
102 | }).catch(res => {
103 | console.log(res)
104 | })
105 | },
106 | //播放结束
107 | playEnd() {
108 | console.log('播放结束')
109 | switch (this.loopType) {
110 | case 0:
111 | this.rePlay()
112 | break;
113 | case 1:
114 | this.next()
115 | break;
116 | case 2:
117 | this.randomPlay()
118 | break;
119 | }
120 | },
121 | async songDetail() {
122 | this.song = await useDetail(this.id)
123 |
124 | this.pushPlayList(false, this.song)
125 | },
126 | //重新播放
127 | rePlay() {
128 | setTimeout(() => {
129 | this.currentTime = 0;
130 | this.audio.play()
131 | }, 1500)
132 | },
133 | //下一曲
134 | next() {
135 | if (this.loopType === 2) {
136 | this.randomPlay()
137 | } else {
138 | this.play(this.nextSong.id)
139 | }
140 |
141 | },
142 | //上一曲
143 | prev() {
144 | this.play(this.prevSong.id)
145 | },
146 | //随机播放
147 | randomPlay() {
148 | this.play(this.playList.sample().id)
149 | },
150 | //播放、暂停
151 | togglePlay() {
152 | if (!this.song.id) return;
153 | this.isPlaying = !this.isPlaying
154 | if (!this.isPlaying) {
155 | this.audio.pause();
156 | this.isPause = true
157 | } else {
158 | this.audio.play();
159 | this.isPause = false
160 | }
161 | },
162 | setPlay() {
163 | if (!this.song.id) return;
164 | this.isPlaying = true
165 | this.audio.play();
166 | this.isPause = false
167 |
168 | },
169 | setPause() {
170 | if (!this.song.id) return;
171 | this.isPlaying = false
172 | this.audio.pause();
173 | this.isPause = true
174 | },
175 | //切换循环类型
176 | toggleLoop() {
177 | if (this.loopType == 2) {
178 | this.loopType = 0;
179 | } else {
180 | this.loopType++;
181 | }
182 | },
183 | //静音切换
184 | toggleMuted() {
185 | this.muted = !this.muted
186 | this.audio.muted = this.muted
187 | },
188 | //音量设置
189 | setVolume(n: number) {
190 | n = n > 100 ? 100 : n
191 | n = n < 0 ? 0 : n
192 | this.volume = n
193 | this.audio.volume = n / 100
194 | localStorage.setItem('PLAYER-VOLUME', n.toString())
195 | },
196 | //修改播放时间
197 | onSliderChange(val: number) {
198 | this.currentTime = val
199 | this.sliderInput = false;
200 | this.audio.currentTime = val
201 | },
202 | //播放时间拖动中
203 | onSliderInput(val: number) {
204 | this.sliderInput = true;
205 | },
206 | //定时器
207 | interval() {
208 | if (this.isPlaying && !this.sliderInput) {
209 | this.currentTime = parseInt(this.audio.currentTime.toString());
210 | this.duration = parseInt(this.audio.duration.toString());
211 | this.ended = this.audio.ended
212 | }
213 | }
214 | }
215 | })
216 |
217 |
218 | export const userPlayerInit = () => {
219 | let timer: NodeJS.Timer;
220 | const {init, interval, playEnd} = usePlayerStore()
221 |
222 | const {ended} = storeToRefs(usePlayerStore())
223 |
224 | //监听播放结束
225 | watch(ended, ended => {
226 | if (!ended) return
227 | playEnd()
228 | })
229 |
230 | //启动定时器
231 | onMounted(() => {
232 | init()
233 | console.log('启动定时器')
234 | timer = setInterval(interval, 1000)
235 | })
236 | //清除定时器
237 | onUnmounted(() => {
238 | console.log('清除定时器')
239 | clearInterval(timer)
240 | })
241 | }
242 |
--------------------------------------------------------------------------------
/src/stores/search.ts:
--------------------------------------------------------------------------------
1 | import {defineStore} from "pinia";
2 | import {useSearchSuggest} from "@/utils/api";
3 | import type {SearchSuggest} from "@/models/search";
4 |
5 | export const useSearchStore = defineStore("search", {
6 | state: () => {
7 | return {
8 | showSearchView: false,
9 | searchKeyword: '',
10 | suggestData: {} as SearchSuggest,
11 | }
12 | },
13 | getters: {
14 | showHot: state => {
15 | return state.searchKeyword == ''
16 | }
17 | },
18 | actions: {
19 | async suggest() {
20 | this.suggestData = await useSearchSuggest(this.searchKeyword)
21 | }
22 | }
23 | })
24 |
--------------------------------------------------------------------------------
/src/stores/user.ts:
--------------------------------------------------------------------------------
1 | import {defineStore} from "pinia";
2 | import {useLogin, useLoginStatus} from "@/utils/api";
3 | import type {UserProfile} from "@/models/user";
4 |
5 | export const useUserStore = defineStore("user", {
6 | state: () => {
7 | return {
8 | token: '',
9 | cookie: '',
10 | showLogin: false,
11 | profile: {} as UserProfile,
12 | }
13 | },
14 | getters: {
15 | isLogin: state => {
16 | return state.profile?.userId > 0
17 | }
18 | },
19 | actions: {
20 | async login(phone: string, password: string) {
21 | const res = await useLogin(phone, password)
22 | if (res.code == 200) {
23 | this.token = res.token
24 | this.cookie = res.cookie
25 | document.cookie = res.cookie
26 | localStorage.setItem("USER-TOKEN", this.token)
27 | localStorage.setItem("USER-COOKIE", this.cookie)
28 | this.checkLogin()
29 | }
30 | },
31 | async checkLogin() {
32 | const {data} = await useLoginStatus()
33 | if (data.code === 200) {
34 | this.profile = data.profile
35 | this.showLogin = false
36 | }
37 |
38 | }
39 | }
40 | })
41 |
--------------------------------------------------------------------------------
/src/stores/video.ts:
--------------------------------------------------------------------------------
1 | import { defineStore } from "pinia";
2 | import { ref } from "vue";
3 | import type { PersonalizedPrivateContent, Video, VideoGroup } from "@/models/video";
4 | import { usePersonalizedMv, usePersonalizedPrivateContentList, useVideoGroupList, useVideoTimelineRecommend } from "@/utils/api";
5 | import type { PersonalizedMv } from "@/models/personalized";
6 |
7 | export const useVideoStore = defineStore('video', () => {
8 |
9 | const videoTimelineRecommend = ref